From fb2ba8c5da083cb5d9558773bf7ffb2a0a81fcaf Mon Sep 17 00:00:00 2001 From: Adhidarma Hadiwinoto <gua@adhisimon.org> Date: Wed, 21 Mar 2018 16:26:27 +0700 Subject: [PATCH] ready to run --- .gitignore | 4 +++ README | 1 + config.sample.json | 21 ++++++++++++ index.js | 8 +++++ lib/partner-rc.json | 8 +++++ lib/partner.js | 92 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/reverse-report.js | 50 ++++++++++++++++++++++++++++ lib/st24.js | 35 ++++++++++++++++++++ package.json | 28 ++++++++++++++++ 9 files changed, 247 insertions(+) create mode 100644 .gitignore create mode 100644 config.sample.json create mode 100644 index.js create mode 100644 lib/partner-rc.json create mode 100644 lib/partner.js create mode 100644 lib/reverse-report.js create mode 100644 lib/st24.js create mode 100644 package.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8e2eaef --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/node_modules/ +/config.json +/tmp/ +/logs/ diff --git a/README b/README index e69de29..2b2d50a 100644 --- a/README +++ b/README @@ -0,0 +1 @@ +Komodo gateway to ST24 XML-RPC diff --git a/config.sample.json b/config.sample.json new file mode 100644 index 0000000..a83de93 --- /dev/null +++ b/config.sample.json @@ -0,0 +1,21 @@ +{ + "handler_name": "ST24", + "products": [ + "PLEASE_CHANGE_ME" + ], + "core_url": "http://127.0.0.1:32972/apikey/PLEASE_CHANGE_ME", + "pull_interval_ms": 1000, + "partner": { + "url": "https://PLEASE_CHANGE_ME:6789/", + "msidn": "PLEASE_CHANGE_ME", + "pin": "PLEASE_CHANGE_ME" + }, + "remote_products": { + "PLEASE_CHANGE_ME": "PLEASE_CHANGE_ME" + }, + "reverse_report_port": 27440, + "control_panel": { + "listen_port": 27441 + }, + "do_not_verbose_log_report": true +} diff --git a/index.js b/index.js new file mode 100644 index 0000000..0d9322b --- /dev/null +++ b/index.js @@ -0,0 +1,8 @@ +"use strict"; +process.chdir(__dirname); + +const pullgw = require('komodo-sdk/gateway/pull'); +const partner = require('./lib/partner'); +const reverseReport = require('./lib/reverse-report'); + +pullgw.setPartner(partner); diff --git a/lib/partner-rc.json b/lib/partner-rc.json new file mode 100644 index 0000000..0a109e8 --- /dev/null +++ b/lib/partner-rc.json @@ -0,0 +1,8 @@ +{ + "00": "00", + "13": "90", + "14": "14", + "68": "68", + "91": "90", + "94": "68" +} diff --git a/lib/partner.js b/lib/partner.js new file mode 100644 index 0000000..57ef0b0 --- /dev/null +++ b/lib/partner.js @@ -0,0 +1,92 @@ +"use strict"; + +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; + +const url = require('url'); +const xmlrpc = require('xmlrpc'); + +const config = require('komodo-sdk/config'); +const logger = require('komodo-sdk/logger'); +const matrix = require('komodo-sdk/matrix'); +const pull = require('komodo-sdk/gateway/pull'); + +const st24 = require('./st24'); +const partnerRc = require('./partner-rc.json'); + +function buy(task) { + const partnerUrl = url.parse(config.partner.url); + const clientOptions = { + host: partnerUrl.hostname, + port: partnerUrl.port, + path: partnerUrl.pathname + }; + + let client; + if (partnerUrl.protocol == 'https:') { + client = xmlrpc.createSecureClient(clientOptions); + } else { + client = xmlrpc.createClient(clientOptions); + } + + const params = { + MSISDN: config.partner.msisdn || config.partner.userid, + REQUESTID: task.trx_id, + PIN: config.partner.pin || config.partner.password, + NOHP: task.destination, + NOM: task.remote_product + }; + + const xmlrpcMethod = 'topUpRequest'; + logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: partnerUrl.href}); + + client.methodCall(xmlrpcMethod, [ params ], function (err, value) { + + if (err) { + let rc = '68'; + let msg = 'XMLRPC Client Error: ' + err; + + if (error.code == 'ECONNREFUSED' || error.code == 'EHOSTUNREACH' || (error.code == 'ETIMEDOUT' && error.syscall == "connect")) { + rc = '91'; + } + + logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err}); + report({ + trx_id: task.trx_id, + rc: rc, + message: 'INTERNAL: ' + msg, + misc: { + task: task + } + }); + + return; + } + + logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value}); + matrix.last_topupRequest_ack = value; + + report({ + trx_id: task.trx_id, + rc: partnerRc[value.RESPONSECODE] || '40', + message: value.MESSAGE, + sn: value.SN || st24.extractSnFromMessage(value.MESSAGE), + amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE), + raw: value, + misc: { + task: task + } + }); + }); +} + +function advice(task) { +} + +function report(data) { + matrix.last_report_to_core = data; + pull.report(data); +} + +exports.buy = buy; +exports.advice = advice; +exports.report = report; diff --git a/lib/reverse-report.js b/lib/reverse-report.js new file mode 100644 index 0000000..3101899 --- /dev/null +++ b/lib/reverse-report.js @@ -0,0 +1,50 @@ +"use strict"; + +const xmlrpc = require('xmlrpc'); + +const config = require('komodo-sdk/config'); +const logger = require('komodo-sdk/logger'); +const matrix = require('komodo-sdk/matrix'); +const pull = require('komodo-sdk/gateway/pull'); + +const st24 = require('./st24'); +const partner = require('./partner'); +const partnerRc = require('./partner-rc.json'); + +function create() { + const server = xmlrpc.createServer({ + port: config.reverse_report_port + }); + + logger.info('Reverse report server listen on port ' + config.reverse_report_port); + + server.on('NotFound', function (method, params) { + logger.warn('REVERSEREPORT: Unknown method recevied on XMLRPC server', {method: method, params: params}); + }); + + server.on('topUpReport', function (err, params, callback) { + + logger.info('REVERSEREPORT: Got XMLRPC topUpReport request from partner', {method: 'topUpReport', params: params}); + matrix.last_topupReport_params = params; + + const paramsCount = params.length; + for (let i = 0; i < paramsCount; i++) { + let value = params[i]; + + partner.report({ + trx_id: value.REQUESTID, + rc: partnerRc[value.RESPONSECODE] || '40', + message: value.MESSAGE, + sn: value.SN || st24.extractSnFromMessage(value.MESSAGE), + amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE), + raw: value, + misc: { + } + }); + } + + callback(null, 'ACK REPORT OK'); + }) +} + +create(); diff --git a/lib/st24.js b/lib/st24.js new file mode 100644 index 0000000..bd5b311 --- /dev/null +++ b/lib/st24.js @@ -0,0 +1,35 @@ +"use strict"; + +function extractSnFromMessage(msg) { + if (!msg || typeof msg !== 'string') { + return; + } + + let match = msg.match(/^SN=(.*?);/); + if (!match || match.length < 2) { + return; + } + + return match[1]; +} + +function extractPriceFromMsg(msg) { + if (!msg || typeof msg !== 'string') { + return; + } + + let match = msg.match(/\d,HRG=(.*?),ID=/); + if (!match || match.length < 2) { + return; + } + + if (!match[1]) { + return; + } + + return parseInt(match[1].replace(/\./g, '')); +} + + +exports.extractSnFromMessage = extractSnFromMessage; +exports.extractPriceFromMsg = extractPriceFromMsg; diff --git a/package.json b/package.json new file mode 100644 index 0000000..7fa8604 --- /dev/null +++ b/package.json @@ -0,0 +1,28 @@ +{ + "name": "komodo-gw-st24", + "version": "0.1.0", + "description": "Komodo Gateway to ST24 XML-RPC", + "main": "index.js", + "scripts": { + "test": "mocha", + "postversion": "git push && git push --tags" + }, + "repository": { + "type": "git", + "url": "git@gitlab.kodesumber.com:komodo/komodo-gw-st24.git" + }, + "keywords": [ + "komodo", + "tektrans", + "ppob", + "st24", + "xmlrpc", + "xml-rpc" + ], + "author": "Adhidarma Hadiwinoto <me@adhisimon.org>", + "license": "ISC", + "dependencies": { + "komodo-sdk": "git+http://gitlab.kodesumber.com/komodo/komodo-sdk.git", + "xmlrpc": "^1.3.2" + } +} -- 1.9.0