partner-bnisp.js 5.97 KB
"use strict";

const http = require('http');
http.globalAgent.maxSockets = Infinity;

const request = require('request');

var config;
var aaa;
var logger;

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;
    } 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);
    }
}

function callbackReport(requestId, rc, message, options) {
    aaa.callbackReportWithPushToMongoDb(requestId, rc, message);
}

function topupRequest(task) {
    aaa.insertTaskToMongoDb(task);
    _hitTopup(task);
}

function _hitTopup(task, isCheckStatus) {

    const remoteProduct = task.remoteProduct.split('/');
    if (remoteProduct.length < 4) {
        callbackReport(task.requestId, '40', 'INTERNAL_MSG: Invalid remoteProduct', task)
        return;
    }

    let pathParams = {
        request_type: "purchase",
        noid: config.h2h_out.noid,
        token: config.h2h_out.token,
        product: remoteProduct[0],
        product_type: remoteProduct[1],
        id_pel: task.destination,
        nominal: remoteProduct[2],
        admin: remoteProduct[3],
        trace_id: task.requestId
    }

    const requestOptions = {
        url: config.h2h_out.partner + createUrlPath(pathParams)
    }

    logger.verbose('Requeting to partner', {requestOptions: requestOptions});
    request(requestOptions, function(error, response, body) {
        if (error) {
            let rc = '68';

            if (!isCheckStatus && (error.syscall == 'connect')) {
                rc = '91';
            }

            logger.warn('Error requesting to partner', {task: task, rc: rc, error: error});
            callbackReport(task.requestId, rc, 'INTERNAL_MSG: Error requesting to partner. ' + error, {task: task});
            return;
        }

        if (response.statusCode != 200) {
            let rc = '68';

            logger.warn('HTTP status code is not 200', {task: task, http_status_code: response.statusCode});
            callbackReport(task.requestId, rc, 'INTERNAL_MSG: HTTP status code ' + response.statusCode, {task: task});
            return;
        }

        if (!body) {
            let rc = '68';

            logger.warn('Error processing response body', {task: task, responseBody: body});
            callbackReport(task.requestId, rc, 'INTERNAL_MSG: Error processing response body', {task: task});
            return;
        }

        if (body.trim() == 'invalid specs') {
            let rc = '40';

            logger.warn('Invalid specs', {task: task, responseBody: body});
            callbackReport(task.requestId, rc, body);
            return;
        }

        logger.verbose('Got response from partner', {task: task, responseBody: body});

        const responseData = parseResponseBody(body);
        logger.verbose('Response body parsed as json value', {responseData: responseData});
        const data = responseDataProcessor(responseData);

        callbackReport(task.requestId, data.rc, data.combinedMessage, {task: task});
    })

}

function createUrlPath(options) {
    let urlPath = [
        "get",
        options.request_type || "purchase",
        "json",
        options.noid,
        options.token,
        options.product,
        options.product_type,
        options.id_pel,
        options.nominal || 0,
        options.admin || 0,
        options.trace_id
    ].join('/');

    return '/' + urlPath;
}

function parseResponseBody(body) {
    let data;

    try {
        data = JSON.parse(body);
    }
    catch(e) {
        if (logger) {
            logger.warn('Exception on parsing result body: ' + e);
            return;
        }
    }

    return data;
}

function responseDataProcessor(responseData) {
    let retval = {
        rc: '68',
        sn: '',
        responseMessage: '',
        amount: 0,
        balance: 0,
        ts: '',
        product: '',
        productType: ''
    }

    let combinedMessage = [];

    if (responseData.response_code == '0000') {
        retval.rc = '00';
    }
    else if (['9990','0099','0068','0063','0005','9997','9999','9998','9990','0600','1003'].indexOf(responseData.response_code) >= 0) {
        retval.rc = '68';
    }
    else {
        retval.rc = '40';
    }

    if (responseData.response_code) {
        combinedMessage.push(responseData.response_code);
    }

    if (responseData.product) {
        combinedMessage.push(responseData.product)
    }

    if (responseData.produk_tipe) {
        combinedMessage.push(responseData.produk_tipe)
    }

    if (responseData.idpel) {
        combinedMessage.push(responseData.idpel)
    }

    retval.responseMessage = responseData.response_message || '';
    if (retval.responseMessage) {
        combinedMessage.push(retval.responseMessage);
    }

    if (responseData.detail) {
        retval.sn = responseData.detail.voucherSerialNumber || '';
    }

    retval.amount = responseData.amount || 0;
    combinedMessage.push('amount: ' + retval.amount);

    retval.balance = responseData.saldo || 0;
    combinedMessage.push('balance: ' + retval.balance);

    retval.ts = responseData.waktu || '';
    combinedMessage.push(retval.ts);

    retval.loadTime = responseData.loadTime || '';
    combinedMessage.push('load time: ' + retval.loadTime);

    retval.combinedMessage = combinedMessage.join(' ');

    if (retval.sn) {
        retval.combinedMessage = 'SN=' + retval.sn + '; ' + retval.combinedMessage;
    }

    return retval;
}

exports.start = start;
exports.createUrlPath = createUrlPath;
exports.parseResponseBody = parseResponseBody;
exports.responseDataProcessor = responseDataProcessor;
exports.topupRequest = topupRequest;