Commit e40d51df36e647b05a97f5b1a9952f5e51e94e28

Authored by Adhidarma Hadiwinoto
1 parent 57cfab2f3f
Exists in master

disable auto resend

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