index.js 5.45 KB
const DEFAULT_CORE_REQUEST_TIMEOUT = 5 * 1000;
const DEFAULT_SLEEP_AFTER_CORE_ERROR_MS = 3000;
const MAX_REPORT_RETRY = 30;
const REPORT_RETRY_SLEEP_MS = 2000;

const axios = require('axios').default;

const config = require('komodo-sdk/config');
const coreUrl = require('komodo-sdk/core-url');
const logger = require('komodo-sdk/logger');

const sleep = require('./lib/sleep');

let partner;
let first = true;
let coreIsHealthy = null;
// let skipNext = 0;

const DEFAULT_CORE_AXIOS_CONFIG = {
    headers: { 'Content-Type': 'application/json' },
    timeout: config.core_request_timeout || config.request_timeout || DEFAULT_CORE_REQUEST_TIMEOUT,
};

const GET_TASK_AXIOS_CONFIG = DEFAULT_CORE_AXIOS_CONFIG;
const REPORT_AXIOS_CONFIG = DEFAULT_CORE_AXIOS_CONFIG;

function detectCoreStatusChange(isHealthy, url, err) {
    if (coreIsHealthy !== isHealthy) {
        coreIsHealthy = isHealthy;

        if (isHealthy) {
            logger.info('POSTPAID2-SDK: CORE is healthy now', { url, err: err && err.message });
        } else {
            logger.warn('POSTPAID2-SDK: CORE is unhealthy now', { url, err: err && err.message });
        }
    }
}

async function getTask() {
    if (!partner) return null;

    // if (skipNext > 0) {
    //     skipNext -= 1;
    //     return null;
    // }

    if (first) {
        first = false;
        logger.verbose('POSTPAID2-SDK: first pull request to CORE');
    }

    const coreEndpoint = `${coreUrl}/postpaid2/task`;

    const payload = {
        handler: config.handler || config.handler_name,
        products: config.products || [],
    };

    let task;
    try {
        const result = await axios.post(
            coreEndpoint, payload, GET_TASK_AXIOS_CONFIG,
        );

        if (!result || !result.data) throw new Error('POSTPAID2-SDK: Empty CORE response on pulling task. MARK-26F332C6');
        if (result && result.data && result.data.task && !result.data.task.postpaid) throw new Error('POSTPAID2-SDK: CORE returning non postpaid task on pulling task. MARK-B338CEF8');

        detectCoreStatusChange(true, coreEndpoint);
        task = result.data.task;
    } catch (e) {
        // skipNext = 3;
        detectCoreStatusChange(false, coreEndpoint, e);
        await sleep(DEFAULT_SLEEP_AFTER_CORE_ERROR_MS);
    }

    if (!task) return null;

    task.remote_product = ((config.remote_products || {})[task.product]) || task.product;
    task.trx_id = Number(task.trx_id) + (config.sdk_trx_id_adder || 0);

    logger.verbose('POSTPAID2-SDK: Got task from CORE on pulling task', { task });

    if (task.inquiry_only) {
        if (typeof partner.inquiry === 'function') partner.inquiry(task);
        return task;
    }

    if (typeof partner.pay === 'function') {
        partner.pay(task);
        return task;
    }

    return null;
}

const getTaskLooper = async () => {
    await getTask();

    setTimeout(() => {
        getTaskLooper();
    }, config.postpaid_pull_interval_ms || config.pull_interval_ms || 1000);
};

exports.setPartner = (val) => {
    partner = val;
    // setInterval(getTaskLooper, config.pull_interval_ms || 1000);
    getTaskLooper();
};

exports.report = async (data, xid, retry) => {
    if (!data.trx_id) {
        logger.warn('POSTPAID2-SDK: INVALID DATA TO REPORT. No trx id in report. MARK-3A37B7CA', { xid, data });
        return;
    }

    if (!data.rc || typeof data.rc !== 'string') {
        logger.warn('POSTPAID2-SDK: INVALID DATA TO REPORT. Rc is not valid. MARK-41ED74FC', {
            xid, trxId: data.trx_id, rc: data.rc, typeofRc: typeof data.rc,
        });
    }

    const dataToReport = {
        handler: config.handler || config.handler_name,
        command: data.command,
        trx_id: Number(data.trx_id) - (config.sdk_trx_id_adder || 0),
        rc: data.rc,
        sn: data.sn,
        amount: data.amount,
        base_bill_amount: data.base_bill_amount,
        bill_count: data.bill_count,
        message: data.message,
        info: data.info,
        detail: data.detail,
        data: data.data,
        struk: data.struk,
    };

    logger.verbose('POSTPAID2-SDK: Going to report to CORE', {
        xid,
        trxId: data.trx_id,
        rc: data.rc,
        sn: data.sn,
        amount: data.amount,
        baseBillAmount: data.base_bill_amount,
    });

    const coreEndpoint = `${coreUrl}/postpaid2/report`;

    try {
        const reportResult = await axios.post(
            coreEndpoint, JSON.stringify(dataToReport), REPORT_AXIOS_CONFIG,
        );

        if (!reportResult) {
            logger.warn('POSTPAID2-SDK: unknown result from CORE on reporting trx result. MARK-795C53DB');
        }
    } catch (e) {
        const newRetry = (retry || 0) + 1;
        logger.warn('POSTPAID2-SDK: Exception on reporting trx result to CORE. MARK-E7F000D8', {
            xid, err: e.message, retry: newRetry, maxRetry: MAX_REPORT_RETRY,
        });

        if (!this || !this.report) {
            logger.warn('POSTPAID2-SDK: Can not retry report because of unkown this.report!');
            return;
        }

        if (newRetry < MAX_REPORT_RETRY) {
            setTimeout(() => {
                logger.info('POSTPAID2-SDK: Retrying to send report to CORE', {
                    xid,
                    trxId: data.trx_id,
                    rc: data.rc,
                    sn: data.sn,
                    amount: data.amount,
                    baseBillAmount: data.base_bill_amount,
                });

                this.report(data, xid, newRetry);
            }, REPORT_RETRY_SLEEP_MS);
        }
    }
};