Commit 35cfaf35e35a061bee8a76a7575291199c97c5c7
1 parent
a16025e056
Exists in
master
perbaikan parameter reffid pada callback ke st24 dari hasil webreport
Showing 1 changed file with 282 additions and 282 deletions Side-by-side Diff
partner-sc.js
1 | -var fs = require('fs'); | |
2 | -var https = require('https'); | |
3 | -var http = require('http'); | |
4 | -var url = require('url'); | |
5 | -var request = require('request'); | |
6 | -var xml2js = require('xml2js').parseString; | |
7 | -var strftime = require('strftime'); | |
8 | -var math = require('mathjs'); | |
9 | -var winston = require('winston'); | |
10 | -var cekstatus = require('./cekstatus.js'); | |
11 | - | |
12 | -var config; | |
13 | -var httpServer; | |
14 | -var aaa; | |
15 | -var logger; | |
16 | -var callbackReport; | |
17 | - | |
18 | -process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; | |
19 | - | |
20 | -var sleep_before_retry = 30000; | |
21 | - | |
22 | -var logTag = __filename.split('/').reverse()[0]; | |
23 | - | |
24 | -function topupRequest(task) { | |
25 | - | |
26 | - var ts = strftime('%Y%m%d%H%M%S', new Date()); | |
27 | - | |
28 | - var data = | |
29 | - config.h2h_out.userid | |
30 | - + '|' + config.h2h_out.password | |
31 | - + '|' + task['remoteProduct'] | |
32 | - + '|' + task['destination'] + '|0'; | |
33 | - | |
34 | - var options = { | |
35 | - url: config.h2h_out.partner, | |
36 | - qs: { | |
37 | - ts: ts, | |
38 | - data: data, | |
39 | - reffid: task['requestId'] | |
40 | - } | |
41 | - }; | |
42 | - logger.info('Creating http request', {options: options}); | |
43 | - | |
44 | - request(options, function (error, response, body) { | |
45 | - var responseCode = '40'; | |
46 | - var responseMessage = 'Gateway Error'; | |
47 | - | |
48 | - if (error) { | |
49 | - | |
50 | - logger.warn('HTTP REQUEST ERROR', error); | |
51 | - callbackReport(task['requestId'], '89', 'HTTP REQUEST ERROR (' + error + ')'); | |
52 | - | |
53 | - } else if (response.statusCode != 200) { | |
54 | - | |
55 | - var error_message = 'GATEWAY ERROR (HTTP RESPONSE CODE: ' + response.statusCode + ')'; | |
56 | - logger.warn(error_message); | |
57 | - callbackReport(task['requestId'], '91', error_message); | |
58 | - | |
59 | - } else { | |
60 | - | |
61 | - logger.info('DIRECT RESPONSE', {body: body}); | |
62 | - | |
63 | - xml2js(body, function (err, result) { | |
64 | - if (err) { | |
65 | - callbackReport(task['requestId'], '40', body); | |
66 | - } else { | |
67 | - var directResponse = result; | |
68 | - logger.info(directResponse); | |
69 | - | |
70 | - try { | |
71 | - var result_price; | |
72 | - try { | |
73 | - result_price = directResponse.Result.Price[0].trim(); | |
74 | - } | |
75 | - catch(err) { | |
76 | - result_price = 0; | |
77 | - } | |
78 | - | |
79 | - var result_error_message; | |
80 | - try { | |
81 | - result_error_message = directResponse.Result.ErrorMsg[0].trim(); | |
82 | - } | |
83 | - catch(err) { | |
84 | - result_error_message = ''; | |
85 | - } | |
86 | - | |
87 | - var resultCode = directResponse.Result.ResultCode[0].trim(); | |
88 | - | |
89 | - responseMessage = | |
90 | - 'ResultCode: ' + resultCode | |
91 | - + ' | ErrorMsg: ' + result_error_message | |
92 | - + ' | DateTime: ' + directResponse.Result.DateTime[0].trim() | |
93 | - + ' | nsm: ' + directResponse.Result.nsm[0].trim() | |
94 | - + ' | idpel: ' + directResponse.Result.idpel[0].trim() | |
95 | - + ' | reffid: ' + directResponse.Result.reffid[0].trim() | |
96 | - + ' | TransID: ' + directResponse.Result.TransID[0].trim() | |
97 | - + ' | reff_switching: ' + directResponse.Result.reff_switching[0].trim() | |
98 | - + ' | amount_trx: ' + directResponse.Result.amount_trx[0].trim() | |
99 | - + ' | token: ' + directResponse.Result.token[0].trim() | |
100 | - + ' | PrevBalance: ' + directResponse.Result.PrevBalance[0].trim() | |
101 | - + ' | Price: ' + result_price | |
102 | - + ' | EndBalance: ' + directResponse.Result.EndBalance[0].trim() | |
103 | - ; | |
104 | - | |
105 | - logger.info('Response message: ' + responseMessage); | |
106 | - | |
107 | - if (aaa) { | |
108 | - // update balance | |
109 | - aaa.updateBalance(directResponse.Result.EndBalance[0]); | |
110 | - } | |
111 | - | |
112 | - if (resultCode == '0000') { | |
113 | - var nama_pelanggan = directResponse.Result.nama_pel[0].trim(); | |
114 | - nama_pelanggan = nama_pelanggan.replace(/-\/-/g, '-'); | |
115 | - var sn = directResponse.Result.token[0].trim() + '/' + nama_pelanggan + '/' + directResponse.Result.tarif[0].trim() + '/' + directResponse.Result.daya[0].trim() + 'VA/' + directResponse.Result.jml_daya[0].trim(); | |
116 | - sn = sn.replace(/\s/g, '-'); | |
117 | - | |
118 | - responseMessage = 'SN=' + sn + '; ' + responseMessage; | |
119 | - logger.info('New response message: ' + responseMessage); | |
120 | - } | |
121 | - | |
122 | - var pendingResultCode = ['0005', '0012', '0068', '0090', '0063', '0018', '0096']; | |
123 | - if (pendingResultCode.indexOf(resultCode) != -1) { | |
124 | - callbackReport(task['requestId'], '68', responseMessage); | |
125 | - | |
126 | - logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms'); | |
127 | - setTimeout(function () { | |
128 | - cekstatus.advice({trxid: directResponse.Result.TransID[0].trim()}, callbackFromWebReport); | |
129 | - }, sleep_before_retry); | |
130 | - | |
131 | - return; | |
132 | - } | |
133 | - | |
134 | - responseCode = resultCode.replace(/^00/, ""); | |
135 | - | |
136 | - if (result_error_message == 'Inq - APLICATION SERVER RESPONSE TIMEOUT') { | |
137 | - responseCode = '91'; | |
138 | - } | |
139 | - | |
140 | - } | |
141 | - catch(err) { | |
142 | - responseCode = '40'; | |
143 | - responseMessage = 'Invalid response from gateway'; | |
144 | - } | |
145 | - } | |
146 | - | |
147 | - callbackReport(task['requestId'], responseCode, responseMessage); | |
148 | - }); | |
149 | - } | |
150 | - | |
151 | - //callbackReport(task['requestId'], responseCode, responseMessage); | |
152 | - }); | |
153 | -} | |
154 | - | |
155 | -function callbackFromWebReport(status) { | |
156 | - if (!status) { | |
157 | - logger.warn('Advice from webreport return empty status'); | |
158 | - return; | |
159 | - } | |
160 | - | |
161 | - logger.info('Got advice result from webreport', {status: status}); | |
162 | - | |
163 | - var responseCode = '68'; | |
164 | - | |
165 | - var result_price = 0; | |
166 | - try { | |
167 | - result_price = directResponse.Result.Price[0].trim(); | |
168 | - } | |
169 | - catch(err) {} | |
170 | - | |
171 | - var errorMsg = ''; | |
172 | - try { | |
173 | - errorMsg = status.response.errormsg[0]; | |
174 | - } | |
175 | - catch(err) {} | |
176 | - | |
177 | - var responseMessage = ''; | |
178 | - try { | |
179 | - responseMessage = | |
180 | - 'Hasil advice dari webreport ' | |
181 | - + 'ResultCode: ' + status.response.resultcode[0] | |
182 | - + ' | ErrorMsg: ' + errorMsg | |
183 | - + ' | DateTime: ' + status.response.datetime[0] | |
184 | - + ' | nsm: ' + status.response.nsm[0] | |
185 | - + ' | idpel: ' + status.response.idpel[0] | |
186 | - + ' | reffid: ' + status.response.reffid[0].trim() | |
187 | - + ' | TransID: ' + status.response.transid[0].trim() | |
188 | - + ' | reff_switching: ' + status.response.reff_switching[0] | |
189 | - + ' | amount_trx: ' + status.response.amount_trx[0] | |
190 | - + ' | token: ' + status.response.token[0] | |
191 | - + ' | PrevBalance: ' + status.response.PrevBalance[0] | |
192 | - + ' | Price: ' + result_price | |
193 | - + ' | EndBalance: ' + status.response.endbalance[0] | |
194 | - ; | |
195 | - } | |
196 | - catch(err) { | |
197 | - logger.warn('Error parsing response message from webreport advice'); | |
198 | - } | |
199 | - | |
200 | - | |
201 | - if ((status.status == 'S') && (status.response.resultcode[0] == '0000')) { | |
202 | - responseCode = '00'; | |
203 | - | |
204 | - var nama_pelanggan = status.response.nama_pel[0] ; | |
205 | - nama_pelanggan = nama_pelanggan.replace(/-\/-/g, '-'); | |
206 | - | |
207 | - var sn = status.response.token[0] + '/' + nama_pelanggan + '/' + status.response.tarif[0] + 'VA' + status.response.jml_daya[0]; | |
208 | - responseMessage = 'SN=' + sn + '; ' + responseMessage; | |
209 | - | |
210 | - } else if ((status.status == 'P') || (status.status == 'W')) { | |
211 | - | |
212 | - callbackReport(task['requestId'], '68', responseMessage); | |
213 | - logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms'); | |
214 | - | |
215 | - setTimeout(function () { | |
216 | - | |
217 | - cekstatus.advice({trxid: status.trxId,}, callbackFromWebReport); | |
218 | - | |
219 | - }, sleep_before_retry); | |
220 | - return; | |
221 | - | |
222 | - } else { | |
223 | - responseCode = status.response.resultcode[0].replace(/^00/, ""); | |
224 | - if (['00', '05', '12', '68', '90', '63', '18', '96'].indexOf(responseCode) >= 0) { | |
225 | - responseCode = '40'; | |
226 | - } | |
227 | - } | |
228 | - | |
229 | - | |
230 | - callbackReport(status.reffId, responseCode, responseMessage); | |
231 | -} | |
232 | - | |
233 | -function createHttpReportServer() { | |
234 | - var httpServer = http.createServer(function(request, response) { | |
235 | - var qs = url.parse(request.url, true).query; | |
236 | - var path = url.parse(request.url).pathname; | |
237 | - | |
238 | - logger.info('Got reverse report from partner', {path: path, qs: qs}); | |
239 | - response.end('OK'); | |
240 | - | |
241 | - var trxid; | |
242 | - try { | |
243 | - trxid = qs.transid; | |
244 | - } | |
245 | - catch(err) { | |
246 | - } | |
247 | - | |
248 | - if (trxid) { | |
249 | - logger.info('Requesting advice from webreport', {trxid: trxid}) | |
250 | - cekstatus.advice({trxid: trxid}, callbackFromWebReport); | |
251 | - } | |
252 | - | |
253 | - }); | |
254 | - | |
255 | - httpServer.listen(config.h2h_out.listen_port, function() { | |
256 | - logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port); | |
257 | - }); | |
258 | -} | |
259 | - | |
260 | -function start(_config, _callbackReport, options) { | |
261 | - config = _config; | |
262 | - callbackReport = _callbackReport; | |
263 | - | |
264 | - if (options && options.aaa) { | |
265 | - aaa = options.aaa; | |
266 | - } | |
267 | - | |
268 | - if (options && options.logger) { | |
269 | - logger = options.logger; | |
270 | - } else { | |
271 | - logger = new winston.Logger({ | |
272 | - transports: [ | |
273 | - new (winston.transports.Console)() | |
274 | - ] | |
275 | - }); | |
276 | - } | |
277 | - | |
278 | - createHttpReportServer(); | |
279 | -} | |
280 | - | |
281 | -exports.start = start; | |
282 | -exports.topupRequest = topupRequest; | |
1 | +var fs = require('fs'); | |
2 | +var https = require('https'); | |
3 | +var http = require('http'); | |
4 | +var url = require('url'); | |
5 | +var request = require('request'); | |
6 | +var xml2js = require('xml2js').parseString; | |
7 | +var strftime = require('strftime'); | |
8 | +var math = require('mathjs'); | |
9 | +var winston = require('winston'); | |
10 | +var cekstatus = require('./cekstatus.js'); | |
11 | + | |
12 | +var config; | |
13 | +var httpServer; | |
14 | +var aaa; | |
15 | +var logger; | |
16 | +var callbackReport; | |
17 | + | |
18 | +process.env.NODE_TLS_REJECT_UNAUTHORIZED = '0'; | |
19 | + | |
20 | +var sleep_before_retry = 30000; | |
21 | + | |
22 | +var logTag = __filename.split('/').reverse()[0]; | |
23 | + | |
24 | +function topupRequest(task) { | |
25 | + | |
26 | + var ts = strftime('%Y%m%d%H%M%S', new Date()); | |
27 | + | |
28 | + var data = | |
29 | + config.h2h_out.userid | |
30 | + + '|' + config.h2h_out.password | |
31 | + + '|' + task['remoteProduct'] | |
32 | + + '|' + task['destination'] + '|0'; | |
33 | + | |
34 | + var options = { | |
35 | + url: config.h2h_out.partner, | |
36 | + qs: { | |
37 | + ts: ts, | |
38 | + data: data, | |
39 | + reffid: task['requestId'] | |
40 | + } | |
41 | + }; | |
42 | + logger.info('Creating http request', {options: options}); | |
43 | + | |
44 | + request(options, function (error, response, body) { | |
45 | + var responseCode = '40'; | |
46 | + var responseMessage = 'Gateway Error'; | |
47 | + | |
48 | + if (error) { | |
49 | + | |
50 | + logger.warn('HTTP REQUEST ERROR', error); | |
51 | + callbackReport(task['requestId'], '89', 'HTTP REQUEST ERROR (' + error + ')'); | |
52 | + | |
53 | + } else if (response.statusCode != 200) { | |
54 | + | |
55 | + var error_message = 'GATEWAY ERROR (HTTP RESPONSE CODE: ' + response.statusCode + ')'; | |
56 | + logger.warn(error_message); | |
57 | + callbackReport(task['requestId'], '91', error_message); | |
58 | + | |
59 | + } else { | |
60 | + | |
61 | + logger.info('DIRECT RESPONSE', {body: body}); | |
62 | + | |
63 | + xml2js(body, function (err, result) { | |
64 | + if (err) { | |
65 | + callbackReport(task['requestId'], '40', body); | |
66 | + } else { | |
67 | + var directResponse = result; | |
68 | + logger.info(directResponse); | |
69 | + | |
70 | + try { | |
71 | + var result_price; | |
72 | + try { | |
73 | + result_price = directResponse.Result.Price[0].trim(); | |
74 | + } | |
75 | + catch(err) { | |
76 | + result_price = 0; | |
77 | + } | |
78 | + | |
79 | + var result_error_message; | |
80 | + try { | |
81 | + result_error_message = directResponse.Result.ErrorMsg[0].trim(); | |
82 | + } | |
83 | + catch(err) { | |
84 | + result_error_message = ''; | |
85 | + } | |
86 | + | |
87 | + var resultCode = directResponse.Result.ResultCode[0].trim(); | |
88 | + | |
89 | + responseMessage = | |
90 | + 'ResultCode: ' + resultCode | |
91 | + + ' | ErrorMsg: ' + result_error_message | |
92 | + + ' | DateTime: ' + directResponse.Result.DateTime[0].trim() | |
93 | + + ' | nsm: ' + directResponse.Result.nsm[0].trim() | |
94 | + + ' | idpel: ' + directResponse.Result.idpel[0].trim() | |
95 | + + ' | reffid: ' + directResponse.Result.reffid[0].trim() | |
96 | + + ' | TransID: ' + directResponse.Result.TransID[0].trim() | |
97 | + + ' | reff_switching: ' + directResponse.Result.reff_switching[0].trim() | |
98 | + + ' | amount_trx: ' + directResponse.Result.amount_trx[0].trim() | |
99 | + + ' | token: ' + directResponse.Result.token[0].trim() | |
100 | + + ' | PrevBalance: ' + directResponse.Result.PrevBalance[0].trim() | |
101 | + + ' | Price: ' + result_price | |
102 | + + ' | EndBalance: ' + directResponse.Result.EndBalance[0].trim() | |
103 | + ; | |
104 | + | |
105 | + logger.info('Response message: ' + responseMessage); | |
106 | + | |
107 | + if (aaa) { | |
108 | + // update balance | |
109 | + aaa.updateBalance(directResponse.Result.EndBalance[0]); | |
110 | + } | |
111 | + | |
112 | + if (resultCode == '0000') { | |
113 | + var nama_pelanggan = directResponse.Result.nama_pel[0].trim(); | |
114 | + nama_pelanggan = nama_pelanggan.replace(/-\/-/g, '-'); | |
115 | + var sn = directResponse.Result.token[0].trim() + '/' + nama_pelanggan + '/' + directResponse.Result.tarif[0].trim() + '/' + directResponse.Result.daya[0].trim() + 'VA/' + directResponse.Result.jml_daya[0].trim(); | |
116 | + sn = sn.replace(/\s/g, '-'); | |
117 | + | |
118 | + responseMessage = 'SN=' + sn + '; ' + responseMessage; | |
119 | + logger.info('New response message: ' + responseMessage); | |
120 | + } | |
121 | + | |
122 | + var pendingResultCode = ['0005', '0012', '0068', '0090', '0063', '0018', '0096']; | |
123 | + if (pendingResultCode.indexOf(resultCode) != -1) { | |
124 | + callbackReport(task['requestId'], '68', responseMessage); | |
125 | + | |
126 | + logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms'); | |
127 | + setTimeout(function () { | |
128 | + cekstatus.advice({trxid: directResponse.Result.TransID[0].trim()}, callbackFromWebReport); | |
129 | + }, sleep_before_retry); | |
130 | + | |
131 | + return; | |
132 | + } | |
133 | + | |
134 | + responseCode = resultCode.replace(/^00/, ""); | |
135 | + | |
136 | + if (result_error_message == 'Inq - APLICATION SERVER RESPONSE TIMEOUT') { | |
137 | + responseCode = '91'; | |
138 | + } | |
139 | + | |
140 | + } | |
141 | + catch(err) { | |
142 | + responseCode = '40'; | |
143 | + responseMessage = 'Invalid response from gateway'; | |
144 | + } | |
145 | + } | |
146 | + | |
147 | + callbackReport(task['requestId'], responseCode, responseMessage); | |
148 | + }); | |
149 | + } | |
150 | + | |
151 | + //callbackReport(task['requestId'], responseCode, responseMessage); | |
152 | + }); | |
153 | +} | |
154 | + | |
155 | +function callbackFromWebReport(status) { | |
156 | + if (!status) { | |
157 | + logger.warn('Advice from webreport return empty status'); | |
158 | + return; | |
159 | + } | |
160 | + | |
161 | + logger.info('Got advice result from webreport', {status: status}); | |
162 | + | |
163 | + var responseCode = '68'; | |
164 | + | |
165 | + var result_price = 0; | |
166 | + try { | |
167 | + result_price = directResponse.Result.Price[0].trim(); | |
168 | + } | |
169 | + catch(err) {} | |
170 | + | |
171 | + var errorMsg = ''; | |
172 | + try { | |
173 | + errorMsg = status.response.errormsg[0]; | |
174 | + } | |
175 | + catch(err) {} | |
176 | + | |
177 | + var responseMessage = ''; | |
178 | + try { | |
179 | + responseMessage = | |
180 | + 'Hasil advice dari webreport ' | |
181 | + + 'ResultCode: ' + status.response.resultcode[0] | |
182 | + + ' | ErrorMsg: ' + errorMsg | |
183 | + + ' | DateTime: ' + status.response.datetime[0] | |
184 | + + ' | nsm: ' + status.response.nsm[0] | |
185 | + + ' | idpel: ' + status.response.idpel[0] | |
186 | + + ' | reffid: ' + status.response.reffid[0].trim() | |
187 | + + ' | TransID: ' + status.response.transid[0].trim() | |
188 | + + ' | reff_switching: ' + status.response.reff_switching[0] | |
189 | + + ' | amount_trx: ' + status.response.amount_trx[0] | |
190 | + + ' | token: ' + status.response.token[0] | |
191 | + + ' | PrevBalance: ' + status.response.PrevBalance[0] | |
192 | + + ' | Price: ' + result_price | |
193 | + + ' | EndBalance: ' + status.response.endbalance[0] | |
194 | + ; | |
195 | + } | |
196 | + catch(err) { | |
197 | + logger.warn('Error parsing response message from webreport advice'); | |
198 | + } | |
199 | + | |
200 | + | |
201 | + if ((status.status == 'S') && (status.response.resultcode[0] == '0000')) { | |
202 | + responseCode = '00'; | |
203 | + | |
204 | + var nama_pelanggan = status.response.nama_pel[0] ; | |
205 | + nama_pelanggan = nama_pelanggan.replace(/-\/-/g, '-'); | |
206 | + | |
207 | + var sn = status.response.token[0] + '/' + nama_pelanggan + '/' + status.response.tarif[0] + 'VA' + status.response.jml_daya[0]; | |
208 | + responseMessage = 'SN=' + sn + '; ' + responseMessage; | |
209 | + | |
210 | + } else if ((status.status == 'P') || (status.status == 'W')) { | |
211 | + | |
212 | + callbackReport(status.response.reffid[0].trim(), '68', responseMessage); | |
213 | + logger.info('Got pending status, requesting advice from webreport in ' + sleep_before_retry + 'ms'); | |
214 | + | |
215 | + setTimeout(function () { | |
216 | + | |
217 | + cekstatus.advice({trxid: status.trxId,}, callbackFromWebReport); | |
218 | + | |
219 | + }, sleep_before_retry); | |
220 | + return; | |
221 | + | |
222 | + } else { | |
223 | + responseCode = status.response.resultcode[0].replace(/^00/, ""); | |
224 | + if (['00', '05', '12', '68', '90', '63', '18', '96'].indexOf(responseCode) >= 0) { | |
225 | + responseCode = '40'; | |
226 | + } | |
227 | + } | |
228 | + | |
229 | + | |
230 | + callbackReport(status.response.reffid[0].trim(), responseCode, responseMessage); | |
231 | +} | |
232 | + | |
233 | +function createHttpReportServer() { | |
234 | + var httpServer = http.createServer(function(request, response) { | |
235 | + var qs = url.parse(request.url, true).query; | |
236 | + var path = url.parse(request.url).pathname; | |
237 | + | |
238 | + logger.info('Got reverse report from partner', {path: path, qs: qs}); | |
239 | + response.end('OK'); | |
240 | + | |
241 | + var trxid; | |
242 | + try { | |
243 | + trxid = qs.transid; | |
244 | + } | |
245 | + catch(err) { | |
246 | + } | |
247 | + | |
248 | + if (trxid) { | |
249 | + logger.info('Requesting advice from webreport', {trxid: trxid}) | |
250 | + cekstatus.advice({trxid: trxid}, callbackFromWebReport); | |
251 | + } | |
252 | + | |
253 | + }); | |
254 | + | |
255 | + httpServer.listen(config.h2h_out.listen_port, function() { | |
256 | + logger.info('HTTP Reverse/Report server listen on port ' + config.h2h_out.listen_port); | |
257 | + }); | |
258 | +} | |
259 | + | |
260 | +function start(_config, _callbackReport, options) { | |
261 | + config = _config; | |
262 | + callbackReport = _callbackReport; | |
263 | + | |
264 | + if (options && options.aaa) { | |
265 | + aaa = options.aaa; | |
266 | + } | |
267 | + | |
268 | + if (options && options.logger) { | |
269 | + logger = options.logger; | |
270 | + } else { | |
271 | + logger = new winston.Logger({ | |
272 | + transports: [ | |
273 | + new (winston.transports.Console)() | |
274 | + ] | |
275 | + }); | |
276 | + } | |
277 | + | |
278 | + createHttpReportServer(); | |
279 | +} | |
280 | + | |
281 | +exports.start = start; | |
282 | +exports.topupRequest = topupRequest; | |
283 | 283 | \ No newline at end of file |