Commit ba13f67f801c7e427eb7e42e2df5ab294c4ef703

Authored by Adhidarma Hadiwinoto
1 parent 55abf3ee55
Exists in master

reverse

Showing 1 changed file with 21 additions and 27 deletions Inline Diff

1 var http = require('http'); 1 var http = require('http');
2 var url = require('url'); 2 var url = require('url');
3 var math = require('mathjs'); 3 var math = require('mathjs');
4 var xml = require('xml'); 4 var xml = require('xml');
5 var xml2js = require('xml2js').parseString; 5 var xml2js = require('xml2js').parseString;
6 var strftime = require('strftime'); 6 var strftime = require('strftime');
7 var xor = require('base64-xor'); 7 var xor = require('base64-xor');
8 var request = require('request'); 8 var request = require('request');
9 9
10 var config; 10 var config;
11 var callbackReport; 11 var callbackReport;
12 12
13 var max_retry = 2; 13 var max_retry = 2;
14 var sleep_before_retry = 2000; 14 var sleep_before_retry = 2000;
15 15
16 var trx_balances = {}; 16 var trx_balances = {};
17 var trx_prices = {}; 17 var trx_prices = {};
18 18
19 function calculateSignature(password, msisdn, timestamp) { 19 function calculateSignature(password, msisdn, timestamp) {
20 var a = timestamp + msisdn.substr(msisdn.length - 4); 20 var a = timestamp + msisdn.substr(msisdn.length - 4);
21 var b = msisdn.substr(msisdn.length - 4).split('').reverse().join('') + password; 21 var b = msisdn.substr(msisdn.length - 4).split('').reverse().join('') + password;
22 22
23 return xor.encode(a,b); 23 return xor.encode(a,b);
24 } 24 }
25 25
26 /** 26 /**
27 * Kalkulasi signature untuk cek balance 27 * Kalkulasi signature untuk cek balance
28 * 28 *
29 * @deprecated 29 * @deprecated
30 */ 30 */
31 function calculateBalanceSignature(userid, password, timestamp) { 31 function calculateBalanceSignature(userid, password, timestamp) {
32 var a = '0000' + timestamp; 32 var a = '0000' + timestamp;
33 var b = userid.substr(0, 4) + password; 33 var b = userid.substr(0, 4) + password;
34 34
35 return xor.encode(a,b); 35 return xor.encode(a,b);
36 } 36 }
37 37
38 38
39 function createPayload(task) { 39 function createPayload(task) {
40 var timestamp = strftime('%H%M%S'); 40 var timestamp = strftime('%H%M%S');
41 41
42 var payload = { 42 var payload = {
43 pulsamatic: [ 43 pulsamatic: [
44 {command: 'TOPUP'}, 44 {command: 'TOPUP'},
45 {vtype: task['remoteProduct']}, 45 {vtype: task['remoteProduct']},
46 {userid: config.h2h_out.userid}, 46 {userid: config.h2h_out.userid},
47 {time: timestamp}, 47 {time: timestamp},
48 {msisdn: task['destination']}, 48 {msisdn: task['destination']},
49 {trxid: task['requestId']}, 49 {trxid: task['requestId']},
50 {sign: calculateSignature(config.h2h_out.password, task['destination'], timestamp)} 50 {sign: calculateSignature(config.h2h_out.password, task['destination'], timestamp)}
51 ] 51 ]
52 }; 52 };
53 53
54 console.log(payload); 54 console.log(payload);
55 return "<?xml version=\"1.0\" ?>\n" + xml(payload); 55 return "<?xml version=\"1.0\" ?>\n" + xml(payload);
56 } 56 }
57 57
58 function topupRequest(task, retry) { 58 function topupRequest(task, retry) {
59 //balanceCheck(); 59 //balanceCheck();
60 60
61 var payload_xml = createPayload(task); 61 var payload_xml = createPayload(task);
62 //console.log(payload_xml); 62 //console.log(payload_xml);
63 63
64 var partner = url.parse(config.h2h_out.partner); 64 var partner = url.parse(config.h2h_out.partner);
65 65
66 var request_options = { 66 var request_options = {
67 host: partner.hostname, 67 host: partner.hostname,
68 path: partner.path, 68 path: partner.path,
69 port: partner.port, 69 port: partner.port,
70 method: "POST", 70 method: "POST",
71 headers: { 71 headers: {
72 'Content-Type': 'text/xml', 72 'Content-Type': 'text/xml',
73 'Content-Length': Buffer.byteLength(payload_xml) 73 'Content-Length': Buffer.byteLength(payload_xml)
74 } 74 }
75 }; 75 };
76 76
77 var buffer = ""; 77 var buffer = "";
78 var req = http.request(request_options, function( res ) { 78 var req = http.request(request_options, function( res ) {
79 79
80 console.log('Status code: ' + res.statusCode ); 80 console.log('Status code: ' + res.statusCode );
81 var buffer = ""; 81 var buffer = "";
82 res.on( "data", function( data ) { buffer = buffer + data; } ); 82 res.on( "data", function( data ) { buffer = buffer + data; } );
83 res.on( "end", function( data ) { 83 res.on( "end", function( data ) {
84 directResponseHandler(buffer, task['requestId']); 84 directResponseHandler(buffer, task['requestId']);
85 }); 85 });
86 86
87 }); 87 });
88 88
89 req.on('error', function(e) { 89 req.on('error', function(e) {
90 console.log('problem with request: ' + e.message); 90 console.log('problem with request: ' + e.message);
91 callbackReport(task['requestId'], '40', e.message); 91 callbackReport(task['requestId'], '40', e.message);
92 }); 92 });
93 93
94 req.write( payload_xml ); 94 req.write( payload_xml );
95 req.end(); 95 req.end();
96 } 96 }
97 97
98 function directResponseHandler(body, request_id) { 98 function directResponseHandler(body, request_id) {
99 xml2js(body, function (err, result) { 99 xml2js(body, function (err, result) {
100 if (err) { 100 if (err) {
101 console.log(body); 101 console.log(body);
102 callbackReport(request_id, '40', buffer); 102 callbackReport(request_id, '40', buffer);
103 return; 103 return;
104 } 104 }
105 console.log(result); 105 console.log(result);
106 //request_id = result.pulsamatic.trxid; 106
107 var response_code = '68';
108
109 var request_id = result.pulsamatic.partner_trxid[0].trim();
110 var message = result.pulsamatic.message[0].trim();
111
112 callbackReport(request_id, response_code, message);
107 }); 113 });
108 114
109 } 115 }
110 116
111 function topupResponseHandler(body, request_id) { 117 function topupResponseHandler(body, request_id) {
112 console.log(body); 118 console.log(body);
113 return; 119 return;
114 xml2js(body, function (err, result) { 120 xml2js(body, function (err, result) {
115 if (err) { 121 if (err) {
116 console.log(body); 122 console.log(body);
117 callbackReport(request_id, '40', buffer); 123 callbackReport(request_id, '40', buffer);
118 return; 124 return;
119 } 125 }
120 126
121 console.log(result); 127 console.log(result);
122 128
123 request_id = result.datacell.ref_trxid[0].trim(); 129 request_id = result.datacell.ref_trxid[0].trim();
124 130
125 var response_code = '68'; 131 var response_code = '68';
126 132
127 var message = ''; 133 var message = '';
128 try { 134 try {
129 if (result.datacell.message && result.datacell.message.length > 0) { 135 if (result.datacell.message && result.datacell.message.length > 0) {
130 message = result.datacell.message[0].trim(); 136 message = result.datacell.message[0].trim();
131 } else if (result.datacell.msg && result.datacell.msg.length > 0) { 137 } else if (result.datacell.msg && result.datacell.msg.length > 0) {
132 message = result.datacell.msg[0].trim(); 138 message = result.datacell.msg[0].trim();
133 } 139 }
134 } 140 }
135 catch(err) { 141 catch(err) {
136 message = 'exception saat parsing message'; 142 message = 'exception saat parsing message';
137 } 143 }
138 144
139 if (result.datacell.resultcode && result.datacell.resultcode[0] == '999') { 145 if (result.datacell.resultcode && result.datacell.resultcode[0] == '999') {
140 response_code = '40'; 146 response_code = '40';
141 } 147 }
142 148
143 if (message.indexOf('Nomor tujuan salah') >= 0) { 149 if (message.indexOf('Nomor tujuan salah') >= 0) {
144 response_code = '14'; 150 response_code = '14';
145 } else if (message.indexOf('*GAGAL, transaksi yang sama sudah ada dalam 10 menit') >= 0) { 151 } else if (message.indexOf('*GAGAL, transaksi yang sama sudah ada dalam 10 menit') >= 0) {
146 response_code = '55'; 152 response_code = '55';
147 } else if (message.indexOf('saldo sdh dikembalikan') >= 0) { 153 } else if (message.indexOf('saldo sdh dikembalikan') >= 0) {
148 response_code = '40' 154 response_code = '40'
149 } else if (message.indexOf('Trx dpt diulang') >= 0) { 155 } else if (message.indexOf('Trx dpt diulang') >= 0) {
150 response_code = '40' 156 response_code = '40'
151 } else if (message.indexOf('SUKSES SN Operator:') >= 0) { 157 } else if (message.indexOf('SUKSES SN Operator:') >= 0) {
152 response_code = '00'; 158 response_code = '00';
153 159
154 var sn = parseSN(message); 160 var sn = parseSN(message);
155 console.log ('SN Operator: ' + sn); 161 console.log ('SN Operator: ' + sn);
156 162
157 if (sn) { 163 if (sn) {
158 message = 'SN=' + sn + '; ' + message; 164 message = 'SN=' + sn + '; ' + message;
159 } else { 165 } else {
160 message = 'SN belum didapat. ' + message; 166 message = 'SN belum didapat. ' + message;
161 response_code = '68'; 167 response_code = '68';
162 } 168 }
163 } 169 }
164 170
165 171
166 var price = priceFromMessage(message); 172 var price = priceFromMessage(message);
167 if (price != null) { 173 if (price != null) {
168 console.log('Harga: ' + price); 174 console.log('Harga: ' + price);
169 trx_prices[request_id] = price; 175 trx_prices[request_id] = price;
170 setTimeout(deleteTrxPrice, 3 * 24 * 3600 * 1000, request_id); 176 setTimeout(deleteTrxPrice, 3 * 24 * 3600 * 1000, request_id);
171 } else if (response_code == '00' && trx_prices[request_id] !== undefined) { 177 } else if (response_code == '00' && trx_prices[request_id] !== undefined) {
172 price = trx_prices[request_id]; 178 price = trx_prices[request_id];
173 console.log('Harga: ' + price); 179 console.log('Harga: ' + price);
174 message = message + ' -- Harga: ' + price; 180 message = message + ' -- Harga: ' + price;
175 } 181 }
176 182
177 var balance = balanceFromMessage(message); 183 var balance = balanceFromMessage(message);
178 if (balance != null) { 184 if (balance != null) {
179 console.log('Saldo: ' + balance); 185 console.log('Saldo: ' + balance);
180 trx_balances[request_id] = balance; 186 trx_balances[request_id] = balance;
181 setTimeout(deleteTrxBalance, 3 * 24 * 3600 * 1000, request_id); 187 setTimeout(deleteTrxBalance, 3 * 24 * 3600 * 1000, request_id);
182 } else if (response_code == '00' && trx_balances[request_id] !== undefined) { 188 } else if (response_code == '00' && trx_balances[request_id] !== undefined) {
183 balance = trx_balances[request_id]; 189 balance = trx_balances[request_id];
184 console.log('Saldo: ' + balance); 190 console.log('Saldo: ' + balance);
185 message = message + ' -- Saldo: ' + balance; 191 message = message + ' -- Saldo: ' + balance;
186 } 192 }
187 193
188 callbackReport(request_id, response_code, message); 194 callbackReport(request_id, response_code, message);
189 }); 195 });
190 } 196 }
191 197
192 function deleteTrxPrice(request_id) { 198 function deleteTrxPrice(request_id) {
193 delete trx_prices[request_id]; 199 delete trx_prices[request_id];
194 } 200 }
195 201
196 function deleteTrxBalance(request_id) { 202 function deleteTrxBalance(request_id) {
197 delete trx_balances[request_id]; 203 delete trx_balances[request_id];
198 } 204 }
199 205
200 function parseSN(message) { 206 function parseSN(message) {
201 var results = message.match(/SN Operator: .+ SN Kami/); 207 var results = message.match(/SN Operator: .+ SN Kami/);
202 if (!results || results.length <= 0) { 208 if (!results || results.length <= 0) {
203 return ''; 209 return '';
204 } 210 }
205 211
206 var result = results[0]; 212 var result = results[0];
207 result = result.replace('SN Operator:', ''); 213 result = result.replace('SN Operator:', '');
208 result = result.replace('SN Kami', ''); 214 result = result.replace('SN Kami', '');
209 result = result.trim(); 215 result = result.trim();
210 216
211 if (result == '00') { 217 if (result == '00') {
212 result = ''; 218 result = '';
213 } 219 }
214 220
215 return result; 221 return result;
216 } 222 }
217 223
218 function createServer() { 224 function createServer() {
219 225
220 var httpServer = http.createServer(function(req, res) { 226 var httpServer = http.createServer(function(req, res) {
221 var parsed_url = url.parse(req.url, true, true); 227 //console.log('Got request from partner ("' + req.url + '")');
222
223 console.log('Got request from partner ("' + req.url + '")');
224 228
225 var body = ""; 229 res.end('OK');
226 req.on('data', function (chunk) {
227 body += chunk;
228 });
229 230
230 req.on('end', function () { 231 var qs = url.parse(req.url, true).query;
231 res.writeHead(200); 232 console.log(qs);
232 res.end('OK'); 233
233 234 var response_code = '68';
234 //console.log(body); 235 var request_id = qs.pid;
235 236 var message = qs.msg;
236 if (parsed_url.pathname == '/sn') { 237
237 console.log('Reverse report -- SN'); 238 if (message.indexOf('REFUND') >= 0) {
238 topupResponseHandler(body); 239 response_code = '40';
239 240 }
240 } else if (parsed_url.pathname = '/refund') { 241
241 console.log('Reverse report -- REFUND'); 242 callbackReport(request_id, response_code, message);
242 callbackReport(parsed_url.query.ref_trxid, '40', parsed_url.query.message);
243
244 } else {
245 console.log('Reverse report -- UNKNOWN');
246 console.log('Ignore unknown request on reverse url');
247 }
248 });
249 }); 243 });
250 244
251 httpServer.listen(config.h2h_out.listen_port, function() { 245 httpServer.listen(config.h2h_out.listen_port, function() {
252 console.log('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port); 246 console.log('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port);
253 }); 247 });
254 } 248 }
255 249
256 function balanceCheck() { 250 function balanceCheck() {
257 var timestamp = strftime('%H%M%S'); 251 var timestamp = strftime('%H%M%S');
258 252
259 var payload = { 253 var payload = {
260 datacell: [ 254 datacell: [
261 {perintah: 'saldo'}, 255 {perintah: 'saldo'},
262 {userid: config.h2h_out.userid}, 256 {userid: config.h2h_out.userid},
263 {time: timestamp}, 257 {time: timestamp},
264 {sgn: calculateBalanceSignature(config.h2h_out.userid, config.h2h_out.password, timestamp)} 258 {sgn: calculateBalanceSignature(config.h2h_out.userid, config.h2h_out.password, timestamp)}
265 ] 259 ]
266 }; 260 };
267 261
268 var postRequest = { 262 var postRequest = {
269 host: "202.152.62.2", 263 host: "202.152.62.2",
270 path: "/RELOAD97.php", 264 path: "/RELOAD97.php",
271 port: 7713, 265 port: 7713,
272 method: "POST", 266 method: "POST",
273 headers: { 267 headers: {
274 'Content-Type': 'text/xml', 268 'Content-Type': 'text/xml',
275 'Content-Length': Buffer.byteLength(payload_xml) 269 'Content-Length': Buffer.byteLength(payload_xml)
276 } 270 }
277 }; 271 };
278 272
279 var buffer = ""; 273 var buffer = "";
280 var req = http.request( postRequest, function( res ) { 274 var req = http.request( postRequest, function( res ) {
281 275
282 console.log('Status code: ' + res.statusCode ); 276 console.log('Status code: ' + res.statusCode );
283 var buffer = ""; 277 var buffer = "";
284 res.on( "data", function( data ) { buffer = buffer + data; } ); 278 res.on( "data", function( data ) { buffer = buffer + data; } );
285 res.on( "end", function( data ) { 279 res.on( "end", function( data ) {
286 console.log('CHECK BALANCE RESULT:'); 280 console.log('CHECK BALANCE RESULT:');
287 console.log(buffer); 281 console.log(buffer);
288 }); 282 });
289 283
290 }); 284 });
291 285
292 req.on('error', function(e) { 286 req.on('error', function(e) {
293 console.log('problem with request: ' + e.message); 287 console.log('problem with request: ' + e.message);
294 }); 288 });
295 289
296 req.write( payload_xml ); 290 req.write( payload_xml );
297 req.end(); 291 req.end();
298 292
299 } 293 }
300 294
301 function balanceFromMessage(message) { 295 function balanceFromMessage(message) {
302 var matches = message.match(/Saldo: Rp (\d+)/); 296 var matches = message.match(/Saldo: Rp (\d+)/);
303 297
304 if (!matches) { 298 if (!matches) {
305 return null; 299 return null;
306 } 300 }
307 if (matches.length < 2) { 301 if (matches.length < 2) {
308 return null; 302 return null;
309 } 303 }
310 304
311 return matches[1]; 305 return matches[1];
312 } 306 }
313 307
314 function priceFromMessage(message) { 308 function priceFromMessage(message) {
315 var matches = message.match(/Harga: (\d+)/); 309 var matches = message.match(/Harga: (\d+)/);
316 310
317 if (!matches) { 311 if (!matches) {
318 return null; 312 return null;
319 } 313 }
320 if (matches.length < 2) { 314 if (matches.length < 2) {
321 return null; 315 return null;
322 } 316 }
323 317
324 return matches[1]; 318 return matches[1];
325 } 319 }
326 320
327 function start(_config, _callbackReport) { 321 function start(_config, _callbackReport) {
328 config = _config; 322 config = _config;
329 callbackReport = _callbackReport 323 callbackReport = _callbackReport
330 324
331 createServer(); 325 createServer();
332 } 326 }
333 327