Commit 733cd34aeb76867a7b38508bc99c73e56bbeb1b8
1 parent
5e82936a82
Exists in
master
resendDelay
Showing 1 changed file with 9 additions and 0 deletions Inline Diff
partner-bnisp.js
1 | "use strict"; | 1 | "use strict"; |
2 | 2 | ||
3 | const http = require('http'); | 3 | const http = require('http'); |
4 | http.globalAgent.maxSockets = Infinity; | 4 | http.globalAgent.maxSockets = Infinity; |
5 | 5 | ||
6 | const request = require('request'); | 6 | const request = require('request'); |
7 | const resendDelay = require('./resend-delay') | ||
7 | 8 | ||
8 | var config; | 9 | var config; |
9 | var aaa; | 10 | var aaa; |
10 | var logger; | 11 | var logger; |
11 | 12 | ||
12 | function start(options) { | 13 | function start(options) { |
13 | if (!options) { | 14 | if (!options) { |
14 | console.log('Undefined options, terminating....'); | 15 | console.log('Undefined options, terminating....'); |
15 | process.exit(1); | 16 | process.exit(1); |
16 | } | 17 | } |
17 | 18 | ||
18 | if (options.config) { | 19 | if (options.config) { |
19 | config = options.config; | 20 | config = options.config; |
20 | } else { | 21 | } else { |
21 | console.log('Undefined options.config, terminating....') | 22 | console.log('Undefined options.config, terminating....') |
22 | process.exit(1); | 23 | process.exit(1); |
23 | } | 24 | } |
24 | 25 | ||
25 | if (options.aaa) { | 26 | if (options.aaa) { |
26 | aaa = options.aaa; | 27 | aaa = options.aaa; |
27 | } else { | 28 | } else { |
28 | console.log('Undefined options.aaa, terminating....') | 29 | console.log('Undefined options.aaa, terminating....') |
29 | process.exit(1); | 30 | process.exit(1); |
30 | } | 31 | } |
31 | 32 | ||
32 | if (options && options.logger) { | 33 | if (options && options.logger) { |
33 | logger = options.logger; | 34 | logger = options.logger; |
34 | } else { | 35 | } else { |
35 | console.log('Undefined options.logger, terminating....') | 36 | console.log('Undefined options.logger, terminating....') |
36 | process.exit(1); | 37 | process.exit(1); |
37 | } | 38 | } |
39 | |||
40 | resendDelay.init({config: config, logger: logger, topupRequest: topupAdvice}); | ||
38 | } | 41 | } |
39 | 42 | ||
40 | function callbackReport(requestId, rc, message, options) { | 43 | function callbackReport(requestId, rc, message, options) { |
44 | if (rc == '68') { | ||
45 | resendDelay.register(options.task); | ||
46 | } else { | ||
47 | resendDelay.cancel(options.task) | ||
48 | } | ||
49 | |||
41 | aaa.callbackReportWithPushToMongoDb(requestId, rc, message); | 50 | aaa.callbackReportWithPushToMongoDb(requestId, rc, message); |
42 | } | 51 | } |
43 | 52 | ||
44 | function splitRemoteProduct(remoteProduct) { | 53 | function splitRemoteProduct(remoteProduct) { |
45 | return remoteProduct.replace(/^\s+|\s+$/gm,'').split(/[\/\W]+/); | 54 | return remoteProduct.replace(/^\s+|\s+$/gm,'').split(/[\/\W]+/); |
46 | } | 55 | } |
47 | 56 | ||
48 | function topupRequest(task) { | 57 | function topupRequest(task) { |
49 | aaa.insertTaskToMongoDb(task); | 58 | aaa.insertTaskToMongoDb(task); |
50 | 59 | ||
51 | const remoteProduct = splitRemoteProduct(task.remoteProduct); | 60 | const remoteProduct = splitRemoteProduct(task.remoteProduct); |
52 | 61 | ||
53 | if (remoteProduct.length < 4) { | 62 | if (remoteProduct.length < 4) { |
54 | callbackReport(task.requestId, '40', 'INTERNAL_MSG: Invalid remoteProduct', task) | 63 | callbackReport(task.requestId, '40', 'INTERNAL_MSG: Invalid remoteProduct', task) |
55 | return; | 64 | return; |
56 | } | 65 | } |
57 | 66 | ||
58 | let pathParams = { | 67 | let pathParams = { |
59 | request_type: "purchase", | 68 | request_type: "purchase", |
60 | noid: config.h2h_out.noid, | 69 | noid: config.h2h_out.noid, |
61 | token: config.h2h_out.token, | 70 | token: config.h2h_out.token, |
62 | product: remoteProduct[0], | 71 | product: remoteProduct[0], |
63 | product_type: remoteProduct[1], | 72 | product_type: remoteProduct[1], |
64 | id_pel: task.destination, | 73 | id_pel: task.destination, |
65 | nominal: remoteProduct[2], | 74 | nominal: remoteProduct[2], |
66 | admin: remoteProduct[3], | 75 | admin: remoteProduct[3], |
67 | trace_id: task.requestId | 76 | trace_id: task.requestId |
68 | } | 77 | } |
69 | 78 | ||
70 | const requestOptions = { | 79 | const requestOptions = { |
71 | url: config.h2h_out.partner.replace(/\/+$/, '') + '/' + createUrlPath(pathParams).replace(/^\/+/, '') | 80 | url: config.h2h_out.partner.replace(/\/+$/, '') + '/' + createUrlPath(pathParams).replace(/^\/+/, '') |
72 | } | 81 | } |
73 | 82 | ||
74 | logger.verbose('Requeting to partner', {requestOptions: requestOptions}); | 83 | logger.verbose('Requeting to partner', {requestOptions: requestOptions}); |
75 | request(requestOptions, function(error, response, body) { | 84 | request(requestOptions, function(error, response, body) { |
76 | if (error) { | 85 | if (error) { |
77 | let rc = '68'; | 86 | let rc = '68'; |
78 | 87 | ||
79 | if (!error.syscall == 'connect') { | 88 | if (!error.syscall == 'connect') { |
80 | rc = '91'; | 89 | rc = '91'; |
81 | } | 90 | } |
82 | 91 | ||
83 | logger.warn('Error requesting to partner', {task: task, rc: rc, error: error}); | 92 | logger.warn('Error requesting to partner', {task: task, rc: rc, error: error}); |
84 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Error requesting to partner. ' + error, {task: task}); | 93 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Error requesting to partner. ' + error, {task: task}); |
85 | return; | 94 | return; |
86 | } | 95 | } |
87 | 96 | ||
88 | if (response.statusCode != 200) { | 97 | if (response.statusCode != 200) { |
89 | let rc = '68'; | 98 | let rc = '68'; |
90 | 99 | ||
91 | logger.warn('HTTP status code is not 200', {task: task, http_status_code: response.statusCode}); | 100 | logger.warn('HTTP status code is not 200', {task: task, http_status_code: response.statusCode}); |
92 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: HTTP status code ' + response.statusCode, {task: task}); | 101 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: HTTP status code ' + response.statusCode, {task: task}); |
93 | return; | 102 | return; |
94 | } | 103 | } |
95 | 104 | ||
96 | if (!body) { | 105 | if (!body) { |
97 | let rc = '68'; | 106 | let rc = '68'; |
98 | 107 | ||
99 | logger.warn('Missing response body', {task: task, responseBody: body}); | 108 | logger.warn('Missing response body', {task: task, responseBody: body}); |
100 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Missing response body', {task: task}); | 109 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Missing response body', {task: task}); |
101 | return; | 110 | return; |
102 | } | 111 | } |
103 | 112 | ||
104 | if (body.trim() == 'invalid specs') { | 113 | if (body.trim() == 'invalid specs') { |
105 | let rc = '40'; | 114 | let rc = '40'; |
106 | 115 | ||
107 | logger.warn('Invalid specs', {task: task, responseBody: body}); | 116 | logger.warn('Invalid specs', {task: task, responseBody: body}); |
108 | callbackReport(task.requestId, rc, body); | 117 | callbackReport(task.requestId, rc, body); |
109 | return; | 118 | return; |
110 | } | 119 | } |
111 | 120 | ||
112 | logger.verbose('Got response from partner', {task: task, responseBody: body}); | 121 | logger.verbose('Got response from partner', {task: task, responseBody: body}); |
113 | 122 | ||
114 | const responseData = parseResponseBody(body); | 123 | const responseData = parseResponseBody(body); |
115 | logger.verbose('Response body parsed as json value', {responseData: responseData}); | 124 | logger.verbose('Response body parsed as json value', {responseData: responseData}); |
116 | const data = responseDataProcessor(responseData); | 125 | const data = responseDataProcessor(responseData); |
117 | 126 | ||
118 | if (data.balance && aaa.updateBalance) { | 127 | if (data.balance && aaa.updateBalance) { |
119 | aaa.updateBalance(data.balance); | 128 | aaa.updateBalance(data.balance); |
120 | } | 129 | } |
121 | 130 | ||
122 | callbackReport(task.requestId, data.rc, data.combinedMessage, {task: task}); | 131 | callbackReport(task.requestId, data.rc, data.combinedMessage, {task: task}); |
123 | }) | 132 | }) |
124 | 133 | ||
125 | } | 134 | } |
126 | 135 | ||
127 | function topupAdvice(task) { | 136 | function topupAdvice(task) { |
128 | 137 | ||
129 | let pathParams = { | 138 | let pathParams = { |
130 | noid: config.h2h_out.noid, | 139 | noid: config.h2h_out.noid, |
131 | token: config.h2h_out.token, | 140 | token: config.h2h_out.token, |
132 | trace_id: task.requestId | 141 | trace_id: task.requestId |
133 | } | 142 | } |
134 | 143 | ||
135 | const requestOptions = { | 144 | const requestOptions = { |
136 | url: config.h2h_out.partner.replace(/\/+$/, '') + '/' + createUrlPathAdvice(pathParams).replace(/^\/+/, '') | 145 | url: config.h2h_out.partner.replace(/\/+$/, '') + '/' + createUrlPathAdvice(pathParams).replace(/^\/+/, '') |
137 | } | 146 | } |
138 | 147 | ||
139 | logger.verbose('Requeting advice to partner', {requestOptions: requestOptions}); | 148 | logger.verbose('Requeting advice to partner', {requestOptions: requestOptions}); |
140 | request(requestOptions, function(error, response, body) { | 149 | request(requestOptions, function(error, response, body) { |
141 | if (error) { | 150 | if (error) { |
142 | let rc = '68'; | 151 | let rc = '68'; |
143 | 152 | ||
144 | logger.warn('Error requesting to advice partner', {task: task, rc: rc, error: error}); | 153 | logger.warn('Error requesting to advice partner', {task: task, rc: rc, error: error}); |
145 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Error requesting advice to partner. ' + error, {task: task}); | 154 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Error requesting advice to partner. ' + error, {task: task}); |
146 | return; | 155 | return; |
147 | } | 156 | } |
148 | 157 | ||
149 | if (response.statusCode != 200) { | 158 | if (response.statusCode != 200) { |
150 | let rc = '68'; | 159 | let rc = '68'; |
151 | 160 | ||
152 | logger.warn('Advice HTTP status code is not 200', {task: task, http_status_code: response.statusCode}); | 161 | logger.warn('Advice HTTP status code is not 200', {task: task, http_status_code: response.statusCode}); |
153 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Advice HTTP status code ' + response.statusCode, {task: task}); | 162 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Advice HTTP status code ' + response.statusCode, {task: task}); |
154 | return; | 163 | return; |
155 | } | 164 | } |
156 | 165 | ||
157 | if (!body) { | 166 | if (!body) { |
158 | let rc = '68'; | 167 | let rc = '68'; |
159 | 168 | ||
160 | logger.warn('Missing advice response body', {task: task, responseBody: body}); | 169 | logger.warn('Missing advice response body', {task: task, responseBody: body}); |
161 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Missing advice response body', {task: task}); | 170 | callbackReport(task.requestId, rc, 'INTERNAL_MSG: Missing advice response body', {task: task}); |
162 | return; | 171 | return; |
163 | } | 172 | } |
164 | 173 | ||
165 | if (body.trim() == 'invalid specs') { | 174 | if (body.trim() == 'invalid specs') { |
166 | let rc = '68'; | 175 | let rc = '68'; |
167 | 176 | ||
168 | logger.warn('Invalid specs', {task: task, responseBody: body}); | 177 | logger.warn('Invalid specs', {task: task, responseBody: body}); |
169 | callbackReport(task.requestId, rc, body); | 178 | callbackReport(task.requestId, rc, body); |
170 | return; | 179 | return; |
171 | } | 180 | } |
172 | 181 | ||
173 | logger.verbose('Got advice response from partner', {task: task, responseBody: body}); | 182 | logger.verbose('Got advice response from partner', {task: task, responseBody: body}); |
174 | 183 | ||
175 | const responseData = parseResponseBody(body); | 184 | const responseData = parseResponseBody(body); |
176 | logger.verbose('Advice response body parsed as json value', {responseData: responseData}); | 185 | logger.verbose('Advice response body parsed as json value', {responseData: responseData}); |
177 | const data = responseDataProcessor(responseData); | 186 | const data = responseDataProcessor(responseData); |
178 | 187 | ||
179 | if (data.balance && aaa.updateBalance) { | 188 | if (data.balance && aaa.updateBalance) { |
180 | aaa.updateBalance(data.balance); | 189 | aaa.updateBalance(data.balance); |
181 | } | 190 | } |
182 | 191 | ||
183 | callbackReport(task.requestId, data.rc, data.combinedMessage, {task: task}); | 192 | callbackReport(task.requestId, data.rc, data.combinedMessage, {task: task}); |
184 | }) | 193 | }) |
185 | 194 | ||
186 | } | 195 | } |
187 | 196 | ||
188 | function createUrlPath(options) { | 197 | function createUrlPath(options) { |
189 | let urlPath = [ | 198 | let urlPath = [ |
190 | "get", | 199 | "get", |
191 | options.request_type || "purchase", | 200 | options.request_type || "purchase", |
192 | "json", | 201 | "json", |
193 | options.noid, | 202 | options.noid, |
194 | options.token, | 203 | options.token, |
195 | options.product, | 204 | options.product, |
196 | options.product_type, | 205 | options.product_type, |
197 | options.id_pel, | 206 | options.id_pel, |
198 | options.nominal || 0, | 207 | options.nominal || 0, |
199 | options.admin || 0, | 208 | options.admin || 0, |
200 | options.trace_id | 209 | options.trace_id |
201 | ].join('/'); | 210 | ].join('/'); |
202 | 211 | ||
203 | return '/' + urlPath; | 212 | return '/' + urlPath; |
204 | } | 213 | } |
205 | 214 | ||
206 | function createUrlPathAdvice(options) { | 215 | function createUrlPathAdvice(options) { |
207 | // pattern: /get/advice/json/[noid]/[token]/[traceid] | 216 | // pattern: /get/advice/json/[noid]/[token]/[traceid] |
208 | 217 | ||
209 | let urlPath = [ | 218 | let urlPath = [ |
210 | "get", | 219 | "get", |
211 | "advice", | 220 | "advice", |
212 | "json", | 221 | "json", |
213 | options.noid, | 222 | options.noid, |
214 | options.token, | 223 | options.token, |
215 | options.trace_id | 224 | options.trace_id |
216 | ].join('/'); | 225 | ].join('/'); |
217 | 226 | ||
218 | return '/' + urlPath; | 227 | return '/' + urlPath; |
219 | } | 228 | } |
220 | 229 | ||
221 | function parseResponseBody(body) { | 230 | function parseResponseBody(body) { |
222 | let data; | 231 | let data; |
223 | 232 | ||
224 | try { | 233 | try { |
225 | data = JSON.parse(body); | 234 | data = JSON.parse(body); |
226 | } | 235 | } |
227 | catch(e) { | 236 | catch(e) { |
228 | if (logger) { | 237 | if (logger) { |
229 | logger.warn('Exception on parsing result body: ' + e); | 238 | logger.warn('Exception on parsing result body: ' + e); |
230 | return; | 239 | return; |
231 | } | 240 | } |
232 | } | 241 | } |
233 | 242 | ||
234 | return data; | 243 | return data; |
235 | } | 244 | } |
236 | 245 | ||
237 | function responseDataProcessor(responseData) { | 246 | function responseDataProcessor(responseData) { |
238 | let retval = { | 247 | let retval = { |
239 | rc: '68', | 248 | rc: '68', |
240 | sn: '', | 249 | sn: '', |
241 | responseMessage: '', | 250 | responseMessage: '', |
242 | combinedMessage: '', | 251 | combinedMessage: '', |
243 | amount: 0, | 252 | amount: 0, |
244 | balance: 0, | 253 | balance: 0, |
245 | saldo: 0, | 254 | saldo: 0, |
246 | ts: '', | 255 | ts: '', |
247 | loadTime: 0, | 256 | loadTime: 0, |
248 | product: '', | 257 | product: '', |
249 | productType: '' | 258 | productType: '' |
250 | } | 259 | } |
251 | 260 | ||
252 | let combinedMessage = []; | 261 | let combinedMessage = []; |
253 | 262 | ||
254 | if (responseData.response_code == '0000') { | 263 | if (responseData.response_code == '0000') { |
255 | retval.rc = '00'; | 264 | retval.rc = '00'; |
256 | } | 265 | } |
257 | else if (responseData.response_code == '0010') { | 266 | else if (responseData.response_code == '0010') { |
258 | retval.rc = '14'; | 267 | retval.rc = '14'; |
259 | } | 268 | } |
260 | else if (responseData.response_code == '0021') { | 269 | else if (responseData.response_code == '0021') { |
261 | retval.rc = '14'; | 270 | retval.rc = '14'; |
262 | } | 271 | } |
263 | else if (['9990','0099','0068','0063','0005','9997','9999','9998','9990','0600','1003'].indexOf(responseData.response_code) >= 0) { | 272 | else if (['9990','0099','0068','0063','0005','9997','9999','9998','9990','0600','1003'].indexOf(responseData.response_code) >= 0) { |
264 | retval.rc = '68'; | 273 | retval.rc = '68'; |
265 | } | 274 | } |
266 | else { | 275 | else { |
267 | retval.rc = '40'; | 276 | retval.rc = '40'; |
268 | } | 277 | } |
269 | 278 | ||
270 | if (responseData.response_code) { | 279 | if (responseData.response_code) { |
271 | combinedMessage.push(responseData.response_code); | 280 | combinedMessage.push(responseData.response_code); |
272 | } | 281 | } |
273 | 282 | ||
274 | if (responseData.product) { | 283 | if (responseData.product) { |
275 | combinedMessage.push(responseData.product) | 284 | combinedMessage.push(responseData.product) |
276 | } | 285 | } |
277 | 286 | ||
278 | if (responseData.produk_tipe) { | 287 | if (responseData.produk_tipe) { |
279 | combinedMessage.push(responseData.produk_tipe) | 288 | combinedMessage.push(responseData.produk_tipe) |
280 | } | 289 | } |
281 | 290 | ||
282 | if (responseData.idpel) { | 291 | if (responseData.idpel) { |
283 | combinedMessage.push(responseData.idpel) | 292 | combinedMessage.push(responseData.idpel) |
284 | } | 293 | } |
285 | 294 | ||
286 | retval.responseMessage = responseData.response_message || ''; | 295 | retval.responseMessage = responseData.response_message || ''; |
287 | if (retval.responseMessage) { | 296 | if (retval.responseMessage) { |
288 | combinedMessage.push(retval.responseMessage); | 297 | combinedMessage.push(retval.responseMessage); |
289 | } | 298 | } |
290 | 299 | ||
291 | if (responseData.detail) { | 300 | if (responseData.detail) { |
292 | retval.sn = responseData.detail.voucherSerialNumber || ''; | 301 | retval.sn = responseData.detail.voucherSerialNumber || ''; |
293 | } | 302 | } |
294 | 303 | ||
295 | retval.amount = responseData.amount || 0; | 304 | retval.amount = responseData.amount || 0; |
296 | combinedMessage.push('Amount: ' + retval.amount); | 305 | combinedMessage.push('Amount: ' + retval.amount); |
297 | 306 | ||
298 | retval.balance = responseData.saldo || 0; | 307 | retval.balance = responseData.saldo || 0; |
299 | retval.saldo = retval.balance; | 308 | retval.saldo = retval.balance; |
300 | combinedMessage.push('Balance: ' + retval.balance); | 309 | combinedMessage.push('Balance: ' + retval.balance); |
301 | 310 | ||
302 | retval.ts = responseData.waktu || ''; | 311 | retval.ts = responseData.waktu || ''; |
303 | combinedMessage.push(retval.ts); | 312 | combinedMessage.push(retval.ts); |
304 | 313 | ||
305 | retval.loadTime = responseData.loadTime || ''; | 314 | retval.loadTime = responseData.loadTime || ''; |
306 | combinedMessage.push('Load time: ' + retval.loadTime); | 315 | combinedMessage.push('Load time: ' + retval.loadTime); |
307 | 316 | ||
308 | retval.combinedMessage = combinedMessage.join(' | '); | 317 | retval.combinedMessage = combinedMessage.join(' | '); |
309 | 318 | ||
310 | if (retval.sn) { | 319 | if (retval.sn) { |
311 | retval.combinedMessage = 'SN=' + retval.sn + '; ' + retval.combinedMessage; | 320 | retval.combinedMessage = 'SN=' + retval.sn + '; ' + retval.combinedMessage; |
312 | } | 321 | } |
313 | 322 | ||
314 | return retval; | 323 | return retval; |
315 | } | 324 | } |
316 | 325 | ||
317 | exports.start = start; | 326 | exports.start = start; |
318 | exports.topupRequest = topupRequest; | 327 | exports.topupRequest = topupRequest; |
319 | exports.topupAdvice = topupAdvice; | 328 | exports.topupAdvice = topupAdvice; |
320 | exports.createUrlPath = createUrlPath; | 329 | exports.createUrlPath = createUrlPath; |
321 | exports.createUrlPathAdvice = createUrlPathAdvice; | 330 | exports.createUrlPathAdvice = createUrlPathAdvice; |
322 | exports.parseResponseBody = parseResponseBody; | 331 | exports.parseResponseBody = parseResponseBody; |
323 | exports.responseDataProcessor = responseDataProcessor; | 332 | exports.responseDataProcessor = responseDataProcessor; |
324 | exports.splitRemoteProduct = splitRemoteProduct; | 333 | exports.splitRemoteProduct = splitRemoteProduct; |
325 | 334 |