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