Commit 5f881b0a757c7a60645f46fa7330cc46607896bc

Authored by Adhidarma Hadiwinoto
1 parent b2d7e7957d
Exists in master

support advice url

Showing 1 changed file with 1 additions and 1 deletions Inline Diff

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