const MODULE_NAME = 'CORE-CALLBACK.SENDER'; const axios = require('axios'); const config = require('komodo-sdk/config'); const logger = require('tektrans-logger'); const dumper = require('./dumper/sender'); const matrix = require('../matrix'); const webhookSender = require('../webhook-sender'); const HTTP_TIMEOUT = Number( config.callback_sender && config.callback_sender.http_timeout_ms, ) || 30 * 1000; const SLEEP_BEFORE_RETRY_MS = Number( config.callback_sender && config.callback_sender.sleep_before_retry_ms, ) || 10 * 1000; const MAX_RETRY = Number( config.callback_sender && config.callback_sender.max_retry, ) || 10; logger.verbose(`${MODULE_NAME} 848B9104: Initialized`, { HTTP_TIMEOUT, SLEEP_BEFORE_RETRY_MS, MAX_RETRY, }); const axiosHeaders = { 'Content-Type': 'application/json', 'User-Agent': 'KOMODO-HTTPGETX callback sender', }; const sleep = require('../sleep'); const urlConcatQs = require('../url-concat-qs'); const sender = async (data, xid, retry) => { const params = { httpgetx_xid: xid, command: data.command, request_id: data.request_id && data.request_id.toString(), transaction_id: data.transaction_id && data.transaction_id.toString(), transaction_date: data.transaction_date, store_name: data.store_name, terminal_name: data.terminal_name, product_name: data.product_name, destination: data.destination, rc: data.rc, sn: data.sn || undefined, amount: Number(data.amount) || undefined, ending_balance: Number(data.ending_balance) || undefined, message: data.message, bill_count: Number(data.bill_count) || undefined, bill_amount: Number(data.bill_amount) || undefined, fee_per_bill: Number(data.fee) || undefined, fee_total: Number(data.fee_total) || undefined, bill_detail: data.bill_detail || undefined, struk: data.struk || undefined, }; if (data.command === 'INQUIRY' && data.amount_to_charge) { params.amount_to_charge = data.amount_to_charge; } const isPostpaid = ['INQUIRY', 'PAY'].indexOf(data.command) >= 0; const isHttpPost = isPostpaid; try { const webhookType = 'KOMODO-CENTER-HTTPGETX.CORE-CALLBACK'; webhookSender(xid, webhookType, params); } catch (e) { logger.warn(`${MODULE_NAME} 1E2BF2CD: Exception calling webhookSender`, { xid, }); } if (!data.reverse_url) { logger.verbose(`${MODULE_NAME} C4FF18FB: Ignoring missing reverse url`, { xid, dataFromCore: data, }); return; } const endpointUrl = isHttpPost ? data.reverse_url : urlConcatQs(data.reverse_url, params); logger.info(`${MODULE_NAME} 8B6A4CEC: Sending to PARTNER`, { xid, retry: retry || 0, isPostpaid, isHttpPost, endpointUrl, }); let responseToDump; let errorResponseToDump; try { const response = isHttpPost ? await axios.post(data.reverse_url, params, { timeout: HTTP_TIMEOUT, headers: axiosHeaders, }) : await axios.get(data.reverse_url, { params, timeout: HTTP_TIMEOUT, headers: axiosHeaders, }); responseToDump = response; matrix.callback_sender.sent += 1; matrix.callback_sender.active_count += 1; matrix.callback_sender.active_sending[xid] = { ts: new Date(), trxId: data.trx_id, reverseUrl: data.reverse_url, }; if (isPostpaid) { matrix.callback_sender.sent_using_post += 1; } else { matrix.callback_sender.sent_using_get += 1; } logger.info(`${MODULE_NAME} 3641FBD7: Has been sent to PARTNER successfully`, { xid, retry, httpStatus: response.status, responseBody: response && response.data, }); } catch (e) { matrix.callback_sender.sent_failed += 1; matrix.callback_sender.last_error = { xid, ts: new Date(), eCode: e.code, eMessage: e.message, trxId: data.trx_id, reverseUrl: data.reverse_url, httpStatus: e.response && e.response.status, responseBody: e.response && e.response.data, }; responseToDump = e.response && e.response.data; errorResponseToDump = e; logger.warn(`${MODULE_NAME} A1EC9E70: Failed on sending to PARTNER`, { xid, retry, maxRetry: MAX_RETRY, errCode: e.code, errMessage: e.message, reverseUrl: data.reverse_url, endpointUrl, httpStatus: e.response && e.response.status, responseBody: e.response && e.response.data, }); if (e.response && e.response.status) { logger.verbose(`${MODULE_NAME} 10AE785C: Skip retry on http status presence`, { xid, httpStatus: e.response && e.response.status, }); return; } if ((retry || 0) < MAX_RETRY) { await sleep(SLEEP_BEFORE_RETRY_MS); logger.verbose(`${MODULE_NAME} D8958695: Going to retry sending CORE-CALLBACK TO PARTNER`, { xid, retried: retry, sleepTime: SLEEP_BEFORE_RETRY_MS, }); sender(data, xid, (retry || 0) + 1); } } finally { matrix.callback_sender.active_count -= 1; if (matrix.callback_sender.active_sending[xid]) { delete matrix.callback_sender.active_sending[xid]; } dumper( xid, isHttpPost ? 'POST' : 'GET', endpointUrl, params, responseToDump, errorResponseToDump, ); } }; module.exports = sender;