partner-hpay.js 7.46 KB
process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';

var request = require('request');
var xml2js = require('xml2js');

var resendDelay = require('sate24/resend-delay.js');
var taskHistory = require('./task-history.js');
var antiSameDayDupe = require('./anti-same-day-dupe.js');

var config;
var aaa;
var _callbackReport;
var logger;

var xmlBuilder = new xml2js.Builder({rootName: 'xml', headless: true});

function start(options) {
    if (!options) {
        console.log('Undefined options, terminating....');
        process.exit(1);
    }

    if (options.config) {
        config = options.config;
    } else {
        console.log('Undefined options.config, terminating....')
        process.exit(1);
    }

    if (options.aaa) {
        aaa = options.aaa;
        _callbackReport = options.aaa.callbackReportWithPushToMongoDb;
    } else {
        console.log('Undefined options.aaa, terminating....')
        process.exit(1);
    }

    if (options && options.logger) {
        logger = options.logger;
    } else {
        console.log('Undefined options.logger, terminating....')
        process.exit(1);
    }

    resendDelay.init({
        config: config,
        topupRequest: _topupStatus,
        logger: logger
    });

    taskHistory.init(options);
    antiSameDayDupe.init(options);
}

function callbackReport(requestId, responseCode, msg, responseToLog) {
    if (responseCode != '68') {
        resendDelay.cancel(requestId)
    } else {
        taskHistory.get(requestId, function(err, task) {
            if (task) {
                resendDelay.register(task);
            }
        });
    }

    aaa.callbackReportWithPushToMongoDb(requestId, responseCode, msg, null, responseToLog);
}

function parseResponse(task, response) {
    var xmlParser = xml2js.parseString;

    xmlParser(response, function(err, result) {
        if (err) {
            var msg = 'Error parsing response. ' + err;
            logger.warn(msg, {task: task, response: response, err: err});
            callbackReport(task.requestId, '68', msg);
            return;
        }

        logger.verbose('Response parsed', {result: result, task: task});

        var st24rc = '68';

        var voucherSerialNumber;
        var trxId = getTrxId(result);
        var responseCode = getResponseCode(result);
        var responseMessage = getResponseMessage(result);
        var nilaiPulsa = getNilaiPulsa(result);
        var noHp = getNoHp(result);

        if (responseCode == '00') {
            st24rc = '00';
            voucherSerialNumber = getVoucherSerialNumber(result);
        }
        else if ((responseCode == '99') && (responseMessage == 'Member Not Found')) {
            st24rc = '40';
        }
        else if (responseCode == '99') {
            st24rc = '68';
        }
        else {
            st24rc = '40';
        }

        var msg = '';
        msg += ' responseCode: ' + responseCode;
        msg += ' responseMessage: ' + responseMessage;
        msg += ' nilaiPulsa: ' + nilaiPulsa;
        msg += ' noHp: ' + noHp;
        msg += ' trxId: ' + trxId;

        if (voucherSerialNumber) {
            msg = 'SN=' + voucherSerialNumber + ';' + msg + ' voucherSerialNumber: ' + voucherSerialNumber;
        }

        var responseToLog = {
            raw: response,
            parsed: {
                MESSAGE: msg
            }
        }

        callbackReport(task.requestId, st24rc, msg, responseToLog);
    });
}

function getNilaiPulsa(data) {
    var result;
    try {
        result = data.hpay.content.nilaiPulsa[0];
    }
    catch(e) {
        //logger.warn('Exception on getNilaiPulsa', {data: data});
        return;
    }

    return result;
}

function getNoHp(data) {
    var result;
    try {
        result = data.hpay.content.noHp[0];
    }
    catch(e) {
        //logger.warn('Exception on getNoHp', {data: data});
        return;
    }

    return result;
}

function getVoucherSerialNumber(data) {
    var result;
    try {
        result = data.hpay.content.voucherSerialNumber[0];
    }
    catch(e) {
        //logger.warn('Exception on getVoucherSerialNumber', {data: data});
        return;
    }

    return result;
}

function getTrxId(data) {
    var result;
    try {
        result = data.hpay.trxId[0];
    }
    catch(e) {
        //logger.warn('Exception on getTrxId', {data: data});
        return;
    }

    return result;
}

function getResponseCode(data) {
    var result;
    try {
        result = data.hpay.responseCode[0];
    }
    catch(e) {
        logger.warn('Exception on getResponseCode', {data: data});
        return;
    }

    return result;
}

function getResponseMessage(data) {
    var result;
    try {
        result = data.hpay.responseMessage[0];
    }
    catch(e) {
        logger.warn('Exception on getResponseMessage', {data: data});
        return;
    }

    return result;
}


function requestToPartner(methodName, task) {
    var payload = createPayload(methodName, task, config.h2h_out.userid, config.h2h_out.noid, config.h2h_out.password);
    if (!payload) {
        callbackReport(task.requestId, '40', 'ERROR: Undefined payload');
        return;
    }

    var requestOpts = {
        url: config.h2h_out.partner,
        method: "POST",
        body: payload,

    }

    logger.verbose('Requesting to partner', {methodName: methodName, task: task, requestOpts: requestOpts});
    request(requestOpts, function (err, response, responseBody) {
        if (err) {
            var rc = '68';
            if (methodName === 'pay') {
                rc = '40';
            }

            var msg = 'Error requesting pay method. ' + err;
            callbackReport(task.requestId, rc, msg);
            return;
        }

        logger.info('Got direct response from partner', {task: task, responseBody: responseBody});
        parseResponse(task, responseBody);
    });
}


function topupRequest(task) {
    if (!aaa.isTodayTrx(task)) {
        logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan');
        callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan');
        resendDelay.cancel(task);
        return;
    }

    aaa.insertTaskToMongoDb(task);
    antiSameDayDupe.check(task, _topupRequest, onSameDayDupe, _topupStatus);
}

function _topupRequest(task) {
    taskHistory.put(task, function() {
        requestToPartner('pay', task);;
    });
}

function _topupStatus(task) {
    requestToPartner('checking', task);
}

function onSameDayDupe(task) {
    callbackReport(task.requestId, '55', 'Transaksi duplikat dalam satu hari yang sama');
}

function extractProductDetail(remoteProduct) {
    var product;

    try {
        product = remoteProduct.split(',');
    }
    catch(e) {
        logger.warn('extractProductDetail: exception on split');
        return null;
    }

    if (product.length !== 3) {
        logger.warn('extractProductDetail: product.length <> 3');
        return null;
    }

    return {product: product[0], productType: product[1], nominal: product[2]};
}

function createPayload(transactionType, task, user, noid, pin) {
    var product = extractProductDetail(task.remoteProduct);
    if (!product) {
        logger.warn('createPayload: undefined product');
        return;
    }

    var payload = {
        transactionType: transactionType,
        product: product.product,
        productType: product.productType,
        idpel: task.destination,
        pin: pin,
        noid: noid,
        user: user,
        nominal: product.nominal
    };

    return xmlBuilder.buildObject(payload);
}

exports.start = start;
exports.topupRequest = topupRequest;