Commit 59492e3126774a0130f74194d23dd24fb61bb8f7

Authored by Adhidarma Hadiwinoto
1 parent 5a248c92d3
Exists in master

MSISDN not found rc 14

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

1 var fs = require('fs'); 1 var fs = require('fs');
2 var https = require('https'); 2 var https = require('https');
3 var http = require('http'); 3 var http = require('http');
4 var url = require('url'); 4 var url = require('url');
5 var request = require('request'); 5 var request = require('request');
6 var xml2js = require('xml2js').parseString; 6 var xml2js = require('xml2js').parseString;
7 var strftime = require('strftime'); 7 var strftime = require('strftime');
8 var redis = require('redis'); 8 var redis = require('redis');
9 9
10 var Router = require('node-simple-router'); 10 var Router = require('node-simple-router');
11 11
12 var winston = require('winston'); 12 var winston = require('winston');
13 13
14 var logger; 14 var logger;
15 var config; 15 var config;
16 var httpServer; 16 var httpServer;
17 var redisClient; 17 var redisClient;
18 18
19 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; 19 process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
20 20
21 var aaa; 21 var aaa;
22 22
23 var logTag = __filename.split('/').reverse()[0]; 23 var logTag = __filename.split('/').reverse()[0];
24 24
25 function getRedisKey(timestamp) { 25 function getRedisKey(timestamp) {
26 var prefix = config.globals.gateway_name; 26 var prefix = config.globals.gateway_name;
27 if (config.globals.redis_prefix) { 27 if (config.globals.redis_prefix) {
28 prefix = config.globals.redis_prefix; 28 prefix = config.globals.redis_prefix;
29 } 29 }
30 return prefix + '.ts:' + timestamp + '.rid'; 30 return prefix + '.ts:' + timestamp + '.rid';
31 } 31 }
32 32
33 function generateTimestamp(request_id) { 33 function generateTimestamp(request_id) {
34 var ts = strftime('%F %T', new Date()); 34 var ts = strftime('%F %T', new Date());
35 35
36 var key = getRedisKey(ts); 36 var key = getRedisKey(ts);
37 redisClient.set(key, request_id); 37 redisClient.set(key, request_id);
38 redisClient.expire(key, 3600*48); 38 redisClient.expire(key, 3600*48);
39 39
40 return ts; 40 return ts;
41 } 41 }
42 42
43 function topupRequest(task) { 43 function topupRequest(task) {
44 aaa.insertTaskToMongoDb(task); 44 aaa.insertTaskToMongoDb(task);
45 45
46 var ts = strftime('%F %T', new Date()); 46 var ts = strftime('%F %T', new Date());
47 ts = generateTimestamp(task['requestId']); 47 ts = generateTimestamp(task['requestId']);
48 48
49 var options = { 49 var options = {
50 url: config.h2h_out.partner, 50 url: config.h2h_out.partner,
51 qs: { 51 qs: {
52 code: task['remoteProduct'], 52 code: task['remoteProduct'],
53 msisdn: task['destination'], 53 msisdn: task['destination'],
54 user_id: config.h2h_out.userid, 54 user_id: config.h2h_out.userid,
55 password: config.h2h_out.password, 55 password: config.h2h_out.password,
56 ts: ts, 56 ts: ts,
57 ref_id: task.requestId 57 ref_id: task.requestId
58 } 58 }
59 }; 59 };
60 60
61 logger.info('Creating http request to gateway', {options: options}); 61 logger.info('Creating http request to gateway', {options: options});
62 62
63 if (aaa) { 63 if (aaa) {
64 aaa.incrementTrxCount(); 64 aaa.incrementTrxCount();
65 aaa.incrementActiveTrxCount(); 65 aaa.incrementActiveTrxCount();
66 } 66 }
67 67
68 request(options, function (error, response, body) { 68 request(options, function (error, response, body) {
69 aaa.decrementActiveTrxCount(); 69 aaa.decrementActiveTrxCount();
70 70
71 if (error) { 71 if (error) {
72 72
73 var error_message = 'Error on http connection to gateway: ' + error; 73 var error_message = 'Error on http connection to gateway: ' + error;
74 logger.warn(error_message); 74 logger.warn(error_message);
75 callbackReport(task['requestId'], '91', error_message); 75 callbackReport(task['requestId'], '91', error_message);
76 return; 76 return;
77 77
78 } 78 }
79 79
80 if (response.statusCode != 200) { 80 if (response.statusCode != 200) {
81 81
82 var error_message = 'Gateway error, http response code: ' + response.statusCode; 82 var error_message = 'Gateway error, http response code: ' + response.statusCode;
83 logger.warn(error_message); 83 logger.warn(error_message);
84 callbackReport(task['requestId'], '91', error_message); 84 callbackReport(task['requestId'], '91', error_message);
85 return; 85 return;
86 } 86 }
87 87
88 var responseCode = 40; 88 var responseCode = 40;
89 var responseMessage; 89 var responseMessage;
90 90
91 xml2js(body, function (err, result) { 91 xml2js(body, function (err, result) {
92 if (err) { 92 if (err) {
93 logger.warn('Error parsing XML', {response_error: err, response_body: body}); 93 logger.warn('Error parsing XML', {response_error: err, response_body: body});
94 callbackReport(task['requestId'], '40', body); 94 callbackReport(task['requestId'], '40', body);
95 return; 95 return;
96 } 96 }
97 97
98 logger.info('Got direct response from request', {result: result}); 98 logger.info('Got direct response from request', {result: result});
99 99
100 try { 100 try {
101 responseMessage = result.direct_ack.info[0]; 101 responseMessage = result.direct_ack.info[0];
102 102
103 if (result.direct_ack.request_status[0] == 'OK') { 103 if (result.direct_ack.request_status[0] == 'OK') {
104 responseCode = '68'; 104 responseCode = '68';
105 } else { 105 } else {
106 responseCode = '40'; 106 responseCode = '40';
107 107
108 var new_response_code = responseCodeFromMessage(responseMessage); 108 var new_response_code = responseCodeFromMessage(responseMessage);
109 if (new_response_code) { 109 if (new_response_code) {
110 responseCode = new_response_code; 110 responseCode = new_response_code;
111 } 111 }
112 112
113 } 113 }
114 114
115 } 115 }
116 catch(err) { 116 catch(err) {
117 logger.warn('Exception on parsing xml response'); 117 logger.warn('Exception on parsing xml response');
118 responseCode = 40; 118 responseCode = 40;
119 responseMessage = 'Invalid xml response from gateway'; 119 responseMessage = 'Invalid xml response from gateway';
120 } 120 }
121 121
122 callbackReport(task['requestId'], responseCode, responseMessage); 122 callbackReport(task['requestId'], responseCode, responseMessage);
123 123
124 }); 124 });
125 125
126 }); 126 });
127 } 127 }
128 128
129 function createRedisClient() { 129 function createRedisClient() {
130 redisClient = redis.createClient(config.globals.redis_port, config.globals.redis_host); 130 redisClient = redis.createClient(config.globals.redis_port, config.globals.redis_host);
131 } 131 }
132 132
133 function paddingSN(sn, _config) { 133 function paddingSN(sn, _config) {
134 134
135 if (!_config) { 135 if (!_config) {
136 _config = config; 136 _config = config;
137 } 137 }
138 138
139 if (_config.h2h_out.sn_min_length && (sn.length < Number(_config.h2h_out.sn_min_length))) { 139 if (_config.h2h_out.sn_min_length && (sn.length < Number(_config.h2h_out.sn_min_length))) {
140 sn = '0000000000000000' + sn; 140 sn = '0000000000000000' + sn;
141 sn = sn.slice(Number(_config.h2h_out.sn_min_length) * -1); 141 sn = sn.slice(Number(_config.h2h_out.sn_min_length) * -1);
142 } 142 }
143 return sn; 143 return sn;
144 } 144 }
145 145
146 function parseSN(message, _config) { 146 function parseSN(message, _config) {
147 147
148 if (!_config) { 148 if (!_config) {
149 _config = config; 149 _config = config;
150 } 150 }
151 151
152 var sn_regex = new RegExp(_config.h2h_out.sn_pattern); 152 var sn_regex = new RegExp(_config.h2h_out.sn_pattern);
153 var sn_match = message.match(sn_regex); 153 var sn_match = message.match(sn_regex);
154 154
155 if (sn_match <= 0) { 155 if (sn_match <= 0) {
156 logger.info('SN Not found: ' + message); 156 logger.info('SN Not found: ' + message);
157 return ''; 157 return '';
158 } 158 }
159 159
160 var match_index = 0; 160 var match_index = 0;
161 if (_config.h2h_out.sn_match_index) { 161 if (_config.h2h_out.sn_match_index) {
162 match_index = Number(_config.h2h_out.sn_match_index) 162 match_index = Number(_config.h2h_out.sn_match_index)
163 } 163 }
164 164
165 var sn = sn_match[match_index]; 165 var sn = sn_match[match_index];
166 166
167 if (_config.h2h_out.sn_remove_whitespace) { 167 if (_config.h2h_out.sn_remove_whitespace) {
168 sn = sn.replace(/\s/g, ''); 168 sn = sn.replace(/\s/g, '');
169 } 169 }
170 170
171 var sn_remove_patterns = _config.h2h_out.sn_remove_patterns.split(_config.h2h_out.sn_remove_patterns_separator); 171 var sn_remove_patterns = _config.h2h_out.sn_remove_patterns.split(_config.h2h_out.sn_remove_patterns_separator);
172 172
173 var count = sn_remove_patterns.length; 173 var count = sn_remove_patterns.length;
174 174
175 for(var i = 0; i < count; i++) { 175 for(var i = 0; i < count; i++) {
176 176
177 //sn = sn.replace(sn_remove_patterns[i], ''); 177 //sn = sn.replace(sn_remove_patterns[i], '');
178 178
179 var re = new RegExp(sn_remove_patterns[i], 'g'); 179 var re = new RegExp(sn_remove_patterns[i], 'g');
180 sn = sn.replace(re, ''); 180 sn = sn.replace(re, '');
181 } 181 }
182 182
183 sn = paddingSN(sn, _config); 183 sn = paddingSN(sn, _config);
184 184
185 return sn.trim(); 185 return sn.trim();
186 } 186 }
187 187
188 function createServer() { 188 function createServer() {
189 var httpServer = http.createServer(function(request, response) { 189 var httpServer = http.createServer(function(request, response) {
190 190
191 var response_code = '68'; 191 var response_code = '68';
192 var sn = ''; 192 var sn = '';
193 193
194 var qs = url.parse(request.url, true).query; 194 var qs = url.parse(request.url, true).query;
195 195
196 logger.info('Got reverse report from gateway', {qs: qs}); 196 logger.info('Got reverse report from gateway', {qs: qs});
197 197
198 if (qs.topup_status == 'S') { 198 if (qs.topup_status == 'S') {
199 response_code = '00'; 199 response_code = '00';
200 if (qs.sn && !config.h2h_out.force_parse_sn && !Number(config.h2h_out.force_parse_sn)) { 200 if (qs.sn && !config.h2h_out.force_parse_sn && !Number(config.h2h_out.force_parse_sn)) {
201 sn = qs.sn; 201 sn = qs.sn;
202 } else { 202 } else {
203 logger.warn('Missing SN from query string. Trying to get SN from message'); 203 logger.warn('Missing SN from query string. Trying to get SN from message');
204 sn = parseSN(qs.info); 204 sn = parseSN(qs.info);
205 } 205 }
206 206
207 if (config.h2h_out.sn_split_index) { 207 if (config.h2h_out.sn_split_index) {
208 sn = splitSN(sn, config); 208 sn = splitSN(sn, config);
209 } 209 }
210 210
211 if (sn) { 211 if (sn) {
212 sn = paddingSN(sn, config); 212 sn = paddingSN(sn, config);
213 } 213 }
214 214
215 sn = sn.trim(); 215 sn = sn.trim();
216 216
217 } else if (qs.topup_status == 'R') { 217 } else if (qs.topup_status == 'R') {
218 218
219 response_code = '40'; 219 response_code = '40';
220 220
221 } 221 }
222 222
223 try { 223 try {
224 224
225 var new_response_code = responseCodeFromMessage(qs.info); 225 var new_response_code = responseCodeFromMessage(qs.info);
226 if (new_response_code) { 226 if (new_response_code) {
227 response_code = new_response_code; 227 response_code = new_response_code;
228 } 228 }
229 229
230 } 230 }
231 catch(err) { 231 catch(err) {
232 logger.warn('Exception on parsing reverse report', {exception: err} ); 232 logger.warn('Exception on parsing reverse report', {exception: err} );
233 response_code = '40'; 233 response_code = '40';
234 } 234 }
235 235
236 message = qs.info; 236 message = qs.info;
237 //updateBalance(message); 237 //updateBalance(message);
238 if (sn) { 238 if (sn) {
239 message = 'SN=' + sn + '; ' + message; 239 message = 'SN=' + sn + '; ' + message;
240 } 240 }
241 241
242 response.end('OK'); 242 response.end('OK');
243 243
244 if (qs.ref_id) { 244 if (qs.ref_id) {
245 callbackReport(qs.ref_id, response_code, message); 245 callbackReport(qs.ref_id, response_code, message);
246 } else { 246 } else {
247 reverseHandlerByTs(qs.ts, response_code, message); 247 reverseHandlerByTs(qs.ts, response_code, message);
248 } 248 }
249 249
250 }); 250 });
251 251
252 httpServer.listen(config.h2h_out.listen_port, function() { 252 httpServer.listen(config.h2h_out.listen_port, function() {
253 logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port); 253 logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port);
254 }); 254 });
255 } 255 }
256 256
257 function reverseHandlerByTs(ts, responseCode, message) { 257 function reverseHandlerByTs(ts, responseCode, message) {
258 var key = getRedisKey(ts); 258 var key = getRedisKey(ts);
259 redisClient.get(key, function(err, request_id) { 259 redisClient.get(key, function(err, request_id) {
260 if (err) { 260 if (err) {
261 logger.warn('Error when requesting request id for ts:' + ts + ' (' + key + ')', {redis_error: err}); 261 logger.warn('Error when requesting request id for ts:' + ts + ' (' + key + ')', {redis_error: err});
262 return; 262 return;
263 } 263 }
264 264
265 callbackReport(request_id, responseCode, message); 265 callbackReport(request_id, responseCode, message);
266 }); 266 });
267 } 267 }
268 268
269 function splitSN(sn, _config) { 269 function splitSN(sn, _config) {
270 var sn_pieces = sn.split(' '); 270 var sn_pieces = sn.split(' ');
271 271
272 if (sn_pieces.length <= 0) { 272 if (sn_pieces.length <= 0) {
273 logger.info('Returning original SN because SN only has one element'); 273 logger.info('Returning original SN because SN only has one element');
274 return sn; 274 return sn;
275 } 275 }
276 276
277 if (!_config.h2h_out.sn_split_index) { 277 if (!_config.h2h_out.sn_split_index) {
278 logger.info('Returning original SN because config.h2h_out.sn_split_index undefined'); 278 logger.info('Returning original SN because config.h2h_out.sn_split_index undefined');
279 return sn; 279 return sn;
280 } 280 }
281 var sn_indexes = _config.h2h_out.sn_split_index.split(','); 281 var sn_indexes = _config.h2h_out.sn_split_index.split(',');
282 282
283 logger.info('Split SN', {sn_pieces: sn_pieces, sn_indexes: sn_indexes}); 283 logger.info('Split SN', {sn_pieces: sn_pieces, sn_indexes: sn_indexes});
284 284
285 var _sn = ''; 285 var _sn = '';
286 286
287 var id_count = sn_indexes.length; 287 var id_count = sn_indexes.length;
288 for(var i = 0; i < id_count; i++) { 288 for(var i = 0; i < id_count; i++) {
289 289
290 var sn_index = sn_indexes[i]; 290 var sn_index = sn_indexes[i];
291 var sn_piece = sn_pieces[sn_index]; 291 var sn_piece = sn_pieces[sn_index];
292 292
293 if (sn_pieces[i]) { 293 if (sn_pieces[i]) {
294 _sn = _sn + sn_piece; 294 _sn = _sn + sn_piece;
295 } else { 295 } else {
296 logger.warn('Undefined value on sn piece ' + sn_index); 296 logger.warn('Undefined value on sn piece ' + sn_index);
297 } 297 }
298 } 298 }
299 299
300 _sn = _sn.trim(); 300 _sn = _sn.trim();
301 301
302 if (_sn) { 302 if (_sn) {
303 sn = _sn; 303 sn = _sn;
304 logger.info('Got new SN: ' + sn); 304 logger.info('Got new SN: ' + sn);
305 } else { 305 } else {
306 logger.warn('Got empty SN when using split SN. Use original SN'); 306 logger.warn('Got empty SN when using split SN. Use original SN');
307 } 307 }
308 308
309 return sn; 309 return sn;
310 } 310 }
311 311
312 function responseCodeFromMessage(message) { 312 function responseCodeFromMessage(message) {
313 if (message.toLowerCase().indexOf('nomor salah/tidak terdaftar') >= 0) { 313 if (message.toLowerCase().indexOf('nomor salah/tidak terdaftar') >= 0) {
314 return '14'; 314 return '14';
315 } 315 }
316 else if (message.toLowerCase().indexOf('nomor tidak di temukan/tidak aktif') >= 0) { 316 else if (message.toLowerCase().indexOf('nomor tidak di temukan/tidak aktif') >= 0) {
317 return '14'; 317 return '14';
318 } 318 }
319 else if (message.toLowerCase().indexOf('kode produk tidak sesuai nomor tujuan') >= 0) { 319 else if (message.toLowerCase().indexOf('kode produk tidak sesuai nomor tujuan') >= 0) {
320 return '14'; 320 return '14';
321 } 321 }
322 else if (message.toLowerCase().indexOf('nomor yang anda masukan salah') >= 0) { 322 else if (message.toLowerCase().indexOf('nomor yang anda masukan salah') >= 0) {
323 return '14'; 323 return '14';
324 } 324 }
325 else if (message.toLowerCase().indexOf('nomor yang anda masukkan salah') >= 0) { 325 else if (message.toLowerCase().indexOf('nomor yang anda masukkan salah') >= 0) {
326 return '14'; 326 return '14';
327 } 327 }
328 else if (message.toLowerCase().indexOf('nomor telepon seluler salah') >= 0) { 328 else if (message.toLowerCase().indexOf('nomor telepon seluler salah') >= 0) {
329 return '14'; 329 return '14';
330 } 330 }
331 else if (message.indexOf('MSISDN not found') >= 0) {
332 return '14';
333 }
331 else if (message.indexOf('UNKNOWN_NUMBER') >= 0) { 334 else if (message.indexOf('UNKNOWN_NUMBER') >= 0) {
332 return '14'; 335 return '14';
333 } 336 }
334 else if (message.toLowerCase().indexOf('bulk or forbidden request') >= 0) { 337 else if (message.toLowerCase().indexOf('bulk or forbidden request') >= 0) {
335 return '55'; 338 return '55';
336 } 339 }
337 else if (message.toLowerCase().indexOf('sudah pernah dilakukan') >= 0) { 340 else if (message.toLowerCase().indexOf('sudah pernah dilakukan') >= 0) {
338 return '55'; 341 return '55';
339 } 342 }
340 else if (message.toLowerCase().indexOf('transaksi yg sama sudah pernah dilakukan tunggu dlm') >= 0) { 343 else if (message.toLowerCase().indexOf('transaksi yg sama sudah pernah dilakukan tunggu dlm') >= 0) {
341 return '55'; 344 return '55';
342 } 345 }
343 else if (message.toLowerCase().indexOf('transaksi tsb sudah pernah dilakukan') >= 0) { 346 else if (message.toLowerCase().indexOf('transaksi tsb sudah pernah dilakukan') >= 0) {
344 return '55'; 347 return '55';
345 } 348 }
346 else if (message.toLowerCase().indexOf('mohon maaf saat ini stock belum tersedia') >= 0) { 349 else if (message.toLowerCase().indexOf('mohon maaf saat ini stock belum tersedia') >= 0) {
347 return '13'; 350 return '13';
348 } 351 }
349 else if (message.toLowerCase().indexOf('stock tidak tersedia') >= 0) { 352 else if (message.toLowerCase().indexOf('stock tidak tersedia') >= 0) {
350 return '13'; 353 return '13';
351 } 354 }
352 else if (message.toLowerCase().indexOf('tidak tersedia atau nonaktif') >= 0) { 355 else if (message.toLowerCase().indexOf('tidak tersedia atau nonaktif') >= 0) {
353 return '13'; 356 return '13';
354 } 357 }
355 else if (message.toLowerCase().indexOf('saldo di account anda saat ini tidak mencukupi') >= 0) { 358 else if (message.toLowerCase().indexOf('saldo di account anda saat ini tidak mencukupi') >= 0) {
356 return '40'; 359 return '40';
357 } 360 }
358 else if (message.toLowerCase().indexOf('tidak mencukupi untuk melakukan transaksi') >= 0) { 361 else if (message.toLowerCase().indexOf('tidak mencukupi untuk melakukan transaksi') >= 0) {
359 return '40'; 362 return '40';
360 } 363 }
361 else if (message.toLowerCase().indexOf('saldo anda tidak mencukupi') >= 0) { 364 else if (message.toLowerCase().indexOf('saldo anda tidak mencukupi') >= 0) {
362 return '40'; 365 return '40';
363 } 366 }
364 else if (message.search(/stok .* tidak tersedia ke nomor .*/i) >= 0) { 367 else if (message.search(/stok .* tidak tersedia ke nomor .*/i) >= 0) {
365 return '13'; 368 return '13';
366 } 369 }
367 else if (message.search(/stok produk .* gangguan ke no tujuan/i) >= 0) { 370 else if (message.search(/stok produk .* gangguan ke no tujuan/i) >= 0) {
368 return '13'; 371 return '13';
369 } 372 }
370 else if (message.toLowerCase().indexOf('stok tidak tersedia dari pilihan2 yg tersedia') >= 0) { 373 else if (message.toLowerCase().indexOf('stok tidak tersedia dari pilihan2 yg tersedia') >= 0) {
371 return '13'; 374 return '13';
372 } 375 }
373 else if (message.search(/system sedang.* maintenance/i) >= 0) { 376 else if (message.search(/system sedang.* maintenance/i) >= 0) {
374 return '91'; 377 return '91';
375 } 378 }
376 else if (message.search(/transaksi gagal di proses, ulangi beberapa saat lagi/i) >= 0) { 379 else if (message.search(/transaksi gagal di proses, ulangi beberapa saat lagi/i) >= 0) {
377 return '40'; 380 return '40';
378 } 381 }
379 else if (message.toLowerCase().indexOf('gagal') >= 0) { 382 else if (message.toLowerCase().indexOf('gagal') >= 0) {
380 return '40'; 383 return '40';
381 } 384 }
382 else if (message.toLowerCase().indexOf('Harga belum diset') >= 0) { 385 else if (message.toLowerCase().indexOf('Harga belum diset') >= 0) {
383 return '40'; 386 return '40';
384 } 387 }
385 else if (message.toLowerCase().indexOf('stok sementara tidak tersedia') == 0) { 388 else if (message.toLowerCase().indexOf('stok sementara tidak tersedia') == 0) {
386 return '13'; 389 return '13';
387 } 390 }
388 391
389 392
390 return; 393 return;
391 } 394 }
392 395
393 function start(options) { 396 function start(options) {
394 if (!options) { 397 if (!options) {
395 console.log('Undefined options, terminating....'); 398 console.log('Undefined options, terminating....');
396 process.exit(1); 399 process.exit(1);
397 } 400 }
398 401
399 if (options.config) { 402 if (options.config) {
400 config = options.config; 403 config = options.config;
401 } else { 404 } else {
402 console.log('Undefined options.config, terminating....') 405 console.log('Undefined options.config, terminating....')
403 process.exit(1); 406 process.exit(1);
404 } 407 }
405 408
406 if (options.aaa) { 409 if (options.aaa) {
407 aaa = options.aaa; 410 aaa = options.aaa;
408 callbackReport = options.aaa.callbackReportWithPushToMongoDb; 411 callbackReport = options.aaa.callbackReportWithPushToMongoDb;
409 } else { 412 } else {
410 console.log('Undefined options.aaa, terminating....') 413 console.log('Undefined options.aaa, terminating....')
411 process.exit(1); 414 process.exit(1);
412 } 415 }
413 416
414 if (options.logger) { 417 if (options.logger) {
415 logger = options.logger; 418 logger = options.logger;
416 } else { 419 } else {
417 logger = new winston.Logger({ 420 logger = new winston.Logger({
418 transports: [ 421 transports: [
419 new (winston.transports.Console)() 422 new (winston.transports.Console)()
420 ] 423 ]
421 }); 424 });
422 } 425 }
423 426
424 createRedisClient(); 427 createRedisClient();
425 createServer(); 428 createServer();
426 } 429 }
427 430
428 exports.start = start; 431 exports.start = start;
429 exports.topupRequest = topupRequest; 432 exports.topupRequest = topupRequest;
430 exports.parseSN = parseSN; 433 exports.parseSN = parseSN;
431 434