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