Commit 4c6bd69790eccd1714826babe302b5f45f0a0731
1 parent
816ab0c381
Exists in
master
topupStatus
Showing 2 changed files with 176 additions and 10 deletions Side-by-side Diff
package.json
... | ... | @@ -21,6 +21,7 @@ |
21 | 21 | "author": "Adhidarma Hadiwinoto <me@adhisimon.org>", |
22 | 22 | "license": "ISC", |
23 | 23 | "dependencies": { |
24 | + "redis": "^2.6.2", | |
24 | 25 | "request": "^2.74.0", |
25 | 26 | "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git", |
26 | 27 | "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git", |
partner-fm.js
1 | 1 | var xml2js = require('xml2js'); |
2 | 2 | var request = require('request'); |
3 | 3 | var http = require('http'); |
4 | +var redis = require('redis'); | |
5 | +var resendDelay = require('sate24/resend-delay.js') | |
4 | 6 | |
5 | 7 | var aaa; |
6 | 8 | var _callbackReport; |
7 | 9 | var config; |
8 | 10 | var logger; |
11 | +var redisClient; | |
9 | 12 | |
10 | 13 | var xmlBuilder = new xml2js.Builder(); |
11 | 14 | |
... | ... | @@ -37,21 +40,34 @@ function start(options) { |
37 | 40 | process.exit(1); |
38 | 41 | } |
39 | 42 | |
43 | + createRedisClient(config.globals.redis_host, config.globals.redis_port); | |
40 | 44 | createServer(); |
41 | 45 | |
42 | - /* | |
43 | 46 | resendDelay.init({ |
44 | 47 | config: config, |
45 | - topupRequest: topupRequest, | |
48 | + topupRequest: topupStatus, | |
46 | 49 | logger: logger |
47 | 50 | }); |
48 | - */ | |
49 | 51 | } |
50 | 52 | |
51 | 53 | function topupRequest(task) { |
52 | 54 | aaa.insertTaskToMongoDb(task); |
53 | 55 | |
54 | - var payload = composeTopupStatusMessage( | |
56 | + getTaskFromHistory(task, function(err, archivedTask) { | |
57 | + putTaskToHistory(task); | |
58 | + | |
59 | + if (archivedTask) { | |
60 | + logger.info('Task has been executed before, going to checkStatus', {task: task, archivedTask: archivedTask}); | |
61 | + topupStatus(task); | |
62 | + } else { | |
63 | + _topupRequest(task); | |
64 | + } | |
65 | + }); | |
66 | +} | |
67 | + | |
68 | +function _topupRequest(task) { | |
69 | + | |
70 | + var payload = composeTopupMessage( | |
55 | 71 | config.h2h_out.pin, |
56 | 72 | task.remoteProduct, |
57 | 73 | task.destination, |
... | ... | @@ -64,20 +80,48 @@ function topupRequest(task) { |
64 | 80 | body: payload, |
65 | 81 | headers: { |
66 | 82 | 'Content-Type': 'text/xml', |
67 | - //'Content-Length': Buffer.byteLength(payload) | |
68 | 83 | } |
69 | 84 | }; |
70 | 85 | |
71 | - logger.verbose('Requesting to partner', {reqOpts: reqOpts, payload: payload}); | |
86 | + logger.verbose('Requesting TOPUP to partner', {reqOpts: reqOpts, payload: payload}); | |
87 | + request(reqOpts, function (err, response, body) { | |
88 | + if (err) { | |
89 | + var msg = 'Error requesting TOPUP to partner: ' + err; | |
90 | + logger.warn(msg, {task: task, err: err}); | |
91 | + callbackReport(task.requestId, '68', msg); | |
92 | + return; | |
93 | + } | |
94 | + | |
95 | + logger.verbose('Got a direct response from TOPUP', {response: body, task: task}); | |
96 | + topupResponseHandler(body, task.requestId, callbackReport); | |
97 | + }); | |
98 | +} | |
99 | + | |
100 | +function topupStatus(task) { | |
101 | + var payload = composeTopupStatusMessage( | |
102 | + config.h2h_out.pin, | |
103 | + task.requestId | |
104 | + ); | |
105 | + | |
106 | + var reqOpts = { | |
107 | + url: config.h2h_out.partner, | |
108 | + method: "POST", | |
109 | + body: payload, | |
110 | + headers: { | |
111 | + 'Content-Type': 'text/xml', | |
112 | + } | |
113 | + }; | |
114 | + | |
115 | + logger.verbose('Requesting TOPUPSTATUS to partner', {reqOpts: reqOpts, payload: payload}); | |
72 | 116 | request(reqOpts, function (err, response, body) { |
73 | 117 | if (err) { |
74 | - var msg = 'Error requesting to partner: ' + err; | |
118 | + var msg = 'Error requesting TOPUPSTATUS to partner: ' + err; | |
75 | 119 | logger.warn(msg, {task: task, err: err}); |
76 | 120 | callbackReport(task.requestId, '68', msg); |
77 | 121 | return; |
78 | 122 | } |
79 | 123 | |
80 | - logger.verbose('Got a direct response from partner', {response: body, task: task}); | |
124 | + logger.verbose('Got a direct response from TOPUPSTATUS', {response: body, task: task}); | |
81 | 125 | topupResponseHandler(body, task.requestId, callbackReport); |
82 | 126 | }); |
83 | 127 | } |
... | ... | @@ -162,7 +206,7 @@ function modifyMessageWithSn(msg) { |
162 | 206 | return msg; |
163 | 207 | } |
164 | 208 | |
165 | -function composeTopupStatusMessage(pin, product, destination, requestId) { | |
209 | +function composeTopupMessage(pin, product, destination, requestId) { | |
166 | 210 | var data = {fm: { |
167 | 211 | command: 'TOPUP', |
168 | 212 | pin: pin, |
... | ... | @@ -174,6 +218,16 @@ function composeTopupStatusMessage(pin, product, destination, requestId) { |
174 | 218 | return xmlBuilder.buildObject(data); |
175 | 219 | } |
176 | 220 | |
221 | +function composeTopupStatusMessage(pin, requestId) { | |
222 | + var data = {fm: { | |
223 | + command: 'TOPUPSTATUS', | |
224 | + pin: pin, | |
225 | + refTrxid: requestId | |
226 | + }} | |
227 | + | |
228 | + return xmlBuilder.buildObject(data); | |
229 | +} | |
230 | + | |
177 | 231 | function createServer() { |
178 | 232 | var httpServer = http.createServer(function(request, response) { |
179 | 233 | |
... | ... | @@ -199,8 +253,119 @@ function createServer() { |
199 | 253 | }); |
200 | 254 | } |
201 | 255 | |
256 | +function createRedisClient(host, port) { | |
257 | + if (!host && !port) { | |
258 | + logger.info('Not creating redis client because unspecified host or port'); | |
259 | + return; | |
260 | + } | |
261 | + | |
262 | + try { | |
263 | + redisClient = redis.createClient(port, host); | |
264 | + } catch(err) { | |
265 | + logger.warn("Error creating redis client to " + host + ':' + port); | |
266 | + } | |
267 | +} | |
268 | + | |
269 | +function getTaskKey(task, chipInfo) { | |
270 | + var requestId; | |
271 | + | |
272 | + if (typeof task === 'string') { | |
273 | + requestId = task; | |
274 | + } else { | |
275 | + try { | |
276 | + requestId = task.requestId; | |
277 | + } | |
278 | + catch(e) { | |
279 | + logger.warn('Something wrong', {task: task}); | |
280 | + console.trace('Cekidot'); | |
281 | + process.exit(1); | |
282 | + } | |
283 | + | |
284 | + } | |
285 | + | |
286 | + if (!chipInfo && config && config.globals && config.globals.gateway_name) { | |
287 | + chipInfo = config.globals.gateway_name; | |
288 | + } | |
289 | + | |
290 | + return chipInfo + '.hitachi.rid:' + requestId; | |
291 | +} | |
292 | + | |
293 | + | |
294 | +function putTaskToHistory(task, cb) { | |
295 | + if (Number(config.globals.no_dupe_check)) { | |
296 | + if (cb) { cb(); } | |
297 | + return; | |
298 | + } | |
299 | + var key = getTaskKey(task, config.globals.gateway_name); | |
300 | + logger.verbose('Saving task to history LRU', {key: key, task: task}); | |
301 | + | |
302 | + try { | |
303 | + taskHistory.set(key, JSON.parse(JSON.stringify(task))); | |
304 | + } catch (e) { } | |
305 | + | |
306 | + putTaskToRedis(task, cb); | |
307 | +} | |
308 | + | |
309 | +function putTaskToRedis(task, cb) { | |
310 | + if (!redisClient) { | |
311 | + logger.verbose('Not saving to redis because of undefined redisClient') | |
312 | + if (cb) { cb(); } | |
313 | + return; | |
314 | + } | |
315 | + | |
316 | + var key = getTaskKey(task, config.globals.gateway_name); | |
317 | + logger.verbose('Saving task to redis', {key: key, task: task}); | |
318 | + | |
319 | + redisClient.set(key, JSON.stringify(task), function() { | |
320 | + redisClient.expire(key, 3600*24*30); | |
321 | + if (cb) { | |
322 | + cb(); | |
323 | + } | |
324 | + }); | |
325 | +} | |
326 | + | |
327 | +function getTaskFromHistory(task, cb) { | |
328 | + logger.verbose('Getting task from history', {task: task}); | |
329 | + var key = getTaskKey(task, config.globals.gateway_name); | |
330 | + var archive = taskHistory.get(key); | |
331 | + | |
332 | + if (archive) { | |
333 | + if (cb) { cb(null, archive); } | |
334 | + } | |
335 | + else { | |
336 | + getTaskFromRedis(task, cb); | |
337 | + } | |
338 | +} | |
339 | + | |
340 | +function getTaskFromRedis(task, cb) { | |
341 | + if (!redisClient) { | |
342 | + if (cb) { cb(null, null); } | |
343 | + return; | |
344 | + } | |
345 | + | |
346 | + var key = getTaskKey(task, config.globals.gateway_name); | |
347 | + redisClient.get(key, function(err, result) { | |
348 | + if (err) { | |
349 | + logger.warn('Error retrieving task from redis', {err: err}); | |
350 | + cb(err, null); | |
351 | + return; | |
352 | + } | |
353 | + | |
354 | + var task; | |
355 | + try { | |
356 | + task = JSON.parse(result); | |
357 | + } | |
358 | + catch(e) { | |
359 | + logger.warn('Exception on parsing redis result as a json', {err: e}); | |
360 | + } | |
361 | + | |
362 | + cb(null, task); | |
363 | + }) | |
364 | +} | |
365 | + | |
366 | + | |
202 | 367 | exports.start = start; |
203 | 368 | exports.topupRequest = topupRequest; |
204 | -exports.composeTopupStatusMessage = composeTopupStatusMessage; | |
369 | +exports.composeTopupMessage = composeTopupMessage; | |
205 | 370 | exports.getSnFromMessage = getSnFromMessage; |
206 | 371 | exports.modifyMessageWithSn = modifyMessageWithSn; |