Commit ed7b35458050219777d371b410afc2a07d17eeb2
1 parent
a097fbf1ce
Exists in
master
moment
Showing 1 changed file with 564 additions and 563 deletions Side-by-side Diff
partner-sc.js
Changes suppressed. Click to show
1 | -var fs = require('fs'); | |
2 | -var https = require('https'); | |
3 | -var http = require('http'); | |
4 | -var url = require('url'); | |
5 | -var request = require('request'); | |
6 | -var xml2js = require('xml2js').parseString; | |
7 | -var strftime = require('strftime'); | |
8 | -var math = require('mathjs'); | |
9 | -var winston = require('winston'); | |
10 | -var cekstatus = require('./cekstatus.js'); | |
11 | -var mongoClient = require('mongodb').MongoClient; | |
12 | -var LRU = require('lru-cache'); | |
13 | - | |
14 | -var config; | |
15 | -var httpServer; | |
16 | -var aaa; | |
17 | -var logger; | |
18 | -var callbackReport; | |
19 | -var mongodb; | |
20 | - | |
21 | -var tasks = LRU(10000); | |
22 | - | |
23 | -process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; | |
24 | - | |
25 | -var sleep_before_retry = 30000; | |
26 | - | |
27 | -var logTag = __filename.split('/').reverse()[0]; | |
28 | - | |
29 | -function initMongoClient() { | |
30 | - if (!config.mongodb || !config.mongodb.url) { | |
31 | - return; | |
32 | - } | |
33 | - | |
34 | - try { | |
35 | - var url = config.mongodb.url; | |
36 | - | |
37 | - mongoClient.connect(url, function(err, db) { | |
38 | - if (err) { | |
39 | - logger.warn('Failed to connect to mongodb', {err: err}); | |
40 | - return; | |
41 | - } | |
42 | - mongodb = db; | |
43 | - logger.info('MongoDB connected'); | |
44 | - }); | |
45 | - } | |
46 | - catch(err) { | |
47 | - logger.warn('Exception when connecting to mongodb', {err: err, url: url}); | |
48 | - } | |
49 | - | |
50 | -} | |
51 | - | |
52 | -function prepareResultData(result) { | |
53 | - var task; | |
54 | - | |
55 | - var data = {}; | |
56 | - data.gateway = config.globals.gateway_name; | |
57 | - | |
58 | - try { | |
59 | - data.requestId = result.reffid[0].trim(); | |
60 | - | |
61 | - var key = config.globals.gateway_name + '.rid:' + data.requestId; | |
62 | - task = tasks.get(key); | |
63 | - } | |
64 | - catch(err) { data.requestId = null; } | |
65 | - | |
66 | - try { | |
67 | - data.status = result.ResultCode[0].trim(); | |
68 | - } | |
69 | - catch(err) { data.status = '68' } | |
70 | - | |
71 | - try { | |
72 | - data.rcmessage = result.ErrorMsg[0].trim(); | |
73 | - } | |
74 | - catch(err) { data.rcmessage = ''; } | |
75 | - | |
76 | - try { | |
77 | - data.resptext = ''; | |
78 | - } | |
79 | - catch(err) { data.resptext = ''; } | |
80 | - | |
81 | - try { | |
82 | - data.dt = task.timestamp; | |
83 | - } | |
84 | - catch(err) { | |
85 | - logger.warn('Exception when getting timestamp data, using current timestamp', {err: err, result: result, task: task}); | |
86 | - data.dt = strftime('%Y-%m-%d %H:%M:%S', new Date()); | |
87 | - } | |
88 | - | |
89 | - try { | |
90 | - data.namapel = result.nama_pel[0].trim(); | |
91 | - } | |
92 | - catch(err) { data.namapel = 'UNKNOWN'; } | |
93 | - | |
94 | - try { | |
95 | - data.msn = result.nsm[0].trim(); | |
96 | - } | |
97 | - catch(err) { data.msn = 'UNKNOWN'; } | |
98 | - | |
99 | - try { | |
100 | - data.idpel = result.idpel[0].trim(); | |
101 | - } | |
102 | - catch(err) { data.idpel = 'UNKNOWN'; } | |
103 | - | |
104 | - try { | |
105 | - data.tarifdaya = result.tarif[0].trim(); | |
106 | - } | |
107 | - catch(err) { data.tarifdaya = 'UNKNOWN'; } | |
108 | - | |
109 | - try { | |
110 | - data.admin = parseInt(result.adminfee[0].trim()); | |
111 | - } | |
112 | - catch(err) { data.admin = 0; } | |
113 | - | |
114 | - try { | |
115 | - data.adm = parseInt(result.adminfee[0].trim()); | |
116 | - } | |
117 | - catch(err) { data.adm = 0; } | |
118 | - | |
119 | - try { | |
120 | - data.hargatotal = parseInt(result.amount_trx[0].trim()); | |
121 | - } | |
122 | - catch(err) { data.hargatotal = 0; } | |
123 | - | |
124 | - try { | |
125 | - data.hargapelanggan = data.hargatotal - data.adm; | |
126 | - } | |
127 | - catch(err) { data.hargapelanggan = 0; } | |
128 | - | |
129 | - try { | |
130 | - data.jumlahkwh = result.jml_daya[0].trim(); | |
131 | - } | |
132 | - catch(err) { data.jumlahkwh = 0; } | |
133 | - | |
134 | - try { | |
135 | - data.token = result.token[0].trim(); | |
136 | - } | |
137 | - catch(err) { data.token = 0; } | |
138 | - | |
139 | - try { | |
140 | - data.ppn = result.ppn_fee[0].trim(); | |
141 | - } | |
142 | - catch(err) { data.ppn_fee = 0; } | |
143 | - | |
144 | - try { | |
145 | - data.ppj = result.ppj_fee[0].trim(); | |
146 | - } | |
147 | - catch(err) { data.ppj = 0; } | |
148 | - | |
149 | - try { | |
150 | - data.angsuran = result.angsuran_fee[0].trim(); | |
151 | - } | |
152 | - catch(err) { data.angsuran = 0; } | |
153 | - | |
154 | - try { | |
155 | - data.meterai = result.materai_fee[0].trim(); | |
156 | - } | |
157 | - catch(err) { data.materai_fee = 0; } | |
158 | - | |
159 | - return data; | |
160 | -} | |
161 | - | |
162 | -function saveTokenToMongoDb(result) { | |
163 | - if (!mongodb) { | |
164 | - return; | |
165 | - } | |
166 | - | |
167 | - if (!config.mongodb) { | |
168 | - return; | |
169 | - } | |
170 | - | |
171 | - if (!config.mongodb.collection) { | |
172 | - return; | |
173 | - } | |
174 | - | |
175 | - data = prepareResultData(result); | |
176 | - | |
177 | - try { | |
178 | - mongodb.collection(config.mongodb.collection).insertOne(data); | |
179 | - } | |
180 | - catch(err) { | |
181 | - logger.warn('Error when inserting data to mongodb', {err: err, data: data}); | |
182 | - } | |
183 | -} | |
184 | - | |
185 | -function putTaskToCache(task) { | |
186 | - var key = config.globals.gateway_name + '.rid:' + task.requestId; | |
187 | - | |
188 | - try { | |
189 | - tasks.set(key, task); | |
190 | - } | |
191 | - catch(err) { | |
192 | - logger.warn('Error writing to task to cache', {err: err, key: key, task: task}); | |
193 | - } | |
194 | -} | |
195 | - | |
196 | -function topupRequest(task) { | |
197 | - putTaskToCache(task); | |
198 | - | |
199 | - var ts = strftime('%Y%m%d%H%M%S', new Date()); | |
200 | - | |
201 | - var data = | |
202 | - config.h2h_out.userid | |
203 | - + '|' + config.h2h_out.password | |
204 | - + '|' + task['remoteProduct'] | |
205 | - + '|' + task['destination'] + '|0'; | |
206 | - | |
207 | - var options = { | |
208 | - url: config.h2h_out.partner, | |
209 | - qs: { | |
210 | - ts: ts, | |
211 | - data: data, | |
212 | - reffid: task['requestId'] | |
213 | - } | |
214 | - }; | |
215 | - logger.info('Creating http request', {options: options}); | |
216 | - | |
217 | - request(options, function (error, response, body) { | |
218 | - var responseCode = '40'; | |
219 | - var responseMessage = 'Gateway Error'; | |
220 | - | |
221 | - if (error) { | |
222 | - | |
223 | - logger.warn('HTTP REQUEST ERROR', error); | |
224 | - callbackReport(task['requestId'], '89', 'HTTP REQUEST ERROR (' + error + ')'); | |
225 | - | |
226 | - } else if (response.statusCode != 200) { | |
227 | - | |
228 | - var error_message = 'GATEWAY ERROR (HTTP RESPONSE CODE: ' + response.statusCode + ')'; | |
229 | - logger.warn(error_message); | |
230 | - callbackReport(task['requestId'], '91', error_message); | |
231 | - | |
232 | - } else { | |
233 | - | |
234 | - logger.info('DIRECT RESPONSE', {body: body}); | |
235 | - | |
236 | - xml2js(body, function (err, result) { | |
237 | - if (err) { | |
238 | - callbackReport(task['requestId'], '40', body); | |
239 | - } else { | |
240 | - var directResponse = result; | |
241 | - logger.info(directResponse); | |
242 | - | |
243 | - saveTokenToMongoDb(directResponse.Result); | |
244 | - | |
245 | - try { | |
246 | - var result_price; | |
247 | - try { | |
248 | - result_price = directResponse.Result.Price[0].trim(); | |
249 | - } | |
250 | - catch(err) { | |
251 | - result_price = 0; | |
252 | - } | |
253 | - | |
254 | - var result_error_message; | |
255 | - try { | |
256 | - result_error_message = directResponse.Result.ErrorMsg[0].trim(); | |
257 | - } | |
258 | - catch(err) { | |
259 | - result_error_message = ''; | |
260 | - } | |
261 | - | |
262 | - var resultCode = directResponse.Result.ResultCode[0].trim(); | |
263 | - | |
264 | - responseMessage = | |
265 | - 'ResultCode: ' + resultCode | |
266 | - + ' | ErrorMsg: ' + result_error_message | |
267 | - + ' | DateTime: ' + directResponse.Result.DateTime[0].trim() | |
268 | - + ' | nsm: ' + directResponse.Result.nsm[0].trim() | |
269 | - + ' | idpel: ' + directResponse.Result.idpel[0].trim() | |
270 | - + ' | reffid: ' + directResponse.Result.reffid[0].trim() | |
271 | - + ' | TransID: ' + directResponse.Result.TransID[0].trim() | |
272 | - + ' | reff_switching: ' + directResponse.Result.reff_switching[0].trim() | |
273 | - + ' | amount_trx: ' + directResponse.Result.amount_trx[0].trim() | |
274 | - + ' | token: ' + directResponse.Result.token[0].trim() | |
275 | - + ' | PrevBalance: ' + directResponse.Result.PrevBalance[0].trim() | |
276 | - + ' | Price: ' + result_price | |
277 | - + ' | EndBalance: ' + directResponse.Result.EndBalance[0].trim() | |
278 | - ; | |
279 | - | |
280 | - logger.info('Response message: ' + responseMessage); | |
281 | - | |
282 | - if (aaa) { | |
283 | - // update balance | |
284 | - aaa.updateBalance(directResponse.Result.EndBalance[0]); | |
285 | - } | |
286 | - | |
287 | - if (resultCode == '0000') { | |
288 | - var nama_pelanggan = directResponse.Result.nama_pel[0].trim(); | |
289 | - nama_pelanggan = nama_pelanggan.replace(/-\/-/g, '-'); | |
290 | - var sn = directResponse.Result.token[0].trim() + '/' + nama_pelanggan + '/' + directResponse.Result.tarif[0].trim() + 'VA/' + directResponse.Result.jml_daya[0].trim(); | |
291 | - sn = sn.replace(/\s/g, '-'); | |
292 | - | |
293 | - responseMessage = 'SN=' + sn + '; ' + responseMessage; | |
294 | - logger.info('New response message: ' + responseMessage); | |
295 | - } | |
296 | - | |
297 | - var pendingResultCode = ['0005', '0012', '0068', '0090', '0063', '0018', '0096']; | |
298 | - if (pendingResultCode.indexOf(resultCode) != -1) { | |
299 | - callbackReport(task['requestId'], '68', responseMessage); | |
300 | - | |
301 | - logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms'); | |
302 | - setTimeout(function () { | |
303 | - cekstatus.advice({trxid: directResponse.Result.TransID[0].trim()}, callbackFromWebReport); | |
304 | - }, sleep_before_retry); | |
305 | - | |
306 | - return; | |
307 | - } | |
308 | - | |
309 | - responseCode = resultCode.replace(/^00/, ""); | |
310 | - | |
311 | - if (result_error_message == 'Inq - APLICATION SERVER RESPONSE TIMEOUT') { | |
312 | - responseCode = '91'; | |
313 | - } | |
314 | - | |
315 | - } | |
316 | - catch(err) { | |
317 | - responseCode = '40'; | |
318 | - responseMessage = 'Invalid response from gateway'; | |
319 | - } | |
320 | - } | |
321 | - | |
322 | - callbackReport(task['requestId'], responseCode, responseMessage); | |
323 | - }); | |
324 | - } | |
325 | - | |
326 | - //callbackReport(task['requestId'], responseCode, responseMessage); | |
327 | - }); | |
328 | -} | |
329 | - | |
330 | -function callbackFromWebReport(status) { | |
331 | - if (!status) { | |
332 | - logger.warn('Advice from webreport return empty status'); | |
333 | - return; | |
334 | - } | |
335 | - | |
336 | - logger.info('Got advice result from webreport', {status: status}); | |
337 | - | |
338 | - var responseCode = '68'; | |
339 | - | |
340 | - var result_price = 0; | |
341 | - try { | |
342 | - result_price = directResponse.Result.Price[0].trim(); | |
343 | - } | |
344 | - catch(err) {} | |
345 | - | |
346 | - var errorMsg = ''; | |
347 | - try { | |
348 | - errorMsg = status.response.errormsg[0]; | |
349 | - } | |
350 | - catch(err) {} | |
351 | - | |
352 | - var responseMessage = ''; | |
353 | - try { | |
354 | - responseMessage = | |
355 | - 'Hasil advice dari webreport ' | |
356 | - + 'ResultCode: ' + status.response.resultcode[0] | |
357 | - } | |
358 | - catch(err) { | |
359 | - logger.warn('Error parsing ResultCode from webreport advice.', {err: err}); | |
360 | - } | |
361 | - | |
362 | - try { | |
363 | - responseMessage = | |
364 | - responseMessage | |
365 | - + ' | ErrorMsg: ' + errorMsg | |
366 | - } | |
367 | - catch(err) { | |
368 | - logger.warn('Error parsing ErrorMsg from webreport advice.', {err: err}); | |
369 | - } | |
370 | - | |
371 | - try { | |
372 | - responseMessage = | |
373 | - responseMessage | |
374 | - + ' | TrxDate: ' + status.trxDate; | |
375 | - } | |
376 | - catch(err) { | |
377 | - logger.warn('Error parsing TrxDate from webreport advice.', {err: err}); | |
378 | - } | |
379 | - | |
380 | - try { | |
381 | - responseMessage = | |
382 | - responseMessage | |
383 | - + ' | UpdateDate: ' + status.updateDate; | |
384 | - | |
385 | - } | |
386 | - catch(err) { | |
387 | - logger.warn('Error parsing UpdateDate from webreport advice.', {err: err}); | |
388 | - } | |
389 | - | |
390 | - try { | |
391 | - responseMessage = | |
392 | - responseMessage | |
393 | - + ' | nsm: ' + status.response.nsm[0]; | |
394 | - } | |
395 | - catch(err) { | |
396 | - logger.warn('Error parsing nsm from webreport advice.', {err: err}); | |
397 | - } | |
398 | - | |
399 | - try { | |
400 | - responseMessage = | |
401 | - responseMessage | |
402 | - + ' | idpel: ' + status.response.idpel[0]; | |
403 | - } | |
404 | - catch(err) { | |
405 | - logger.warn('Error parsing idpel from webreport advice.', {err: err}); | |
406 | - } | |
407 | - | |
408 | - try { | |
409 | - responseMessage = | |
410 | - responseMessage | |
411 | - + ' | reffid: ' + status.response.reffid[0].trim(); | |
412 | - } | |
413 | - catch(err) { | |
414 | - logger.warn('Error parsing reffid from webreport advice.', {err: err}); | |
415 | - } | |
416 | - | |
417 | - try { | |
418 | - responseMessage = | |
419 | - responseMessage | |
420 | - + ' | TransID: ' + status.response.transid[0].trim(); | |
421 | - } | |
422 | - catch(err) { | |
423 | - logger.warn('Error parsing TransID from webreport advice.', {err: err}); | |
424 | - } | |
425 | - | |
426 | - try { | |
427 | - responseMessage = | |
428 | - responseMessage | |
429 | - + ' | reff_switching: ' + status.response.reff_switching[0]; | |
430 | - } | |
431 | - catch(err) { | |
432 | - logger.warn('Error parsing reff_switching from webreport advice.', {err: err}); | |
433 | - } | |
434 | - | |
435 | - try { | |
436 | - responseMessage = | |
437 | - responseMessage | |
438 | - + ' | amount_trx: ' + status.response.amount_trx[0]; | |
439 | - } | |
440 | - catch(err) { | |
441 | - logger.warn('Error parsing amount_trx from webreport advice.', {err: err}); | |
442 | - } | |
443 | - | |
444 | - try { | |
445 | - responseMessage = | |
446 | - responseMessage | |
447 | - + ' | token: ' + status.response.token[0]; | |
448 | - } | |
449 | - catch(err) { | |
450 | - logger.warn('Error parsing token from webreport advice.', {err: err}); | |
451 | - } | |
452 | - | |
453 | - try { | |
454 | - responseMessage = | |
455 | - responseMessage | |
456 | - + ' | PrevBalance: ' + status.response.prevbalance[0]; | |
457 | - } | |
458 | - catch(err) { | |
459 | - logger.warn('Error parsing PrevBalance from webreport advice.', {err: err}); | |
460 | - } | |
461 | - | |
462 | - try { | |
463 | - responseMessage = | |
464 | - responseMessage | |
465 | - + ' | Price: ' + status.amount; | |
466 | - } | |
467 | - catch(err) { | |
468 | - logger.warn('Error parsing Price from webreport advice.', {err: err}); | |
469 | - } | |
470 | - | |
471 | - try { | |
472 | - responseMessage = | |
473 | - responseMessage | |
474 | - + ' | EndBalance: ' + status.response.endbalance[0]; | |
475 | - } | |
476 | - catch(err) { | |
477 | - logger.warn('Error parsing EndBalance from webreport advice.', {err: err}); | |
478 | - } | |
479 | - | |
480 | - | |
481 | - if ((status.status == 'S') && (status.response.resultcode[0] == '0000')) { | |
482 | - responseCode = '00'; | |
483 | - | |
484 | - var nama_pelanggan = status.response.nama_pel[0] ; | |
485 | - nama_pelanggan = nama_pelanggan.replace(/-\/-/g, '-'); | |
486 | - | |
487 | - var sn = status.response.token[0] + '/' + nama_pelanggan + '/' + status.response.tarif[0] + 'VA/' + status.response.jml_daya[0]; | |
488 | - responseMessage = 'SN=' + sn + '; ' + responseMessage; | |
489 | - | |
490 | - } else if ((status.status == 'P') || (status.status == 'W')) { | |
491 | - | |
492 | - callbackReport(status.response.reffid[0].trim(), '68', responseMessage); | |
493 | - logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms'); | |
494 | - | |
495 | - setTimeout(function () { | |
496 | - | |
497 | - cekstatus.advice({trxid: status.trxId,}, callbackFromWebReport); | |
498 | - | |
499 | - }, sleep_before_retry); | |
500 | - return; | |
501 | - | |
502 | - } else { | |
503 | - responseCode = status.response.resultcode[0].replace(/^00/, ""); | |
504 | - if (['00', '05', '12', '68', '90', '63', '18', '96'].indexOf(responseCode) >= 0) { | |
505 | - responseCode = '40'; | |
506 | - } | |
507 | - } | |
508 | - | |
509 | - | |
510 | - callbackReport(status.response.reffid[0].trim(), responseCode, responseMessage); | |
511 | -} | |
512 | - | |
513 | -function createHttpReportServer() { | |
514 | - var httpServer = http.createServer(function(request, response) { | |
515 | - var qs = url.parse(request.url, true).query; | |
516 | - var path = url.parse(request.url).pathname; | |
517 | - | |
518 | - logger.info('Got reverse report from partner', {path: path, qs: qs}); | |
519 | - response.end('OK'); | |
520 | - | |
521 | - var trxid; | |
522 | - try { | |
523 | - trxid = qs.transid; | |
524 | - } | |
525 | - catch(err) { | |
526 | - } | |
527 | - | |
528 | - if (trxid) { | |
529 | - logger.info('Requesting advice from webreport', {trxid: trxid}) | |
530 | - cekstatus.advice({trxid: trxid}, callbackFromWebReport); | |
531 | - } | |
532 | - | |
533 | - }); | |
534 | - | |
535 | - httpServer.listen(config.h2h_out.listen_port, function() { | |
536 | - logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port); | |
537 | - }); | |
538 | -} | |
539 | - | |
540 | -function start(_config, _callbackReport, options) { | |
541 | - config = _config; | |
542 | - callbackReport = _callbackReport; | |
543 | - | |
544 | - if (options && options.aaa) { | |
545 | - aaa = options.aaa; | |
546 | - } | |
547 | - | |
548 | - if (options && options.logger) { | |
549 | - logger = options.logger; | |
550 | - } else { | |
551 | - logger = new winston.Logger({ | |
552 | - transports: [ | |
553 | - new (winston.transports.Console)() | |
554 | - ] | |
555 | - }); | |
556 | - } | |
557 | - | |
558 | - createHttpReportServer(); | |
559 | - initMongoClient(); | |
560 | -} | |
561 | - | |
562 | -exports.start = start; | |
563 | -exports.topupRequest = topupRequest; | |
1 | +var fs = require('fs'); | |
2 | +var https = require('https'); | |
3 | +var http = require('http'); | |
4 | +var url = require('url'); | |
5 | +var request = require('request'); | |
6 | +var xml2js = require('xml2js').parseString; | |
7 | +var strftime = require('strftime'); | |
8 | +var math = require('mathjs'); | |
9 | +var winston = require('winston'); | |
10 | +var cekstatus = require('./cekstatus.js'); | |
11 | +var mongoClient = require('mongodb').MongoClient; | |
12 | +var LRU = require('lru-cache'); | |
13 | + | |
14 | +var config; | |
15 | +var httpServer; | |
16 | +var aaa; | |
17 | +var logger; | |
18 | +var callbackReport; | |
19 | +var mongodb; | |
20 | + | |
21 | +var tasks = LRU(10000); | |
22 | + | |
23 | +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; | |
24 | + | |
25 | +var sleep_before_retry = 30000; | |
26 | + | |
27 | +var logTag = __filename.split('/').reverse()[0]; | |
28 | + | |
29 | +function initMongoClient() { | |
30 | + if (!config.mongodb || !config.mongodb.url) { | |
31 | + return; | |
32 | + } | |
33 | + | |
34 | + try { | |
35 | + var url = config.mongodb.url; | |
36 | + | |
37 | + mongoClient.connect(url, function(err, db) { | |
38 | + if (err) { | |
39 | + logger.warn('Failed to connect to mongodb', {err: err}); | |
40 | + return; | |
41 | + } | |
42 | + mongodb = db; | |
43 | + logger.info('MongoDB connected'); | |
44 | + }); | |
45 | + } | |
46 | + catch(err) { | |
47 | + logger.warn('Exception when connecting to mongodb', {err: err, url: url}); | |
48 | + } | |
49 | + | |
50 | +} | |
51 | + | |
52 | +function prepareResultData(result) { | |
53 | + var task; | |
54 | + | |
55 | + var data = {}; | |
56 | + data.gateway = config.globals.gateway_name; | |
57 | + | |
58 | + try { | |
59 | + data.requestId = result.reffid[0].trim(); | |
60 | + | |
61 | + var key = config.globals.gateway_name + '.rid:' + data.requestId; | |
62 | + task = tasks.get(key); | |
63 | + } | |
64 | + catch(err) { data.requestId = null; } | |
65 | + | |
66 | + try { | |
67 | + data.status = result.ResultCode[0].trim(); | |
68 | + } | |
69 | + catch(err) { data.status = '68' } | |
70 | + | |
71 | + try { | |
72 | + data.rcmessage = result.ErrorMsg[0].trim(); | |
73 | + } | |
74 | + catch(err) { data.rcmessage = ''; } | |
75 | + | |
76 | + try { | |
77 | + data.resptext = ''; | |
78 | + } | |
79 | + catch(err) { data.resptext = ''; } | |
80 | + | |
81 | + try { | |
82 | + var ts = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss') | |
83 | + data.dt = ts; | |
84 | + } | |
85 | + catch(err) { | |
86 | + logger.warn('Exception when getting timestamp data, using current timestamp', {err: err, result: result, task: task}); | |
87 | + data.dt = strftime('%Y-%m-%d %H:%M:%S', new Date()); | |
88 | + } | |
89 | + | |
90 | + try { | |
91 | + data.namapel = result.nama_pel[0].trim(); | |
92 | + } | |
93 | + catch(err) { data.namapel = 'UNKNOWN'; } | |
94 | + | |
95 | + try { | |
96 | + data.msn = result.nsm[0].trim(); | |
97 | + } | |
98 | + catch(err) { data.msn = 'UNKNOWN'; } | |
99 | + | |
100 | + try { | |
101 | + data.idpel = result.idpel[0].trim(); | |
102 | + } | |
103 | + catch(err) { data.idpel = 'UNKNOWN'; } | |
104 | + | |
105 | + try { | |
106 | + data.tarifdaya = result.tarif[0].trim(); | |
107 | + } | |
108 | + catch(err) { data.tarifdaya = 'UNKNOWN'; } | |
109 | + | |
110 | + try { | |
111 | + data.admin = parseInt(result.adminfee[0].trim()); | |
112 | + } | |
113 | + catch(err) { data.admin = 0; } | |
114 | + | |
115 | + try { | |
116 | + data.adm = parseInt(result.adminfee[0].trim()); | |
117 | + } | |
118 | + catch(err) { data.adm = 0; } | |
119 | + | |
120 | + try { | |
121 | + data.hargatotal = parseInt(result.amount_trx[0].trim()); | |
122 | + } | |
123 | + catch(err) { data.hargatotal = 0; } | |
124 | + | |
125 | + try { | |
126 | + data.hargapelanggan = data.hargatotal - data.adm; | |
127 | + } | |
128 | + catch(err) { data.hargapelanggan = 0; } | |
129 | + | |
130 | + try { | |
131 | + data.jumlahkwh = result.jml_daya[0].trim(); | |
132 | + } | |
133 | + catch(err) { data.jumlahkwh = 0; } | |
134 | + | |
135 | + try { | |
136 | + data.token = result.token[0].trim(); | |
137 | + } | |
138 | + catch(err) { data.token = 0; } | |
139 | + | |
140 | + try { | |
141 | + data.ppn = result.ppn_fee[0].trim(); | |
142 | + } | |
143 | + catch(err) { data.ppn_fee = 0; } | |
144 | + | |
145 | + try { | |
146 | + data.ppj = result.ppj_fee[0].trim(); | |
147 | + } | |
148 | + catch(err) { data.ppj = 0; } | |
149 | + | |
150 | + try { | |
151 | + data.angsuran = result.angsuran_fee[0].trim(); | |
152 | + } | |
153 | + catch(err) { data.angsuran = 0; } | |
154 | + | |
155 | + try { | |
156 | + data.meterai = result.materai_fee[0].trim(); | |
157 | + } | |
158 | + catch(err) { data.materai_fee = 0; } | |
159 | + | |
160 | + return data; | |
161 | +} | |
162 | + | |
163 | +function saveTokenToMongoDb(result) { | |
164 | + if (!mongodb) { | |
165 | + return; | |
166 | + } | |
167 | + | |
168 | + if (!config.mongodb) { | |
169 | + return; | |
170 | + } | |
171 | + | |
172 | + if (!config.mongodb.collection) { | |
173 | + return; | |
174 | + } | |
175 | + | |
176 | + data = prepareResultData(result); | |
177 | + | |
178 | + try { | |
179 | + mongodb.collection(config.mongodb.collection).insertOne(data); | |
180 | + } | |
181 | + catch(err) { | |
182 | + logger.warn('Error when inserting data to mongodb', {err: err, data: data}); | |
183 | + } | |
184 | +} | |
185 | + | |
186 | +function putTaskToCache(task) { | |
187 | + var key = config.globals.gateway_name + '.rid:' + task.requestId; | |
188 | + | |
189 | + try { | |
190 | + tasks.set(key, task); | |
191 | + } | |
192 | + catch(err) { | |
193 | + logger.warn('Error writing to task to cache', {err: err, key: key, task: task}); | |
194 | + } | |
195 | +} | |
196 | + | |
197 | +function topupRequest(task) { | |
198 | + putTaskToCache(task); | |
199 | + | |
200 | + var ts = strftime('%Y%m%d%H%M%S', new Date()); | |
201 | + | |
202 | + var data = | |
203 | + config.h2h_out.userid | |
204 | + + '|' + config.h2h_out.password | |
205 | + + '|' + task['remoteProduct'] | |
206 | + + '|' + task['destination'] + '|0'; | |
207 | + | |
208 | + var options = { | |
209 | + url: config.h2h_out.partner, | |
210 | + qs: { | |
211 | + ts: ts, | |
212 | + data: data, | |
213 | + reffid: task['requestId'] | |
214 | + } | |
215 | + }; | |
216 | + logger.info('Creating http request', {options: options}); | |
217 | + | |
218 | + request(options, function (error, response, body) { | |
219 | + var responseCode = '40'; | |
220 | + var responseMessage = 'Gateway Error'; | |
221 | + | |
222 | + if (error) { | |
223 | + | |
224 | + logger.warn('HTTP REQUEST ERROR', error); | |
225 | + callbackReport(task['requestId'], '89', 'HTTP REQUEST ERROR (' + error + ')'); | |
226 | + | |
227 | + } else if (response.statusCode != 200) { | |
228 | + | |
229 | + var error_message = 'GATEWAY ERROR (HTTP RESPONSE CODE: ' + response.statusCode + ')'; | |
230 | + logger.warn(error_message); | |
231 | + callbackReport(task['requestId'], '91', error_message); | |
232 | + | |
233 | + } else { | |
234 | + | |
235 | + logger.info('DIRECT RESPONSE', {body: body}); | |
236 | + | |
237 | + xml2js(body, function (err, result) { | |
238 | + if (err) { | |
239 | + callbackReport(task['requestId'], '40', body); | |
240 | + } else { | |
241 | + var directResponse = result; | |
242 | + logger.info(directResponse); | |
243 | + | |
244 | + saveTokenToMongoDb(directResponse.Result); | |
245 | + | |
246 | + try { | |
247 | + var result_price; | |
248 | + try { | |
249 | + result_price = directResponse.Result.Price[0].trim(); | |
250 | + } | |
251 | + catch(err) { | |
252 | + result_price = 0; | |
253 | + } | |
254 | + | |
255 | + var result_error_message; | |
256 | + try { | |
257 | + result_error_message = directResponse.Result.ErrorMsg[0].trim(); | |
258 | + } | |
259 | + catch(err) { | |
260 | + result_error_message = ''; | |
261 | + } | |
262 | + | |
263 | + var resultCode = directResponse.Result.ResultCode[0].trim(); | |
264 | + | |
265 | + responseMessage = | |
266 | + 'ResultCode: ' + resultCode | |
267 | + + ' | ErrorMsg: ' + result_error_message | |
268 | + + ' | DateTime: ' + directResponse.Result.DateTime[0].trim() | |
269 | + + ' | nsm: ' + directResponse.Result.nsm[0].trim() | |
270 | + + ' | idpel: ' + directResponse.Result.idpel[0].trim() | |
271 | + + ' | reffid: ' + directResponse.Result.reffid[0].trim() | |
272 | + + ' | TransID: ' + directResponse.Result.TransID[0].trim() | |
273 | + + ' | reff_switching: ' + directResponse.Result.reff_switching[0].trim() | |
274 | + + ' | amount_trx: ' + directResponse.Result.amount_trx[0].trim() | |
275 | + + ' | token: ' + directResponse.Result.token[0].trim() | |
276 | + + ' | PrevBalance: ' + directResponse.Result.PrevBalance[0].trim() | |
277 | + + ' | Price: ' + result_price | |
278 | + + ' | EndBalance: ' + directResponse.Result.EndBalance[0].trim() | |
279 | + ; | |
280 | + | |
281 | + logger.info('Response message: ' + responseMessage); | |
282 | + | |
283 | + if (aaa) { | |
284 | + // update balance | |
285 | + aaa.updateBalance(directResponse.Result.EndBalance[0]); | |
286 | + } | |
287 | + | |
288 | + if (resultCode == '0000') { | |
289 | + var nama_pelanggan = directResponse.Result.nama_pel[0].trim(); | |
290 | + nama_pelanggan = nama_pelanggan.replace(/-\/-/g, '-'); | |
291 | + var sn = directResponse.Result.token[0].trim() + '/' + nama_pelanggan + '/' + directResponse.Result.tarif[0].trim() + 'VA/' + directResponse.Result.jml_daya[0].trim(); | |
292 | + sn = sn.replace(/\s/g, '-'); | |
293 | + | |
294 | + responseMessage = 'SN=' + sn + '; ' + responseMessage; | |
295 | + logger.info('New response message: ' + responseMessage); | |
296 | + } | |
297 | + | |
298 | + var pendingResultCode = ['0005', '0012', '0068', '0090', '0063', '0018', '0096']; | |
299 | + if (pendingResultCode.indexOf(resultCode) != -1) { | |
300 | + callbackReport(task['requestId'], '68', responseMessage); | |
301 | + | |
302 | + logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms'); | |
303 | + setTimeout(function () { | |
304 | + cekstatus.advice({trxid: directResponse.Result.TransID[0].trim()}, callbackFromWebReport); | |
305 | + }, sleep_before_retry); | |
306 | + | |
307 | + return; | |
308 | + } | |
309 | + | |
310 | + responseCode = resultCode.replace(/^00/, ""); | |
311 | + | |
312 | + if (result_error_message == 'Inq - APLICATION SERVER RESPONSE TIMEOUT') { | |
313 | + responseCode = '91'; | |
314 | + } | |
315 | + | |
316 | + } | |
317 | + catch(err) { | |
318 | + responseCode = '40'; | |
319 | + responseMessage = 'Invalid response from gateway'; | |
320 | + } | |
321 | + } | |
322 | + | |
323 | + callbackReport(task['requestId'], responseCode, responseMessage); | |
324 | + }); | |
325 | + } | |
326 | + | |
327 | + //callbackReport(task['requestId'], responseCode, responseMessage); | |
328 | + }); | |
329 | +} | |
330 | + | |
331 | +function callbackFromWebReport(status) { | |
332 | + if (!status) { | |
333 | + logger.warn('Advice from webreport return empty status'); | |
334 | + return; | |
335 | + } | |
336 | + | |
337 | + logger.info('Got advice result from webreport', {status: status}); | |
338 | + | |
339 | + var responseCode = '68'; | |
340 | + | |
341 | + var result_price = 0; | |
342 | + try { | |
343 | + result_price = directResponse.Result.Price[0].trim(); | |
344 | + } | |
345 | + catch(err) {} | |
346 | + | |
347 | + var errorMsg = ''; | |
348 | + try { | |
349 | + errorMsg = status.response.errormsg[0]; | |
350 | + } | |
351 | + catch(err) {} | |
352 | + | |
353 | + var responseMessage = ''; | |
354 | + try { | |
355 | + responseMessage = | |
356 | + 'Hasil advice dari webreport ' | |
357 | + + 'ResultCode: ' + status.response.resultcode[0] | |
358 | + } | |
359 | + catch(err) { | |
360 | + logger.warn('Error parsing ResultCode from webreport advice.', {err: err}); | |
361 | + } | |
362 | + | |
363 | + try { | |
364 | + responseMessage = | |
365 | + responseMessage | |
366 | + + ' | ErrorMsg: ' + errorMsg | |
367 | + } | |
368 | + catch(err) { | |
369 | + logger.warn('Error parsing ErrorMsg from webreport advice.', {err: err}); | |
370 | + } | |
371 | + | |
372 | + try { | |
373 | + responseMessage = | |
374 | + responseMessage | |
375 | + + ' | TrxDate: ' + status.trxDate; | |
376 | + } | |
377 | + catch(err) { | |
378 | + logger.warn('Error parsing TrxDate from webreport advice.', {err: err}); | |
379 | + } | |
380 | + | |
381 | + try { | |
382 | + responseMessage = | |
383 | + responseMessage | |
384 | + + ' | UpdateDate: ' + status.updateDate; | |
385 | + | |
386 | + } | |
387 | + catch(err) { | |
388 | + logger.warn('Error parsing UpdateDate from webreport advice.', {err: err}); | |
389 | + } | |
390 | + | |
391 | + try { | |
392 | + responseMessage = | |
393 | + responseMessage | |
394 | + + ' | nsm: ' + status.response.nsm[0]; | |
395 | + } | |
396 | + catch(err) { | |
397 | + logger.warn('Error parsing nsm from webreport advice.', {err: err}); | |
398 | + } | |
399 | + | |
400 | + try { | |
401 | + responseMessage = | |
402 | + responseMessage | |
403 | + + ' | idpel: ' + status.response.idpel[0]; | |
404 | + } | |
405 | + catch(err) { | |
406 | + logger.warn('Error parsing idpel from webreport advice.', {err: err}); | |
407 | + } | |
408 | + | |
409 | + try { | |
410 | + responseMessage = | |
411 | + responseMessage | |
412 | + + ' | reffid: ' + status.response.reffid[0].trim(); | |
413 | + } | |
414 | + catch(err) { | |
415 | + logger.warn('Error parsing reffid from webreport advice.', {err: err}); | |
416 | + } | |
417 | + | |
418 | + try { | |
419 | + responseMessage = | |
420 | + responseMessage | |
421 | + + ' | TransID: ' + status.response.transid[0].trim(); | |
422 | + } | |
423 | + catch(err) { | |
424 | + logger.warn('Error parsing TransID from webreport advice.', {err: err}); | |
425 | + } | |
426 | + | |
427 | + try { | |
428 | + responseMessage = | |
429 | + responseMessage | |
430 | + + ' | reff_switching: ' + status.response.reff_switching[0]; | |
431 | + } | |
432 | + catch(err) { | |
433 | + logger.warn('Error parsing reff_switching from webreport advice.', {err: err}); | |
434 | + } | |
435 | + | |
436 | + try { | |
437 | + responseMessage = | |
438 | + responseMessage | |
439 | + + ' | amount_trx: ' + status.response.amount_trx[0]; | |
440 | + } | |
441 | + catch(err) { | |
442 | + logger.warn('Error parsing amount_trx from webreport advice.', {err: err}); | |
443 | + } | |
444 | + | |
445 | + try { | |
446 | + responseMessage = | |
447 | + responseMessage | |
448 | + + ' | token: ' + status.response.token[0]; | |
449 | + } | |
450 | + catch(err) { | |
451 | + logger.warn('Error parsing token from webreport advice.', {err: err}); | |
452 | + } | |
453 | + | |
454 | + try { | |
455 | + responseMessage = | |
456 | + responseMessage | |
457 | + + ' | PrevBalance: ' + status.response.prevbalance[0]; | |
458 | + } | |
459 | + catch(err) { | |
460 | + logger.warn('Error parsing PrevBalance from webreport advice.', {err: err}); | |
461 | + } | |
462 | + | |
463 | + try { | |
464 | + responseMessage = | |
465 | + responseMessage | |
466 | + + ' | Price: ' + status.amount; | |
467 | + } | |
468 | + catch(err) { | |
469 | + logger.warn('Error parsing Price from webreport advice.', {err: err}); | |
470 | + } | |
471 | + | |
472 | + try { | |
473 | + responseMessage = | |
474 | + responseMessage | |
475 | + + ' | EndBalance: ' + status.response.endbalance[0]; | |
476 | + } | |
477 | + catch(err) { | |
478 | + logger.warn('Error parsing EndBalance from webreport advice.', {err: err}); | |
479 | + } | |
480 | + | |
481 | + | |
482 | + if ((status.status == 'S') && (status.response.resultcode[0] == '0000')) { | |
483 | + responseCode = '00'; | |
484 | + | |
485 | + var nama_pelanggan = status.response.nama_pel[0] ; | |
486 | + nama_pelanggan = nama_pelanggan.replace(/-\/-/g, '-'); | |
487 | + | |
488 | + var sn = status.response.token[0] + '/' + nama_pelanggan + '/' + status.response.tarif[0] + 'VA/' + status.response.jml_daya[0]; | |
489 | + responseMessage = 'SN=' + sn + '; ' + responseMessage; | |
490 | + | |
491 | + } else if ((status.status == 'P') || (status.status == 'W')) { | |
492 | + | |
493 | + callbackReport(status.response.reffid[0].trim(), '68', responseMessage); | |
494 | + logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms'); | |
495 | + | |
496 | + setTimeout(function () { | |
497 | + | |
498 | + cekstatus.advice({trxid: status.trxId,}, callbackFromWebReport); | |
499 | + | |
500 | + }, sleep_before_retry); | |
501 | + return; | |
502 | + | |
503 | + } else { | |
504 | + responseCode = status.response.resultcode[0].replace(/^00/, ""); | |
505 | + if (['00', '05', '12', '68', '90', '63', '18', '96'].indexOf(responseCode) >= 0) { | |
506 | + responseCode = '40'; | |
507 | + } | |
508 | + } | |
509 | + | |
510 | + | |
511 | + callbackReport(status.response.reffid[0].trim(), responseCode, responseMessage); | |
512 | +} | |
513 | + | |
514 | +function createHttpReportServer() { | |
515 | + var httpServer = http.createServer(function(request, response) { | |
516 | + var qs = url.parse(request.url, true).query; | |
517 | + var path = url.parse(request.url).pathname; | |
518 | + | |
519 | + logger.info('Got reverse report from partner', {path: path, qs: qs}); | |
520 | + response.end('OK'); | |
521 | + | |
522 | + var trxid; | |
523 | + try { | |
524 | + trxid = qs.transid; | |
525 | + } | |
526 | + catch(err) { | |
527 | + } | |
528 | + | |
529 | + if (trxid) { | |
530 | + logger.info('Requesting advice from webreport', {trxid: trxid}) | |
531 | + cekstatus.advice({trxid: trxid}, callbackFromWebReport); | |
532 | + } | |
533 | + | |
534 | + }); | |
535 | + | |
536 | + httpServer.listen(config.h2h_out.listen_port, function() { | |
537 | + logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port); | |
538 | + }); | |
539 | +} | |
540 | + | |
541 | +function start(_config, _callbackReport, options) { | |
542 | + config = _config; | |
543 | + callbackReport = _callbackReport; | |
544 | + | |
545 | + if (options && options.aaa) { | |
546 | + aaa = options.aaa; | |
547 | + } | |
548 | + | |
549 | + if (options && options.logger) { | |
550 | + logger = options.logger; | |
551 | + } else { | |
552 | + logger = new winston.Logger({ | |
553 | + transports: [ | |
554 | + new (winston.transports.Console)() | |
555 | + ] | |
556 | + }); | |
557 | + } | |
558 | + | |
559 | + createHttpReportServer(); | |
560 | + initMongoClient(); | |
561 | +} | |
562 | + | |
563 | +exports.start = start; | |
564 | +exports.topupRequest = topupRequest; |