Compare View

switch
from
...
to
 
Commits (2)

Changes

Showing 2 changed files Inline Diff

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 fs = require('fs'); 5 const fs = require('fs');
6 const url = require('url'); 6 const url = require('url');
7 const https = require('https'); 7 const https = require('https');
8 const xmlrpc = require('xmlrpc'); 8 const xmlrpc = require('xmlrpc');
9 const moment = require('moment'); 9 const moment = require('moment');
10 const stringify = require("json-stringify-pretty-compact"); 10 const stringify = require("json-stringify-pretty-compact");
11 11
12 const config = require('komodo-sdk/config'); 12 const config = require('komodo-sdk/config');
13 const logger = require('komodo-sdk/logger'); 13 const logger = require('komodo-sdk/logger');
14 const matrix = require('komodo-sdk/matrix'); 14 const matrix = require('komodo-sdk/matrix');
15 const pull = require('komodo-sdk/gateway/pull'); 15 const pull = require('komodo-sdk/gateway/pull');
16 const resendDelay = require('komodo-sdk/gateway/resend-delay'); 16 const resendDelay = require('komodo-sdk/gateway/resend-delay');
17 17
18 const st24 = require('./st24'); 18 const st24 = require('./st24');
19 19
20 if (config.partner.use_sslv3) { 20 if (config.partner.use_sslv3) {
21 https.globalAgent.options.secureProtocol = 'SSLv3_method'; 21 https.globalAgent.options.secureProtocol = 'SSLv3_method';
22 } 22 }
23 23
24 const partnerRc = fs.existsSync(__dirname + '/../rc-local.json') ? require('../rc-local.json') : require('./partner-rc.json'); 24 const partnerRc = fs.existsSync(__dirname + '/../rc-local.json') ? require('../rc-local.json') : require('./partner-rc.json');
25 logger.verbose('Partner RC dictionary loaded', {partner_rc: partnerRc}); 25 logger.verbose('Partner RC dictionary loaded', {partner_rc: partnerRc});
26 26
27 const RESPONSECODE_TAG = config.responsecode_tag ? config.responsecode_tag : 'RESPONSECODE'; 27 const RESPONSECODE_TAG = config.responsecode_tag ? config.responsecode_tag : 'RESPONSECODE';
28 28
29 function komodoRc(rc) { 29 function komodoRc(rc) {
30 return (config.partner.override_rc ? config.partner.override_rc[rc] : null) || partnerRc[rc] || '40'; 30 return (config.partner.override_rc ? config.partner.override_rc[rc] : null) || partnerRc[rc] || '40';
31 } 31 }
32 32
33 function createXmlRpcClient(endpoint) { 33 function createXmlRpcClient(endpoint) {
34 const partnerUrl = url.parse(endpoint); 34 const partnerUrl = url.parse(endpoint);
35 const clientOptions = { 35 const clientOptions = {
36 host: partnerUrl.hostname, 36 host: partnerUrl.hostname,
37 port: partnerUrl.port, 37 port: partnerUrl.port,
38 path: partnerUrl.pathname 38 path: partnerUrl.pathname
39 }; 39 };
40 40
41 logger.verbose('Creating XML-RPC client using ' + partnerUrl.protocol, clientOptions); 41 logger.verbose('Creating XML-RPC client using ' + partnerUrl.protocol, clientOptions);
42 42
43 return (partnerUrl.protocol === 'https:') ? xmlrpc.createSecureClient(clientOptions) : xmlrpc.createClient(clientOptions); 43 return (partnerUrl.protocol === 'https:') ? xmlrpc.createSecureClient(clientOptions) : xmlrpc.createClient(clientOptions);
44 } 44 }
45 45
46 function buy(task) { 46 function buy(task) {
47 _topUpRequest(task); 47 _topUpRequest(task);
48 } 48 }
49 49
50 function _topUpRequest(task, isAdvice) { 50 function _topUpRequest(task, isAdvice) {
51 const params = { 51 const params = {
52 MSISDN: config.partner.msisdn || config.partner.userid, 52 MSISDN: config.partner.msisdn || config.partner.userid,
53 REQUESTID: task.trx_id, 53 REQUESTID: task.trx_id,
54 PIN: config.partner.pin || config.partner.password, 54 PIN: config.partner.pin || config.partner.password,
55 NOHP: task.destination, 55 NOHP: task.destination,
56 NOM: task.remote_product 56 NOM: task.remote_product
57 }; 57 };
58 58
59 const xmlrpcMethod = 'topUpRequest'; 59 const xmlrpcMethod = 'topUpRequest';
60 logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url}); 60 logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url});
61 61
62 const client = createXmlRpcClient(config.partner.url); 62 const client = createXmlRpcClient(config.partner.url);
63 client.methodCall(xmlrpcMethod, [ params ], function (err, value) { 63 client.methodCall(xmlrpcMethod, [ params ], function (err, value) {
64 64
65 if (err) { 65 if (err) {
66 66
67 let msg = 'XMLRPC Client Error: ' + err; 67 let msg = 'XMLRPC Client Error: ' + err;
68 let rc = '68'; 68 let rc = '68';
69 69
70 if ( 70 if (
71 !isAdvice && 71 !isAdvice &&
72 ( 72 (
73 err.code === 'ECONNREFUSED' 73 err.code === 'ECONNREFUSED'
74 || err.code === 'EHOSTUNREACH' 74 || err.code === 'EHOSTUNREACH'
75 || (err.code === 'ETIMEDOUT' && err.syscall === "connect") 75 || (err.code === 'ETIMEDOUT' && err.syscall === "connect")
76 || (err.code === 'EPROTO' && err.syscall === "write") 76 || (err.code === 'EPROTO' && err.syscall === "write")
77 ) 77 )
78 ) { 78 ) {
79 rc = '91'; 79 rc = '91';
80 } 80 }
81 81
82 logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err}); 82 logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err});
83 report({ 83 report({
84 trx_id: task.trx_id, 84 trx_id: task.trx_id,
85 rc: rc, 85 rc: rc,
86 message: 'INTERNAL: ' + msg, 86 message: 'INTERNAL: ' + msg,
87 misc: { 87 misc: {
88 task: task 88 task: task
89 } 89 }
90 }); 90 });
91 91
92 return; 92 return;
93 } 93 }
94 94
95 logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value}); 95 logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value});
96 matrix.last_topupRequest_ack = value; 96 matrix.last_topupRequest_ack = value;
97 97
98 report({ 98 report({
99 trx_id: task.trx_id, 99 trx_id: task.trx_id,
100 rc: komodoRc(value[RESPONSECODE_TAG]) || '40', 100 rc: komodoRc(value[RESPONSECODE_TAG]) || '40',
101 message: stringify(value), 101 message: stringify(value),
102 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern), 102 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern),
103 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern), 103 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern),
104 balance: st24.extractBalanceFromMsg(value.MESSAGE, config.balance_pattern),
104 balance: st24.extractBalanceFromMsg(value.MESSAGE, config.balance_pattern), 105 raw: value,
105 raw: value, 106 misc: {
106 misc: { 107 task: task
107 task: task 108 }
108 } 109 });
109 }); 110 });
110 }); 111 }
111 } 112
112 113 function _topUpInquiry(task) {
113 function _topUpInquiry(task) { 114 const params = {
114 const params = { 115 REQUESTID: task.trx_id,
115 REQUESTID: task.trx_id, 116 MSISDN: config.partner.msisdn || config.partner.userid,
116 MSISDN: config.partner.msisdn || config.partner.userid, 117 PIN: config.partner.pin || config.partner.password,
117 PIN: config.partner.pin || config.partner.password, 118 NOHP: task.destination
118 NOHP: task.destination 119 };
119 }; 120
120 121 const xmlrpcMethod = 'topUpInquiry';
121 const xmlrpcMethod = 'topUpInquiry'; 122 logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url});
122 logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url}); 123
123 124 const client = createXmlRpcClient(config.partner.url);
124 const client = createXmlRpcClient(config.partner.url); 125 client.methodCall(xmlrpcMethod, [ params ], function (err, value) {
125 client.methodCall(xmlrpcMethod, [ params ], function (err, value) { 126
126 127 if (err) {
127 if (err) { 128
128 129 const msg = 'XMLRPC Client Error: ' + err;
129 const msg = 'XMLRPC Client Error: ' + err; 130
130 131 logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err});
131 logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err}); 132 report({
132 report({ 133 trx_id: task.trx_id,
133 trx_id: task.trx_id, 134 rc: '68',
134 rc: '68', 135 message: 'INTERNAL: ' + msg,
135 message: 'INTERNAL: ' + msg, 136 misc: {
136 misc: { 137 task: task
137 task: task 138 }
138 } 139 });
139 }); 140
140 141 return;
141 return; 142 }
142 } 143
143 144 logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value});
144 logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value}); 145 //matrix.last_topupRequest_ack = value;
145 //matrix.last_topupRequest_ack = value; 146
146 147 report({
147 report({ 148 trx_id: task.trx_id,
148 trx_id: task.trx_id, 149 rc: komodoRc(value[RESPONSECODE_TAG]) || '40',
149 rc: komodoRc(value[RESPONSECODE_TAG]) || '40', 150 message: stringify(value),
150 message: stringify(value), 151 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern),
151 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern), 152 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern),
152 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern), 153 balance: st24.extractBalanceFromMsg(value.MESSAGE, config.balance_pattern),
153 balance: st24.extractBalanceFromMsg(value.MESSAGE, config.balance_pattern), 154 raw: value,
154 raw: value, 155 misc: {
155 misc: { 156 task: task
156 task: task 157 }
157 } 158 });
158 }); 159 });
159 }); 160 }
160 } 161
161 162 function advice(task) {
162 function advice(task) { 163 if (config && config.advice_is_not_allowed) {
163 if (config && config.advice_is_not_allowed) { 164 return;
164 return; 165 }
165 } 166
166 167 if (config && config.advice_max_age_ms) {
167 if (config && config.advice_max_age_ms) { 168 if (moment() - moment(task.created) > config.advice_max_age_ms) {
168 if (moment() - moment(task.created) > config.advice_max_age_ms) { 169 logger.verbose('Ignoring advice request because of expired task', {trx_id: task.trx_id, destination: task.destination, product: task.product, created: task.created, max_age: config.advice_max_age_ms});
169 logger.verbose('Ignoring advice request because of expired task', {trx_id: task.trx_id, destination: task.destination, product: task.product, created: task.created, max_age: config.advice_max_age_ms}); 170 return;
170 return; 171 }
171 } 172 }
172 } 173
173 174 if (config && config.advice_is_topuprequest) {
174 if (config && config.advice_is_topuprequest) { 175 _topUpRequest(task, true);
175 _topUpRequest(task, true); 176 }
176 } 177 else {
177 else { 178 _topUpInquiry(task);
178 _topUpInquiry(task); 179 }
179 } 180 }
180 } 181
181 182 function report(data) {
182 function report(data) { 183 if (!data) {
183 if (!data) { 184 return;
184 return; 185 }
185 } 186
186 187 if (config && config.force_all_to_pending) {
187 if (config && config.force_all_to_pending) { 188 data.rc = '68';
188 data.rc = '68'; 189 }
189 } 190
190 191 matrix.last_report_to_core = data;
191 matrix.last_report_to_core = data; 192 pull.report(data);
192 pull.report(data); 193
193 194 if (!resendDelay.isEnabled()) {
194 if (!resendDelay.isEnabled()) { 195 //logger.verbose('Skipping resend delay because resend delay has not configured yet', {trx_id: task.trx_id, destination: task.destination, product: task.product});
195 //logger.verbose('Skipping resend delay because resend delay has not configured yet', {trx_id: task.trx_id, destination: task.destination, product: task.product}); 196 return;
196 return; 197 }
197 } 198
198 199 if (data.rc !== '68') {
199 if (data.rc !== '68') { 200 logger.verbose('Canceling resend delay', {trx_id: data.trx_id})
200 logger.verbose('Canceling resend delay', {trx_id: data.trx_id}) 201 resendDelay.cancel(data.trx_id);
201 resendDelay.cancel(data.trx_id); 202 return;
202 return; 203 }
203 } 204
204 205
205 206 if (!data.misc || !data.misc.task || typeof data.misc.task !== 'object') {
206 if (!data.misc || !data.misc.task || typeof data.misc.task !== 'object') { 207 return;
207 return; 208 }
208 } 209
209 210 const task = data.misc.task;
210 const task = data.misc.task; 211 logger.verbose('Registering resend delay', {trx_id: task.trx_id, destination: task.destination, product: task.product})
211 logger.verbose('Registering resend delay', {trx_id: task.trx_id, destination: task.destination, product: task.product}) 212 resendDelay.register(task, advice);
212 resendDelay.register(task, advice); 213
213 214 }
214 } 215
215 216 exports.buy = buy;
216 exports.buy = buy; 217 exports.advice = advice;
217 exports.advice = advice; 218 exports.report = report;
218 exports.report = report; 219
1 { 1 {
2 "name": "komodo-gw-st24", 2 "name": "komodo-gw-st24",
3 "version": "2.1.0", 3 "version": "2.1.1",
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 "json-stringify-pretty-compact": "^1.1.0", 25 "json-stringify-pretty-compact": "^1.1.0",
26 "komodo-sdk": "git+http://gitlab.kodesumber.com/komodo/komodo-sdk.git", 26 "komodo-sdk": "git+http://gitlab.kodesumber.com/komodo/komodo-sdk.git",
27 "moment": "^2.22.1", 27 "moment": "^2.22.1",
28 "xmlrpc": "^1.3.2" 28 "xmlrpc": "^1.3.2"
29 }, 29 },
30 "devDependencies": { 30 "devDependencies": {
31 "should": "^13.2.1" 31 "should": "^13.2.1"
32 } 32 }
33 } 33 }
34 34