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