Commit 4ce3f5feeba5838ad71b2216adcf696cb95c7e56
1 parent
a801df497e
Exists in
master
debug partnerrc
Showing 1 changed file with 1 additions and 0 deletions Inline Diff
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 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 | const partnerRc = fs.existsSync(__dirname + '/../rc-local.json') ? require('../rc-local.json') : require('./partner-rc.json'); | 20 | const partnerRc = fs.existsSync(__dirname + '/../rc-local.json') ? require('../rc-local.json') : require('./partner-rc.json'); |
21 | logger.verbose('Partner RC dictionary loaded', {partner_rc: partnerRc}); | ||
21 | 22 | ||
22 | if (config.partner.use_sslv3) { | 23 | if (config.partner.use_sslv3) { |
23 | https.globalAgent.options.secureProtocol = 'SSLv3_method'; | 24 | https.globalAgent.options.secureProtocol = 'SSLv3_method'; |
24 | } | 25 | } |
25 | 26 | ||
26 | function createXmlRpcClient(endpoint) { | 27 | function createXmlRpcClient(endpoint) { |
27 | const partnerUrl = url.parse(endpoint); | 28 | const partnerUrl = url.parse(endpoint); |
28 | const clientOptions = { | 29 | const clientOptions = { |
29 | host: partnerUrl.hostname, | 30 | host: partnerUrl.hostname, |
30 | port: partnerUrl.port, | 31 | port: partnerUrl.port, |
31 | path: partnerUrl.pathname | 32 | path: partnerUrl.pathname |
32 | }; | 33 | }; |
33 | 34 | ||
34 | logger.verbose('Creating XML-RPC client using ' + partnerUrl.protocol, clientOptions); | 35 | logger.verbose('Creating XML-RPC client using ' + partnerUrl.protocol, clientOptions); |
35 | 36 | ||
36 | return (partnerUrl.protocol === 'https:') ? xmlrpc.createSecureClient(clientOptions) : xmlrpc.createClient(clientOptions); | 37 | return (partnerUrl.protocol === 'https:') ? xmlrpc.createSecureClient(clientOptions) : xmlrpc.createClient(clientOptions); |
37 | } | 38 | } |
38 | 39 | ||
39 | function buy(task) { | 40 | function buy(task) { |
40 | _topUpRequest(task); | 41 | _topUpRequest(task); |
41 | } | 42 | } |
42 | 43 | ||
43 | function _topUpRequest(task, isAdvice) { | 44 | function _topUpRequest(task, isAdvice) { |
44 | const params = { | 45 | const params = { |
45 | MSISDN: config.partner.msisdn || config.partner.userid, | 46 | MSISDN: config.partner.msisdn || config.partner.userid, |
46 | REQUESTID: task.trx_id, | 47 | REQUESTID: task.trx_id, |
47 | PIN: config.partner.pin || config.partner.password, | 48 | PIN: config.partner.pin || config.partner.password, |
48 | NOHP: task.destination, | 49 | NOHP: task.destination, |
49 | NOM: task.remote_product | 50 | NOM: task.remote_product |
50 | }; | 51 | }; |
51 | 52 | ||
52 | const xmlrpcMethod = 'topUpRequest'; | 53 | const xmlrpcMethod = 'topUpRequest'; |
53 | logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url}); | 54 | logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url}); |
54 | 55 | ||
55 | const client = createXmlRpcClient(config.partner.url); | 56 | const client = createXmlRpcClient(config.partner.url); |
56 | client.methodCall(xmlrpcMethod, [ params ], function (err, value) { | 57 | client.methodCall(xmlrpcMethod, [ params ], function (err, value) { |
57 | 58 | ||
58 | if (err) { | 59 | if (err) { |
59 | 60 | ||
60 | let msg = 'XMLRPC Client Error: ' + err; | 61 | let msg = 'XMLRPC Client Error: ' + err; |
61 | let rc = '68'; | 62 | let rc = '68'; |
62 | 63 | ||
63 | if ( | 64 | if ( |
64 | !isAdvice && | 65 | !isAdvice && |
65 | ( | 66 | ( |
66 | err.code === 'ECONNREFUSED' | 67 | err.code === 'ECONNREFUSED' |
67 | || err.code === 'EHOSTUNREACH' | 68 | || err.code === 'EHOSTUNREACH' |
68 | || (err.code === 'ETIMEDOUT' && err.syscall === "connect") | 69 | || (err.code === 'ETIMEDOUT' && err.syscall === "connect") |
69 | || (err.code === 'EPROTO' && err.syscall === "write") | 70 | || (err.code === 'EPROTO' && err.syscall === "write") |
70 | ) | 71 | ) |
71 | ) { | 72 | ) { |
72 | rc = '91'; | 73 | rc = '91'; |
73 | } | 74 | } |
74 | 75 | ||
75 | logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err}); | 76 | logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err}); |
76 | report({ | 77 | report({ |
77 | trx_id: task.trx_id, | 78 | trx_id: task.trx_id, |
78 | rc: rc, | 79 | rc: rc, |
79 | message: 'INTERNAL: ' + msg, | 80 | message: 'INTERNAL: ' + msg, |
80 | misc: { | 81 | misc: { |
81 | task: task | 82 | task: task |
82 | } | 83 | } |
83 | }); | 84 | }); |
84 | 85 | ||
85 | return; | 86 | return; |
86 | } | 87 | } |
87 | 88 | ||
88 | logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value}); | 89 | logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value}); |
89 | matrix.last_topupRequest_ack = value; | 90 | matrix.last_topupRequest_ack = value; |
90 | 91 | ||
91 | report({ | 92 | report({ |
92 | trx_id: task.trx_id, | 93 | trx_id: task.trx_id, |
93 | rc: partnerRc[value.RESPONSECODE] || '40', | 94 | rc: partnerRc[value.RESPONSECODE] || '40', |
94 | message: stringify(value), | 95 | message: stringify(value), |
95 | sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE), | 96 | sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE), |
96 | amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE), | 97 | amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE), |
97 | raw: value, | 98 | raw: value, |
98 | misc: { | 99 | misc: { |
99 | task: task | 100 | task: task |
100 | } | 101 | } |
101 | }); | 102 | }); |
102 | }); | 103 | }); |
103 | } | 104 | } |
104 | 105 | ||
105 | function _topUpInquiry(task) { | 106 | function _topUpInquiry(task) { |
106 | const params = { | 107 | const params = { |
107 | REQUESTID: task.trx_id, | 108 | REQUESTID: task.trx_id, |
108 | MSISDN: config.partner.msisdn || config.partner.userid, | 109 | MSISDN: config.partner.msisdn || config.partner.userid, |
109 | PIN: config.partner.pin || config.partner.password, | 110 | PIN: config.partner.pin || config.partner.password, |
110 | NOHP: task.destination | 111 | NOHP: task.destination |
111 | }; | 112 | }; |
112 | 113 | ||
113 | const xmlrpcMethod = 'topUpInquiry'; | 114 | const xmlrpcMethod = 'topUpInquiry'; |
114 | logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url}); | 115 | logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url}); |
115 | 116 | ||
116 | const client = createXmlRpcClient(config.partner.url); | 117 | const client = createXmlRpcClient(config.partner.url); |
117 | client.methodCall(xmlrpcMethod, [ params ], function (err, value) { | 118 | client.methodCall(xmlrpcMethod, [ params ], function (err, value) { |
118 | 119 | ||
119 | if (err) { | 120 | if (err) { |
120 | 121 | ||
121 | const msg = 'XMLRPC Client Error: ' + err; | 122 | const msg = 'XMLRPC Client Error: ' + err; |
122 | 123 | ||
123 | logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err}); | 124 | logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err}); |
124 | report({ | 125 | report({ |
125 | trx_id: task.trx_id, | 126 | trx_id: task.trx_id, |
126 | rc: '68', | 127 | rc: '68', |
127 | message: 'INTERNAL: ' + msg, | 128 | message: 'INTERNAL: ' + msg, |
128 | misc: { | 129 | misc: { |
129 | task: task | 130 | task: task |
130 | } | 131 | } |
131 | }); | 132 | }); |
132 | 133 | ||
133 | return; | 134 | return; |
134 | } | 135 | } |
135 | 136 | ||
136 | logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value}); | 137 | logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value}); |
137 | //matrix.last_topupRequest_ack = value; | 138 | //matrix.last_topupRequest_ack = value; |
138 | 139 | ||
139 | report({ | 140 | report({ |
140 | trx_id: task.trx_id, | 141 | trx_id: task.trx_id, |
141 | rc: partnerRc[value.RESPONSECODE] || '40', | 142 | rc: partnerRc[value.RESPONSECODE] || '40', |
142 | message: stringify(value), | 143 | message: stringify(value), |
143 | sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern), | 144 | sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern), |
144 | amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE), | 145 | amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE), |
145 | raw: value, | 146 | raw: value, |
146 | misc: { | 147 | misc: { |
147 | task: task | 148 | task: task |
148 | } | 149 | } |
149 | }); | 150 | }); |
150 | }); | 151 | }); |
151 | } | 152 | } |
152 | 153 | ||
153 | function advice(task) { | 154 | function advice(task) { |
154 | if (config && config.advice_is_not_allowed) { | 155 | if (config && config.advice_is_not_allowed) { |
155 | return; | 156 | return; |
156 | } | 157 | } |
157 | 158 | ||
158 | if (config && config.advice_max_age_ms) { | 159 | if (config && config.advice_max_age_ms) { |
159 | if (moment() - moment(task.created) > config.advice_max_age_ms) { | 160 | if (moment() - moment(task.created) > config.advice_max_age_ms) { |
160 | 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}); | 161 | 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}); |
161 | return; | 162 | return; |
162 | } | 163 | } |
163 | } | 164 | } |
164 | 165 | ||
165 | if (config && config.advice_is_topuprequest) { | 166 | if (config && config.advice_is_topuprequest) { |
166 | _topUpRequest(task, true); | 167 | _topUpRequest(task, true); |
167 | } | 168 | } |
168 | else { | 169 | else { |
169 | _topUpInquiry(task); | 170 | _topUpInquiry(task); |
170 | } | 171 | } |
171 | } | 172 | } |
172 | 173 | ||
173 | function report(data) { | 174 | function report(data) { |
174 | if (!data) { | 175 | if (!data) { |
175 | return; | 176 | return; |
176 | } | 177 | } |
177 | 178 | ||
178 | if (config && config.force_all_to_pending) { | 179 | if (config && config.force_all_to_pending) { |
179 | data.rc = '68'; | 180 | data.rc = '68'; |
180 | } | 181 | } |
181 | 182 | ||
182 | matrix.last_report_to_core = data; | 183 | matrix.last_report_to_core = data; |
183 | pull.report(data); | 184 | pull.report(data); |
184 | 185 | ||
185 | if (!resendDelay.isEnabled()) return; | 186 | if (!resendDelay.isEnabled()) return; |
186 | 187 | ||
187 | if (data.task && data.rc && data.rc === '68') { | 188 | if (data.task && data.rc && data.rc === '68') { |
188 | resendDelay.register(data.task, advice); | 189 | resendDelay.register(data.task, advice); |
189 | } | 190 | } |
190 | else { | 191 | else { |
191 | resendDelay.cancel(data.trx_id); | 192 | resendDelay.cancel(data.trx_id); |
192 | } | 193 | } |
193 | } | 194 | } |
194 | 195 | ||
195 | exports.buy = buy; | 196 | exports.buy = buy; |
196 | exports.advice = advice; | 197 | exports.advice = advice; |
197 | exports.report = report; | 198 | exports.report = report; |
198 | 199 |