Blame view
partner-kospinjasa.js
14.8 KB
1f837fd31
|
1 2 |
var winston = require('winston'); var soap = require('soap'); |
5a947e400
|
3 4 |
var crypto = require('crypto'); var strftime = require('strftime'); |
97991a1dc
|
5 |
var fs = require("fs"); |
97991a1dc
|
6 |
var http = require("http"); |
e7d59da25
|
7 |
var url = require("url"); |
1caba187c
|
8 9 |
var mongoClient = require('mongodb').MongoClient; var moment = require('moment'); |
97991a1dc
|
10 11 |
process.chdir(__dirname); |
1f837fd31
|
12 13 14 15 16 |
var max_retry = 10; var sleep_before_retry = 5000; var config; |
bc5bcfea8
|
17 |
var matrix; |
1f837fd31
|
18 19 20 21 |
var callbackReport; var aaa; var logger; var options; |
1caba187c
|
22 |
var mongodb; |
1f837fd31
|
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
function start(_config, _callbackReport, options) { config = _config; callbackReport = _callbackReport if (options && options.aaa) { aaa = options.aaa; } if (options && options.logger) { logger = options.logger; } else { logger = new winston.Logger({ transports: [ new (winston.transports.Console)() ] }); } |
1caba187c
|
41 |
|
bc5bcfea8
|
42 43 44 |
if (options && options.matrix) { matrix = options.matrix; } |
1caba187c
|
45 46 |
initMongoClient(); } |
bc5bcfea8
|
47 48 49 50 51 52 53 54 55 56 57 58 59 |
function callbackReportWrapper(requestId, responseCode, message, dontIncrement) { callbackReport(requestId, responseCode, message); if (dontIncrement) { return; } try { aaa.incrementStrikeStatus(responseCode); } catch(err) { logger.warn("Gagal aaa.incrementStrikeStatus: " + err); } } |
1caba187c
|
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
function initMongoClient() { if (!config || !config.mongodb || !config.mongodb.url) { return; } try { var url = config.mongodb.url; mongoClient.connect(url, function(err, db) { if (err) { logger.warn('Failed to connect to mongodb', {err: err}); return; } mongodb = db; logger.info('MongoDB connected'); }); } catch(err) { logger.warn('Exception when connecting to mongodb', {err: err, url: url}); } } function insertTaskToMongoDb(task) { if (!isMongoReady()) { return; } task.supplier = config.globals.gateway_name; task.rc = '68'; try { mongodb.collection(config.mongodb.collection).insertOne(task); } catch(err) { //logger.warn('Exception when inserting document to mongodb', {err: err, task: task}); } } function pushResponseToMongoDb(task, response, rc) { if (!isMongoReady()) { return; } |
2af28a398
|
98 |
|
1caba187c
|
99 |
try { |
2af28a398
|
100 101 102 |
if (!response.ts) { response.ts = strftime('%Y-%m-%d %H:%M:%S', new Date()); } |
1caba187c
|
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
mongodb.collection(config.mongodb.collection).updateOne( {requestId: task.requestId}, { $set: { lastResponse: response, supplier: config.globals.gateway_name, rc: rc }, $push: { responses: response } }, function(err, result) { if (err) { logger.warn('Error when pushing response to mongodb', {err: err, task: task, response: response}); return; } } ); } catch(err) { logger.warn('Exception when pushing response to mongodb', {err: err, task: task, response: response}); } } function isMongoReady() { if (!config.mongodb) { return; } if (!config.mongodb.collection) { return; } if (!mongodb) { return; } return true; |
1f837fd31
|
134 135 136 |
} function topupRequest(task, retry) { |
04671bba9
|
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 |
try { if (config && config.globals && config.globals.reject_on_pending_count && matrix && matrix.strikeStatus && matrix.strikeStatus.pending) { var pendingCount = matrix.strikeStatus.pending; var pendingLimitCount = parseInt(config.globals.reject_on_pending_count); if (pendingLimitCount <= matrix.strikeStatus.pending) { logger.warn( 'Reject trx karena pending terlalu banyak', {pendingCount: pendingCount, pendingLimitCount: pendingLimitCount} ); callbackReport(task.requestId, '13', 'Reject trx karena pending terlalu banyak'); return; } |
bc5bcfea8
|
154 155 |
} } |
04671bba9
|
156 157 158 |
catch(err) { logger.warn("Exception saat periksa pendingLimit: " + err); } |
bc5bcfea8
|
159 |
|
1caba187c
|
160 161 162 163 |
task.ts = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD HH:mm:ss'); task.ts_date = moment(task.timestamp, 'YYYYMMDDHHmmss').format('YYYY-MM-DD'); insertTaskToMongoDb(task); |
9e047c122
|
164 165 166 167 168 169 170 171 172 173 |
saldoCheck(billpayment, task); } function saldoCheck(callback, task) { var params = { userName: config.h2h_out.userid, productCode: '00000' , terminal: 'H2HIPN10', transactionType: '61', |
1c0291c88
|
174 |
reff: Math.ceil( Math.random() * 99999999 ), |
9e047c122
|
175 |
timeStamp: strftime('%Y-%m-%d %H:%M:%S', new Date()) |
1f837fd31
|
176 |
} |
9e047c122
|
177 |
params.signature = createSignatureForSaldoCheck(params, config.h2h_out.password); |
9b569c12b
|
178 |
soap.createClient(config.h2h_out.partner, function(err, soapClient) { |
9e047c122
|
179 180 |
if (err) { |
1caba187c
|
181 182 183 184 |
var errorMessage = 'Error creating soap client for saldoCheck: ' + err; logger.warn(errorMessage, {err: err}); |
bc5bcfea8
|
185 |
callbackReportWrapper(task.requestId, '40', errorMessage); |
2af28a398
|
186 |
pushResponseToMongoDb(task, {supplier: config.globals.gateway_name, raw: errorMessage}, '40'); |
1caba187c
|
187 |
|
9b569c12b
|
188 |
return; |
9e047c122
|
189 |
} |
9b569c12b
|
190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
logger.info('Requesting to service', {url: config.h2h_out.partner, params: params}); soapClient.apih2h.apih2hPort.saldoCheck({ inputSaldo: params }, function(err, result) { logger.verbose( 'Got saldoCheck response', { lastEndpoint: soapClient.lastEndpoint, lastRequest: soapClient.lastRequest, lastMessage: soapClient.lastMessage, lastResponse: soapClient.lastResponse, } ); if (err) { |
1caba187c
|
204 205 206 |
var errorMessage = 'Error requesting saldoCheck: ' + err; logger.warn(errorMessage, {err: err}); |
bc5bcfea8
|
207 |
callbackReportWrapper(task.requestId, '40', errorMessage); |
2af28a398
|
208 |
pushResponseToMongoDb(task, {supplier: config.globals.gateway_name, raw: errorMessage}, '40'); |
9b569c12b
|
209 |
} |
9e047c122
|
210 |
|
9b569c12b
|
211 212 |
var balance; logger.verbose('saldoCheck result', {result: result}); |
9e047c122
|
213 |
|
d309c00e0
|
214 215 216 217 218 219 |
try { balance = result.outputParameter.bit61.$value; } catch(e) { balance = 'UNKNOWN'; } |
9b569c12b
|
220 221 222 223 224 |
if (task) { callback(task, balance); } }); |
7a475ed37
|
225 |
}); |
9e047c122
|
226 227 228 229 |
} function billpayment(task, balance) { |
ba873b76b
|
230 |
var terminalSuffix = Math.ceil( Math.random() * 20 ) + 10; |
5a947e400
|
231 |
var remoteProduct = task.remoteProduct.split(','); |
ba873b76b
|
232 |
|
b6b185202
|
233 |
var params = { |
7f796c813
|
234 235 |
userName: config.h2h_out.userid, productCode: remoteProduct[0] , |
ba873b76b
|
236 |
terminal: 'H2HIPN' + terminalSuffix, |
7f796c813
|
237 238 239 240 241 |
transactionType: '50', billNumber: createBillNumber(task.destination), amount: remoteProduct[1], bit61: createBillNumber(task.destination), reff: task.requestId, |
342d268ac
|
242 |
timeStamp: strftime('%Y-%m-%d %H:%M:%S', new Date()) |
7f796c813
|
243 |
} |
b6b185202
|
244 245 |
var signature = createSignature(params, config.h2h_out.password); params.signature = signature; |
7f796c813
|
246 |
|
777c49c56
|
247 |
soap.createClient(config.h2h_out.partner, function(err, soapClient) { |
35d3e5057
|
248 |
|
699851497
|
249 250 251 252 253 254 255 256 257 258 259 260 |
var _params = { userName: params.userName, signature: params.signature, productCode: params.productCode, terminal: params.terminal, transactionType: params.transactionType, billNumber: params.billNumber, amount: params.amount, bit61: params.bit61, reff: params.reff, timeStamp: params.timeStamp } |
dfaddca74
|
261 |
logger.info('Requesting to billpayment service', {url: config.h2h_out.partner, params: _params}); |
699851497
|
262 263 |
soapClient.apih2h.apih2hPort.billpayment({ inputCheck: _params }, function(err, result) { |
4252c2818
|
264 265 266 267 268 269 270 |
logger.verbose( 'Got response', { lastEndpoint: soapClient.lastEndpoint, lastRequest: soapClient.lastRequest, lastMessage: soapClient.lastMessage, lastResponse: soapClient.lastResponse, |
89c3ecab5
|
271 |
lastElapsedTime: soapClient.lastElapsedTime, |
4252c2818
|
272 273 |
} ); |
3899d9816
|
274 |
|
5a947e400
|
275 |
if (err) { |
dfaddca74
|
276 |
var errorMessage = 'Error requesting billpayment service: ' + err; |
1caba187c
|
277 278 |
logger.warn(errorMessage, {err: err}); |
bc5bcfea8
|
279 |
callbackReportWrapper(task.requestId, '68', errorMessage); |
64e3e4b8c
|
280 |
pushResponseToMongoDb(task, {supplier: config.globals.gateway_name, raw: soapClient.lastResponse}, '68'); |
1caba187c
|
281 |
|
5a947e400
|
282 283 |
return; } |
dfaddca74
|
284 |
topupResponseHandler(task, result, balance, soapClient); |
cb87e5477
|
285 |
}, {timeout: 120000, time: true}, {connection: 'keep-alive'}); |
1f837fd31
|
286 287 |
}); } |
dfaddca74
|
288 |
function topupResponseHandler(task, response, balance, soapClient) { |
4252c2818
|
289 290 |
var st24rc = '68'; var st24message = response.outputParameter.resultDesc.$value; |
97991a1dc
|
291 |
|
aa561d430
|
292 293 |
var resultCode = parseInt(response.outputParameter.resultCode.$value); var bit39 = parseInt(response.outputParameter.bit39.$value); |
064e7c879
|
294 |
var sn = ''; |
aa561d430
|
295 |
if ( resultCode == 1 ) { |
4252c2818
|
296 297 298 |
// product disabled st24rc = '13'; } |
aa561d430
|
299 |
else if ( resultCode == 2 ) { |
4252c2818
|
300 301 302 |
// prodcode disable st24rc = '13'; } |
aa561d430
|
303 |
else if ( resultCode == 3 ) { |
4252c2818
|
304 305 306 |
// duplicate reff st24rc = '55'; } |
aa561d430
|
307 |
else if ( resultCode == 4 ) { |
4252c2818
|
308 309 310 |
// not enough balance st24rc = '40'; } |
aa561d430
|
311 |
else if ( resultCode == 5 ) { |
4252c2818
|
312 313 314 |
// username blocked st24rc = '40'; } |
aa561d430
|
315 |
else if ( resultCode == 6 ) { |
4252c2818
|
316 317 318 |
// not exists username st24rc = '40'; } |
aa561d430
|
319 |
else if ( resultCode == 11 ) { |
4252c2818
|
320 321 322 |
// invalid request st24rc = '40' } |
aa561d430
|
323 |
else if ( resultCode == 12 ) { |
4252c2818
|
324 325 326 |
// no route to host st24rc = '40' } |
aa561d430
|
327 |
else if ( resultCode == 13 ) { |
4252c2818
|
328 329 330 |
// invalid signature st24rc = '40' } |
aa561d430
|
331 |
else if ( bit39 == 6 ) { |
4252c2818
|
332 333 334 |
st24rc = '40'; st24message = 'Error Transaksi ditolak karena terjadi error di H2H dengan response code diluar daftar ini. Silahkan hubungi H2H'; } |
aa561d430
|
335 |
else if ( bit39 == 12 ) { |
4252c2818
|
336 337 338 |
st24rc = '40'; st24message = 'Invalid Transaction Transaksi ditolak karena flow transaksi tidak valid'; } |
aa561d430
|
339 |
else if ( bit39 == 13 ) { |
4252c2818
|
340 341 342 |
st24rc = '13'; st24message = 'Invalid voucher nominal'; } |
aa561d430
|
343 |
else if ( bit39 == 14 ) { |
4252c2818
|
344 345 346 |
st24rc = '14'; st24message = 'MSISDN tidak ditemukan'; } |
aa561d430
|
347 |
else if ( bit39 == 30 ) { |
4252c2818
|
348 349 350 |
st24rc = '40'; st24message = 'Format Error'; } |
aa561d430
|
351 |
else if ( bit39 == 31 ) { |
4252c2818
|
352 353 354 |
st24rc = '40'; st24message = 'Kode bank tidak terdaftar'; } |
aa561d430
|
355 |
else if ( bit39 == 63 ) { |
4252c2818
|
356 357 358 |
st24rc = '40'; st24message = 'Reversal denied'; } |
aa561d430
|
359 |
else if ( bit39 == 68 ) { |
4252c2818
|
360 361 362 |
st24rc = '68'; st24message = 'Transaksi sedang dalam proses'; } |
aa561d430
|
363 |
else if ( bit39 == 69 ) { |
4252c2818
|
364 365 366 |
st24rc = '68'; st24message = 'Respon Ok lebih dari 24 detik'; } |
aa561d430
|
367 |
else if ( bit39 == 70 ) { |
4252c2818
|
368 369 370 |
st24rc = '13'; st24message = 'Voucher out of stock'; } |
aa561d430
|
371 |
else if ( bit39 == 79 ) { |
4252c2818
|
372 373 374 |
st24rc = '14'; st24message = 'Phone number is blocked by Telkomsel'; } |
aa561d430
|
375 |
else if ( bit39 == 81 ) { |
4252c2818
|
376 377 378 |
st24rc = '14'; st24message = 'Phone number is expired'; } |
aa561d430
|
379 |
else if ( bit39 == 89 ) { |
4252c2818
|
380 381 382 |
st24rc = '40'; st24message = 'Link to billing provider is down'; } |
aa561d430
|
383 |
else if ( bit39 == 91 ) { |
4252c2818
|
384 385 386 |
st24rc = '40'; st24message = 'Database problem'; } |
aa561d430
|
387 |
else if ( bit39 == 92 ) { |
4252c2818
|
388 389 390 |
st24rc = '40'; st24message = 'Unable to route transaction'; } |
aa561d430
|
391 |
else if ( bit39 == 94 ) { |
4252c2818
|
392 393 394 |
st24rc = '40'; st24message = 'Duplicate reversal request'; } |
aa561d430
|
395 |
else if ( resultCode == 0 && bit39 == 0) { |
aa561d430
|
396 397 398 |
try { sn = response.outputParameter.bit61.$value.substring(43); } |
e2e928e50
|
399 |
catch(e) { |
aa561d430
|
400 401 402 403 404 405 |
sn = ''; } st24message = 'SN=' + sn + '; ' + st24message; st24rc = '00'; } |
97991a1dc
|
406 |
|
4252c2818
|
407 408 409 |
var message = response.outputParameter.resultCode.$value + " " + response.outputParameter.resultDesc.$value |
aa561d430
|
410 |
+ "; BIT39: " + response.outputParameter.bit39.$value |
4252c2818
|
411 |
; |
97991a1dc
|
412 |
|
4252c2818
|
413 414 415 |
if (response.outputParameter.resultDesc.$value != st24message) { var message = message + " " + st24message; } |
97991a1dc
|
416 |
|
d309c00e0
|
417 |
message = message + ' -- Prev Balance: ' + balance; |
64e3e4b8c
|
418 |
var parsedResponse = { |
a5668f44f
|
419 420 421 422 423 424 425 426 427 428 429 |
productCode: response.outputParameter.productCode.$value, terminal: response.outputParameter.terminal.$value, transactionType: response.outputParameter.transactionType.$value, billNumber: response.outputParameter.billNumber.$value, amount: response.outputParameter.amount.$value, bit61: response.outputParameter.bit61.$value, reff: response.outputParameter.reff.$value, timeStamp: response.outputParameter.timeStamp.$value, resultCode: response.outputParameter.resultCode.$value, resultDesc: response.outputParameter.resultDesc.$value, bit39: response.outputParameter.bit39.$value, |
dfaddca74
|
430 |
st24Message: st24message, |
064e7c879
|
431 |
sn: sn, |
dfaddca74
|
432 433 |
prevBalance: balance, processTime: soapClient.lastElapsedTime, |
64e3e4b8c
|
434 |
} |
872fa65c3
|
435 436 437 |
var combinedMessage = ''; Object.keys(parsedResponse).forEach(function(key,index) { |
064e7c879
|
438 |
combinedMessage += key + ': ' + parsedResponse[key] + '; ' |
872fa65c3
|
439 440 441 442 |
}); combinedMessage = combinedMessage.trim(); parsedResponse.MESSAGE = combinedMessage; |
13e965f4e
|
443 |
logger.info('Got result: ' + message, {response: response}); |
bc5bcfea8
|
444 |
callbackReportWrapper(task.requestId, st24rc, st24message + ' -- Prev Balance: ' + balance); |
dfaddca74
|
445 |
pushResponseToMongoDb(task, {supplier: config.globals.gateway_name, raw: soapClient.lastResponse, parsed: parsedResponse}, st24rc); |
97991a1dc
|
446 |
} |
b6b185202
|
447 |
function createSignature(params, password) { |
5a947e400
|
448 |
var passwordHash = crypto.createHash('sha256').update(password).digest().toString('hex'); |
dfcc535b5
|
449 |
var plain = |
b6b185202
|
450 |
params.userName |
5a947e400
|
451 |
+ passwordHash |
b6b185202
|
452 453 454 455 456 457 458 |
+ params.productCode + params.terminal + params.transactionType + params.billNumber + params.amount + params.reff + params.timeStamp; |
dfcc535b5
|
459 |
|
4252c2818
|
460 |
return crypto.createHash('sha1').update(plain).digest().toString('hex'); |
5a947e400
|
461 |
} |
9e047c122
|
462 463 464 465 466 467 468 469 470 471 472 473 474 |
function createSignatureForSaldoCheck(params, password) { var passwordHash = crypto.createHash('sha256').update(password).digest().toString('hex'); var plain = params.userName + passwordHash + params.productCode + params.terminal + params.transactionType + params.reff + params.timeStamp; return crypto.createHash('sha1').update(plain).digest().toString('hex'); } |
5a947e400
|
475 476 |
function createBillNumber(destination) { return ("0000000000000" + destination).slice(-13); |
1f837fd31
|
477 478 479 480 |
} exports.start = start; exports.topupRequest = topupRequest; |
5a947e400
|
481 482 |
exports.createSignature = createSignature; exports.createBillNumber = createBillNumber; |