Commit beb4ecff35c39ab8ae8696907e3cb3c17a2de84f

Authored by Adhidarma Hadiwinoto
1 parent 655aff866b
Exists in master

disable topupCheck sampai dapat konfirmasi perubahan spesifikasi nomor tujuan 13 digit pading left 0

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

partner-bayarkilat.js
1 var request = require('request'); 1 var request = require('request');
2 var url = require('url'); 2 var url = require('url');
3 var winston = require('winston'); 3 var winston = require('winston');
4 var xml2jsParser = require('xml2js').parseString; 4 var xml2jsParser = require('xml2js').parseString;
5 var redis = require('redis'); 5 var redis = require('redis');
6 6
7 var config; 7 var config;
8 var aaa; 8 var aaa;
9 var callbackReport; 9 var callbackReport;
10 var logger; 10 var logger;
11 var redisClient; 11 var redisClient;
12 12
13 var maxCheckRetry = 20; 13 var maxCheckRetry = 20;
14 var delayBeforeCheckRetry = 30 * 1000; 14 var delayBeforeCheckRetry = 30 * 1000;
15 15
16 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; 16 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
17 17
18 function createRedisClient(host, port) { 18 function createRedisClient(host, port) {
19 try { 19 try {
20 redisClient = redis.createClient(port, host); 20 redisClient = redis.createClient(port, host);
21 } catch(err) { 21 } catch(err) {
22 logger.warn("Error creating redis client to " + host + ':' + port); 22 logger.warn("Error creating redis client to " + host + ':' + port);
23 } 23 }
24 } 24 }
25 25
26 function start(_config, _callbackReport, options) { 26 function start(_config, _callbackReport, options) {
27 config = _config; 27 config = _config;
28 callbackReport = _callbackReport; 28 callbackReport = _callbackReport;
29 29
30 if (options && options.aaa) { 30 if (options && options.aaa) {
31 aaa = options.aaa; 31 aaa = options.aaa;
32 } 32 }
33 33
34 if (options && options.logger) { 34 if (options && options.logger) {
35 logger = options.logger; 35 logger = options.logger;
36 } else { 36 } else {
37 logger = new winston.Logger({ 37 logger = new winston.Logger({
38 transports: [ 38 transports: [
39 new (winston.transports.Console)() 39 new (winston.transports.Console)()
40 ] 40 ]
41 }); 41 });
42 } 42 }
43 43
44 createRedisClient(config.globals.redis_host, config.globals.redis_port); 44 createRedisClient(config.globals.redis_host, config.globals.redis_port);
45 } 45 }
46 46
47 function createRequestOptions(methodName, task) { 47 function createRequestOptions(methodName, task) {
48 var partnerUrl = url.parse(config.h2h_out.partner); 48 var partnerUrl = url.parse(config.h2h_out.partner);
49 var product = prepareRemoteProductCode(task.remoteProduct); 49 var product = prepareRemoteProductCode(task.remoteProduct);
50 50
51 var destination = task.destination; 51 var destination = task.destination;
52 if (methodName == 'CHECKING') { 52 if (methodName == 'CHECKING') {
53 destination = paddingDestination(destination); 53 destination = paddingDestination(destination);
54 } 54 }
55 55
56 var options = { 56 var options = {
57 url: config.h2h_out.partner, 57 url: config.h2h_out.partner,
58 qs: { 58 qs: {
59 request: methodName + '*' 59 request: methodName + '*'
60 + task.requestId + '*' 60 + task.requestId + '*'
61 + product.product + '*' 61 + product.product + '*'
62 + product.productDetail + '*' 62 + product.productDetail + '*'
63 + destination + '*' 63 + destination + '*'
64 + product.nominal + '*' 64 + product.nominal + '*'
65 + '0*' 65 + '0*'
66 + config.h2h_out.noid + '*' 66 + config.h2h_out.noid + '*'
67 + config.h2h_out.userid + '*' 67 + config.h2h_out.userid + '*'
68 + config.h2h_out.password 68 + config.h2h_out.password
69 } 69 }
70 }; 70 };
71 71
72 return options; 72 return options;
73 } 73 }
74 74
75 function topupCheck(task, _retry) { 75 function topupCheck(task, _retry) {
76 // disable topupCheck sampai dapat konfirmasi perubahan spesifikasi nomor tujuan 13 digit pading left 0
77 return;
78
76 var retry = _retry; 79 var retry = _retry;
77 80
78 if (retry === null || retry === undefined) { 81 if (retry === null || retry === undefined) {
79 retry = maxCheckRetry + 1; 82 retry = maxCheckRetry + 1;
80 } 83 }
81 84
82 retry = retry - 1; 85 retry = retry - 1;
83 86
84 if (retry < 0) { 87 if (retry < 0) {
85 var message = 'Max retry check transaction retry exceeded'; 88 var message = 'Max retry check transaction retry exceeded';
86 var response = { 89 var response = {
87 raw: message, 90 raw: message,
88 parsed: { 91 parsed: {
89 MESSAGE: message 92 MESSAGE: message
90 } 93 }
91 } 94 }
92 aaa.pushResponseToMongoDb(task, response, '68'); 95 aaa.pushResponseToMongoDb(task, response, '68');
93 callbackReport(task.requestId, '68', message); 96 callbackReport(task.requestId, '68', message);
94 return; 97 return;
95 } 98 }
96 99
97 requestToPartner('CHECKING', task, retry); 100 requestToPartner('CHECKING', task, retry);
98 } 101 }
99 102
100 function topupRequest(task) { 103 function topupRequest(task) {
101 if (!aaa.isTodayTrx(task)) { 104 if (!aaa.isTodayTrx(task)) {
102 logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan'); 105 logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan');
103 callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan'); 106 callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan');
104 return; 107 return;
105 } 108 }
106 109
107 getTaskForDupeCheck(task, function(err, dupeTask) { 110 getTaskForDupeCheck(task, function(err, dupeTask) {
108 if (dupeTask) { 111 if (dupeTask) {
109 logger.info('Duplicate task detected, requesting topupCheck', {task: task}); 112 logger.info('Duplicate task detected, requesting topupCheck', {task: task});
110 topupCheck(task); 113 topupCheck(task);
111 } else { 114 } else {
112 saveTaskForDupeCheck(task); 115 saveTaskForDupeCheck(task);
113 requestToPartner('PURCHASE', task); 116 requestToPartner('PURCHASE', task);
114 } 117 }
115 }); 118 });
116 119
117 } 120 }
118 121
119 function requestToPartner(methodName, task, retry) { 122 function requestToPartner(methodName, task, retry) {
120 aaa.insertTaskToMongoDb(task); 123 aaa.insertTaskToMongoDb(task);
121 124
122 var options = createRequestOptions(methodName, task); 125 var options = createRequestOptions(methodName, task);
123 126
124 logger.info('Requesting to partner', {requestOption: options}); 127 logger.info('Requesting to partner', {requestOption: options});
125 request(options, function(error, response, body) { 128 request(options, function(error, response, body) {
126 if (error) { 129 if (error) {
127 var msg = 'Error requesting to partner. ' + error; 130 var msg = 'Error requesting to partner. ' + error;
128 var rc = '68'; 131 var rc = '68';
129 132
130 try { 133 try {
131 if (methodName == 'PURCHASE') { 134 if (methodName == 'PURCHASE') {
132 if ((error.connect === true || error.syscall == "connect") && (error.code === 'ETIMEDOUT' || error.code === 'ECONNREFUSED')) { 135 if ((error.connect === true || error.syscall == "connect") && (error.code === 'ETIMEDOUT' || error.code === 'ECONNREFUSED')) {
133 rc = '40'; 136 rc = '40';
134 } 137 }
135 } 138 }
136 } 139 }
137 catch(e) { 140 catch(e) {
138 logger.warn('Parsing error exception on requestToPartner()'); 141 logger.warn('Parsing error exception on requestToPartner()');
139 } 142 }
140 143
141 logger.warn(msg, {error: error}); 144 logger.warn(msg, {error: error});
142 callbackReport(task.requestId, rc, msg); 145 callbackReport(task.requestId, rc, msg);
143 146
144 var _response = { 147 var _response = {
145 raw: JSON.stringify({msg: msg, error: error}), 148 raw: JSON.stringify({msg: msg, error: error}),
146 parsed: { 149 parsed: {
147 MESSAGE: msg, 150 MESSAGE: msg,
148 error: error 151 error: error
149 } 152 }
150 } 153 }
151 aaa.pushResponseToMongoDb(task, _response, rc); 154 aaa.pushResponseToMongoDb(task, _response, rc);
152 155
153 if (rc == '68') { 156 if (rc == '68') {
154 setTimeout( 157 setTimeout(
155 topupCheck, 158 topupCheck,
156 delayBeforeCheckRetry, 159 delayBeforeCheckRetry,
157 task, 160 task,
158 retry 161 retry
159 ); 162 );
160 } 163 }
161 164
162 return; 165 return;
163 } 166 }
164 167
165 if (response.statusCode != 200) { 168 if (response.statusCode != 200) {
166 var message = 'Partner response with http status code other that 200 (' + response.statusCode + ')'; 169 var message = 'Partner response with http status code other that 200 (' + response.statusCode + ')';
167 var rc = '68'; 170 var rc = '68';
168 171
169 if (!retry && response.statusCode == 404) { 172 if (!retry && response.statusCode == 404) {
170 rc = '91'; 173 rc = '91';
171 } 174 }
172 175
173 logger.warn(message); 176 logger.warn(message);
174 callbackReport(task.requestId, rc, message); 177 callbackReport(task.requestId, rc, message);
175 178
176 var _response = { 179 var _response = {
177 raw: message, 180 raw: message,
178 parsed: { 181 parsed: {
179 MESSAGE: message, 182 MESSAGE: message,
180 responseHttpStatus: response.statusCode, 183 responseHttpStatus: response.statusCode,
181 responseBody: body, 184 responseBody: body,
182 } 185 }
183 } 186 }
184 aaa.pushResponseToMongoDb(task, _response, rc); 187 aaa.pushResponseToMongoDb(task, _response, rc);
185 188
186 if (rc == '68') { 189 if (rc == '68') {
187 setTimeout( 190 setTimeout(
188 topupCheck, 191 topupCheck,
189 delayBeforeCheckRetry, 192 delayBeforeCheckRetry,
190 task, 193 task,
191 retry 194 retry
192 ); 195 );
193 } 196 }
194 197
195 return; 198 return;
196 } 199 }
197 200
198 logger.verbose('Got respose', {rawBody: body}); 201 logger.verbose('Got respose', {rawBody: body});
199 parseResponse(body, task); 202 parseResponse(body, task);
200 }); 203 });
201 } 204 }
202 205
203 function getSn(response) { 206 function getSn(response) {
204 try { 207 try {
205 var sn = response.xml.ket1[0]; 208 var sn = response.xml.ket1[0];
206 return sn; 209 return sn;
207 } 210 }
208 catch (err) { 211 catch (err) {
209 return; 212 return;
210 } 213 }
211 } 214 }
212 215
213 function getHarga(response) { 216 function getHarga(response) {
214 try { 217 try {
215 var harga = response.xml.amount[0]; 218 var harga = response.xml.amount[0];
216 return harga; 219 return harga;
217 } 220 }
218 catch (err) { 221 catch (err) {
219 return; 222 return;
220 } 223 }
221 } 224 }
222 225
223 function getSaldo(response) { 226 function getSaldo(response) {
224 try { 227 try {
225 var saldo = response.xml.saldo[0]; 228 var saldo = response.xml.saldo[0];
226 return saldo; 229 return saldo;
227 } 230 }
228 catch (err) { 231 catch (err) {
229 return; 232 return;
230 } 233 }
231 } 234 }
232 235
233 function parseResponse(body, task) { 236 function parseResponse(body, task) {
234 xml2jsParser(body, function(err, response) { 237 xml2jsParser(body, function(err, response) {
235 if (err) { 238 if (err) {
236 logger.warn('Error parsing XML', {error: err, task: task, responseBody: body}); 239 logger.warn('Error parsing XML', {error: err, task: task, responseBody: body});
237 240
238 var message = 'Error parsing XML. ' + err + '. ' + body; 241 var message = 'Error parsing XML. ' + err + '. ' + body;
239 242
240 var _response = { 243 var _response = {
241 raw: body, 244 raw: body,
242 parsed: { 245 parsed: {
243 MESSAGE: message 246 MESSAGE: message
244 } 247 }
245 } 248 }
246 aaa.pushResponseToMongoDb(task, _response, '68'); 249 aaa.pushResponseToMongoDb(task, _response, '68');
247 250
248 callbackReport(task.requestId, '68', message); 251 callbackReport(task.requestId, '68', message);
249 return; 252 return;
250 } 253 }
251 254
252 logger.info('Got response', {response: response}); 255 logger.info('Got response', {response: response});
253 256
254 var responseCode; 257 var responseCode;
255 var message; 258 var message;
256 259
257 try { 260 try {
258 responseCode = response.xml.response_code[0]; 261 responseCode = response.xml.response_code[0];
259 message = response.xml.response_message[0]; 262 message = response.xml.response_message[0];
260 } 263 }
261 catch(errGetParam) { 264 catch(errGetParam) {
262 logger.warn('Exception saat parsing hasil', {error: errGetParam, task: task, responseBody: body}); 265 logger.warn('Exception saat parsing hasil', {error: errGetParam, task: task, responseBody: body});
263 266
264 var _response = { 267 var _response = {
265 raw: body, 268 raw: body,
266 parsed: { 269 parsed: {
267 MESSAGE: 'Exception saat parsing hasil. ' + errGetParam, 270 MESSAGE: 'Exception saat parsing hasil. ' + errGetParam,
268 xml: response.xml 271 xml: response.xml
269 } 272 }
270 } 273 }
271 aaa.pushResponseToMongoDb(task, _response, '68'); 274 aaa.pushResponseToMongoDb(task, _response, '68');
272 275
273 callbackReport(task.requestId, '68', 'Exception saat parsing hasil. ' + errGetParam); 276 callbackReport(task.requestId, '68', 'Exception saat parsing hasil. ' + errGetParam);
274 return; 277 return;
275 } 278 }
276 279
277 var st24rc; 280 var st24rc;
278 if (parseInt(responseCode) == 0) { 281 if (parseInt(responseCode) == 0) {
279 st24rc = '00'; 282 st24rc = '00';
280 } 283 }
281 else if (parseInt(responseCode) == 99) { 284 else if (parseInt(responseCode) == 99) {
282 st24rc = '68' 285 st24rc = '68'
283 } 286 }
284 else if (parseInt(responseCode) == 201) { 287 else if (parseInt(responseCode) == 201) {
285 st24rc = '68' 288 st24rc = '68'
286 } 289 }
287 else if (message.indexOf('Transaksi sedang dalam proses') >= 0) { 290 else if (message.indexOf('Transaksi sedang dalam proses') >= 0) {
288 st24rc = '68'; 291 st24rc = '68';
289 } 292 }
290 else { 293 else {
291 st24rc = '40'; 294 st24rc = '40';
292 } 295 }
293 296
294 var st24message = message; 297 var st24message = message;
295 if (responseCode) { 298 if (responseCode) {
296 st24message = responseCode + ' ' + st24message; 299 st24message = responseCode + ' ' + st24message;
297 } 300 }
298 301
299 if (st24rc == '00') { 302 if (st24rc == '00') {
300 var sn = getSn(response); 303 var sn = getSn(response);
301 304
302 if (sn) { 305 if (sn) {
303 st24message = 'SN=' + sn + ';' + st24message + '. SN=' + sn; 306 st24message = 'SN=' + sn + ';' + st24message + '. SN=' + sn;
304 } 307 }
305 } 308 }
306 309
307 var harga = getHarga(response); 310 var harga = getHarga(response);
308 if (harga) { 311 if (harga) {
309 st24message = st24message + '. Harga ' + harga; 312 st24message = st24message + '. Harga ' + harga;
310 } 313 }
311 314
312 var saldo = getSaldo(response); 315 var saldo = getSaldo(response);
313 if (saldo) { 316 if (saldo) {
314 st24message = st24message + '. Saldo ' + saldo; 317 st24message = st24message + '. Saldo ' + saldo;
315 aaa.updateBalance(saldo); 318 aaa.updateBalance(saldo);
316 } 319 }
317 320
318 var _response = { 321 var _response = {
319 raw: body, 322 raw: body,
320 parsed: { 323 parsed: {
321 MESSAGE: st24message, 324 MESSAGE: st24message,
322 xml: response.xml 325 xml: response.xml
323 } 326 }
324 } 327 }
325 328
326 aaa.pushResponseToMongoDb(task, _response, st24rc); 329 aaa.pushResponseToMongoDb(task, _response, st24rc);
327 330
328 callbackReport(task.requestId, st24rc, st24message); 331 callbackReport(task.requestId, st24rc, st24message);
329 }); 332 });
330 } 333 }
331 334
332 function prepareRemoteProductCode(remoteProduct) { 335 function prepareRemoteProductCode(remoteProduct) {
333 var product = remoteProduct.split(','); 336 var product = remoteProduct.split(',');
334 337
335 if (product.length != 3) { 338 if (product.length != 3) {
336 return; 339 return;
337 } 340 }
338 341
339 return { 342 return {
340 product: product[0], 343 product: product[0],
341 productDetail: product[1], 344 productDetail: product[1],
342 nominal: product[2] 345 nominal: product[2]
343 } 346 }
344 } 347 }
345 348
346 function paddingDestination(destination, _width) { 349 function paddingDestination(destination, _width) {
347 var width = _width; 350 var width = _width;
348 if (!width) { 351 if (!width) {
349 width = 13; 352 width = 13;
350 } 353 }
351 354
352 if (destination.length > width) { 355 if (destination.length > width) {
353 return destination; 356 return destination;
354 } 357 }
355 358
356 var padder = "000000000000000000000000000"; 359 var padder = "000000000000000000000000000";
357 360
358 return (padder + destination).slice(-1 * width); 361 return (padder + destination).slice(-1 * width);
359 } 362 }
360 363
361 function getTaskKeyForDupeCheck(task) { 364 function getTaskKeyForDupeCheck(task) {
362 return config.globals.gateway_name + '.dupecheck.reqId:' + task.requestId; 365 return config.globals.gateway_name + '.dupecheck.reqId:' + task.requestId;
363 } 366 }
364 367
365 function saveTaskForDupeCheck(task, cb) { 368 function saveTaskForDupeCheck(task, cb) {
366 var key = getTaskKeyForDupeCheck(task); 369 var key = getTaskKeyForDupeCheck(task);
367 370
368 logger.verbose('Saving ' + key + ' to redis for dupecheck protection'); 371 logger.verbose('Saving ' + key + ' to redis for dupecheck protection');
369 372
370 redisClient.set(key, JSON.stringify(task), function() { 373 redisClient.set(key, JSON.stringify(task), function() {
371 redisClient.expire(key, 3600*24*7); 374 redisClient.expire(key, 3600*24*7);
372 if (cb) { 375 if (cb) {
373 cb(null, task); 376 cb(null, task);
374 } 377 }
375 }); 378 });
376 } 379 }
377 380
378 function getTaskForDupeCheck(task, cb) { 381 function getTaskForDupeCheck(task, cb) {
379 var key = getTaskKeyForDupeCheck(task); 382 var key = getTaskKeyForDupeCheck(task);
380 383
381 redisClient.get(key, function(err, result) { 384 redisClient.get(key, function(err, result) {
382 if (err) { 385 if (err) {
383 cb(err, null); 386 cb(err, null);
384 return; 387 return;
385 } 388 }
386 389
387 var taskOnRedis = null; 390 var taskOnRedis = null;
388 try { 391 try {
389 taskOnRedis = JSON.parse(result); 392 taskOnRedis = JSON.parse(result);
390 } 393 }
391 catch(err1) { 394 catch(err1) {
392 cb(err1, null); 395 cb(err1, null);
393 return; 396 return;
394 } 397 }
395 398
396 cb(null, taskOnRedis); 399 cb(null, taskOnRedis);
397 }); 400 });
398 } 401 }
399 402
400 exports.start = start; 403 exports.start = start;
401 exports.topupRequest = topupRequest; 404 exports.topupRequest = topupRequest;
402 exports.prepareRemoteProductCode = prepareRemoteProductCode; 405 exports.prepareRemoteProductCode = prepareRemoteProductCode;
403 exports.paddingDestination = paddingDestination; 406 exports.paddingDestination = paddingDestination;
404 407