Commit 789684cdef5c77e27a0ca2366dfdbed417b39dcb

Authored by Adhidarma Hadiwinoto
1 parent 1ed0cc06f9
Exists in master

coba ditest

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