Commit c87c3a687fb873c5e8ae02e94fd694443f6356d9

Authored by Adhidarma Hadiwinoto
1 parent ad628905e1
Exists in master

typo

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