Commit 8b0822182ada0b004da504c223171d02c63aacff

Authored by Adhidarma Hadiwinoto
1 parent 78c4805ea9
Exists in master

DEBUG diag

Showing 1 changed file with 8 additions and 0 deletions Inline Diff

partner-simplepay.js
1 "use strict"; 1 "use strict";
2 2
3 process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; 3 process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0";
4 4
5 const request = require('request'); 5 const request = require('request');
6 const crypto = require('crypto'); 6 const crypto = require('crypto');
7 const moment = require('moment'); 7 const moment = require('moment');
8 const URL = require('url'); 8 const URL = require('url');
9 9
10 10
11 const http = require('http'); 11 const http = require('http');
12 http.globalAgent.maxSockets = Infinity; 12 http.globalAgent.maxSockets = Infinity;
13 13
14 const seconds_to_wait_before_resend_on_pending = 4; 14 const seconds_to_wait_before_resend_on_pending = 4;
15 15
16 var config; 16 var config;
17 var aaa; 17 var aaa;
18 var logger; 18 var logger;
19 19
20 function start(options) { 20 function start(options) {
21 if (!options) { 21 if (!options) {
22 console.log('Undefined options, terminating....'); 22 console.log('Undefined options, terminating....');
23 process.exit(1); 23 process.exit(1);
24 } 24 }
25 25
26 if (options.config) { 26 if (options.config) {
27 config = options.config; 27 config = options.config;
28 } else { 28 } else {
29 console.log('Undefined options.config, terminating....') 29 console.log('Undefined options.config, terminating....')
30 process.exit(1); 30 process.exit(1);
31 } 31 }
32 32
33 if (options.aaa) { 33 if (options.aaa) {
34 aaa = options.aaa; 34 aaa = options.aaa;
35 } else { 35 } else {
36 console.log('Undefined options.aaa, terminating....') 36 console.log('Undefined options.aaa, terminating....')
37 process.exit(1); 37 process.exit(1);
38 } 38 }
39 39
40 if (options && options.logger) { 40 if (options && options.logger) {
41 logger = options.logger; 41 logger = options.logger;
42 } else { 42 } else {
43 console.log('Undefined options.logger, terminating....') 43 console.log('Undefined options.logger, terminating....')
44 process.exit(1); 44 process.exit(1);
45 } 45 }
46 46
47 createReverseHttpServer(); 47 createReverseHttpServer();
48 } 48 }
49 49
50 function callbackReport(requestId, rc, message, options) { 50 function callbackReport(requestId, rc, message, options) {
51 aaa.callbackReportWithPushToMongoDb(requestId, rc, message); 51 aaa.callbackReportWithPushToMongoDb(requestId, rc, message);
52 52
53 //return; 53 //return;
54 // resend trx as status check if rc 68 and task is defined 54 // resend trx as status check if rc 68 and task is defined
55 if (config && config.h2h_out.auto_resend && Number(config.h2h_out.auto_resend) && options && options.task && (rc == '68')) { 55 if (config && config.h2h_out.auto_resend && Number(config.h2h_out.auto_resend) && options && options.task && (rc == '68')) {
56 logger.verbose('Got pending trx, requesting in ' + seconds_to_wait_before_resend_on_pending + ' secs'); 56 logger.verbose('Got pending trx, requesting in ' + seconds_to_wait_before_resend_on_pending + ' secs');
57 setTimeout(function() { 57 setTimeout(function() {
58 checkStatus(options.task); 58 checkStatus(options.task);
59 }, seconds_to_wait_before_resend_on_pending * 1000) 59 }, seconds_to_wait_before_resend_on_pending * 1000)
60 } 60 }
61 } 61 }
62 62
63 function calculateSign(dt, trx_ref_id, cust_num, username, password) { 63 function calculateSign(dt, trx_ref_id, cust_num, username, password) {
64 const cryptoHashPassword = crypto.createHash('sha1'); 64 const cryptoHashPassword = crypto.createHash('sha1');
65 const cryptoHashUsernamePassword = crypto.createHash('sha1'); 65 const cryptoHashUsernamePassword = crypto.createHash('sha1');
66 const cryptoHashOutest = crypto.createHash('sha1'); 66 const cryptoHashOutest = crypto.createHash('sha1');
67 67
68 cryptoHashPassword.update(password); 68 cryptoHashPassword.update(password);
69 const hashPassword = cryptoHashPassword.digest('hex'); 69 const hashPassword = cryptoHashPassword.digest('hex');
70 70
71 cryptoHashUsernamePassword.update(username + hashPassword); 71 cryptoHashUsernamePassword.update(username + hashPassword);
72 const hashUsernamePassword = cryptoHashUsernamePassword.digest('hex'); 72 const hashUsernamePassword = cryptoHashUsernamePassword.digest('hex');
73 73
74 cryptoHashOutest.update(dt + trx_ref_id + cust_num + hashUsernamePassword); 74 cryptoHashOutest.update(dt + trx_ref_id + cust_num + hashUsernamePassword);
75 return cryptoHashOutest.digest('hex'); 75 return cryptoHashOutest.digest('hex');
76 } 76 }
77 77
78 function _decodeResponseBody(responseBody) { 78 function _decodeResponseBody(responseBody) {
79 let response; 79 let response;
80 80
81 try { 81 try {
82 response = JSON.parse(responseBody); 82 response = JSON.parse(responseBody);
83 } 83 }
84 catch(e) { 84 catch(e) {
85 logger.warn('Error parsing response body'); 85 logger.warn('Error parsing response body');
86 } 86 }
87 87
88 return response; 88 return response;
89 } 89 }
90 90
91 function _composeMessageFromResponseData(responseDataObj) { 91 function _composeMessageFromResponseData(responseDataObj) {
92 const diag = _getPropertyFromObjectSafe(responseDataObj, 'diag'); 92 const diag = _getPropertyFromObjectSafe(responseDataObj, 'diag');
93 const msg = _getPropertyFromObjectSafe(responseDataObj, 'message'); 93 const msg = _getPropertyFromObjectSafe(responseDataObj, 'message');
94 const balance = _getPropertyFromObjectSafe(responseDataObj, 'balance'); 94 const balance = _getPropertyFromObjectSafe(responseDataObj, 'balance');
95 const timestamp = _getPropertyFromObjectSafe(responseDataObj, 'timestamp'); 95 const timestamp = _getPropertyFromObjectSafe(responseDataObj, 'timestamp');
96 const price = _getPropertyFromObjectSafe(responseDataObj, 'harga'); 96 const price = _getPropertyFromObjectSafe(responseDataObj, 'harga');
97 97
98 let messages = []; 98 let messages = [];
99 99
100 if (timestamp) { 100 if (timestamp) {
101 messages.push(timestamp); 101 messages.push(timestamp);
102 } 102 }
103 103
104 if (diag) { 104 if (diag) {
105 messages.push(diag); 105 messages.push(diag);
106 } 106 }
107 107
108 if (msg) { 108 if (msg) {
109 messages.push(msg); 109 messages.push(msg);
110 } 110 }
111 111
112 if (balance) { 112 if (balance) {
113 messages.push('Balance: ' + balance); 113 messages.push('Balance: ' + balance);
114 } 114 }
115 115
116 if (price) { 116 if (price) {
117 messages.push('Price: ' + price); 117 messages.push('Price: ' + price);
118 } 118 }
119 119
120 return messages.join('. ') + '.'; 120 return messages.join('. ') + '.';
121 } 121 }
122 122
123 function _composeCompleteSn(responseDataObj) { 123 function _composeCompleteSn(responseDataObj) {
124 let serial = _getPropertyFromObjectSafe(responseDataObj, 'serial'); 124 let serial = _getPropertyFromObjectSafe(responseDataObj, 'serial');
125 const info = _getPropertyFromObjectSafe(responseDataObj, 'info'); 125 const info = _getPropertyFromObjectSafe(responseDataObj, 'info');
126 126
127 if (serial) { 127 if (serial) {
128 serial = serial.replace(/ /g, '-'); 128 serial = serial.replace(/ /g, '-');
129 } 129 }
130 130
131 if (!info) { 131 if (!info) {
132 //logger.warn('Undefined data.info on _composeCompleteSn'); 132 //logger.warn('Undefined data.info on _composeCompleteSn');
133 return serial; 133 return serial;
134 } 134 }
135 135
136 const cleanedData = { 136 const cleanedData = {
137 token: serial, 137 token: serial,
138 cust_name: _getPropertyFromObjectSafe(info, 'cust_name'), 138 cust_name: _getPropertyFromObjectSafe(info, 'cust_name'),
139 tariff: _getPropertyFromObjectSafe(info, 'kelas'), 139 tariff: _getPropertyFromObjectSafe(info, 'kelas'),
140 total_kwh: _getPropertyFromObjectSafe(info, 'size') 140 total_kwh: _getPropertyFromObjectSafe(info, 'size')
141 } 141 }
142 142
143 if (cleanedData && cleanedData.tariff && typeof cleanedData === 'string' && (cleanedData.tariff.search(/VA$/) < 0) ) { 143 if (cleanedData && cleanedData.tariff && typeof cleanedData === 'string' && (cleanedData.tariff.search(/VA$/) < 0) ) {
144 cleanedData.tariff += 'VA'; 144 cleanedData.tariff += 'VA';
145 145
146 } 146 }
147 147
148 if (cleanedData.cust_name) { 148 if (cleanedData.cust_name) {
149 cleanedData.cust_name = cleanedData.cust_name.replace(/\W+/g, '-').replace(/\W+/g, '-').replace(/-+$/, '').replace(/^-+/, '').toUpperCase(); 149 cleanedData.cust_name = cleanedData.cust_name.replace(/\W+/g, '-').replace(/\W+/g, '-').replace(/-+$/, '').replace(/^-+/, '').toUpperCase();
150 } 150 }
151 151
152 if (cleanedData.total_kwh) { 152 if (cleanedData.total_kwh) {
153 cleanedData.total_kwh = cleanedData.total_kwh.replace(/kWh\s*/g, ''); 153 cleanedData.total_kwh = cleanedData.total_kwh.replace(/kWh\s*/g, '');
154 } 154 }
155 155
156 156
157 logger.verbose('Detail token info extracted', {originalResponseInfo: info, cleanedData: cleanedData}); 157 logger.verbose('Detail token info extracted', {originalResponseInfo: info, cleanedData: cleanedData});
158 158
159 return [ 159 return [
160 cleanedData.token, cleanedData.cust_name, cleanedData.tariff, cleanedData.total_kwh 160 cleanedData.token, cleanedData.cust_name, cleanedData.tariff, cleanedData.total_kwh
161 ].join('/'); 161 ].join('/');
162 } 162 }
163 163
164 function _responseBodyHandler(responseBody, task) { 164 function _responseBodyHandler(responseBody, task) {
165 let rc = '68'; 165 let rc = '68';
166 let response = _decodeResponseBody(responseBody); 166 let response = _decodeResponseBody(responseBody);
167 167
168 logger.verbose('RESPONSE', {response: response}); 168 logger.verbose('RESPONSE', {response: response});
169 169
170 const responseStatus = _getPropertyFromObjectSafe(response, 'status'); 170 const responseStatus = _getPropertyFromObjectSafe(response, 'status');
171 const responseInfo = _getPropertyFromObjectSafe(response, 'info'); 171 const responseInfo = _getPropertyFromObjectSafe(response, 'info');
172 172
173 if (responseStatus == 'Error') { 173 if (responseStatus == 'Error') {
174 if (['insufficient balance', 'System Cut-Off'].indexOf(responseInfo) >= 0) { 174 if (['insufficient balance', 'System Cut-Off'].indexOf(responseInfo) >= 0) {
175 rc = '91'; 175 rc = '91';
176 } 176 }
177 callbackReport(task.requestId, '91', [responseStatus, responseInfo].join(': '), {task: task}); 177 callbackReport(task.requestId, '91', [responseStatus, responseInfo].join(': '), {task: task});
178 return; 178 return;
179 } 179 }
180 180
181 const requestId = _getPropertyFromObjectSafe(response.data, 'request_id'); 181 const requestId = _getPropertyFromObjectSafe(response.data, 'request_id');
182 const trxStatus = _getPropertyFromObjectSafe(response.data, 'trx_status'); 182 const trxStatus = _getPropertyFromObjectSafe(response.data, 'trx_status');
183 const diag = _getPropertyFromObjectSafe(response.data, 'diag'); 183 const diag = _getPropertyFromObjectSafe(response.data, 'diag');
184 let balance = _getPropertyFromObjectSafe(response.data, 'balance'); 184 let balance = _getPropertyFromObjectSafe(response.data, 'balance');
185 185
186 if ((typeof balance === 'string') && balance && aaa.updateBalance) { 186 if ((typeof balance === 'string') && balance && aaa.updateBalance) {
187 balance = balance.replace(/\D/g, ''); 187 balance = balance.replace(/\D/g, '');
188 if (balance) { 188 if (balance) {
189 aaa.updateBalance(balance); 189 aaa.updateBalance(balance);
190 } 190 }
191 } 191 }
192 192
193 let aaaMessage = _composeMessageFromResponseData(response.data); 193 let aaaMessage = _composeMessageFromResponseData(response.data);
194 if (!aaaMessage) { 194 if (!aaaMessage) {
195 aaaMessage = 'Transaksi sedang diproses'; 195 aaaMessage = 'Transaksi sedang diproses';
196 } 196 }
197 197
198 if (trxStatus == 'P') { 198 if (trxStatus == 'P') {
199 logger.verbose('Got pending trx response', {response: response.data}); 199 logger.verbose('Got pending trx response', {response: response.data});
200 rc = '68'; 200 rc = '68';
201 } 201 }
202 else if (trxStatus == 'S') { 202 else if (trxStatus == 'S') {
203 logger.verbose('Got succcess trx response', {response: response.data}); 203 logger.verbose('Got succcess trx response', {response: response.data});
204 204
205 rc = '00'; 205 rc = '00';
206 aaaMessage = 'SN=' + _composeCompleteSn(response.data) + '; ' + aaaMessage; 206 aaaMessage = 'SN=' + _composeCompleteSn(response.data) + '; ' + aaaMessage;
207 } 207 }
208 else if (trxStatus == 'R') { 208 else if (trxStatus == 'R') {
209 logger.verbose('Got rejected trx response', {response: response.data}); 209 logger.verbose('Got rejected trx response', {response: response.data});
210 210
211 const partnerRC = getPartnerRCFromDiagMessage(diag); 211 const partnerRC = getPartnerRCFromDiagMessage(diag);
212 if (partnerRC == '15') { 212 if (partnerRC == '15') {
213 rc = '14'; 213 rc = '14';
214 } 214 }
215 else { 215 else {
216 rc = '40'; 216 rc = '40';
217 } 217 }
218 } 218 }
219 219
220 callbackReport(requestId, rc, aaaMessage, {task: task}); 220 callbackReport(requestId, rc, aaaMessage, {task: task});
221 } 221 }
222 222
223 function getPartnerRCFromDiagMessage(diag) { 223 function getPartnerRCFromDiagMessage(diag) {
224 let matches = diag.match(/^\s*\[(.*)\]/); 224 let matches = diag.match(/^\s*\[(.*)\]/);
225 if (!matches || matches.length < 2) { 225 if (!matches || matches.length < 2) {
226 return; 226 return;
227 } 227 }
228 228
229 return matches[1]; 229 return matches[1];
230 } 230 }
231 231
232 function _hitTopup(task, isCheckStatus) { 232 function _hitTopup(task, isCheckStatus) {
233 233
234 const dt = moment().format('YYYY-MM-DD HH:mm:ss'); 234 const dt = moment().format('YYYY-MM-DD HH:mm:ss');
235 const username = config.h2h_out.username || config.h2h_out.userid; 235 const username = config.h2h_out.username || config.h2h_out.userid;
236 const password = config.h2h_out.password || config.h2h_out.pin; 236 const password = config.h2h_out.password || config.h2h_out.pin;
237 const sign = calculateSign(dt, task.requestId, task.destination, username, password); 237 const sign = calculateSign(dt, task.requestId, task.destination, username, password);
238 238
239 logger.verbose('Sign for ' + dt + ', ' + task.requestId + ', ' + task.destination + ', ' + username + ', ' + password + ' is ' + sign); 239 logger.verbose('Sign for ' + dt + ', ' + task.requestId + ', ' + task.destination + ', ' + username + ', ' + password + ' is ' + sign);
240 const requestOptions = { 240 const requestOptions = {
241 url: config.h2h_out.partner, 241 url: config.h2h_out.partner,
242 form: { 242 form: {
243 username: username, 243 username: username,
244 datetime: dt, 244 datetime: dt,
245 code: task.remoteProduct, 245 code: task.remoteProduct,
246 trx_ref_id: task.requestId, 246 trx_ref_id: task.requestId,
247 cust_num: task.destination, 247 cust_num: task.destination,
248 sign: sign 248 sign: sign
249 } 249 }
250 } 250 }
251 251
252 logger.verbose('Requesting to partner', {requestOptions: requestOptions}); 252 logger.verbose('Requesting to partner', {requestOptions: requestOptions});
253 253
254 request.post(requestOptions, function(error, response, body) { 254 request.post(requestOptions, function(error, response, body) {
255 if (error) { 255 if (error) {
256 let rc = '68'; 256 let rc = '68';
257 257
258 if (!isCheckStatus && (error.syscall == 'connect')) { 258 if (!isCheckStatus && (error.syscall == 'connect')) {
259 rc = '91'; 259 rc = '91';
260 } 260 }
261 261
262 logger.warn('Error requesting to partner', {task: task, rc: rc, error: error, isCheckStatus: isCheckStatus}); 262 logger.warn('Error requesting to partner', {task: task, rc: rc, error: error, isCheckStatus: isCheckStatus});
263 callbackReport(task.requestId, rc, 'Error requesting to partner. ' + error, {task: task}); 263 callbackReport(task.requestId, rc, 'Error requesting to partner. ' + error, {task: task});
264 return; 264 return;
265 } 265 }
266 266
267 if (response.statusCode != 200) { 267 if (response.statusCode != 200) {
268 let rc = '68'; 268 let rc = '68';
269 269
270 logger.warn('HTTP status code is not 200', {task: task, http_status_code: response.statusCode, isCheckStatus: isCheckStatus}); 270 logger.warn('HTTP status code is not 200', {task: task, http_status_code: response.statusCode, isCheckStatus: isCheckStatus});
271 callbackReport(task.requestId, rc, 'HTTP status code ' + response.statusCode, {task: task}); 271 callbackReport(task.requestId, rc, 'HTTP status code ' + response.statusCode, {task: task});
272 return; 272 return;
273 } 273 }
274 274
275 logger.info('Transaksi sedang diproses', {task: task, response_body: body}); 275 logger.info('Transaksi sedang diproses', {task: task, response_body: body});
276 276
277 _responseBodyHandler(body, task); 277 _responseBodyHandler(body, task);
278 278
279 }) 279 })
280 } 280 }
281 281
282 function _getPropertyFromObjectSafe(obj, property) { 282 function _getPropertyFromObjectSafe(obj, property) {
283 let retval; 283 let retval;
284 284
285 if (!obj) { 285 if (!obj) {
286 logger.warn('Invalid object') 286 logger.warn('Invalid object')
287 return; 287 return;
288 } 288 }
289 289
290 try { 290 try {
291 retval = obj[property]; 291 retval = obj[property];
292 } 292 }
293 catch(e) { 293 catch(e) {
294 logger.warn('Error getting ' + property + ' from object'); 294 logger.warn('Error getting ' + property + ' from object');
295 } 295 }
296 296
297 return retval; 297 return retval;
298 } 298 }
299 299
300 function topupRequest(task) { 300 function topupRequest(task) {
301 aaa.insertTaskToMongoDb(task); 301 aaa.insertTaskToMongoDb(task);
302 _hitTopup(task); 302 _hitTopup(task);
303 } 303 }
304 304
305 function checkStatus(task) { 305 function checkStatus(task) {
306 _hitTopup(task, true); 306 _hitTopup(task, true);
307 } 307 }
308 308
309 309
310 function reverseReportHandler(data) { 310 function reverseReportHandler(data) {
311 //logger.info('Got reverse report', {body: body}); 311 //logger.info('Got reverse report', {body: body});
312 312
313 const qs = URL.parse(data, true).query; 313 const qs = URL.parse(data, true).query;
314 314
315 if (!qs || !qs.request_id) { 315 if (!qs || !qs.request_id) {
316 return; 316 return;
317 } 317 }
318 318
319 if ((typeof qs.balance === 'string') && qs.balance && aaa.updateBalance) { 319 if ((typeof qs.balance === 'string') && qs.balance && aaa.updateBalance) {
320 const balance = qs.balance.replace(/\D/g, ''); 320 const balance = qs.balance.replace(/\D/g, '');
321 if (balance) { 321 if (balance) {
322 aaa.updateBalance(balance); 322 aaa.updateBalance(balance);
323 } 323 }
324 } 324 }
325 325
326 326
327 let rc = '68'; 327 let rc = '68';
328 if (qs.trx_status === 'S') { 328 if (qs.trx_status === 'S') {
329 rc = '00'; 329 rc = '00';
330 } 330 }
331 else if (qs.trx_status === 'R') { 331 else if (qs.trx_status === 'R') {
332 rc = '40'; 332 rc = '40';
333 } 333 }
334 334
335 if ((typeof qs.serial === 'string') && qs.serial) { 335 if ((typeof qs.serial === 'string') && qs.serial) {
336 rc = '00'; 336 rc = '00';
337 } 337 }
338 338
339 if (rc === '40') {
340 const partnerRC = getPartnerRCFromDiagMessage(qs.diag);
341 if (['14', '15'].indexOf(partnerRC) >= 0) {
342 rc = '14';
343 }
344 logger.verbose('REVERSE-REPORT: parsing diag', {request_id: qs.request_id, diag: diag, partnerRC: partnerRC, newRc: rc});
345 }
346
339 const sn = (rc === '00') ? _createSnFromReverseReport(qs) : null; 347 const sn = (rc === '00') ? _createSnFromReverseReport(qs) : null;
340 let msg = [ 348 let msg = [
341 'REVERSE REPORT', 349 'REVERSE REPORT',
342 'Diag: ' + (qs.diag || '-'), 350 'Diag: ' + (qs.diag || '-'),
343 'Message: ' + (qs.message || '-'), 351 'Message: ' + (qs.message || '-'),
344 'Status: ' + (qs.trx_status || '-'), 352 'Status: ' + (qs.trx_status || '-'),
345 'Balance: ' + (qs.balance || '-'), 353 'Balance: ' + (qs.balance || '-'),
346 'Harga: ' + (qs.harga || '-') 354 'Harga: ' + (qs.harga || '-')
347 ].join('. '); 355 ].join('. ');
348 356
349 if (sn) { 357 if (sn) {
350 msg = 'SN=' + sn + '; ' + msg; 358 msg = 'SN=' + sn + '; ' + msg;
351 } 359 }
352 360
353 callbackReport(qs.request_id, rc, msg); 361 callbackReport(qs.request_id, rc, msg);
354 } 362 }
355 363
356 function _parseInfoFromReverseReport(info) { 364 function _parseInfoFromReverseReport(info) {
357 let result; 365 let result;
358 try { 366 try {
359 result = JSON.parse(info); 367 result = JSON.parse(info);
360 } 368 }
361 catch (e) { 369 catch (e) {
362 logger.warn('Exception on parsing qs info as JSON', {info: info}); 370 logger.warn('Exception on parsing qs info as JSON', {info: info});
363 } 371 }
364 372
365 return result; 373 return result;
366 } 374 }
367 375
368 function _createSnFromReverseReport(qs) { 376 function _createSnFromReverseReport(qs) {
369 let token = qs.serial; 377 let token = qs.serial;
370 if (token && typeof token === 'string') { 378 if (token && typeof token === 'string') {
371 token = token.replace(/\W+/g, '-'); 379 token = token.replace(/\W+/g, '-');
372 380
373 } 381 }
374 382
375 let sn = token || '-'; 383 let sn = token || '-';
376 384
377 const info = _parseInfoFromReverseReport(qs.info); 385 const info = _parseInfoFromReverseReport(qs.info);
378 if (info) { 386 if (info) {
379 const cust_name = (typeof info.cust_name === 'string') ? info.cust_name.replace(/\W+/g, '-').replace(/^\W+/, '').replace(/\W+$/, '') : '-'; 387 const cust_name = (typeof info.cust_name === 'string') ? info.cust_name.replace(/\W+/g, '-').replace(/^\W+/, '').replace(/\W+$/, '') : '-';
380 const kelas = (typeof info.kelas === 'string') ? info.kelas.trim() : '-'; 388 const kelas = (typeof info.kelas === 'string') ? info.kelas.trim() : '-';
381 const kwh = (typeof info.size === 'string') ? info.size.trim() : '-'; 389 const kwh = (typeof info.size === 'string') ? info.size.trim() : '-';
382 390
383 sn = [ 391 sn = [
384 token || '-', 392 token || '-',
385 cust_name || '-', 393 cust_name || '-',
386 kelas || '-', 394 kelas || '-',
387 kwh || '-' 395 kwh || '-'
388 ].join('/'); 396 ].join('/');
389 } 397 }
390 398
391 return sn; 399 return sn;
392 } 400 }
393 401
394 function createReverseHttpServer() { 402 function createReverseHttpServer() {
395 var httpServer = http.createServer(function(req, res) { 403 var httpServer = http.createServer(function(req, res) {
396 404
397 logger.info('Got request from partner (reverse report)', {remote_address: req.connection.remoteAddress, url: req.url}); 405 logger.info('Got request from partner (reverse report)', {remote_address: req.connection.remoteAddress, url: req.url});
398 406
399 var body = ""; 407 var body = "";
400 req.on('data', function (chunk) { 408 req.on('data', function (chunk) {
401 body += chunk; 409 body += chunk;
402 }); 410 });
403 411
404 req.on('end', function () { 412 req.on('end', function () {
405 res.writeHead(200); 413 res.writeHead(200);
406 res.end('OK'); 414 res.end('OK');
407 415
408 logger.info('Got reverse report with POST method', {body: body}); 416 logger.info('Got reverse report with POST method', {body: body});
409 417
410 reverseReportHandler('?' + body); 418 reverseReportHandler('?' + body);
411 }); 419 });
412 420
413 return; 421 return;
414 422
415 const qs = URL.parse(req.url, true).query; 423 const qs = URL.parse(req.url, true).query;
416 424
417 425
418 if (!qs || !qs.request_id) { 426 if (!qs || !qs.request_id) {
419 return; 427 return;
420 } 428 }
421 429
422 let rc = '68'; 430 let rc = '68';
423 if (qs.trx_status === 'S') { 431 if (qs.trx_status === 'S') {
424 rc = '00'; 432 rc = '00';
425 } 433 }
426 else if (qs.trx_status === 'R') { 434 else if (qs.trx_status === 'R') {
427 rc = '40'; 435 rc = '40';
428 } 436 }
429 437
430 if (rc === '40') { 438 if (rc === '40') {
431 const partnerRC = getPartnerRCFromDiagMessage(diag); 439 const partnerRC = getPartnerRCFromDiagMessage(diag);
432 if (['14', '15'].indexOf(partnerRC) >= 0) { 440 if (['14', '15'].indexOf(partnerRC) >= 0) {
433 rc = '14'; 441 rc = '14';
434 } 442 }
435 logger.verbose('REVERSE-REPORT: parsing diag', {request_id: qs.request_id, diag: diag, partnerRC: partnerRC, newRc: rc}); 443 logger.verbose('REVERSE-REPORT: parsing diag', {request_id: qs.request_id, diag: diag, partnerRC: partnerRC, newRc: rc});
436 } 444 }
437 445
438 if ((typeof qs.balance === 'string') && qs.balance && aaa.updateBalance) { 446 if ((typeof qs.balance === 'string') && qs.balance && aaa.updateBalance) {
439 const balance = qs.balance.replace(/\D/g, ''); 447 const balance = qs.balance.replace(/\D/g, '');
440 if (balance) { 448 if (balance) {
441 aaa.updateBalance(balance); 449 aaa.updateBalance(balance);
442 } 450 }
443 } 451 }
444 452
445 const sn = (rc === '00') ? _createSnFromReverseReport(qs) : null; 453 const sn = (rc === '00') ? _createSnFromReverseReport(qs) : null;
446 let msg = [ 454 let msg = [
447 'REVERSE REPORT', 455 'REVERSE REPORT',
448 qs.diag, 456 qs.diag,
449 'Status: ' + (qs.trx_status || '-'), 457 'Status: ' + (qs.trx_status || '-'),
450 'Balance: ' + (qs.balance || '-'), 458 'Balance: ' + (qs.balance || '-'),
451 'Harga: ' + (qs.harga || '-') 459 'Harga: ' + (qs.harga || '-')
452 ].join('. '); 460 ].join('. ');
453 461
454 if (sn) { 462 if (sn) {
455 msg = 'SN=' + sn + '; ' + msg; 463 msg = 'SN=' + sn + '; ' + msg;
456 } 464 }
457 465
458 callbackReport(qs.request_id, rc, msg); 466 callbackReport(qs.request_id, rc, msg);
459 467
460 }); 468 });
461 469
462 httpServer.listen(config.h2h_out.listen_port, function() { 470 httpServer.listen(config.h2h_out.listen_port, function() {
463 logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port); 471 logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port);
464 }); 472 });
465 } 473 }
466 474
467 475
468 exports.calculateSign = calculateSign; 476 exports.calculateSign = calculateSign;
469 exports.start = start; 477 exports.start = start;
470 exports.topupRequest = topupRequest; 478 exports.topupRequest = topupRequest;
471 exports.checkStatus = checkStatus; 479 exports.checkStatus = checkStatus;
472 480