Commit 0ecfb2bae3b7cc7c168a892313aa81b6119779e1

Authored by Adhidarma Hadiwinoto
1 parent 15414ae66c
Exists in master

Perbaikan extract balance pada topupRequest

Showing 1 changed file with 1 additions and 1 deletions 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.toString(), 53 REQUESTID: task.trx_id.toString(),
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 const msg = `XMLRPC Client Error: ${err}. HTTP status code: ${err && err.res && err.res.statusCode ? err.res.statusCode : '-'}. Raw response body: ${err.body}`; 67 const msg = `XMLRPC Client Error: ${err}. HTTP status code: ${err && err.res && err.res.statusCode ? err.res.statusCode : '-'}. Raw response body: ${err.body}`;
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: 'topUpRequest INTERNAL ERROR: ' + msg, 86 message: 'topUpRequest INTERNAL ERROR: ' + 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 const balance = st24.extractBalanceFromMsg(value.MESSAGE, config.balance_pattern) || null; 98 const balance = st24.extractBalanceFromMsg(value.MESSAGE, config.partner.balance_pattern || config.balance_pattern) || null;
99 99
100 if (balance) { 100 if (balance) {
101 logger.verbose('TOPUPREQUEST: Balance from supplier extracted', { 101 logger.verbose('TOPUPREQUEST: Balance from supplier extracted', {
102 trxId: task.trx_id, 102 trxId: task.trx_id,
103 balance, 103 balance,
104 }); 104 });
105 } 105 }
106 106
107 report({ 107 report({
108 trx_id: task.trx_id, 108 trx_id: task.trx_id,
109 rc: komodoRc(value[RESPONSECODE_TAG]) || '40', 109 rc: komodoRc(value[RESPONSECODE_TAG]) || '40',
110 message: 'topUpRequest: ' + stringify(value), 110 message: 'topUpRequest: ' + stringify(value),
111 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern), 111 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern),
112 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern), 112 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern),
113 balance, 113 balance,
114 raw: value, 114 raw: value,
115 misc: { 115 misc: {
116 task: task 116 task: task
117 } 117 }
118 }); 118 });
119 }); 119 });
120 } 120 }
121 121
122 function _topUpInquiry(task) { 122 function _topUpInquiry(task) {
123 const params = { 123 const params = {
124 REQUESTID: task.trx_id.toString(), 124 REQUESTID: task.trx_id.toString(),
125 MSISDN: config.partner.msisdn || config.partner.userid, 125 MSISDN: config.partner.msisdn || config.partner.userid,
126 PIN: config.partner.pin || config.partner.password, 126 PIN: config.partner.pin || config.partner.password,
127 NOHP: task.destination 127 NOHP: task.destination
128 }; 128 };
129 129
130 const xmlrpcMethod = 'topUpInquiry'; 130 const xmlrpcMethod = 'topUpInquiry';
131 logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url}); 131 logger.info('Preparing XMLRPC request', {method: xmlrpcMethod, params: params, partnerUrl: config.partner.url});
132 132
133 const client = createXmlRpcClient(config.partner.url); 133 const client = createXmlRpcClient(config.partner.url);
134 client.methodCall(xmlrpcMethod, [ params ], function (err, value) { 134 client.methodCall(xmlrpcMethod, [ params ], function (err, value) {
135 135
136 if (err) { 136 if (err) {
137 137
138 const msg = 'XMLRPC Client Error: ' + err; 138 const msg = 'XMLRPC Client Error: ' + err;
139 139
140 logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err}); 140 logger.warn(msg, {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, err: err});
141 report({ 141 report({
142 trx_id: task.trx_id, 142 trx_id: task.trx_id,
143 rc: '68', 143 rc: '68',
144 message: 'topUpInquiry INTERNAL ERROR: ' + msg, 144 message: 'topUpInquiry INTERNAL ERROR: ' + msg,
145 misc: { 145 misc: {
146 task: task 146 task: task
147 } 147 }
148 }); 148 });
149 149
150 return; 150 return;
151 } 151 }
152 152
153 logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value}); 153 logger.info('Got XMLRPC response from partner for', {method: xmlrpcMethod, trx_id: task.trx_id, destination: task.destination, response: value});
154 //matrix.last_topupRequest_ack = value; 154 //matrix.last_topupRequest_ack = value;
155 155
156 report({ 156 report({
157 trx_id: task.trx_id, 157 trx_id: task.trx_id,
158 rc: (value[RESPONSECODE_TAG] && (komodoRc(value[RESPONSECODE_TAG]) || '40')) || '68', 158 rc: (value[RESPONSECODE_TAG] && (komodoRc(value[RESPONSECODE_TAG]) || '40')) || '68',
159 message: 'topUpInquiry: ' + stringify(value), 159 message: 'topUpInquiry: ' + stringify(value),
160 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern), 160 sn: (value.SN || '').replace(/;$/, '') || st24.extractSnFromMessage(value.MESSAGE, config.sn_pattern),
161 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern), 161 amount: value.PRICE || st24.extractPriceFromMsg(value.MESSAGE, config.amount_pattern),
162 balance: st24.extractBalanceFromMsg(value.MESSAGE, config.balance_pattern), 162 balance: st24.extractBalanceFromMsg(value.MESSAGE, config.balance_pattern),
163 raw: value, 163 raw: value,
164 misc: { 164 misc: {
165 task: task 165 task: task
166 } 166 }
167 }); 167 });
168 }); 168 });
169 } 169 }
170 170
171 function advice(task) { 171 function advice(task) {
172 if (config && config.advice_is_not_allowed) { 172 if (config && config.advice_is_not_allowed) {
173 return; 173 return;
174 } 174 }
175 175
176 if (config && config.advice_max_age_ms) { 176 if (config && config.advice_max_age_ms) {
177 if (moment() - moment(task.created) > config.advice_max_age_ms) { 177 if (moment() - moment(task.created) > config.advice_max_age_ms) {
178 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}); 178 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});
179 return; 179 return;
180 } 180 }
181 } 181 }
182 182
183 if (config && config.advice_is_topuprequest) { 183 if (config && config.advice_is_topuprequest) {
184 _topUpRequest(task, true); 184 _topUpRequest(task, true);
185 } 185 }
186 else { 186 else {
187 _topUpInquiry(task); 187 _topUpInquiry(task);
188 } 188 }
189 } 189 }
190 190
191 function report(data) { 191 function report(data) {
192 if (!data) { 192 if (!data) {
193 return; 193 return;
194 } 194 }
195 195
196 if (config && config.force_all_to_pending) { 196 if (config && config.force_all_to_pending) {
197 data.rc = '68'; 197 data.rc = '68';
198 } 198 }
199 199
200 matrix.last_report_to_core = data; 200 matrix.last_report_to_core = data;
201 pull.report(data); 201 pull.report(data);
202 202
203 if (!resendDelay.isEnabled()) { 203 if (!resendDelay.isEnabled()) {
204 //logger.verbose('Skipping resend delay because resend delay has not configured yet', {trx_id: task.trx_id, destination: task.destination, product: task.product}); 204 //logger.verbose('Skipping resend delay because resend delay has not configured yet', {trx_id: task.trx_id, destination: task.destination, product: task.product});
205 return; 205 return;
206 } 206 }
207 207
208 if (data.rc !== '68') { 208 if (data.rc !== '68') {
209 logger.verbose('Canceling resend delay', {trx_id: data.trx_id}) 209 logger.verbose('Canceling resend delay', {trx_id: data.trx_id})
210 resendDelay.cancel(data.trx_id); 210 resendDelay.cancel(data.trx_id);
211 return; 211 return;
212 } 212 }
213 213
214 214
215 if (!data.misc || !data.misc.task || typeof data.misc.task !== 'object') { 215 if (!data.misc || !data.misc.task || typeof data.misc.task !== 'object') {
216 return; 216 return;
217 } 217 }
218 218
219 const task = data.misc.task; 219 const task = data.misc.task;
220 logger.verbose('Registering resend delay', {trx_id: task.trx_id, destination: task.destination, product: task.product}) 220 logger.verbose('Registering resend delay', {trx_id: task.trx_id, destination: task.destination, product: task.product})
221 resendDelay.register(task, advice); 221 resendDelay.register(task, advice);
222 222
223 } 223 }
224 224
225 exports.buy = buy; 225 exports.buy = buy;
226 exports.advice = advice; 226 exports.advice = advice;
227 exports.report = report; 227 exports.report = report;
228 exports.komodoRc = komodoRc; 228 exports.komodoRc = komodoRc;
229 exports.RESPONSECODE_TAG = RESPONSECODE_TAG; 229 exports.RESPONSECODE_TAG = RESPONSECODE_TAG;