Commit 1ed0cc06f9deb52a24f2f7ffde9260645e284784

Authored by Adhidarma Hadiwinoto
1 parent 3c1fd084ae
Exists in master

coba bajak hasil

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

1 var xmlrpc = require('xmlrpc'); 1 var xmlrpc = require('xmlrpc');
2 var url = require('url'); 2 var url = require('url');
3 var math = require('mathjs'); 3 var math = require('mathjs');
4 var winston = require('winston'); 4 var winston = require('winston');
5 var redis = require('redis'); 5 var redis = require('redis');
6 var resendDelay = require('./resend-delay.js'); 6 var resendDelay = require('./resend-delay.js');
7 var LRU = require('lru-cache'); 7 var LRU = require('lru-cache');
8 8
9 var aaa; 9 var aaa;
10 var logger; 10 var logger;
11 var config; 11 var config;
12 var _callbackReport; 12 var _callbackReport;
13 var redisClient; 13 var redisClient;
14 14
15 var taskHistory = LRU({max: 500, maxAge: 1000 * 3600 * 2}); 15 var taskHistory = LRU({max: 500, maxAge: 1000 * 3600 * 2});
16 16
17 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; 17 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
18 18
19 function callbackReport(requestId, responseCode, message) { 19 function callbackReport(requestId, responseCode, message) {
20 if (responseCode != '68') { 20 if (responseCode != '68') {
21 resendDelay.cancel(requestId); 21 resendDelay.cancel(requestId);
22 } else { 22 } else {
23 getTaskFromHistory(requestId, function(err, archivedTask) { 23 getTaskFromHistory(requestId, function(err, archivedTask) {
24 if (archivedTask) { 24 if (archivedTask) {
25 logger.verbose('DEBUG', {archivedTask: archivedTask}); 25 logger.verbose('DEBUG', {archivedTask: archivedTask});
26 resendDelay.register(archivedTask); 26 resendDelay.register(archivedTask);
27 } 27 }
28 }); 28 });
29 } 29 }
30
31 if (responseCode == '00') {
32 return;
33 }
30 _callbackReport(requestId, responseCode, message); 34 _callbackReport(requestId, responseCode, message);
31 } 35 }
32 36
33 function createRedisClient(host, port) { 37 function createRedisClient(host, port) {
34 if (!host && !port) { 38 if (!host && !port) {
35 logger.info('Not creating redis client because unspecified host or port'); 39 logger.info('Not creating redis client because unspecified host or port');
36 return; 40 return;
37 } 41 }
38 42
39 try { 43 try {
40 redisClient = redis.createClient(port, host); 44 redisClient = redis.createClient(port, host);
41 } catch(err) { 45 } catch(err) {
42 logger.warn("Error creating redis client to " + host + ':' + port); 46 logger.warn("Error creating redis client to " + host + ':' + port);
43 } 47 }
44 } 48 }
45 49
46 function topupRequest(task) { 50 function topupRequest(task) {
47 aaa.insertTaskToMongoDb(task); 51 aaa.insertTaskToMongoDb(task);
48 52
49 getTaskFromHistory(task, function(err, archivedTask) { 53 getTaskFromHistory(task, function(err, archivedTask) {
50 putTaskToHistory(task); 54 putTaskToHistory(task);
51 55
52 if (archivedTask) { 56 if (archivedTask) {
53 logger.info('Task has been executed before, going to checkStatus', {task: task, archivedTask: archivedTask}); 57 logger.info('Task has been executed before, going to checkStatus', {task: task, archivedTask: archivedTask});
54 checkStatus(task); 58 checkStatus(task);
55 } else { 59 } else {
56 _topupRequest(task); 60 _topupRequest(task);
57 } 61 }
58 }); 62 });
59 } 63 }
60 64
61 function _topupRequest(task) { 65 function _topupRequest(task) {
62 66
63 var partnerUrl = url.parse(config.h2h_out.partner); 67 var partnerUrl = url.parse(config.h2h_out.partner);
64 var clientOptions = { 68 var clientOptions = {
65 host: partnerUrl.hostname, 69 host: partnerUrl.hostname,
66 port: partnerUrl.port, 70 port: partnerUrl.port,
67 path: partnerUrl.pathname 71 path: partnerUrl.pathname
68 }; 72 };
69 logger.info('Preparing XMLRPC client options', {options: clientOptions}); 73 logger.info('Preparing XMLRPC client options', {options: clientOptions});
70 74
71 var client; 75 var client;
72 if (partnerUrl.protocol == 'https:') { 76 if (partnerUrl.protocol == 'https:') {
73 client = xmlrpc.createSecureClient(clientOptions); 77 client = xmlrpc.createSecureClient(clientOptions);
74 } else { 78 } else {
75 client = xmlrpc.createClient(clientOptions); 79 client = xmlrpc.createClient(clientOptions);
76 } 80 }
77 81
78 var params = { 82 var params = {
79 MSISDN: config.h2h_out.userid, 83 MSISDN: config.h2h_out.userid,
80 REQUESTID: task['requestId'], 84 REQUESTID: task['requestId'],
81 PIN: config.h2h_out.password, 85 PIN: config.h2h_out.password,
82 NOHP: task['destination'], 86 NOHP: task['destination'],
83 NOM: task['remoteProduct'] 87 NOM: task['remoteProduct']
84 }; 88 };
85 89
86 var methodName = 'topUpRequest'; 90 var methodName = 'topUpRequest';
87 logger.info('Preparing XMLRPC client method', {methodname: methodName, params: params}); 91 logger.info('Preparing XMLRPC client method', {methodname: methodName, params: params});
88 92
89 client.methodCall(methodName, [ params ], function (error, value) { 93 client.methodCall(methodName, [ params ], function (error, value) {
90 94
91 // Results of the method response 95 // Results of the method response
92 if (error) { 96 if (error) {
93 97
94 logger.warn('XMLRPC Client Error', {requestId: task['requestId'], errorMessage: error}); 98 logger.warn('XMLRPC Client Error', {requestId: task['requestId'], errorMessage: error});
95 callbackReport(task['requestId'], '91', 'Gangguan koneksi ke suplier: ' + error); 99 callbackReport(task['requestId'], '91', 'Gangguan koneksi ke suplier: ' + error);
96 return; 100 return;
97 } 101 }
98 102
99 logger.info('Got XMLRPC response from partner for', {response_method: methodName, response_message: value}); 103 logger.info('Got XMLRPC response from partner for', {response_method: methodName, response_message: value});
100 104
101 if (value['RESPONSECODE'] == '94') { 105 if (value['RESPONSECODE'] == '94') {
102 logger.info('Change RC 94 to 68'); 106 logger.info('Change RC 94 to 68');
103 value['RESPONSECODE'] = '68'; 107 value['RESPONSECODE'] = '68';
104 } 108 }
105 109
106 if (value['RESPONSECODE'] == '00' && config.h2h_out.parse_sn == 'YES') { 110 if (value['RESPONSECODE'] == '00' && config.h2h_out.parse_sn == 'YES') {
107 value['MESSAGE'] = 'SN=' + parseSN(value['MESSAGE']) + '; ' + value['MESSAGE']; 111 value['MESSAGE'] = 'SN=' + parseSN(value['MESSAGE']) + '; ' + value['MESSAGE'];
108 } 112 }
109 113
110 callbackReport(value['REQUESTID'], value['RESPONSECODE'], value['MESSAGE']); 114 callbackReport(value['REQUESTID'], value['RESPONSECODE'], value['MESSAGE']);
111 }); 115 });
112 } 116 }
113 117
114 function createServer() { 118 function createServer() {
115 119
116 logger.info('Creating XML-RPC server on port ' + config.h2h_out.listen_port); 120 logger.info('Creating XML-RPC server on port ' + config.h2h_out.listen_port);
117 var serverOptions = { 121 var serverOptions = {
118 port: config.h2h_out.listen_port 122 port: config.h2h_out.listen_port
119 }; 123 };
120 124
121 var server = xmlrpc.createServer(serverOptions); 125 var server = xmlrpc.createServer(serverOptions);
122 126
123 server.on('NotFound', function (method, params) { 127 server.on('NotFound', function (method, params) {
124 logger.warn('Unknown method recevied on XMLRPC server', {xmlrpc_method: method, xmlrpc_params: params}); 128 logger.warn('Unknown method recevied on XMLRPC server', {xmlrpc_method: method, xmlrpc_params: params});
125 }); 129 });
126 130
127 server.on('topUpReport', function (err, params, callback) { 131 server.on('topUpReport', function (err, params, callback) {
128 132
129 logger.info('Got XMLRPC topUpReport request from partner', {xmlrpc_method: 'topUpReport', xmlrpc_params: params}); 133 logger.info('Got XMLRPC topUpReport request from partner', {xmlrpc_method: 'topUpReport', xmlrpc_params: params});
130 134
131 var paramscount = params.length; 135 var paramscount = params.length;
132 for (var i = 0; i < paramscount; i++) { 136 for (var i = 0; i < paramscount; i++) {
133 var value = params[i]; 137 var value = params[i];
134 138
135 if (value['RESPONSECODE'] == '94') { 139 if (value['RESPONSECODE'] == '94') {
136 logger.info('Change RC 94 to 68'); 140 logger.info('Change RC 94 to 68');
137 value['RESPONSECODE'] = '68'; 141 value['RESPONSECODE'] = '68';
138 } 142 }
139 143
140 if (value['RESPONSECODE'] == '00' && config.h2h_out.parse_sn == 'YES') { 144 if (value['RESPONSECODE'] == '00' && config.h2h_out.parse_sn == 'YES') {
141 value['MESSAGE'] = 'SN=' + parseSN(value['MESSAGE']) + '; ' + value['MESSAGE']; 145 value['MESSAGE'] = 'SN=' + parseSN(value['MESSAGE']) + '; ' + value['MESSAGE'];
142 } 146 }
143 147
144 callbackReport(value['REQUESTID'], value['RESPONSECODE'], value['MESSAGE']); 148 callbackReport(value['REQUESTID'], value['RESPONSECODE'], value['MESSAGE']);
145 } 149 }
146 150
147 callback(null, 'ACK REPORT OK'); 151 callback(null, 'ACK REPORT OK');
148 }) 152 })
149 153
150 } 154 }
151 155
152 function getBalanceFromMessage(message, balance_regex) { 156 function getBalanceFromMessage(message, balance_regex) {
153 if (!balance_regex) { 157 if (!balance_regex) {
154 if (config && config.globals && config.globals.balance_regex) { 158 if (config && config.globals && config.globals.balance_regex) {
155 balance_regex = config.globals.balance_regex; 159 balance_regex = config.globals.balance_regex;
156 } 160 }
157 } 161 }
158 162
159 if (!balance_regex) { 163 if (!balance_regex) {
160 return; 164 return;
161 } 165 }
162 166
163 try { 167 try {
164 var re = new RegExp(balance_regex); 168 var re = new RegExp(balance_regex);
165 var matches = message.match(re); 169 var matches = message.match(re);
166 170
167 var result = matches[1]; 171 var result = matches[1];
168 result = result.replace(/\./g, ''); 172 result = result.replace(/\./g, '');
169 result = result.replace(/,/g, ''); 173 result = result.replace(/,/g, '');
170 174
171 175
172 return Number(result); 176 return Number(result);
173 } 177 }
174 catch(err) { 178 catch(err) {
175 return; 179 return;
176 } 180 }
177 } 181 }
178 182
179 function updateBalance(message) { 183 function updateBalance(message) {
180 var balance = getBalanceFromMessage(message); 184 var balance = getBalanceFromMessage(message);
181 if (balance) { 185 if (balance) {
182 logger.info('Balance: ' + balance); 186 logger.info('Balance: ' + balance);
183 aaa.updateBalance(balance); 187 aaa.updateBalance(balance);
184 } 188 }
185 } 189 }
186 190
187 function checkStatus(task) { 191 function checkStatus(task) {
188 var partnerUrl = url.parse(config.h2h_out.partner); 192 var partnerUrl = url.parse(config.h2h_out.partner);
189 var clientOptions = { 193 var clientOptions = {
190 host: partnerUrl.hostname 194 host: partnerUrl.hostname
191 , port: partnerUrl.port 195 , port: partnerUrl.port
192 , path: partnerUrl.pathname 196 , path: partnerUrl.pathname
193 }; 197 };
194 logger.info('XMLRPC client options:'); 198 logger.info('XMLRPC client options:');
195 logger.info(clientOptions); 199 logger.info(clientOptions);
196 200
197 var client; 201 var client;
198 if (partnerUrl.protocol == 'https:') { 202 if (partnerUrl.protocol == 'https:') {
199 client = xmlrpc.createSecureClient(clientOptions); 203 client = xmlrpc.createSecureClient(clientOptions);
200 } else { 204 } else {
201 client = xmlrpc.createClient(clientOptions); 205 client = xmlrpc.createClient(clientOptions);
202 } 206 }
203 207
204 var methodName = 'topUpInquiry'; 208 var methodName = 'topUpInquiry';
205 209
206 var params = { 210 var params = {
207 REQUESTID: task['requestId'], 211 REQUESTID: task['requestId'],
208 MSISDN: config.h2h_out.userid, 212 MSISDN: config.h2h_out.userid,
209 PIN: config.h2h_out.password, 213 PIN: config.h2h_out.password,
210 NOHP: task['destination'] 214 NOHP: task['destination']
211 }; 215 };
212 216
213 logger.info('Requesting topUpInquiry', {params: params}); 217 logger.info('Requesting topUpInquiry', {params: params});
214 218
215 client.methodCall(methodName, [ params ], function (error, value) { 219 client.methodCall(methodName, [ params ], function (error, value) {
216 // Results of the method response 220 // Results of the method response
217 if (error) { 221 if (error) {
218 logger.warn('Error requesting topUpInquiry: ', {err: error, params: params}); 222 logger.warn('Error requesting topUpInquiry: ', {err: error, params: params});
219 callbackReport(task.requestId, '68', 'Error requesting topUpInquiry: ' + error); 223 callbackReport(task.requestId, '68', 'Error requesting topUpInquiry: ' + error);
220 return; 224 return;
221 } 225 }
222 logger.info('Method response for \'' + methodName, {response: value}); 226 logger.info('Method response for \'' + methodName, {response: value});
223 227
224 callbackReport(task.requestId, value['RESPONSECODE'], value['MESSAGE']); 228 callbackReport(task.requestId, value['RESPONSECODE'], value['MESSAGE']);
225 }); 229 });
226 } 230 }
227 231
228 function start(options) { 232 function start(options) {
229 if (!options) { 233 if (!options) {
230 console.log('Undefined options, terminating....'); 234 console.log('Undefined options, terminating....');
231 process.exit(1); 235 process.exit(1);
232 } 236 }
233 237
234 if (options.config) { 238 if (options.config) {
235 config = options.config; 239 config = options.config;
236 } else { 240 } else {
237 console.log('Undefined options.config, terminating....') 241 console.log('Undefined options.config, terminating....')
238 process.exit(1); 242 process.exit(1);
239 } 243 }
240 244
241 if (options.aaa) { 245 if (options.aaa) {
242 aaa = options.aaa; 246 aaa = options.aaa;
243 _callbackReport = options.aaa.callbackReportWithPushToMongoDb; 247 _callbackReport = options.aaa.callbackReportWithPushToMongoDb;
244 } else { 248 } else {
245 console.log('Undefined options.aaa, terminating....') 249 console.log('Undefined options.aaa, terminating....')
246 process.exit(1); 250 process.exit(1);
247 } 251 }
248 252
249 if (options && options.logger) { 253 if (options && options.logger) {
250 logger = options.logger; 254 logger = options.logger;
251 } else { 255 } else {
252 logger = new winston.Logger({ 256 logger = new winston.Logger({
253 transports: [ 257 transports: [
254 new (winston.transports.Console)() 258 new (winston.transports.Console)()
255 ] 259 ]
256 }); 260 });
257 } 261 }
258 262
259 createRedisClient(config.globals.redis_host, config.globals.redis_port); 263 createRedisClient(config.globals.redis_host, config.globals.redis_port);
260 createServer(); 264 createServer();
261 265
262 resendDelay.init({ 266 resendDelay.init({
263 config: config, 267 config: config,
264 topupRequest: topupRequest, 268 topupRequest: topupRequest,
265 logger: logger 269 logger: logger
266 }); 270 });
267 } 271 }
268 272
269 function parseSN(message, _config) { 273 function parseSN(message, _config) {
270 274
271 if (!_config) { 275 if (!_config) {
272 _config = config; 276 _config = config;
273 } 277 }
274 278
275 var sn_regex = new RegExp(_config.h2h_out.sn_pattern); 279 var sn_regex = new RegExp(_config.h2h_out.sn_pattern);
276 var sn_match = message.match(sn_regex); 280 var sn_match = message.match(sn_regex);
277 281
278 if (sn_match <= 0) { 282 if (sn_match <= 0) {
279 logger.info('SN Not found: ' + message); 283 logger.info('SN Not found: ' + message);
280 return ''; 284 return '';
281 } 285 }
282 286
283 var match_index = 0; 287 var match_index = 0;
284 if (_config.h2h_out.sn_match_index) { 288 if (_config.h2h_out.sn_match_index) {
285 match_index = Number(_config.h2h_out.sn_match_index); 289 match_index = Number(_config.h2h_out.sn_match_index);
286 } 290 }
287 291
288 var sn = sn_match[match_index]; 292 var sn = sn_match[match_index];
289 293
290 if (_config.h2h_out.sn_remove_whitespace) { 294 if (_config.h2h_out.sn_remove_whitespace) {
291 sn = sn.replace(/\s/g, ''); 295 sn = sn.replace(/\s/g, '');
292 } 296 }
293 297
294 var sn_remove_patterns = []; 298 var sn_remove_patterns = [];
295 if (_config.h2h_out.sn_remove_patterns && _config.h2h_out.sn_remove_patterns_separator) { 299 if (_config.h2h_out.sn_remove_patterns && _config.h2h_out.sn_remove_patterns_separator) {
296 sn_remove_patterns = _config.h2h_out.sn_remove_patterns.split(_config.h2h_out.sn_remove_patterns_separator); 300 sn_remove_patterns = _config.h2h_out.sn_remove_patterns.split(_config.h2h_out.sn_remove_patterns_separator);
297 } 301 }
298 var count = sn_remove_patterns.length; 302 var count = sn_remove_patterns.length;
299 303
300 for(var i = 0; i < count; i++) { 304 for(var i = 0; i < count; i++) {
301 305
302 //sn = sn.replace(sn_remove_patterns[i], ''); 306 //sn = sn.replace(sn_remove_patterns[i], '');
303 307
304 var re = new RegExp(sn_remove_patterns[i], 'g'); 308 var re = new RegExp(sn_remove_patterns[i], 'g');
305 sn = sn.replace(re, ''); 309 sn = sn.replace(re, '');
306 } 310 }
307 311
308 //sn = paddingSN(sn, _config); 312 //sn = paddingSN(sn, _config);
309 313
310 return sn.trim(); 314 return sn.trim();
311 } 315 }
312 316
313 function getTaskKey(task, chipInfo) { 317 function getTaskKey(task, chipInfo) {
314 var requestId; 318 var requestId;
315 319
316 if (typeof task === 'string') { 320 if (typeof task === 'string') {
317 requestId = task; 321 requestId = task;
318 } else { 322 } else {
319 try { 323 try {
320 requestId = task.requestId; 324 requestId = task.requestId;
321 } 325 }
322 catch(e) { 326 catch(e) {
323 logger.warn('Something wrong', {task: task}); 327 logger.warn('Something wrong', {task: task});
324 console.trace('Cekidot'); 328 console.trace('Cekidot');
325 process.exit(1); 329 process.exit(1);
326 } 330 }
327 331
328 } 332 }
329 333
330 if (!chipInfo && config && config.globals && config.globals.gateway_name) { 334 if (!chipInfo && config && config.globals && config.globals.gateway_name) {
331 chipInfo = config.globals.gateway_name; 335 chipInfo = config.globals.gateway_name;
332 } 336 }
333 337
334 return chipInfo + '.hitachi.rid:' + requestId; 338 return chipInfo + '.hitachi.rid:' + requestId;
335 } 339 }
336 340
337 341
338 function putTaskToHistory(task, cb) { 342 function putTaskToHistory(task, cb) {
339 var key = getTaskKey(task, config.globals.gateway_name); 343 var key = getTaskKey(task, config.globals.gateway_name);
340 logger.verbose('Saving task to history LRU', {key: key, task: task}); 344 logger.verbose('Saving task to history LRU', {key: key, task: task});
341 345
342 try { 346 try {
343 taskHistory.set(key, JSON.parse(JSON.stringify(task))); 347 taskHistory.set(key, JSON.parse(JSON.stringify(task)));
344 } catch (e) { } 348 } catch (e) { }
345 349
346 putTaskToRedis(task, cb); 350 putTaskToRedis(task, cb);
347 } 351 }
348 352
349 function putTaskToRedis(task, cb) { 353 function putTaskToRedis(task, cb) {
350 if (!redisClient) { 354 if (!redisClient) {
351 logger.verbose('Not saving to redis because of undefined redisClient') 355 logger.verbose('Not saving to redis because of undefined redisClient')
352 if (cb) { cb(); } 356 if (cb) { cb(); }
353 return; 357 return;
354 } 358 }
355 359
356 var key = getTaskKey(task, config.globals.gateway_name); 360 var key = getTaskKey(task, config.globals.gateway_name);
357 logger.verbose('Saving task to redis', {key: key, task: task}); 361 logger.verbose('Saving task to redis', {key: key, task: task});
358 362
359 redisClient.set(key, JSON.stringify(task), function() { 363 redisClient.set(key, JSON.stringify(task), function() {
360 redisClient.expire(key, 3600*24*30); 364 redisClient.expire(key, 3600*24*30);
361 if (cb) { 365 if (cb) {
362 cb(); 366 cb();
363 } 367 }
364 }); 368 });
365 } 369 }
366 370
367 function getTaskFromHistory(task, cb) { 371 function getTaskFromHistory(task, cb) {
368 logger.verbose('Getting task from history', {task: task}); 372 logger.verbose('Getting task from history', {task: task});
369 var key = getTaskKey(task, config.globals.gateway_name); 373 var key = getTaskKey(task, config.globals.gateway_name);
370 var archive = taskHistory.get(key); 374 var archive = taskHistory.get(key);
371 375
372 if (archive) { 376 if (archive) {
373 if (cb) { cb(null, archive); } 377 if (cb) { cb(null, archive); }
374 } 378 }
375 else { 379 else {
376 getTaskFromRedis(task, cb); 380 getTaskFromRedis(task, cb);
377 } 381 }
378 } 382 }
379 383
380 function getTaskFromRedis(task, cb) { 384 function getTaskFromRedis(task, cb) {
381 if (!redisClient) { 385 if (!redisClient) {
382 if (cb) { cb(null, null); } 386 if (cb) { cb(null, null); }
383 return; 387 return;
384 } 388 }
385 389
386 var key = getTaskKey(task, config.globals.gateway_name); 390 var key = getTaskKey(task, config.globals.gateway_name);
387 redisClient.get(key, function(err, result) { 391 redisClient.get(key, function(err, result) {
388 if (err) { 392 if (err) {
389 logger.warn('Error retrieving task from redis', {err: err}); 393 logger.warn('Error retrieving task from redis', {err: err});
390 cb(err, null); 394 cb(err, null);
391 return; 395 return;
392 } 396 }
393 397
394 var task; 398 var task;
395 try { 399 try {
396 task = JSON.parse(result); 400 task = JSON.parse(result);
397 } 401 }
398 catch(e) { 402 catch(e) {
399 logger.warn('Exception on parsing redis result as a json', {err: e}); 403 logger.warn('Exception on parsing redis result as a json', {err: e});
400 } 404 }
401 405
402 cb(null, task); 406 cb(null, task);
403 }) 407 })
404 } 408 }
405 409
406 exports.start = start; 410 exports.start = start;
407 exports.topupRequest = topupRequest; 411 exports.topupRequest = topupRequest;
408 exports.getBalanceFromMessage = getBalanceFromMessage; 412 exports.getBalanceFromMessage = getBalanceFromMessage;
409 exports.checkStatus = checkStatus; 413 exports.checkStatus = checkStatus;
410 414