Commit fb2ba8c5da083cb5d9558773bf7ffb2a0a81fcaf

Authored by Adhidarma Hadiwinoto
1 parent d0cd029e97
Exists in master

ready to run

Showing 9 changed files with 247 additions and 0 deletions Side-by-side Diff

... ... @@ -0,0 +1,4 @@
  1 +/node_modules/
  2 +/config.json
  3 +/tmp/
  4 +/logs/
... ... @@ -0,0 +1 @@
  1 +Komodo gateway to ST24 XML-RPC
... ... @@ -0,0 +1,21 @@
  1 +{
  2 + "handler_name": "ST24",
  3 + "products": [
  4 + "PLEASE_CHANGE_ME"
  5 + ],
  6 + "core_url": "http://127.0.0.1:32972/apikey/PLEASE_CHANGE_ME",
  7 + "pull_interval_ms": 1000,
  8 + "partner": {
  9 + "url": "https://PLEASE_CHANGE_ME:6789/",
  10 + "msidn": "PLEASE_CHANGE_ME",
  11 + "pin": "PLEASE_CHANGE_ME"
  12 + },
  13 + "remote_products": {
  14 + "PLEASE_CHANGE_ME": "PLEASE_CHANGE_ME"
  15 + },
  16 + "reverse_report_port": 27440,
  17 + "control_panel": {
  18 + "listen_port": 27441
  19 + },
  20 + "do_not_verbose_log_report": true
  21 +}
... ... @@ -0,0 +1,8 @@
  1 +"use strict";
  2 +process.chdir(__dirname);
  3 +
  4 +const pullgw = require('komodo-sdk/gateway/pull');
  5 +const partner = require('./lib/partner');
  6 +const reverseReport = require('./lib/reverse-report');
  7 +
  8 +pullgw.setPartner(partner);
... ... @@ -0,0 +1,8 @@
  1 +{
  2 + "00": "00",
  3 + "13": "90",
  4 + "14": "14",
  5 + "68": "68",
  6 + "91": "90",
  7 + "94": "68"
  8 +}
... ... @@ -0,0 +1,92 @@
  1 +"use strict";
  2 +
  3 +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0';
  4 +
  5 +const url = require('url');
  6 +const xmlrpc = require('xmlrpc');
  7 +
  8 +const config = require('komodo-sdk/config');
  9 +const logger = require('komodo-sdk/logger');
  10 +const matrix = require('komodo-sdk/matrix');
  11 +const pull = require('komodo-sdk/gateway/pull');
  12 +
  13 +const st24 = require('./st24');
  14 +const partnerRc = require('./partner-rc.json');
  15 +
  16 +function buy(task) {
  17 + const partnerUrl = url.parse(config.partner.url);
  18 + const clientOptions = {
  19 + host: partnerUrl.hostname,
  20 + port: partnerUrl.port,
  21 + path: partnerUrl.pathname
  22 + };
  23 +
  24 + let client;
  25 + if (partnerUrl.protocol == 'https:') {
  26 + client = xmlrpc.createSecureClient(clientOptions);
  27 + } else {
  28 + client = xmlrpc.createClient(clientOptions);
  29 + }
  30 +
  31 + const params = {
  32 + MSISDN: config.partner.msisdn || config.partner.userid,
  33 + REQUESTID: task.trx_id,
  34 + PIN: config.partner.pin || config.partner.password,
  35 + NOHP: task.destination,
  36 + NOM: task.remote_product
  37 + };
  38 +
  39 + const xmlrpcMethod = 'topUpRequest';
  40 + logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: partnerUrl.href});
  41 +
  42 + client.methodCall(xmlrpcMethod, [ params ], function (err, value) {
  43 +
  44 + if (err) {
  45 + let rc = '68';
  46 + let msg = 'XMLRPC Client Error: ' + err;
  47 +
  48 + if (error.code == 'ECONNREFUSED' || error.code == 'EHOSTUNREACH' || (error.code == 'ETIMEDOUT' && error.syscall == "connect")) {
  49 + rc = '91';
  50 + }
  51 +
  52 + logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err});
  53 + report({
  54 + trx_id: task.trx_id,
  55 + rc: rc,
  56 + message: 'INTERNAL: ' + msg,
  57 + misc: {
  58 + task: task
  59 + }
  60 + });
  61 +
  62 + return;
  63 + }
  64 +
  65 + logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value});
  66 + matrix.last_topupRequest_ack = value;
  67 +
  68 + report({
  69 + trx_id: task.trx_id,
  70 + rc: partnerRc[value.RESPONSECODE] || '40',
  71 + message: value.MESSAGE,
  72 + sn: value.SN || st24.extractSnFromMessage(value.MESSAGE),
  73 + amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE),
  74 + raw: value,
  75 + misc: {
  76 + task: task
  77 + }
  78 + });
  79 + });
  80 +}
  81 +
  82 +function advice(task) {
  83 +}
  84 +
  85 +function report(data) {
  86 + matrix.last_report_to_core = data;
  87 + pull.report(data);
  88 +}
  89 +
  90 +exports.buy = buy;
  91 +exports.advice = advice;
  92 +exports.report = report;
lib/reverse-report.js
... ... @@ -0,0 +1,50 @@
  1 +"use strict";
  2 +
  3 +const xmlrpc = require('xmlrpc');
  4 +
  5 +const config = require('komodo-sdk/config');
  6 +const logger = require('komodo-sdk/logger');
  7 +const matrix = require('komodo-sdk/matrix');
  8 +const pull = require('komodo-sdk/gateway/pull');
  9 +
  10 +const st24 = require('./st24');
  11 +const partner = require('./partner');
  12 +const partnerRc = require('./partner-rc.json');
  13 +
  14 +function create() {
  15 + const server = xmlrpc.createServer({
  16 + port: config.reverse_report_port
  17 + });
  18 +
  19 + logger.info('Reverse report server listen on port ' + config.reverse_report_port);
  20 +
  21 + server.on('NotFound', function (method, params) {
  22 + logger.warn('REVERSEREPORT: Unknown method recevied on XMLRPC server', {method: method, params: params});
  23 + });
  24 +
  25 + server.on('topUpReport', function (err, params, callback) {
  26 +
  27 + logger.info('REVERSEREPORT: Got XMLRPC topUpReport request from partner', {method: 'topUpReport', params: params});
  28 + matrix.last_topupReport_params = params;
  29 +
  30 + const paramsCount = params.length;
  31 + for (let i = 0; i < paramsCount; i++) {
  32 + let value = params[i];
  33 +
  34 + partner.report({
  35 + trx_id: value.REQUESTID,
  36 + rc: partnerRc[value.RESPONSECODE] || '40',
  37 + message: value.MESSAGE,
  38 + sn: value.SN || st24.extractSnFromMessage(value.MESSAGE),
  39 + amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE),
  40 + raw: value,
  41 + misc: {
  42 + }
  43 + });
  44 + }
  45 +
  46 + callback(null, 'ACK REPORT OK');
  47 + })
  48 +}
  49 +
  50 +create();
... ... @@ -0,0 +1,35 @@
  1 +"use strict";
  2 +
  3 +function extractSnFromMessage(msg) {
  4 + if (!msg || typeof msg !== 'string') {
  5 + return;
  6 + }
  7 +
  8 + let match = msg.match(/^SN=(.*?);/);
  9 + if (!match || match.length < 2) {
  10 + return;
  11 + }
  12 +
  13 + return match[1];
  14 +}
  15 +
  16 +function extractPriceFromMsg(msg) {
  17 + if (!msg || typeof msg !== 'string') {
  18 + return;
  19 + }
  20 +
  21 + let match = msg.match(/\d,HRG=(.*?),ID=/);
  22 + if (!match || match.length < 2) {
  23 + return;
  24 + }
  25 +
  26 + if (!match[1]) {
  27 + return;
  28 + }
  29 +
  30 + return parseInt(match[1].replace(/\./g, ''));
  31 +}
  32 +
  33 +
  34 +exports.extractSnFromMessage = extractSnFromMessage;
  35 +exports.extractPriceFromMsg = extractPriceFromMsg;
... ... @@ -0,0 +1,28 @@
  1 +{
  2 + "name": "komodo-gw-st24",
  3 + "version": "0.1.0",
  4 + "description": "Komodo Gateway to ST24 XML-RPC",
  5 + "main": "index.js",
  6 + "scripts": {
  7 + "test": "mocha",
  8 + "postversion": "git push && git push --tags"
  9 + },
  10 + "repository": {
  11 + "type": "git",
  12 + "url": "git@gitlab.kodesumber.com:komodo/komodo-gw-st24.git"
  13 + },
  14 + "keywords": [
  15 + "komodo",
  16 + "tektrans",
  17 + "ppob",
  18 + "st24",
  19 + "xmlrpc",
  20 + "xml-rpc"
  21 + ],
  22 + "author": "Adhidarma Hadiwinoto <me@adhisimon.org>",
  23 + "license": "ISC",
  24 + "dependencies": {
  25 + "komodo-sdk": "git+http://gitlab.kodesumber.com/komodo/komodo-sdk.git",
  26 + "xmlrpc": "^1.3.2"
  27 + }
  28 +}