Commit be81adcc21ea131b956c897a4be9faa4bc9aba1a

Authored by Adhidarma Hadiwinoto
1 parent 8e7aae966a
Exists in master

mocha test

Showing 3 changed files with 14 additions and 0 deletions Inline Diff

1 { 1 {
2 "name": "sate24-to-trustlink", 2 "name": "sate24-to-trustlink",
3 "version": "1.0.0", 3 "version": "1.0.0",
4 "description": "ST24 to TrustLink", 4 "description": "ST24 to TrustLink",
5 "main": "index.js", 5 "main": "index.js",
6 "scripts": { 6 "scripts": {
7 "test": "mocha" 7 "test": "mocha"
8 }, 8 },
9 "repository": { 9 "repository": {
10 "type": "git", 10 "type": "git",
11 "url": "git@gitlab.kodesumber.com:reload97/sate24-to-trustlink.git" 11 "url": "git@gitlab.kodesumber.com:reload97/sate24-to-trustlink.git"
12 }, 12 },
13 "keywords": [ 13 "keywords": [
14 "st24", 14 "st24",
15 "ppob", 15 "ppob",
16 "r97", 16 "r97",
17 "trust" 17 "trust"
18 ], 18 ],
19 "author": "Adhidarma Hadiwinoto <adhisimon@host2host.id>", 19 "author": "Adhidarma Hadiwinoto <adhisimon@host2host.id>",
20 "license": "ISC", 20 "license": "ISC",
21 "dependencies": { 21 "dependencies": {
22 "base64-xor": "^0.10.0", 22 "base64-xor": "^0.10.0",
23 "ini": "^1.3.4", 23 "ini": "^1.3.4",
24 "request": "^2.72.0", 24 "request": "^2.72.0",
25 "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git", 25 "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git",
26 "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git", 26 "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git",
27 "strftime": "^0.9.2", 27 "strftime": "^0.9.2",
28 "winston": "^2.2.0", 28 "winston": "^2.2.0",
29 "xml": "^1.0.1", 29 "xml": "^1.0.1",
30 "xml2js": "^0.4.16" 30 "xml2js": "^0.4.16"
31 },
32 "devDependencies": {
33 "should": "^8.3.1"
31 } 34 }
32 } 35 }
33 36
partner-trustlink.js
1 var winston = require('winston'); 1 var winston = require('winston');
2 var request = require('request'); 2 var request = require('request');
3 var strftime = require('strftime'); 3 var strftime = require('strftime');
4 var url = require('url'); 4 var url = require('url');
5 var xor = require('base64-xor'); 5 var xor = require('base64-xor');
6 var http = require('http'); 6 var http = require('http');
7 var xml = require('xml'); 7 var xml = require('xml');
8 var xml2js = require('xml2js').parseString; 8 var xml2js = require('xml2js').parseString;
9 9
10 var max_retry = 3; 10 var max_retry = 3;
11 var sleep_before_retry = 2000; 11 var sleep_before_retry = 2000;
12 12
13 var config; 13 var config;
14 var callbackReport; 14 var callbackReport;
15 var aaa; 15 var aaa;
16 var logger; 16 var logger;
17 var options; 17 var options;
18 18
19 function start(_config, _callbackReport, options) { 19 function start(_config, _callbackReport, options) {
20 config = _config; 20 config = _config;
21 callbackReport = _callbackReport 21 callbackReport = _callbackReport
22 22
23 if (options && options.aaa) { 23 if (options && options.aaa) {
24 aaa = options.aaa; 24 aaa = options.aaa;
25 } 25 }
26 26
27 if (options && options.logger) { 27 if (options && options.logger) {
28 logger = options.logger; 28 logger = options.logger;
29 } else { 29 } else {
30 logger = new winston.Logger({ 30 logger = new winston.Logger({
31 transports: [ 31 transports: [
32 new (winston.transports.Console)() 32 new (winston.transports.Console)()
33 ] 33 ]
34 }); 34 });
35 } 35 }
36 36
37 createReverseReportServer(); 37 createReverseReportServer();
38 } 38 }
39 39
40 function createReverseReportServer() { 40 function createReverseReportServer() {
41 var httpServer = http.createServer(onReverseReport).listen(config.h2h_out.listen_port, function() { 41 var httpServer = http.createServer(onReverseReport).listen(config.h2h_out.listen_port, function() {
42 logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port); 42 logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port);
43 }); 43 });
44 } 44 }
45 45
46 function onReverseReport(req, res) { 46 function onReverseReport(req, res) {
47 res.end('OK'); 47 res.end('OK');
48 48
49 var qs = url.parse(req.url, true).query; 49 var qs = url.parse(req.url, true).query;
50 logger.info('Reverse Report', {qs: qs}); 50 logger.info('Reverse Report', {qs: qs});
51 } 51 }
52 52
53 function calculateSignature(ts, destination, password) { 53 function calculateSignature(ts, destination, password) {
54 var a = ts + destination.substr(destination.length - 4); 54 var a = ts + destination.substr(destination.length - 4);
55 var b = destination.substr(destination.length - 4).split('').reverse().join('') + password; 55 var b = destination.substr(destination.length - 4).split('').reverse().join('') + password;
56 56
57 return xor.encode(a,b); 57 return xor.encode(a,b);
58 } 58 }
59 59
60 function createXmlPayload(task, userid, password) { 60 function createXmlPayload(task, userid, password) {
61 var ts = strftime('%H%M%S', new Date()); 61 var ts = strftime('%H%M%S', new Date());
62 62
63 var signature = calculateSignature(ts, task.destination, password); 63 var signature = calculateSignature(ts, task.destination, password);
64 64
65 var payload = { 65 var payload = {
66 evoucher: [ 66 evoucher: [
67 {command: 'TOPUP'}, 67 {command: 'TOPUP'},
68 {product: task.remoteProduct}, 68 {product: task.remoteProduct},
69 {userid: userid}, 69 {userid: userid},
70 {time: ts}, 70 {time: ts},
71 {msisdn: task.destination}, 71 {msisdn: task.destination},
72 {partner_trxid: task.requestId}, 72 {partner_trxid: task.requestId},
73 {signature: signature}, 73 {signature: signature},
74 {trxke: 1}, 74 {trxke: 1},
75 ] 75 ]
76 }; 76 };
77 77
78 if (logger) { 78 if (logger) {
79 logger.verbose('Generate xml payload', {payload: payload}); 79 logger.verbose('Generate xml payload', {payload: payload});
80 } 80 }
81 81
82 return "<?xml version=\"1.0\" ?>\n" + xml(payload); 82 return "<?xml version=\"1.0\" ?>\n" + xml(payload);
83 } 83 }
84 84
85 function topupRequest(task, retry) { 85 function topupRequest(task, retry) {
86 if (retry === undefined) { 86 if (retry === undefined) {
87 retry = max_retry; 87 retry = max_retry;
88 } 88 }
89 89
90 var payload = createXmlPayload(task, config.h2h_out.userid, config.h2h_out.password); 90 var payload = createXmlPayload(task, config.h2h_out.userid, config.h2h_out.password);
91 91
92 var partner = url.parse(config.h2h_out.partner); 92 var partner = url.parse(config.h2h_out.partner);
93 93
94 var request_options = { 94 var request_options = {
95 host: partner.hostname, 95 host: partner.hostname,
96 path: partner.path, 96 path: partner.path,
97 port: partner.port, 97 port: partner.port,
98 method: "POST", 98 method: "POST",
99 headers: { 99 headers: {
100 'Content-Type': 'text/xml', 100 'Content-Type': 'text/xml',
101 'Content-Length': Buffer.byteLength(payload) 101 'Content-Length': Buffer.byteLength(payload)
102 } 102 }
103 }; 103 };
104 104
105 var buffer = ""; 105 var buffer = "";
106 106
107 logger.info('Requesting to partner', {request_options: request_options}); 107 logger.info('Requesting to partner', {request_options: request_options});
108 108
109 var req = http.request(request_options, function( res ) { 109 var req = http.request(request_options, function( res ) {
110 110
111 logger.info('Status code: ' + res.statusCode ); 111 logger.info('Status code: ' + res.statusCode );
112 var buffer = ""; 112 var buffer = "";
113 res.on( "data", function( data ) { buffer = buffer + data; } ); 113 res.on( "data", function( data ) { buffer = buffer + data; } );
114 res.on( "end", function( data ) { 114 res.on( "end", function( data ) {
115 logger.verbose('Got direct response from partner', {resp: buffer}); 115 logger.verbose('Got direct response from partner', {resp: buffer});
116 //directResponseHandler(buffer, task); 116 //directResponseHandler(buffer, task);
117 }); 117 });
118 118
119 }); 119 });
120 120
121 req.on('error', function(e) { 121 req.on('error', function(e) {
122 logger.warn('problem with request: ' + e.message); 122 logger.warn('problem with request: ' + e.message);
123 callbackReport(task.requestId, '68', e.message); 123 callbackReport(task.requestId, '68', e.message);
124 return; 124 return;
125 }); 125 });
126 126
127 logger.verbose('Sending payload to partner', {payload: payload}); 127 logger.verbose('Sending payload to partner', {payload: payload});
128 req.write( payload ); 128 req.write( payload );
129 req.end(); 129 req.end();
130 } 130 }
131 131
132 function directResponseHandler(body, task) { 132 function directResponseHandler(body, task) {
133 133
134 logger.info('Got direct response'); 134 logger.info('Got direct response');
135 135
136 xml2js(body, function (err, result) { 136 xml2js(body, function (err, result) {
137 if (err) { 137 if (err) {
138 logger.warn('Error parsing xml', {body: body}); 138 logger.warn('Error parsing xml', {body: body});
139 callbackReport(request_id, '68', buffer); 139 callbackReport(request_id, '68', buffer);
140 return; 140 return;
141 } 141 }
142 142
143 logger.info('Direct response parsed', {result: result}); 143 logger.info('Direct response parsed', {result: result});
144 144
145 var response_code = '68'; 145 var response_code = '68';
146 146
147 var request_id = result.evoucher.partner_trxid[0].trim(); 147 var request_id = result.evoucher.partner_trxid[0].trim();
148 var message = result.evoucher.message[0].trim(); 148 var message = result.evoucher.message[0].trim();
149 var status = result.evoucher.result[0].trim(); 149 var status = result.evoucher.result[0].trim();
150 150
151 if (status === 'failed') { 151 if (status === 'failed') {
152 response_code = '40'; 152 response_code = '40';
153 153
154 var new_response_code = responseCodeFromMessage(message); 154 var new_response_code = responseCodeFromMessage(message);
155 if (new_response_code) { 155 if (new_response_code) {
156 response_code = new_response_code; 156 response_code = new_response_code;
157 } 157 }
158 158
159 } 159 }
160 160
161 callbackReport(request_id, response_code, message); 161 callbackReport(request_id, response_code, message);
162 }); 162 });
163 } 163 }
164 164
165 exports.start = start; 165 exports.start = start;
166 exports.topupRequest = topupRequest; 166 exports.topupRequest = topupRequest;
167 exports.calculateSignature = calculateSignature;
167 168
File was created 1 var should = require("should");
2 var partner = require("./partner-trustlink");
3
4 describe('#partner-trustlink', function() {
5 describe('#calculateSignature', function() {
6 it('should return correct signature', function() {
7 partner.calculateSignature('191001', '0812345678', 'abcdef').should.equal('CQ4HBVFTVlJSXg==');
8 });
9 });
10 });
11