From ed7b35458050219777d371b410afc2a07d17eeb2 Mon Sep 17 00:00:00 2001
From: Adhidarma Hadiwinoto <gua@adhisimon.org>
Date: Thu, 21 Apr 2016 17:43:02 +0700
Subject: [PATCH] moment

---
 partner-sc.js | 1127 +++++++++++++++++++++++++++++----------------------------
 1 file changed, 564 insertions(+), 563 deletions(-)

diff --git a/partner-sc.js b/partner-sc.js
index d389616..51a7491 100644
--- a/partner-sc.js
+++ b/partner-sc.js
@@ -1,563 +1,564 @@
-var fs = require('fs');
-var https = require('https');
-var http = require('http');
-var url = require('url');
-var request = require('request');
-var xml2js = require('xml2js').parseString;
-var strftime = require('strftime');
-var math = require('mathjs');
-var winston = require('winston');
-var cekstatus = require('./cekstatus.js');
-var mongoClient = require('mongodb').MongoClient;
-var LRU = require('lru-cache');
-
-var config;
-var httpServer;
-var aaa;
-var logger;
-var callbackReport;
-var mongodb;
-
-var tasks = LRU(10000);
-
-process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
-
-var sleep_before_retry = 30000;
-
-var logTag = __filename.split('/').reverse()[0];
-
-function initMongoClient() {
-    if (!config.mongodb || !config.mongodb.url) {
-        return;
-    }
-    
-    try {
-        var url = config.mongodb.url;
-    
-        mongoClient.connect(url, function(err, db) {
-            if (err) {
-                logger.warn('Failed to connect to mongodb', {err: err});
-                return;
-            }
-            mongodb = db;
-            logger.info('MongoDB connected');
-        });
-    }
-    catch(err) {
-        logger.warn('Exception when connecting to mongodb', {err: err, url: url});
-    }
-    
-}
-
-function prepareResultData(result) {
-    var task;
-    
-    var data = {};
-    data.gateway = config.globals.gateway_name;
-    
-    try {
-        data.requestId = result.reffid[0].trim();
-        
-        var key = config.globals.gateway_name + '.rid:' + data.requestId;
-        task = tasks.get(key);
-    }
-    catch(err) { data.requestId = null; }
-    
-    try {
-        data.status = result.ResultCode[0].trim();
-    }
-    catch(err) { data.status = '68' }
-    
-    try {
-        data.rcmessage = result.ErrorMsg[0].trim();                        
-    }
-    catch(err) { data.rcmessage = ''; }
-    
-    try {
-        data.resptext = '';                        
-    }
-    catch(err) { data.resptext = ''; }
-    
-    try {
-        data.dt = task.timestamp;               
-    }
-    catch(err) { 
-        logger.warn('Exception when getting timestamp data, using current timestamp', {err: err, result: result, task: task});
-        data.dt = strftime('%Y-%m-%d %H:%M:%S', new Date()); 
-    }
-    
-    try {
-        data.namapel = result.nama_pel[0].trim();
-    }
-    catch(err) { data.namapel = 'UNKNOWN'; }
-    
-    try {
-        data.msn = result.nsm[0].trim();
-    }
-    catch(err) { data.msn = 'UNKNOWN'; }
-    
-    try {
-        data.idpel = result.idpel[0].trim();
-    }
-    catch(err) { data.idpel = 'UNKNOWN'; }
-    
-    try {
-        data.tarifdaya = result.tarif[0].trim();
-    }
-    catch(err) { data.tarifdaya = 'UNKNOWN'; }
-    
-    try {
-        data.admin = parseInt(result.adminfee[0].trim());
-    }
-    catch(err) { data.admin = 0; }
-    
-    try {
-        data.adm = parseInt(result.adminfee[0].trim());
-    }
-    catch(err) { data.adm = 0; }
-    
-    try {
-        data.hargatotal = parseInt(result.amount_trx[0].trim());
-    }
-    catch(err) { data.hargatotal = 0; }
-    
-    try {
-        data.hargapelanggan = data.hargatotal - data.adm;
-    }
-    catch(err) { data.hargapelanggan = 0; }
-    
-    try {
-        data.jumlahkwh = result.jml_daya[0].trim();
-    }
-    catch(err) { data.jumlahkwh = 0; }
-    
-    try {
-        data.token = result.token[0].trim();
-    }
-    catch(err) { data.token = 0; }
-    
-    try {
-        data.ppn = result.ppn_fee[0].trim();
-    }
-    catch(err) { data.ppn_fee = 0; }
-    
-    try {
-        data.ppj = result.ppj_fee[0].trim();
-    }
-    catch(err) { data.ppj = 0; }
-    
-    try {
-        data.angsuran = result.angsuran_fee[0].trim();
-    }
-    catch(err) { data.angsuran = 0; }
-    
-    try {
-        data.meterai = result.materai_fee[0].trim();
-    }
-    catch(err) { data.materai_fee = 0; }
-    
-    return data;
-}
-
-function saveTokenToMongoDb(result) {
-    if (!mongodb) {
-        return;
-    }
-    
-    if (!config.mongodb) {
-        return;
-    }
-    
-    if (!config.mongodb.collection) {
-        return;
-    }
-    
-    data = prepareResultData(result);
-
-    try {
-        mongodb.collection(config.mongodb.collection).insertOne(data);
-    }
-    catch(err) {
-        logger.warn('Error when inserting data to mongodb', {err: err, data: data});
-    }
-}
-
-function putTaskToCache(task) {
-    var key = config.globals.gateway_name + '.rid:' + task.requestId;
-    
-    try {
-        tasks.set(key, task);
-    }
-    catch(err) {
-        logger.warn('Error writing to task to cache', {err: err, key: key, task: task});
-    }
-}
-
-function topupRequest(task) {
-    putTaskToCache(task);
-    
-    var ts = strftime('%Y%m%d%H%M%S', new Date());
-    
-    var data = 
-        config.h2h_out.userid 
-        + '|' + config.h2h_out.password 
-        + '|' + task['remoteProduct'] 
-        + '|' + task['destination'] + '|0';
-    
-    var options = {
-        url: config.h2h_out.partner,
-        qs: {
-            ts: ts,
-            data: data,
-            reffid: task['requestId']
-        }
-    };
-    logger.info('Creating http request', {options: options});
-
-    request(options, function (error, response, body) {
-        var responseCode = '40';
-        var responseMessage = 'Gateway Error';
-
-        if (error) {
-            
-            logger.warn('HTTP REQUEST ERROR', error);
-            callbackReport(task['requestId'], '89', 'HTTP REQUEST ERROR (' + error + ')');
-            
-        } else if (response.statusCode != 200) {
-            
-            var error_message = 'GATEWAY ERROR (HTTP RESPONSE CODE: ' + response.statusCode + ')';
-            logger.warn(error_message);
-            callbackReport(task['requestId'], '91', error_message);
-            
-        } else {
-
-            logger.info('DIRECT RESPONSE', {body: body});
-
-            xml2js(body, function (err, result) {
-                if (err) {
-                    callbackReport(task['requestId'], '40', body);
-                } else {
-                    var directResponse = result;
-                    logger.info(directResponse);
-                    
-                    saveTokenToMongoDb(directResponse.Result);
-                    
-                    try {
-                        var result_price;
-                        try {
-                            result_price = directResponse.Result.Price[0].trim();
-                        }
-                        catch(err) {
-                            result_price = 0;
-                        }
-                        
-                        var result_error_message;
-                        try {
-                            result_error_message = directResponse.Result.ErrorMsg[0].trim();
-                        }
-                        catch(err) {
-                            result_error_message = '';
-                        }
-                        
-                        var resultCode = directResponse.Result.ResultCode[0].trim();
-                        
-                        responseMessage = 
-                            'ResultCode: ' + resultCode
-                            + ' | ErrorMsg: ' + result_error_message
-                            + ' | DateTime: ' + directResponse.Result.DateTime[0].trim()
-                            + ' | nsm: ' + directResponse.Result.nsm[0].trim()
-                            + ' | idpel: ' + directResponse.Result.idpel[0].trim()
-                            + ' | reffid: ' + directResponse.Result.reffid[0].trim()
-                            + ' | TransID: ' + directResponse.Result.TransID[0].trim()
-                            + ' | reff_switching: ' + directResponse.Result.reff_switching[0].trim()
-                            + ' | amount_trx: ' + directResponse.Result.amount_trx[0].trim()
-                            + ' | token: ' + directResponse.Result.token[0].trim()
-                            + ' | PrevBalance: ' + directResponse.Result.PrevBalance[0].trim()
-                            + ' | Price: ' + result_price
-                            + ' | EndBalance: ' + directResponse.Result.EndBalance[0].trim()
-                            ;
-                            
-                        logger.info('Response message: ' + responseMessage);
-                        
-                        if (aaa) {
-                            // update balance
-                            aaa.updateBalance(directResponse.Result.EndBalance[0]);
-                        }
-                        
-                        if (resultCode == '0000') {
-                            var nama_pelanggan = directResponse.Result.nama_pel[0].trim();
-                            nama_pelanggan =  nama_pelanggan.replace(/-\/-/g, '-');
-                            var sn = directResponse.Result.token[0].trim() + '/' + nama_pelanggan + '/' + directResponse.Result.tarif[0].trim() +  'VA/' + directResponse.Result.jml_daya[0].trim();
-                            sn = sn.replace(/\s/g, '-');
-                            
-                            responseMessage = 'SN=' + sn + '; ' + responseMessage;
-                            logger.info('New response message: ' + responseMessage);
-                        }
-                        
-                        var pendingResultCode = ['0005', '0012', '0068', '0090', '0063', '0018', '0096'];
-                        if (pendingResultCode.indexOf(resultCode) != -1) {
-                            callbackReport(task['requestId'], '68', responseMessage);
-                            
-                            logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms');
-                            setTimeout(function () {
-                                cekstatus.advice({trxid: directResponse.Result.TransID[0].trim()}, callbackFromWebReport);
-                            }, sleep_before_retry);
-                            
-                            return;
-                        }
-                        
-                        responseCode = resultCode.replace(/^00/, "");
-                        
-                        if (result_error_message == 'Inq - APLICATION SERVER RESPONSE TIMEOUT') {
-                            responseCode = '91';
-                        }                        
-                        
-                    }
-                    catch(err) {
-                        responseCode = '40';
-                        responseMessage = 'Invalid response from gateway';
-                    }
-                }
-                
-                callbackReport(task['requestId'], responseCode, responseMessage);
-            });
-        }
-
-        //callbackReport(task['requestId'], responseCode, responseMessage);
-    });
-}
-
-function callbackFromWebReport(status) {
-    if (!status) {
-        logger.warn('Advice from webreport return empty status');
-        return;
-    }
-    
-    logger.info('Got advice result from webreport', {status: status});
-    
-    var responseCode = '68';
-    
-    var result_price = 0;
-    try {
-        result_price = directResponse.Result.Price[0].trim();
-    }
-    catch(err) {}
-    
-    var errorMsg = '';
-    try {
-        errorMsg = status.response.errormsg[0];
-    }
-    catch(err) {}
-    
-    var responseMessage = '';
-    try {
-        responseMessage = 
-            'Hasil advice dari webreport '
-            + 'ResultCode: ' + status.response.resultcode[0]
-    }
-    catch(err) {
-        logger.warn('Error parsing ResultCode from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | ErrorMsg: ' + errorMsg
-    }
-    catch(err) {
-        logger.warn('Error parsing ErrorMsg from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | TrxDate: ' + status.trxDate;
-    }
-    catch(err) {
-        logger.warn('Error parsing TrxDate from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | UpdateDate: ' + status.updateDate;
-    
-    }
-    catch(err) {
-        logger.warn('Error parsing UpdateDate from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | nsm: ' + status.response.nsm[0];
-    }
-    catch(err) {
-        logger.warn('Error parsing nsm from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | idpel: ' + status.response.idpel[0];
-    }
-    catch(err) {
-        logger.warn('Error parsing idpel from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | reffid: ' + status.response.reffid[0].trim();
-    }
-    catch(err) {
-        logger.warn('Error parsing reffid from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | TransID: ' + status.response.transid[0].trim();
-    }
-    catch(err) {
-        logger.warn('Error parsing TransID from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | reff_switching: ' + status.response.reff_switching[0];
-    }
-    catch(err) {
-        logger.warn('Error parsing reff_switching from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | amount_trx: ' + status.response.amount_trx[0];
-    }
-    catch(err) {
-        logger.warn('Error parsing amount_trx from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | token: ' + status.response.token[0];
-    }
-    catch(err) {
-        logger.warn('Error parsing token from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | PrevBalance: ' + status.response.prevbalance[0];
-    }
-    catch(err) {
-        logger.warn('Error parsing PrevBalance from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | Price: ' + status.amount;
-    }
-    catch(err) {
-        logger.warn('Error parsing Price from webreport advice.', {err: err});
-    }
-    
-    try {
-        responseMessage = 
-            responseMessage
-            + ' | EndBalance: ' + status.response.endbalance[0];
-    }
-    catch(err) {
-        logger.warn('Error parsing EndBalance from webreport advice.', {err: err});
-    }
-    
-    
-    if ((status.status == 'S') && (status.response.resultcode[0] == '0000')) {
-        responseCode = '00';
-        
-        var nama_pelanggan = status.response.nama_pel[0] ;
-        nama_pelanggan =  nama_pelanggan.replace(/-\/-/g, '-');
-        
-        var sn = status.response.token[0] + '/' + nama_pelanggan + '/' + status.response.tarif[0] + 'VA/' + status.response.jml_daya[0];
-        responseMessage = 'SN=' + sn + '; ' + responseMessage;
-    
-    } else if ((status.status == 'P') || (status.status == 'W')) {
-        
-        callbackReport(status.response.reffid[0].trim(), '68', responseMessage);
-        logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms');
-        
-        setTimeout(function () {
-            
-            cekstatus.advice({trxid: status.trxId,}, callbackFromWebReport);
-            
-        }, sleep_before_retry);
-        return;
-        
-    } else {
-        responseCode = status.response.resultcode[0].replace(/^00/, "");
-        if (['00', '05', '12', '68', '90', '63', '18', '96'].indexOf(responseCode) >= 0) {
-            responseCode = '40';
-        }
-    }
-    
-    
-    callbackReport(status.response.reffid[0].trim(), responseCode, responseMessage);
-}
-
-function createHttpReportServer() {
-    var httpServer = http.createServer(function(request, response) {
-        var qs = url.parse(request.url, true).query;
-        var path = url.parse(request.url).pathname;
-        
-        logger.info('Got reverse report from partner', {path: path, qs: qs});
-        response.end('OK');
-        
-        var  trxid;
-        try {
-            trxid = qs.transid;
-        }
-        catch(err) {
-        }
-        
-        if (trxid) {
-            logger.info('Requesting advice from webreport', {trxid: trxid})
-            cekstatus.advice({trxid: trxid}, callbackFromWebReport);
-        }
-        
-    });
-    
-    httpServer.listen(config.h2h_out.listen_port, function() {
-        logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port);
-    });
-}
-
-function start(_config, _callbackReport, options) {
-    config = _config;
-    callbackReport = _callbackReport;
-    
-    if (options && options.aaa) {
-            aaa = options.aaa;
-    }
-    
-    if (options && options.logger) {
-        logger = options.logger;
-    } else {
-        logger = new winston.Logger({
-            transports: [
-              new (winston.transports.Console)()
-            ]
-        });
-    }
-    
-    createHttpReportServer();
-    initMongoClient();
-}
-
-exports.start = start;
-exports.topupRequest = topupRequest;
+var fs = require('fs');
+var https = require('https');
+var http = require('http');
+var url = require('url');
+var request = require('request');
+var xml2js = require('xml2js').parseString;
+var strftime = require('strftime');
+var math = require('mathjs');
+var winston = require('winston');
+var cekstatus = require('./cekstatus.js');
+var mongoClient = require('mongodb').MongoClient;
+var LRU = require('lru-cache');
+
+var config;
+var httpServer;
+var aaa;
+var logger;
+var callbackReport;
+var mongodb;
+
+var tasks = LRU(10000);
+
+process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
+
+var sleep_before_retry = 30000;
+
+var logTag = __filename.split('/').reverse()[0];
+
+function initMongoClient() {
+    if (!config.mongodb || !config.mongodb.url) {
+        return;
+    }
+    
+    try {
+        var url = config.mongodb.url;
+    
+        mongoClient.connect(url, function(err, db) {
+            if (err) {
+                logger.warn('Failed to connect to mongodb', {err: err});
+                return;
+            }
+            mongodb = db;
+            logger.info('MongoDB connected');
+        });
+    }
+    catch(err) {
+        logger.warn('Exception when connecting to mongodb', {err: err, url: url});
+    }
+    
+}
+
+function prepareResultData(result) {
+    var task;
+    
+    var data = {};
+    data.gateway = config.globals.gateway_name;
+    
+    try {
+        data.requestId = result.reffid[0].trim();
+        
+        var key = config.globals.gateway_name + '.rid:' + data.requestId;
+        task = tasks.get(key);
+    }
+    catch(err) { data.requestId = null; }
+    
+    try {
+        data.status = result.ResultCode[0].trim();
+    }
+    catch(err) { data.status = '68' }
+    
+    try {
+        data.rcmessage = result.ErrorMsg[0].trim();                        
+    }
+    catch(err) { data.rcmessage = ''; }
+    
+    try {
+        data.resptext = '';                        
+    }
+    catch(err) { data.resptext = ''; }
+    
+    try {
+        var ts = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss')
+        data.dt = ts;
+    }
+    catch(err) { 
+        logger.warn('Exception when getting timestamp data, using current timestamp', {err: err, result: result, task: task});
+        data.dt = strftime('%Y-%m-%d %H:%M:%S', new Date()); 
+    }
+    
+    try {
+        data.namapel = result.nama_pel[0].trim();
+    }
+    catch(err) { data.namapel = 'UNKNOWN'; }
+    
+    try {
+        data.msn = result.nsm[0].trim();
+    }
+    catch(err) { data.msn = 'UNKNOWN'; }
+    
+    try {
+        data.idpel = result.idpel[0].trim();
+    }
+    catch(err) { data.idpel = 'UNKNOWN'; }
+    
+    try {
+        data.tarifdaya = result.tarif[0].trim();
+    }
+    catch(err) { data.tarifdaya = 'UNKNOWN'; }
+    
+    try {
+        data.admin = parseInt(result.adminfee[0].trim());
+    }
+    catch(err) { data.admin = 0; }
+    
+    try {
+        data.adm = parseInt(result.adminfee[0].trim());
+    }
+    catch(err) { data.adm = 0; }
+    
+    try {
+        data.hargatotal = parseInt(result.amount_trx[0].trim());
+    }
+    catch(err) { data.hargatotal = 0; }
+    
+    try {
+        data.hargapelanggan = data.hargatotal - data.adm;
+    }
+    catch(err) { data.hargapelanggan = 0; }
+    
+    try {
+        data.jumlahkwh = result.jml_daya[0].trim();
+    }
+    catch(err) { data.jumlahkwh = 0; }
+    
+    try {
+        data.token = result.token[0].trim();
+    }
+    catch(err) { data.token = 0; }
+    
+    try {
+        data.ppn = result.ppn_fee[0].trim();
+    }
+    catch(err) { data.ppn_fee = 0; }
+    
+    try {
+        data.ppj = result.ppj_fee[0].trim();
+    }
+    catch(err) { data.ppj = 0; }
+    
+    try {
+        data.angsuran = result.angsuran_fee[0].trim();
+    }
+    catch(err) { data.angsuran = 0; }
+    
+    try {
+        data.meterai = result.materai_fee[0].trim();
+    }
+    catch(err) { data.materai_fee = 0; }
+    
+    return data;
+}
+
+function saveTokenToMongoDb(result) {
+    if (!mongodb) {
+        return;
+    }
+    
+    if (!config.mongodb) {
+        return;
+    }
+    
+    if (!config.mongodb.collection) {
+        return;
+    }
+    
+    data = prepareResultData(result);
+
+    try {
+        mongodb.collection(config.mongodb.collection).insertOne(data);
+    }
+    catch(err) {
+        logger.warn('Error when inserting data to mongodb', {err: err, data: data});
+    }
+}
+
+function putTaskToCache(task) {
+    var key = config.globals.gateway_name + '.rid:' + task.requestId;
+    
+    try {
+        tasks.set(key, task);
+    }
+    catch(err) {
+        logger.warn('Error writing to task to cache', {err: err, key: key, task: task});
+    }
+}
+
+function topupRequest(task) {
+    putTaskToCache(task);
+    
+    var ts = strftime('%Y%m%d%H%M%S', new Date());
+    
+    var data = 
+        config.h2h_out.userid 
+        + '|' + config.h2h_out.password 
+        + '|' + task['remoteProduct'] 
+        + '|' + task['destination'] + '|0';
+    
+    var options = {
+        url: config.h2h_out.partner,
+        qs: {
+            ts: ts,
+            data: data,
+            reffid: task['requestId']
+        }
+    };
+    logger.info('Creating http request', {options: options});
+
+    request(options, function (error, response, body) {
+        var responseCode = '40';
+        var responseMessage = 'Gateway Error';
+
+        if (error) {
+            
+            logger.warn('HTTP REQUEST ERROR', error);
+            callbackReport(task['requestId'], '89', 'HTTP REQUEST ERROR (' + error + ')');
+            
+        } else if (response.statusCode != 200) {
+            
+            var error_message = 'GATEWAY ERROR (HTTP RESPONSE CODE: ' + response.statusCode + ')';
+            logger.warn(error_message);
+            callbackReport(task['requestId'], '91', error_message);
+            
+        } else {
+
+            logger.info('DIRECT RESPONSE', {body: body});
+
+            xml2js(body, function (err, result) {
+                if (err) {
+                    callbackReport(task['requestId'], '40', body);
+                } else {
+                    var directResponse = result;
+                    logger.info(directResponse);
+                    
+                    saveTokenToMongoDb(directResponse.Result);
+                    
+                    try {
+                        var result_price;
+                        try {
+                            result_price = directResponse.Result.Price[0].trim();
+                        }
+                        catch(err) {
+                            result_price = 0;
+                        }
+                        
+                        var result_error_message;
+                        try {
+                            result_error_message = directResponse.Result.ErrorMsg[0].trim();
+                        }
+                        catch(err) {
+                            result_error_message = '';
+                        }
+                        
+                        var resultCode = directResponse.Result.ResultCode[0].trim();
+                        
+                        responseMessage = 
+                            'ResultCode: ' + resultCode
+                            + ' | ErrorMsg: ' + result_error_message
+                            + ' | DateTime: ' + directResponse.Result.DateTime[0].trim()
+                            + ' | nsm: ' + directResponse.Result.nsm[0].trim()
+                            + ' | idpel: ' + directResponse.Result.idpel[0].trim()
+                            + ' | reffid: ' + directResponse.Result.reffid[0].trim()
+                            + ' | TransID: ' + directResponse.Result.TransID[0].trim()
+                            + ' | reff_switching: ' + directResponse.Result.reff_switching[0].trim()
+                            + ' | amount_trx: ' + directResponse.Result.amount_trx[0].trim()
+                            + ' | token: ' + directResponse.Result.token[0].trim()
+                            + ' | PrevBalance: ' + directResponse.Result.PrevBalance[0].trim()
+                            + ' | Price: ' + result_price
+                            + ' | EndBalance: ' + directResponse.Result.EndBalance[0].trim()
+                            ;
+                            
+                        logger.info('Response message: ' + responseMessage);
+                        
+                        if (aaa) {
+                            // update balance
+                            aaa.updateBalance(directResponse.Result.EndBalance[0]);
+                        }
+                        
+                        if (resultCode == '0000') {
+                            var nama_pelanggan = directResponse.Result.nama_pel[0].trim();
+                            nama_pelanggan =  nama_pelanggan.replace(/-\/-/g, '-');
+                            var sn = directResponse.Result.token[0].trim() + '/' + nama_pelanggan + '/' + directResponse.Result.tarif[0].trim() +  'VA/' + directResponse.Result.jml_daya[0].trim();
+                            sn = sn.replace(/\s/g, '-');
+                            
+                            responseMessage = 'SN=' + sn + '; ' + responseMessage;
+                            logger.info('New response message: ' + responseMessage);
+                        }
+                        
+                        var pendingResultCode = ['0005', '0012', '0068', '0090', '0063', '0018', '0096'];
+                        if (pendingResultCode.indexOf(resultCode) != -1) {
+                            callbackReport(task['requestId'], '68', responseMessage);
+                            
+                            logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms');
+                            setTimeout(function () {
+                                cekstatus.advice({trxid: directResponse.Result.TransID[0].trim()}, callbackFromWebReport);
+                            }, sleep_before_retry);
+                            
+                            return;
+                        }
+                        
+                        responseCode = resultCode.replace(/^00/, "");
+                        
+                        if (result_error_message == 'Inq - APLICATION SERVER RESPONSE TIMEOUT') {
+                            responseCode = '91';
+                        }                        
+                        
+                    }
+                    catch(err) {
+                        responseCode = '40';
+                        responseMessage = 'Invalid response from gateway';
+                    }
+                }
+                
+                callbackReport(task['requestId'], responseCode, responseMessage);
+            });
+        }
+
+        //callbackReport(task['requestId'], responseCode, responseMessage);
+    });
+}
+
+function callbackFromWebReport(status) {
+    if (!status) {
+        logger.warn('Advice from webreport return empty status');
+        return;
+    }
+    
+    logger.info('Got advice result from webreport', {status: status});
+    
+    var responseCode = '68';
+    
+    var result_price = 0;
+    try {
+        result_price = directResponse.Result.Price[0].trim();
+    }
+    catch(err) {}
+    
+    var errorMsg = '';
+    try {
+        errorMsg = status.response.errormsg[0];
+    }
+    catch(err) {}
+    
+    var responseMessage = '';
+    try {
+        responseMessage = 
+            'Hasil advice dari webreport '
+            + 'ResultCode: ' + status.response.resultcode[0]
+    }
+    catch(err) {
+        logger.warn('Error parsing ResultCode from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | ErrorMsg: ' + errorMsg
+    }
+    catch(err) {
+        logger.warn('Error parsing ErrorMsg from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | TrxDate: ' + status.trxDate;
+    }
+    catch(err) {
+        logger.warn('Error parsing TrxDate from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | UpdateDate: ' + status.updateDate;
+    
+    }
+    catch(err) {
+        logger.warn('Error parsing UpdateDate from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | nsm: ' + status.response.nsm[0];
+    }
+    catch(err) {
+        logger.warn('Error parsing nsm from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | idpel: ' + status.response.idpel[0];
+    }
+    catch(err) {
+        logger.warn('Error parsing idpel from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | reffid: ' + status.response.reffid[0].trim();
+    }
+    catch(err) {
+        logger.warn('Error parsing reffid from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | TransID: ' + status.response.transid[0].trim();
+    }
+    catch(err) {
+        logger.warn('Error parsing TransID from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | reff_switching: ' + status.response.reff_switching[0];
+    }
+    catch(err) {
+        logger.warn('Error parsing reff_switching from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | amount_trx: ' + status.response.amount_trx[0];
+    }
+    catch(err) {
+        logger.warn('Error parsing amount_trx from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | token: ' + status.response.token[0];
+    }
+    catch(err) {
+        logger.warn('Error parsing token from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | PrevBalance: ' + status.response.prevbalance[0];
+    }
+    catch(err) {
+        logger.warn('Error parsing PrevBalance from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | Price: ' + status.amount;
+    }
+    catch(err) {
+        logger.warn('Error parsing Price from webreport advice.', {err: err});
+    }
+    
+    try {
+        responseMessage = 
+            responseMessage
+            + ' | EndBalance: ' + status.response.endbalance[0];
+    }
+    catch(err) {
+        logger.warn('Error parsing EndBalance from webreport advice.', {err: err});
+    }
+    
+    
+    if ((status.status == 'S') && (status.response.resultcode[0] == '0000')) {
+        responseCode = '00';
+        
+        var nama_pelanggan = status.response.nama_pel[0] ;
+        nama_pelanggan =  nama_pelanggan.replace(/-\/-/g, '-');
+        
+        var sn = status.response.token[0] + '/' + nama_pelanggan + '/' + status.response.tarif[0] + 'VA/' + status.response.jml_daya[0];
+        responseMessage = 'SN=' + sn + '; ' + responseMessage;
+    
+    } else if ((status.status == 'P') || (status.status == 'W')) {
+        
+        callbackReport(status.response.reffid[0].trim(), '68', responseMessage);
+        logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms');
+        
+        setTimeout(function () {
+            
+            cekstatus.advice({trxid: status.trxId,}, callbackFromWebReport);
+            
+        }, sleep_before_retry);
+        return;
+        
+    } else {
+        responseCode = status.response.resultcode[0].replace(/^00/, "");
+        if (['00', '05', '12', '68', '90', '63', '18', '96'].indexOf(responseCode) >= 0) {
+            responseCode = '40';
+        }
+    }
+    
+    
+    callbackReport(status.response.reffid[0].trim(), responseCode, responseMessage);
+}
+
+function createHttpReportServer() {
+    var httpServer = http.createServer(function(request, response) {
+        var qs = url.parse(request.url, true).query;
+        var path = url.parse(request.url).pathname;
+        
+        logger.info('Got reverse report from partner', {path: path, qs: qs});
+        response.end('OK');
+        
+        var  trxid;
+        try {
+            trxid = qs.transid;
+        }
+        catch(err) {
+        }
+        
+        if (trxid) {
+            logger.info('Requesting advice from webreport', {trxid: trxid})
+            cekstatus.advice({trxid: trxid}, callbackFromWebReport);
+        }
+        
+    });
+    
+    httpServer.listen(config.h2h_out.listen_port, function() {
+        logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port);
+    });
+}
+
+function start(_config, _callbackReport, options) {
+    config = _config;
+    callbackReport = _callbackReport;
+    
+    if (options && options.aaa) {
+            aaa = options.aaa;
+    }
+    
+    if (options && options.logger) {
+        logger = options.logger;
+    } else {
+        logger = new winston.Logger({
+            transports: [
+              new (winston.transports.Console)()
+            ]
+        });
+    }
+    
+    createHttpReportServer();
+    initMongoClient();
+}
+
+exports.start = start;
+exports.topupRequest = topupRequest;
-- 
1.9.0