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 raw: value, 104 raw: value,
105 misc: { 105 misc: {
106 task: task 106 task: task
107 } 107 }
108 }); 108 });
109 }); 109 });
110 } 110 }
111 111
112 function _topUpInquiry(task) { 112 function _topUpInquiry(task) {
113 const params = { 113 const params = {
114 REQUESTID: task.trx_id, 114 REQUESTID: task.trx_id,
115 MSISDN: config.partner.msisdn || config.partner.userid, 115 MSISDN: config.partner.msisdn || config.partner.userid,
116 PIN: config.partner.pin || config.partner.password, 116 PIN: config.partner.pin || config.partner.password,
117 NOHP: task.destination 117 NOHP: task.destination
118 }; 118 };
119 119
120 const xmlrpcMethod = 'topUpInquiry'; 120 const xmlrpcMethod = 'topUpInquiry';
121 logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url}); 121 logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url});
122 122
123 const client = createXmlRpcClient(config.partner.url); 123 const client = createXmlRpcClient(config.partner.url);
124 client.methodCall(xmlrpcMethod, [ params ], function (err, value) { 124 client.methodCall(xmlrpcMethod, [ params ], function (err, value) {
125 125
126 if (err) { 126 if (err) {
127 127
128 const msg = 'XMLRPC Client Error: ' + err; 128 const msg = 'XMLRPC Client Error: ' + err;
129 129
130 logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err}); 130 logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err});
131 report({ 131 report({
132 trx_id: task.trx_id, 132 trx_id: task.trx_id,
133 rc: '68', 133 rc: '68',
134 message: 'INTERNAL: ' + msg, 134 message: 'INTERNAL: ' + msg,
135 misc: { 135 misc: {
136 task: task 136 task: task
137 } 137 }
138 }); 138 });
139 139
140 return; 140 return;
141 } 141 }
142 142
143 logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value}); 143 logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value});
144 //matrix.last_topupRequest_ack = value; 144 //matrix.last_topupRequest_ack = value;
145 145
146 report({ 146 report({
147 trx_id: task.trx_id, 147 trx_id: task.trx_id,
148 rc: komodoRc(value[RESPONSECODE_TAG]) || '40', 148 rc: komodoRc(value[RESPONSECODE_TAG]) || '40',
149 message: stringify(value), 149 message: stringify(value),
150 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern), 150 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern),
151 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern), 151 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern),
152 raw: value, 152 raw: value,
153 misc: { 153 misc: {
154 task: task 154 task: task
155 } 155 }
156 }); 156 });
157 }); 157 });
158 } 158 }
159 159
160 function advice(task) { 160 function advice(task) {
161 if (config && config.advice_is_not_allowed) { 161 if (config && config.advice_is_not_allowed) {
162 return; 162 return;
163 } 163 }
164 164
165 if (config && config.advice_max_age_ms) { 165 if (config && config.advice_max_age_ms) {
166 if (moment() - moment(task.created) > config.advice_max_age_ms) { 166 if (moment() - moment(task.created) > config.advice_max_age_ms) {
167 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}); 167 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});
168 return; 168 return;
169 } 169 }
170 } 170 }
171 171
172 if (config && config.advice_is_topuprequest) { 172 if (config && config.advice_is_topuprequest) {
173 _topUpRequest(task, true); 173 _topUpRequest(task, true);
174 } 174 }
175 else { 175 else {
176 _topUpInquiry(task); 176 _topUpInquiry(task);
177 } 177 }
178 } 178 }
179 179
180 function report(data) { 180 function report(data) {
181 if (!data) { 181 if (!data) {
182 return; 182 return;
183 } 183 }
184 184
185 if (config && config.force_all_to_pending) { 185 if (config && config.force_all_to_pending) {
186 data.rc = '68'; 186 data.rc = '68';
187 } 187 }
188 188
189 matrix.last_report_to_core = data; 189 matrix.last_report_to_core = data;
190 pull.report(data); 190 pull.report(data);
191 191
192 if (!data.misc && !data.misc.task) { 192 if (!data.misc && !data.misc.task) {
193 return; 193 return;
194 } 194 }
195 195
196 const task = data.misc.task; 196 const task = data.misc.task;
197 197
198 if (!resendDelay.isEnabled()) { 198 if (!resendDelay.isEnabled()) {
199 //logger.verbose('Skipping resend delay because resend delay has not configured yet', {trx_id: task.trx_id, destination: task.destination, product: task.product}); 199 //logger.verbose('Skipping resend delay because resend delay has not configured yet', {trx_id: task.trx_id, destination: task.destination, product: task.product});
200 return; 200 return;
201 } 201 }
202 202
203 if (data.rc && data.rc === '68') { 203 if (data.rc && data.rc === '68') {
204 logger.verbose('Registering resend delay', {trx_id: task.trx_id, destination: task.destination, product: task.product}) 204 logger.verbose('Registering resend delay', {trx_id: task.trx_id, destination: task.destination, product: task.product})
205 resendDelay.register(task, advice); 205 resendDelay.register(task, advice);
206 } 206 }
207 else { 207 else {
208 logger.verbose('Canceling resend delay', {trx_id: task.trx_id, destination: task.destination, product: task.product}) 208 logger.verbose('Canceling resend delay', {trx_id: task.trx_id, destination: task.destination, product: task.product})
209 resendDelay.cancel(task.trx_id); 209 resendDelay.cancel(task.trx_id);
210 } 210 }
211 } 211 }
212 212
213 exports.buy = buy; 213 exports.buy = buy;
214 exports.advice = advice; 214 exports.advice = advice;
215 exports.report = report; 215 exports.report = report;
216 216
1 { 1 {
2 "name": "komodo-gw-st24", 2 "name": "komodo-gw-st24",
3 "version": "2.0.3", 3 "version": "2.0.4",
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