partner-misc.js 5.82 KB
"use strict";

const crypto = require('crypto');
const moment = require('moment');

const config = require('komodo-sdk/config');
const logger = require('komodo-sdk/logger');
const pull = require('komodo-sdk/gateway/pull');

const partner = require('./partner');

function calculateSign(dt, trx_ref_id, cust_num, username, password) {
    const cryptoHashPassword = crypto.createHash('sha1');
    const cryptoHashUsernamePassword = crypto.createHash('sha1');
    const cryptoHashOutest = crypto.createHash('sha1');

    cryptoHashPassword.update(password);
    const hashPassword = cryptoHashPassword.digest('hex');

    cryptoHashUsernamePassword.update(username + hashPassword);
    const hashUsernamePassword = cryptoHashUsernamePassword.digest('hex');

    cryptoHashOutest.update(dt + trx_ref_id + cust_num + hashUsernamePassword);
    return cryptoHashOutest.digest('hex');
}

function createRequestOptions(task, config) {
    const dt = moment().format('YYYY-MM-DD HH:mm:ss');
    const sign = calculateSign(dt, task.trx_id, task.destination, config.partner.username, config.partner.password);

    return {
        url: config.partner.url,
        form: {
            username: config.partner.username,
            datetime: dt,
            code: task.remote_product,
            trx_ref_id: task.trx_id,
            cust_num: task.destination,
            sign: sign
        }
    }
}

function decodeResponseBody(responseBody) {
    let response;

    try {
        response = JSON.parse(responseBody);
    }
    catch(e) {
        logger.warn('Error parsing response body');
    }

    return response;
}

function cleanNumber(balance) {
    try {
        balance = balance.replace(/\D/g, '');
    }
    catch(e) { };

    return balance;

}

function processPartnerResponseBody(body, task) {
    let response = decodeResponseBody(body);
    let messages = [];

    if (!response) {
        return;
    }

    logger.verbose('RESPONSE', {response: response});

    const responseStatus = response.status;
    const responseInfo = response.info;

    let taskTrxId;
    if (task && task.trx_id) {
        taskTrxId = task.trx_id;
    }

    let responseRequestId;
    if (response.data && response.data.request_id) {
        responseRequestId = response.data.request_id;
    }


    let responseTrxStatus;
    if (response.data && response.data.trx_status) {
        responseTrxStatus = response.data.trx_status;
    }

    let responseTimestamp;
    if (response.data && response.data.timestamp) {
        responseTimestamp = response.data.timestamp;
        messages.push(responseTimestamp);
    }

    let responseDiag;
    if (response.data && response.data.diag) {
        responseDiag = response.data.diag;
        messages.push(responseDiag);
    }

    let responseMessage;
    if (response.data && response.data.message) {
        responseMessage = response.data.message;
        messages.push(responseMessage);
    }

    let responseHarga;
    if (response.data && response.data.harga) {
        responseHarga = response.data.harga;
        messages.push('Price: ' + responseHarga);

        if (responseHarga) {
            responseHarga = cleanNumber(responseHarga);
        }
    }

    let responseBalance;
    if (response.data && response.data.balance) {
        responseBalance = response.data.balance;
        messages.push('Balance: ' + responseBalance);

        if (responseBalance) {
            responseBalance = cleanNumber(responseBalance);
        }
    }

    if (messages.length <= 0) { messages.push('Transaksi anda sedang diproses'); }

    let coreReportData = {
        trx_id: taskTrxId || responseRequestId,
        rc: '68',
        message: messages.join('. ') + '.',
        sn: null,
        handler: config.handler_name,
        amount: responseHarga,
        balance: responseBalance,
        task: task,
        raw: body
    }

    if (responseStatus == 'Error') {
        if (responseInfo == ['insufficient balance', 'System Cut-Off'] >= 0) {
            coreReportData.rc = '91';
        }

        coreReportData.message = [responseStatus, responseInfo].join(': ');

        partner.reportToCore(coreReportData);
        return;
    }


    if (responseTrxStatus == 'P') {
        logger.verbose('Got pending trx response', {response: response.data});
        coreReportData.rc = '68';
    }
    else if (responseTrxStatus == 'S') {
        logger.verbose('Got succcess trx response', {response: response.data});

        coreReportData.rc = '00'

        coreReportData.sn = composeSn(response);
        coreReportData.message += ' SN=' + coreReportData.sn + '.';
    }
    else if (responseTrxStatus == 'R') {
        logger.verbose('Got rejected trx response', {response: response.data});

        const partnerRC = getPartnerRCFromDiagMessage(responseDiag);
        if (['14', '15'].indexOf(partnerRC) >= 0) {
            coreReportData.rc = '14';
        }
        else {
            coreReportData.rc = '40';
        }
    }

    partner.reportToCore(coreReportData);
}

function composeSn(response) {
    if (!response && !response.data) { return; }

    if (!response.data.info) {
        return response.data.serial;
    }

    let token = response.data.serial;
    let cust_name = response.data.info.cust_name;
    let tariff = response.data.info.kelas;
    let total_kwh = response.data.info.size;

    if (tariff.indexOf('VA') < 0) {
        tariff += 'VA';
    }

    if (cust_name) {
        cust_name = cust_name.replace(/\W+/g, ' ').trim().replace(/\W+/g, '-').toUpperCase();
    }

    return [ token, cust_name, tariff, total_kwh ].join('/');
}

function getPartnerRCFromDiagMessage(diag) {
    let matches = diag.match(/^\s*\[(.*)\]/);
    if (!matches || matches.length < 2) {
        return;
    }

    return matches[1];
}


exports.calculateSign = calculateSign;
exports.createRequestOptions = createRequestOptions;
exports.processPartnerResponseBody = processPartnerResponseBody;