Commit 3b800bacd751a36f43cfab230463d0ee21e2a5a9

Authored by Adhidarma Hadiwinoto
1 parent c28f9dc004
Exists in master

make retry arguments v8 optimization friendly

Showing 1 changed file with 3 additions and 1 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 var retry = _retry;
77
76 if (retry === null || retry === undefined) { 78 if (retry === null || retry === undefined) {
77 retry = maxCheckRetry + 1; 79 retry = maxCheckRetry + 1;
78 } 80 }
79 81
80 retry = retry - 1; 82 retry = retry - 1;
81 83
82 if (retry < 0) { 84 if (retry < 0) {
83 var message = 'Max retry check transaction retry exceeded'; 85 var message = 'Max retry check transaction retry exceeded';
84 var response = { 86 var response = {
85 raw: message, 87 raw: message,
86 parsed: { 88 parsed: {
87 MESSAGE: message 89 MESSAGE: message
88 } 90 }
89 } 91 }
90 aaa.pushResponseToMongoDb(task, response, '68'); 92 aaa.pushResponseToMongoDb(task, response, '68');
91 callbackReport(task.requestId, '68', message); 93 callbackReport(task.requestId, '68', message);
92 return; 94 return;
93 } 95 }
94 96
95 requestToPartner('CHECKING', task, retry); 97 requestToPartner('CHECKING', task, retry);
96 } 98 }
97 99
98 function topupRequest(task) { 100 function topupRequest(task) {
99 if (!aaa.isTodayTrx(task)) { 101 if (!aaa.isTodayTrx(task)) {
100 logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan'); 102 logger.warn('Maaf, transaksi beda hari tidak dapat dilakukan');
101 callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan'); 103 callbackReport(task.requestId, '68', 'Maaf, transaksi beda hari tidak dapat dilakukan');
102 return; 104 return;
103 } 105 }
104 106
105 getTaskForDupeCheck(task, function(err, dupeTask) { 107 getTaskForDupeCheck(task, function(err, dupeTask) {
106 if (dupeTask) { 108 if (dupeTask) {
107 logger.info('Duplicate task detected, requesting topupCheck', {task: task}); 109 logger.info('Duplicate task detected, requesting topupCheck', {task: task});
108 topupCheck(task); 110 topupCheck(task);
109 } else { 111 } else {
110 saveTaskForDupeCheck(task); 112 saveTaskForDupeCheck(task);
111 requestToPartner('PURCHASE', task); 113 requestToPartner('PURCHASE', task);
112 } 114 }
113 }); 115 });
114 116
115 } 117 }
116 118
117 function requestToPartner(methodName, task, retry) { 119 function requestToPartner(methodName, task, retry) {
118 aaa.insertTaskToMongoDb(task); 120 aaa.insertTaskToMongoDb(task);
119 121
120 var options = createRequestOptions(methodName, task); 122 var options = createRequestOptions(methodName, task);
121 123
122 logger.info('Requesting to partner', {requestOption: options}); 124 logger.info('Requesting to partner', {requestOption: options});
123 request(options, function(error, response, body) { 125 request(options, function(error, response, body) {
124 if (error) { 126 if (error) {
125 var msg = 'Error requesting to partner. ' + error; 127 var msg = 'Error requesting to partner. ' + error;
126 var rc = '68'; 128 var rc = '68';
127 129
128 try { 130 try {
129 if (methodName == 'PURCHASE') { 131 if (methodName == 'PURCHASE') {
130 if ((error.connect === true || error.syscall == "connect") && (error.code === 'ETIMEDOUT' || error.code === 'ECONNREFUSED')) { 132 if ((error.connect === true || error.syscall == "connect") && (error.code === 'ETIMEDOUT' || error.code === 'ECONNREFUSED')) {
131 rc = '40'; 133 rc = '40';
132 } 134 }
133 } 135 }
134 } 136 }
135 catch(e) { 137 catch(e) {
136 logger.warn('Parsing error exception on requestToPartner()'); 138 logger.warn('Parsing error exception on requestToPartner()');
137 } 139 }
138 140
139 logger.warn(msg, {error: error}); 141 logger.warn(msg, {error: error});
140 callbackReport(task.requestId, rc, msg); 142 callbackReport(task.requestId, rc, msg);
141 143
142 var _response = { 144 var _response = {
143 raw: JSON.stringify({msg: msg, error: error}), 145 raw: JSON.stringify({msg: msg, error: error}),
144 parsed: { 146 parsed: {
145 MESSAGE: msg, 147 MESSAGE: msg,
146 error: error 148 error: error
147 } 149 }
148 } 150 }
149 aaa.pushResponseToMongoDb(task, _response, rc); 151 aaa.pushResponseToMongoDb(task, _response, rc);
150 152
151 if (rc == '68') { 153 if (rc == '68') {
152 setTimeout( 154 setTimeout(
153 topupCheck, 155 topupCheck,
154 delayBeforeCheckRetry, 156 delayBeforeCheckRetry,
155 task, 157 task,
156 retry 158 retry
157 ); 159 );
158 } 160 }
159 161
160 return; 162 return;
161 } 163 }
162 164
163 if (response.statusCode != 200) { 165 if (response.statusCode != 200) {
164 var message = 'Partner response with http status code other that 200 (' + response.statusCode + ')'; 166 var message = 'Partner response with http status code other that 200 (' + response.statusCode + ')';
165 var rc = '68'; 167 var rc = '68';
166 168
167 if (!retry && response.statusCode == 404) { 169 if (!retry && response.statusCode == 404) {
168 rc = '91'; 170 rc = '91';
169 } 171 }
170 172
171 logger.warn(message); 173 logger.warn(message);
172 callbackReport(task.requestId, rc, message); 174 callbackReport(task.requestId, rc, message);
173 175
174 var _response = { 176 var _response = {
175 raw: message, 177 raw: message,
176 parsed: { 178 parsed: {
177 MESSAGE: message, 179 MESSAGE: message,
178 responseHttpStatus: response.statusCode, 180 responseHttpStatus: response.statusCode,
179 responseBody: body, 181 responseBody: body,
180 } 182 }
181 } 183 }
182 aaa.pushResponseToMongoDb(task, _response, rc); 184 aaa.pushResponseToMongoDb(task, _response, rc);
183 185
184 if (rc == '68') { 186 if (rc == '68') {
185 setTimeout( 187 setTimeout(
186 topupCheck, 188 topupCheck,
187 delayBeforeCheckRetry, 189 delayBeforeCheckRetry,
188 task, 190 task,
189 retry 191 retry
190 ); 192 );
191 } 193 }
192 194
193 return; 195 return;
194 } 196 }
195 197
196 logger.verbose('Got respose', {rawBody: body}); 198 logger.verbose('Got respose', {rawBody: body});
197 parseResponse(body, task); 199 parseResponse(body, task);
198 }); 200 });
199 } 201 }
200 202
201 function getSn(response) { 203 function getSn(response) {
202 try { 204 try {
203 var sn = response.xml.ket1[0]; 205 var sn = response.xml.ket1[0];
204 return sn; 206 return sn;
205 } 207 }
206 catch (err) { 208 catch (err) {
207 return; 209 return;
208 } 210 }
209 } 211 }
210 212
211 function getHarga(response) { 213 function getHarga(response) {
212 try { 214 try {
213 var harga = response.xml.amount[0]; 215 var harga = response.xml.amount[0];
214 return harga; 216 return harga;
215 } 217 }
216 catch (err) { 218 catch (err) {
217 return; 219 return;
218 } 220 }
219 } 221 }
220 222
221 function getSaldo(response) { 223 function getSaldo(response) {
222 try { 224 try {
223 var saldo = response.xml.saldo[0]; 225 var saldo = response.xml.saldo[0];
224 return saldo; 226 return saldo;
225 } 227 }
226 catch (err) { 228 catch (err) {
227 return; 229 return;
228 } 230 }
229 } 231 }
230 232
231 function parseResponse(body, task) { 233 function parseResponse(body, task) {
232 xml2jsParser(body, function(err, response) { 234 xml2jsParser(body, function(err, response) {
233 if (err) { 235 if (err) {
234 logger.warn('Error parsing XML', {error: err, task: task, responseBody: body}); 236 logger.warn('Error parsing XML', {error: err, task: task, responseBody: body});
235 237
236 var message = 'Error parsing XML. ' + err + '. ' + body; 238 var message = 'Error parsing XML. ' + err + '. ' + body;
237 239
238 var _response = { 240 var _response = {
239 raw: body, 241 raw: body,
240 parsed: { 242 parsed: {
241 MESSAGE: message 243 MESSAGE: message
242 } 244 }
243 } 245 }
244 aaa.pushResponseToMongoDb(task, _response, '68'); 246 aaa.pushResponseToMongoDb(task, _response, '68');
245 247
246 callbackReport(task.requestId, '68', message); 248 callbackReport(task.requestId, '68', message);
247 return; 249 return;
248 } 250 }
249 251
250 logger.info('Got response', {response: response}); 252 logger.info('Got response', {response: response});
251 253
252 var responseCode; 254 var responseCode;
253 var message; 255 var message;
254 256
255 try { 257 try {
256 responseCode = response.xml.response_code[0]; 258 responseCode = response.xml.response_code[0];
257 message = response.xml.response_message[0]; 259 message = response.xml.response_message[0];
258 } 260 }
259 catch(errGetParam) { 261 catch(errGetParam) {
260 logger.warn('Exception saat parsing hasil', {error: errGetParam, task: task, responseBody: body}); 262 logger.warn('Exception saat parsing hasil', {error: errGetParam, task: task, responseBody: body});
261 263
262 var _response = { 264 var _response = {
263 raw: body, 265 raw: body,
264 parsed: { 266 parsed: {
265 MESSAGE: 'Exception saat parsing hasil. ' + errGetParam, 267 MESSAGE: 'Exception saat parsing hasil. ' + errGetParam,
266 xml: response.xml 268 xml: response.xml
267 } 269 }
268 } 270 }
269 aaa.pushResponseToMongoDb(task, _response, '68'); 271 aaa.pushResponseToMongoDb(task, _response, '68');
270 272
271 callbackReport(task.requestId, '68', 'Exception saat parsing hasil. ' + errGetParam); 273 callbackReport(task.requestId, '68', 'Exception saat parsing hasil. ' + errGetParam);
272 return; 274 return;
273 } 275 }
274 276
275 var st24rc; 277 var st24rc;
276 if (parseInt(responseCode) == 0) { 278 if (parseInt(responseCode) == 0) {
277 st24rc = '00'; 279 st24rc = '00';
278 } 280 }
279 else if (parseInt(responseCode) == '99') { 281 else if (parseInt(responseCode) == '99') {
280 st24rc = '68' 282 st24rc = '68'
281 } 283 }
282 else { 284 else {
283 st24rc = '40'; 285 st24rc = '40';
284 } 286 }
285 287
286 var st24message = message; 288 var st24message = message;
287 if (responseCode) { 289 if (responseCode) {
288 st24message = responseCode + ' ' + st24message; 290 st24message = responseCode + ' ' + st24message;
289 } 291 }
290 292
291 if (st24rc == '00') { 293 if (st24rc == '00') {
292 var sn = getSn(response); 294 var sn = getSn(response);
293 295
294 if (sn) { 296 if (sn) {
295 st24message = 'SN=' + sn + ';' + st24message + '. SN=' + sn; 297 st24message = 'SN=' + sn + ';' + st24message + '. SN=' + sn;
296 } 298 }
297 } 299 }
298 300
299 var harga = getHarga(response); 301 var harga = getHarga(response);
300 if (harga) { 302 if (harga) {
301 st24message = st24message + '. Harga ' + harga; 303 st24message = st24message + '. Harga ' + harga;
302 } 304 }
303 305
304 var saldo = getSaldo(response); 306 var saldo = getSaldo(response);
305 if (saldo) { 307 if (saldo) {
306 st24message = st24message + '. Saldo ' + saldo; 308 st24message = st24message + '. Saldo ' + saldo;
307 aaa.updateBalance(saldo); 309 aaa.updateBalance(saldo);
308 } 310 }
309 311
310 var _response = { 312 var _response = {
311 raw: body, 313 raw: body,
312 parsed: { 314 parsed: {
313 MESSAGE: st24message, 315 MESSAGE: st24message,
314 xml: response.xml 316 xml: response.xml
315 } 317 }
316 } 318 }
317 319
318 aaa.pushResponseToMongoDb(task, _response, st24rc); 320 aaa.pushResponseToMongoDb(task, _response, st24rc);
319 321
320 callbackReport(task.requestId, st24rc, st24message); 322 callbackReport(task.requestId, st24rc, st24message);
321 }); 323 });
322 } 324 }
323 325
324 function prepareRemoteProductCode(remoteProduct) { 326 function prepareRemoteProductCode(remoteProduct) {
325 var product = remoteProduct.split(','); 327 var product = remoteProduct.split(',');
326 328
327 if (product.length != 3) { 329 if (product.length != 3) {
328 return; 330 return;
329 } 331 }
330 332
331 return { 333 return {
332 product: product[0], 334 product: product[0],
333 productDetail: product[1], 335 productDetail: product[1],
334 nominal: product[2] 336 nominal: product[2]
335 } 337 }
336 } 338 }
337 339
338 function paddingDestination(destination, _width) { 340 function paddingDestination(destination, _width) {
339 var width = _width; 341 var width = _width;
340 if (!width) { 342 if (!width) {
341 width = 13; 343 width = 13;
342 } 344 }
343 345
344 if (destination.length > width) { 346 if (destination.length > width) {
345 return destination; 347 return destination;
346 } 348 }
347 349
348 var padder = "000000000000000000000000000"; 350 var padder = "000000000000000000000000000";
349 351
350 return (padder + destination).slice(-1 * width); 352 return (padder + destination).slice(-1 * width);
351 } 353 }
352 354
353 function getTaskKeyForDupeCheck(task) { 355 function getTaskKeyForDupeCheck(task) {
354 return config.globals.gateway_name + '.dupecheck.reqId:' + task.requestId; 356 return config.globals.gateway_name + '.dupecheck.reqId:' + task.requestId;
355 } 357 }
356 358
357 function saveTaskForDupeCheck(task, cb) { 359 function saveTaskForDupeCheck(task, cb) {
358 var key = getTaskKeyForDupeCheck(task); 360 var key = getTaskKeyForDupeCheck(task);
359 361
360 logger.verbose('Saving ' + key + ' to redis for dupecheck protection'); 362 logger.verbose('Saving ' + key + ' to redis for dupecheck protection');
361 363
362 redisClient.set(key, JSON.stringify(task), function() { 364 redisClient.set(key, JSON.stringify(task), function() {
363 redisClient.expire(key, 3600*24*7); 365 redisClient.expire(key, 3600*24*7);
364 if (cb) { 366 if (cb) {
365 cb(null, task); 367 cb(null, task);
366 } 368 }
367 }); 369 });
368 } 370 }
369 371
370 function getTaskForDupeCheck(task, cb) { 372 function getTaskForDupeCheck(task, cb) {
371 var key = getTaskKeyForDupeCheck(task); 373 var key = getTaskKeyForDupeCheck(task);
372 374
373 redisClient.get(key, function(err, result) { 375 redisClient.get(key, function(err, result) {
374 if (err) { 376 if (err) {
375 cb(err, null); 377 cb(err, null);
376 return; 378 return;
377 } 379 }
378 380
379 var taskOnRedis = null; 381 var taskOnRedis = null;
380 try { 382 try {
381 taskOnRedis = JSON.parse(result); 383 taskOnRedis = JSON.parse(result);
382 } 384 }
383 catch(err1) { 385 catch(err1) {
384 cb(err1, null); 386 cb(err1, null);
385 return; 387 return;
386 } 388 }
387 389
388 cb(null, taskOnRedis); 390 cb(null, taskOnRedis);
389 }); 391 });
390 } 392 }
391 393
392 exports.start = start; 394 exports.start = start;
393 exports.topupRequest = topupRequest; 395 exports.topupRequest = topupRequest;
394 exports.prepareRemoteProductCode = prepareRemoteProductCode; 396 exports.prepareRemoteProductCode = prepareRemoteProductCode;
395 exports.paddingDestination = paddingDestination; 397 exports.paddingDestination = paddingDestination;
396 398