From 3f8e65bfd8b88d9484bc741a721f78e7612ef82d Mon Sep 17 00:00:00 2001
From: Adhidarma Hadiwinoto <gua@adhisimon.org>
Date: Tue, 18 Aug 2015 14:19:12 +0700
Subject: [PATCH] payload trugee

---
 partner-trugee.js | 334 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 334 insertions(+)
 create mode 100644 partner-trugee.js

diff --git a/partner-trugee.js b/partner-trugee.js
new file mode 100644
index 0000000..6f49908
--- /dev/null
+++ b/partner-trugee.js
@@ -0,0 +1,334 @@
+var http = require('http');
+var url = require('url');
+var math = require('mathjs');
+var xml = require('xml');
+var xml2js = require('xml2js').parseString;
+var strftime = require('strftime');
+var xor = require('base64-xor');
+var request = require('request');
+
+var config;
+var callbackReport;
+
+var max_retry = 2;
+var sleep_before_retry = 2000;
+
+var trx_balances = {};
+var trx_prices = {};
+
+function calculateSignature(password, msisdn, timestamp) {
+    var a = timestamp + msisdn.substr(msisdn.length - 4);
+    var b = msisdn.substr(msisdn.length - 4).split('').reverse().join('') + password;
+    
+    return xor.encode(a,b);
+}
+
+/**
+ * Kalkulasi signature untuk cek balance
+ * 
+ * @deprecated
+ */
+function calculateBalanceSignature(userid, password, timestamp) {
+    var a = '0000' + timestamp;
+    var b = userid.substr(0, 4) + password;
+    
+    return xor.encode(a,b);
+}
+
+
+function createPayload(task) {
+    var timestamp = strftime('%H%M%S');
+    
+    var payload = {
+        datacell: [
+            {command: 'TOPUP'},
+            {vtype: task['remoteProduct']},
+            {userid: config.h2h_out.userid},
+            {time: timestamp},
+            {msisdn: task['destination']},
+            {trxid: task['requestId']},
+            {sign: calculateSignature(config.h2h_out.password, task['destination'], timestamp)}
+        ]
+    };
+    
+    console.log(payload);
+    return "<?xml version=\"1.0\" ?>\n" + xml(payload);
+}
+
+function topupRequest(task, retry) {
+    //balanceCheck();
+    
+    var payload_xml = createPayload(task);
+    //console.log(payload_xml);
+    
+    var postRequest = {
+        host: "202.152.62.2",
+        path: "/RELOAD97.php",
+        port: 7713,
+        method: "POST",
+        headers: {
+            'Content-Type': 'text/xml',
+            'Content-Length': Buffer.byteLength(payload_xml)
+        }
+    };
+    
+    var buffer = "";
+    var req = http.request( postRequest, function( res )    {
+
+        console.log('Status code: ' + res.statusCode );
+        var buffer = "";
+        res.on( "data", function( data ) { buffer = buffer + data; } );
+        res.on( "end", function( data ) {             
+                topupResponseHandler(buffer);
+        });
+
+    });
+
+    req.on('error', function(e) {
+        console.log('problem with request: ' + e.message);
+        callbackReport(task['requestId'], '40', e.message);
+    });
+
+    req.write( payload_xml );
+    req.end();
+}
+
+function topupResponseHandler(body, request_id) {
+    xml2js(body, function (err, result) {
+        if (err) {
+            console.log(body);
+            callbackReport(request_id, '40', buffer);
+            return;
+        }
+        
+        console.log(result);
+        
+        request_id = result.datacell.ref_trxid[0].trim();
+        
+        var response_code = '68';
+        
+        var message = '';
+        try {
+            if (result.datacell.message && result.datacell.message.length > 0) {
+                message = result.datacell.message[0].trim();
+            } else if (result.datacell.msg && result.datacell.msg.length > 0) {
+                message = result.datacell.msg[0].trim();
+            } 
+        }
+        catch(err) {
+            message = 'exception saat parsing message';
+        }
+        
+        if (result.datacell.resultcode && result.datacell.resultcode[0] == '999') {
+            response_code = '40';
+        }
+        
+        if (message.indexOf('Nomor tujuan salah') >= 0) {
+            response_code = '14';
+        } else if (message.indexOf('*GAGAL, transaksi yang sama sudah ada dalam 10 menit') >= 0) {
+            response_code = '55';
+        } else if (message.indexOf('saldo sdh dikembalikan') >= 0) {
+            response_code = '40'
+        } else if (message.indexOf('Trx dpt diulang') >= 0) {
+            response_code = '40'
+        } else if (message.indexOf('SUKSES SN Operator:') >= 0) {
+            response_code = '00';
+            
+            var sn = parseSN(message);
+            console.log ('SN Operator: ' + sn);
+            
+            /*
+            if (!sn) {
+                
+                console.log('Missing real operator SN, using SN from suplier');
+                try {
+                    sn = result.datacell.trxid[0].trim();
+                }
+                catch(err) {
+                    sn = '';
+                }
+            }
+            */
+            
+            if (sn) {
+                message = 'SN=' + sn + '; ' + message;
+            } else {
+                message = 'SN belum didapat. ' + message;
+                response_code = '68';
+            }
+        }
+
+        
+        var price = priceFromMessage(message);
+        if (price != null) {
+            console.log('Harga: ' + price);
+            trx_prices[request_id] = price;
+            setTimeout(deleteTrxPrice, 3 * 24 * 3600 * 1000, request_id);
+        } else if (response_code == '00' && trx_prices[request_id] !==  undefined) {
+            price = trx_prices[request_id];
+            console.log('Harga: ' + price);
+            message = message + ' -- Harga: ' + price;
+        }
+        
+        var balance = balanceFromMessage(message);
+        if (balance != null) {
+            console.log('Saldo: ' + balance);
+            trx_balances[request_id] = balance;
+            setTimeout(deleteTrxBalance, 3 * 24 * 3600 * 1000, request_id);
+        } else if (response_code == '00' && trx_balances[request_id] !==  undefined) {
+            balance = trx_balances[request_id];
+            console.log('Saldo: ' + balance);
+            message = message + ' -- Saldo: ' + balance;
+        }
+    
+        callbackReport(request_id, response_code, message);
+    });
+}
+
+function deleteTrxPrice(request_id) {
+    delete trx_prices[request_id];
+}
+
+function deleteTrxBalance(request_id) {
+    delete trx_balances[request_id];
+}
+
+function parseSN(message) {
+    var results = message.match(/SN Operator: .+ SN Kami/);
+    if (!results || results.length <= 0) {
+        return '';
+    }
+    
+    var result = results[0];
+    result = result.replace('SN Operator:', '');
+    result = result.replace('SN Kami', '');
+    result = result.trim();
+    
+    if (result == '00') {
+        result = '';
+    }
+    
+    return result;
+}
+
+function createServer() {
+
+    var httpServer = http.createServer(function(req, res) {
+        var parsed_url = url.parse(req.url, true, true);
+
+        console.log('Got request from partner ("' + req.url + '")');
+        
+        var body = "";
+        req.on('data', function (chunk) {
+            body += chunk;
+        });
+        
+        req.on('end', function () {
+            res.writeHead(200);
+            res.end('OK');
+            
+            //console.log(body);
+            
+            if (parsed_url.pathname == '/sn') {
+                console.log('Reverse report -- SN');
+                topupResponseHandler(body);
+                
+            } else if (parsed_url.pathname = '/refund') {
+                console.log('Reverse report -- REFUND');
+                callbackReport(parsed_url.query.ref_trxid, '40', parsed_url.query.message);
+                
+            } else {
+                console.log('Reverse report -- UNKNOWN');
+                console.log('Ignore unknown request on reverse url');
+            }
+        });
+    });
+    
+    httpServer.listen(config.h2h_out.listen_port, function() {
+        console.log('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port);
+    });
+}
+
+function balanceCheck() {
+    var timestamp = strftime('%H%M%S');
+    
+    var payload = {
+        datacell: [
+            {perintah: 'saldo'},
+            {userid: config.h2h_out.userid},
+            {time: timestamp},
+            {sgn: calculateBalanceSignature(config.h2h_out.userid, config.h2h_out.password, timestamp)}
+        ]
+    };
+    
+    var postRequest = {
+        host: "202.152.62.2",
+        path: "/RELOAD97.php",
+        port: 7713,
+        method: "POST",
+        headers: {
+            'Content-Type': 'text/xml',
+            'Content-Length': Buffer.byteLength(payload_xml)
+        }
+    };
+    
+    var buffer = "";
+    var req = http.request( postRequest, function( res )    {
+
+        console.log('Status code: ' + res.statusCode );
+        var buffer = "";
+        res.on( "data", function( data ) { buffer = buffer + data; } );
+        res.on( "end", function( data ) {             
+            console.log('CHECK BALANCE RESULT:');
+            console.log(buffer);
+        });
+
+    });
+
+    req.on('error', function(e) {
+        console.log('problem with request: ' + e.message);
+    });
+
+    req.write( payload_xml );
+    req.end();
+    
+}
+
+function balanceFromMessage(message) {
+    var matches = message.match(/Saldo: Rp (\d+)/);
+    
+    if (!matches) {
+        return null;
+    }
+    if (matches.length < 2) {
+        return null;
+    }
+    
+    return matches[1];
+}
+
+function priceFromMessage(message) {
+    var matches = message.match(/Harga: (\d+)/);
+    
+    if (!matches) {
+        return null;
+    }
+    if (matches.length < 2) {
+        return null;
+    }
+    
+    return matches[1];
+}
+
+function start(_config, _callbackReport) {
+    config = _config;
+    callbackReport = _callbackReport
+
+    createServer();
+}
+
+exports.start = start;
+exports.topupRequest = topupRequest;
+exports.balanceFromMessage = balanceFromMessage;
+exports.priceFromMessage = priceFromMessage;
+exports.calculateSignature = calculateSignature;
-- 
1.9.0