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;