Commit c01126a249f16b0cebdcd9f41845f0f854e39a54

Authored by Adhidarma Hadiwinoto
1 parent e2b360a02d
Exists in master

saveTaskForDupeCheck before request

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