diff --git a/package.json b/package.json index 41c57d5..6bad3dc 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "author": "Adhidarma Hadiwinoto <me@adhisimon.org>", "license": "ISC", "dependencies": { + "redis": "^2.6.2", "request": "^2.74.0", "sate24": "git+http://gitlab.kodesumber.com/reload97/node-sate24.git", "sate24-expresso": "git+http://gitlab.kodesumber.com/reload97/sate24-expresso.git", diff --git a/partner-fm.js b/partner-fm.js index 80514bf..5852699 100644 --- a/partner-fm.js +++ b/partner-fm.js @@ -1,11 +1,14 @@ var xml2js = require('xml2js'); var request = require('request'); var http = require('http'); +var redis = require('redis'); +var resendDelay = require('sate24/resend-delay.js') var aaa; var _callbackReport; var config; var logger; +var redisClient; var xmlBuilder = new xml2js.Builder(); @@ -37,21 +40,34 @@ function start(options) { process.exit(1); } + createRedisClient(config.globals.redis_host, config.globals.redis_port); createServer(); - /* resendDelay.init({ config: config, - topupRequest: topupRequest, + topupRequest: topupStatus, logger: logger }); - */ } function topupRequest(task) { aaa.insertTaskToMongoDb(task); - var payload = composeTopupStatusMessage( + getTaskFromHistory(task, function(err, archivedTask) { + putTaskToHistory(task); + + if (archivedTask) { + logger.info('Task has been executed before, going to checkStatus', {task: task, archivedTask: archivedTask}); + topupStatus(task); + } else { + _topupRequest(task); + } + }); +} + +function _topupRequest(task) { + + var payload = composeTopupMessage( config.h2h_out.pin, task.remoteProduct, task.destination, @@ -64,20 +80,48 @@ function topupRequest(task) { body: payload, headers: { 'Content-Type': 'text/xml', - //'Content-Length': Buffer.byteLength(payload) } }; - logger.verbose('Requesting to partner', {reqOpts: reqOpts, payload: payload}); + logger.verbose('Requesting TOPUP to partner', {reqOpts: reqOpts, payload: payload}); + request(reqOpts, function (err, response, body) { + if (err) { + var msg = 'Error requesting TOPUP to partner: ' + err; + logger.warn(msg, {task: task, err: err}); + callbackReport(task.requestId, '68', msg); + return; + } + + logger.verbose('Got a direct response from TOPUP', {response: body, task: task}); + topupResponseHandler(body, task.requestId, callbackReport); + }); +} + +function topupStatus(task) { + var payload = composeTopupStatusMessage( + config.h2h_out.pin, + task.requestId + ); + + var reqOpts = { + url: config.h2h_out.partner, + method: "POST", + body: payload, + headers: { + 'Content-Type': 'text/xml', + } + }; + + logger.verbose('Requesting TOPUPSTATUS to partner', {reqOpts: reqOpts, payload: payload}); request(reqOpts, function (err, response, body) { if (err) { - var msg = 'Error requesting to partner: ' + err; + var msg = 'Error requesting TOPUPSTATUS to partner: ' + err; logger.warn(msg, {task: task, err: err}); callbackReport(task.requestId, '68', msg); return; } - logger.verbose('Got a direct response from partner', {response: body, task: task}); + logger.verbose('Got a direct response from TOPUPSTATUS', {response: body, task: task}); topupResponseHandler(body, task.requestId, callbackReport); }); } @@ -162,7 +206,7 @@ function modifyMessageWithSn(msg) { return msg; } -function composeTopupStatusMessage(pin, product, destination, requestId) { +function composeTopupMessage(pin, product, destination, requestId) { var data = {fm: { command: 'TOPUP', pin: pin, @@ -174,6 +218,16 @@ function composeTopupStatusMessage(pin, product, destination, requestId) { return xmlBuilder.buildObject(data); } +function composeTopupStatusMessage(pin, requestId) { + var data = {fm: { + command: 'TOPUPSTATUS', + pin: pin, + refTrxid: requestId + }} + + return xmlBuilder.buildObject(data); +} + function createServer() { var httpServer = http.createServer(function(request, response) { @@ -199,8 +253,119 @@ function createServer() { }); } +function createRedisClient(host, port) { + if (!host && !port) { + logger.info('Not creating redis client because unspecified host or port'); + return; + } + + try { + redisClient = redis.createClient(port, host); + } catch(err) { + logger.warn("Error creating redis client to " + host + ':' + port); + } +} + +function getTaskKey(task, chipInfo) { + var requestId; + + if (typeof task === 'string') { + requestId = task; + } else { + try { + requestId = task.requestId; + } + catch(e) { + logger.warn('Something wrong', {task: task}); + console.trace('Cekidot'); + process.exit(1); + } + + } + + if (!chipInfo && config && config.globals && config.globals.gateway_name) { + chipInfo = config.globals.gateway_name; + } + + return chipInfo + '.hitachi.rid:' + requestId; +} + + +function putTaskToHistory(task, cb) { + if (Number(config.globals.no_dupe_check)) { + if (cb) { cb(); } + return; + } + var key = getTaskKey(task, config.globals.gateway_name); + logger.verbose('Saving task to history LRU', {key: key, task: task}); + + try { + taskHistory.set(key, JSON.parse(JSON.stringify(task))); + } catch (e) { } + + putTaskToRedis(task, cb); +} + +function putTaskToRedis(task, cb) { + if (!redisClient) { + logger.verbose('Not saving to redis because of undefined redisClient') + if (cb) { cb(); } + return; + } + + var key = getTaskKey(task, config.globals.gateway_name); + logger.verbose('Saving task to redis', {key: key, task: task}); + + redisClient.set(key, JSON.stringify(task), function() { + redisClient.expire(key, 3600*24*30); + if (cb) { + cb(); + } + }); +} + +function getTaskFromHistory(task, cb) { + logger.verbose('Getting task from history', {task: task}); + var key = getTaskKey(task, config.globals.gateway_name); + var archive = taskHistory.get(key); + + if (archive) { + if (cb) { cb(null, archive); } + } + else { + getTaskFromRedis(task, cb); + } +} + +function getTaskFromRedis(task, cb) { + if (!redisClient) { + if (cb) { cb(null, null); } + return; + } + + var key = getTaskKey(task, config.globals.gateway_name); + redisClient.get(key, function(err, result) { + if (err) { + logger.warn('Error retrieving task from redis', {err: err}); + cb(err, null); + return; + } + + var task; + try { + task = JSON.parse(result); + } + catch(e) { + logger.warn('Exception on parsing redis result as a json', {err: e}); + } + + cb(null, task); + }) +} + + exports.start = start; exports.topupRequest = topupRequest; -exports.composeTopupStatusMessage = composeTopupStatusMessage; +exports.composeTopupMessage = composeTopupMessage; exports.getSnFromMessage = getSnFromMessage; exports.modifyMessageWithSn = modifyMessageWithSn;