UNPKG

bc-payments-sdk

Version:

BetterCommerce's Payments NodeJS SDK is a complete solution for storefront clients that integrate payments. `bc-payments-sdk` is a single point interface for storefront clients for interacting with payment gateways.

493 lines 87.1 kB
"use strict"; var __rest = (this && this.__rest) || function (s, e) { var t = {}; for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) t[p] = s[p]; if (s != null && typeof Object.getOwnPropertySymbols === "function") for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) { if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i])) t[p[i]] = s[p[i]]; } return t; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BetterCommerceOperation = void 0; // Other Imports const Logger_1 = require("../modules/better-commerce/Logger"); const B2B_1 = require("../modules/better-commerce/B2B"); const Order_1 = require("../modules/better-commerce/Order"); const PaymentMethod_1 = require("../modules/better-commerce/PaymentMethod"); const PayPalPayment_1 = require("../modules/payments/PayPalPayment"); const CheckoutPayment_1 = require("../modules/payments/CheckoutPayment"); const Checkout_1 = require("../modules/better-commerce/Checkout"); const constants_1 = require("../constants/constants"); const BCEnvironment_1 = require("../base/config/BCEnvironment"); const PaymentStatus_1 = require("../constants/enums/PaymentStatus"); const PaymentMethodType_1 = require("../constants/enums/PaymentMethodType"); const PaymentStatus_2 = require("../constants/enums/PaymentStatus"); const StripePayment_1 = require("../modules/payments/StripePayment"); const OrderStatus_1 = require("../constants/enums/OrderStatus"); const KlarnaPayment_1 = require("../modules/payments/KlarnaPayment"); const ClearPayPament_1 = require("../modules/payments/ClearPayPament"); const constants_2 = require("../constants"); const parse_util_1 = require("../utils/parse-util"); const payment_util_1 = require("../utils/payment-util"); const OmniCapitalPayment_1 = require("../modules/payments/OmniCapitalPayment"); const NuveiPayment_1 = require("../modules/payments/NuveiPayment"); const constants_3 = require("../constants/constants"); /** * Class {BetterCommerceOperation} is the main entry point for all the operations related to BetterCommerce. * It contains methods for getting order details, creating orders, updating orders, getting payment methods, processing payments and more. * @implements {ICommerceProvider} */ class BetterCommerceOperation { /** * Retrieves the company details by user id. This method is used to get the company details which is linked to the user * API Reference - https://api20.bettercommerce.io/swagger/ui/index#!/B2B/B2BGetCompanyDetailByUserId * @param data - The data which contains the user id * @returns The company details */ async getCompanyDetails(data) { var _a, _b; const companyDetailsResult = await B2B_1.B2B.getCompanyDetailsByUserId(data, { headers: (_a = data === null || data === void 0 ? void 0 : data.extras) === null || _a === void 0 ? void 0 : _a.headers, cookies: (_b = data === null || data === void 0 ? void 0 : data.extras) === null || _b === void 0 ? void 0 : _b.cookies }); return companyDetailsResult; } /** * Converts a basket into an order on the CommerceHub platform. * API Reference - https://api20.bettercommerce.io/swagger/ui/index#!/Checkout/CheckoutConvertBasket * @param data - The data which contains the basket id * @returns The order details response from the CommerceHub platform */ async convertOrder(data) { var _a, _b; const createOrderResult = await Checkout_1.Checkout.convertOrder(data, { headers: (_a = data === null || data === void 0 ? void 0 : data.extras) === null || _a === void 0 ? void 0 : _a.headers, cookies: (_b = data === null || data === void 0 ? void 0 : data.extras) === null || _b === void 0 ? void 0 : _b.cookies }); return createOrderResult; } /** * Processes a payment based on the provided payment data. * * This method handles different payment gateways, including PayPal, Checkout, * Stripe, Klarna, and ClearPay. It retrieves payment method details, constructs * the order model with payment information, and updates the payment response. * The method also handles Cash on Delivery (COD) orders and different payment * statuses such as authorized, paid, declined, and pending. * * @param data - The payment processing data, including order details, payment * method, extras, and more. * @returns A promise that resolves to the payment status or an error object * if an error occurs during the payment process. */ async processPayment(data) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14; try { const getPaymentInfoPayload = (paymentInfo) => { /* ****** Info ****** paymentInfo1 is for [pspInformation[] paymentInfo2 is for [paymentIdentifier] paymentInfo3 is for gateway type i.e. Billdesk, Razorpay, etc paymentInfo4 is for [cardType] paymentInfo5 is for [cardIssuer] paymentInfo6 is for [cardBrand] paymentInfo7 is for [chequeNumber] paymentInfo8 is untilized */ let info = {}; if (paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo1) { info = Object.assign(Object.assign({}, info), { paymentInfo1: paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo1 }); } if (paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo2) { info = Object.assign(Object.assign({}, info), { paymentInfo2: paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo2 }); } if (paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo3) { info = Object.assign(Object.assign({}, info), { paymentInfo3: paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo3 }); } if (paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo4) { info = Object.assign(Object.assign({}, info), { paymentInfo4: paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo4 }); } if (paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo5) { info = Object.assign(Object.assign({}, info), { paymentInfo5: paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo5 }); } if (paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo6) { info = Object.assign(Object.assign({}, info), { paymentInfo6: paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo6 }); } if (paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo7) { info = Object.assign(Object.assign({}, info), { paymentInfo7: paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo7 }); } if (paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo8) { info = Object.assign(Object.assign({}, info), { paymentInfo8: paymentInfo === null || paymentInfo === void 0 ? void 0 : paymentInfo.paymentInfo8 }); } return info; }; let orderModel; const isCancelled = (_b = (_a = data === null || data === void 0 ? void 0 : data.extras) === null || _a === void 0 ? void 0 : _a.isCancelled) !== null && _b !== void 0 ? _b : false; const gateway = ((_c = data === null || data === void 0 ? void 0 : data.extras) === null || _c === void 0 ? void 0 : _c.gateway) || constants_1.Defaults.String.Value; let paymentType = ((_d = data === null || data === void 0 ? void 0 : data.extras) === null || _d === void 0 ? void 0 : _d.paymentType) || constants_2.PaymentSelectionType.FULL; // Default value is FULL let partialAmount = ((_e = data === null || data === void 0 ? void 0 : data.extras) === null || _e === void 0 ? void 0 : _e.partialAmount) || constants_1.Defaults.Int.Value; // Default value is 0 if (gateway) { let paymentGatewayOrderTxnId = ""; // For PayPal, Checkout, Stripe, Klarna & ClearPay if ((gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_f = PaymentMethodType_1.PaymentMethodType.PAYPAL) === null || _f === void 0 ? void 0 : _f.toLowerCase()) || (gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_g = PaymentMethodType_1.PaymentMethodType.CHECKOUT) === null || _g === void 0 ? void 0 : _g.toLowerCase()) || (gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_h = PaymentMethodType_1.PaymentMethodType.STRIPE) === null || _h === void 0 ? void 0 : _h.toLowerCase()) || (gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_j = PaymentMethodType_1.PaymentMethodType.KLARNA) === null || _j === void 0 ? void 0 : _j.toLowerCase()) || (gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_k = PaymentMethodType_1.PaymentMethodType.CLEAR_PAY) === null || _k === void 0 ? void 0 : _k.toLowerCase()) || (gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_l = PaymentMethodType_1.PaymentMethodType.OMNICAPITAL) === null || _l === void 0 ? void 0 : _l.toLowerCase())) { // For PayPal, Checkout, Stripe, Klarna & ClearPay, the order id is the payment gateway order txn id paymentGatewayOrderTxnId = (_m = data === null || data === void 0 ? void 0 : data.extras) === null || _m === void 0 ? void 0 : _m.orderId; } else if ((gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_o = PaymentMethodType_1.PaymentMethodType.NUVEI) === null || _o === void 0 ? void 0 : _o.toLowerCase()) || (gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_p = PaymentMethodType_1.PaymentMethodType.NUVEI_GOOGLE_PAY) === null || _p === void 0 ? void 0 : _p.toLowerCase())) { paymentGatewayOrderTxnId = (_q = data === null || data === void 0 ? void 0 : data.extras) === null || _q === void 0 ? void 0 : _q.token; // data?.extras?.orderId; } // Get payment method const paymentMethod = await this.getPaymentMethod(gateway, { headers: (_r = data === null || data === void 0 ? void 0 : data.extras) === null || _r === void 0 ? void 0 : _r.headers, cookies: (_s = data === null || data === void 0 ? void 0 : data.extras) === null || _s === void 0 ? void 0 : _s.cookies }); // If payment method is found if (paymentMethod) { // Get additional service charge const additionalServiceCharge = ((_t = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.settings) === null || _t === void 0 ? void 0 : _t.length) ? ((_v = (_u = paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.settings) === null || _u === void 0 ? void 0 : _u.find((x) => (x === null || x === void 0 ? void 0 : x.key) === "AdditionalServiceCharge")) === null || _v === void 0 ? void 0 : _v.value) || "0" : "0"; const { isCOD, orderId, txnOrderId, bankOfferDetails } = data; // Get order details const { result: orderResult } = await Order_1.Order.get(orderId, { headers: (_w = data === null || data === void 0 ? void 0 : data.extras) === null || _w === void 0 ? void 0 : _w.headers, cookies: (_x = data === null || data === void 0 ? void 0 : data.extras) === null || _x === void 0 ? void 0 : _x.cookies }); const _15 = data === null || data === void 0 ? void 0 : data.extras, { headers, cookies } = _15, rest = __rest(_15, ["headers", "cookies"]); // If order is found if (orderResult) { let paymentStatus; // Get order amount const orderAmount = ((_z = (_y = orderResult === null || orderResult === void 0 ? void 0 : orderResult.grandTotal) === null || _y === void 0 ? void 0 : _y.raw) === null || _z === void 0 ? void 0 : _z.withTax) || 0; // Get amount to be paid let amountToBePaid = (paymentType === constants_2.PaymentSelectionType.FULL) ? orderAmount : partialAmount; //console.log({ gateway, paymentType, orderAmount, partialAmount }) // If this is COD order. if (isCOD) { let paymentInfo9 = 0; let isLastPartialPayment = false; if (paymentType === constants_2.PaymentSelectionType.PARTIAL) { const payments = (orderResult === null || orderResult === void 0 ? void 0 : orderResult.payments) || []; const orderPayments = (payments === null || payments === void 0 ? void 0 : payments.filter((x) => (x === null || x === void 0 ? void 0 : x.isPartialPaymentEnabled) && (x === null || x === void 0 ? void 0 : x.orderAmount) == orderAmount)) || []; const totalPartiallyPaidAmount = (orderPayments === null || orderPayments === void 0 ? void 0 : orderPayments.reduce((sum, x) => sum + x.paidAmount, 0)) || 0; console.log('totalPartiallyPaidAmount', totalPartiallyPaidAmount); if (totalPartiallyPaidAmount > 0) { isLastPartialPayment = ((totalPartiallyPaidAmount + partialAmount) === orderAmount); } paymentInfo9 = !isLastPartialPayment ? partialAmount : orderAmount; } orderModel = Object.assign({ id: txnOrderId === null || txnOrderId === void 0 ? void 0 : txnOrderId.split('-')[1], cardNo: null, orderNo: parseInt(txnOrderId === null || txnOrderId === void 0 ? void 0 : txnOrderId.split('-')[0]), orderAmount: orderAmount, paidAmount: 0.0, balanceAmount: orderAmount, isValid: true, status: !isCancelled ? PaymentStatus_1.PaymentStatus.AUTHORIZED : PaymentStatus_1.PaymentStatus.DECLINED, authCode: null, issuerUrl: null, paRequest: null, pspSessionCookie: null, pspResponseCode: null, pspResponseMessage: null, paymentGatewayId: paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.id, paymentGateway: paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.systemName, token: null, payerId: null, cvcResult: null, avsResult: null, secure3DResult: null, cardHolderName: null, issuerCountry: null, info1: '', fraudScore: null, paymentMethod: gateway, cardType: null, operatorId: null, refStoreId: null, tillNumber: null, externalRefNo: null, expiryYear: null, expiryMonth: null, isMoto: true, upFrontPayment: false, upFrontAmount: '0.00', upFrontTerm: '76245369', isPrePaid: false, additionalServiceCharge: additionalServiceCharge }, Object.assign(Object.assign({}, getPaymentInfoPayload((_0 = data === null || data === void 0 ? void 0 : data.extras) === null || _0 === void 0 ? void 0 : _0.paymentInfo)), { paymentInfo9 })); paymentStatus = { statusId: PaymentStatus_1.PaymentStatus.AUTHORIZED, }; } else { if ((gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_1 = PaymentMethodType_1.PaymentMethodType.ACCOUNT_CREDIT) === null || _1 === void 0 ? void 0 : _1.toLowerCase()) || (gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_2 = PaymentMethodType_1.PaymentMethodType.WALLET) === null || _2 === void 0 ? void 0 : _2.toLowerCase())) { paymentStatus = { statusId: PaymentStatus_1.PaymentStatus.PAID, purchaseAmount: orderAmount }; } else if ((gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_3 = PaymentMethodType_1.PaymentMethodType.CHEQUE) === null || _3 === void 0 ? void 0 : _3.toLowerCase())) { paymentStatus = { statusId: PaymentStatus_1.PaymentStatus.AUTHORIZED, purchaseAmount: orderAmount }; } else if ((gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_4 = PaymentMethodType_1.PaymentMethodType.OMNICAPITAL) === null || _4 === void 0 ? void 0 : _4.toLowerCase())) { const apiPaymentStatus = await this.getPaymentStatus(gateway, paymentGatewayOrderTxnId); paymentStatus = { statusId: apiPaymentStatus.statusId, purchaseAmount: apiPaymentStatus.purchaseAmount /*orderAmount*/ }; } else { // Call gateway specific SDK API to get the order/payment status. paymentStatus = await this.getPaymentStatus(gateway, paymentGatewayOrderTxnId); paymentType = paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.paymentType; partialAmount = paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.partialAmount; amountToBePaid = (paymentType === constants_2.PaymentSelectionType.FULL) ? orderAmount : partialAmount; } /**************** This block is for partial payments only (STARTS) ****************/ let paymentInfo9 = 0; let isLastPartialPayment = false; let isPartialPaymentEnabled = (paymentType === constants_2.PaymentSelectionType.PARTIAL); // For partial payment, re-evaluate the payment status. // Except for COD & Cheque, all other payment methods support partial payments. if (![(_5 = PaymentMethodType_1.PaymentMethodType.COD) === null || _5 === void 0 ? void 0 : _5.toLowerCase(), (_6 = PaymentMethodType_1.PaymentMethodType.CHEQUE) === null || _6 === void 0 ? void 0 : _6.toLowerCase()].includes(gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase())) { // Get all payments for this order. const payments = (orderResult === null || orderResult === void 0 ? void 0 : orderResult.payments) || []; // Get all partial payments for this order. const orderPayments = (payments === null || payments === void 0 ? void 0 : payments.filter((x) => (x === null || x === void 0 ? void 0 : x.isPartialPaymentEnabled) && (x === null || x === void 0 ? void 0 : x.orderAmount) == orderAmount)) || []; // Calculate the total partially paid amount for this order. const totalPartiallyPaidAmount = (orderPayments === null || orderPayments === void 0 ? void 0 : orderPayments.reduce((sum, x) => sum + x.paidAmount, 0)) || 0; console.log('totalPartiallyPaidAmount', totalPartiallyPaidAmount); // Is this a partial payment? let isPartialPayment = (paymentType === constants_2.PaymentSelectionType.PARTIAL); // If payment type is FULL and there are any partial payments, then it is next partial payment. if (paymentType === constants_2.PaymentSelectionType.FULL && totalPartiallyPaidAmount > 0) { // This is a partial payment. isPartialPayment = true; isPartialPaymentEnabled = true; // Calculate the partial amount. partialAmount = orderAmount - totalPartiallyPaidAmount; } // If this is a partial payment. if (isPartialPayment) { // Always set paymentInfo9 to partial amount. paymentInfo9 = partialAmount; // If there are any partial payments, check if the total paid amount is equal to the order amount. if (totalPartiallyPaidAmount > 0) { isLastPartialPayment = ((totalPartiallyPaidAmount + partialAmount) === orderAmount); paymentStatus = { // If the [total partially paid + current partial amount] is equal to the order amount, then the payment status is PAID. statusId: isLastPartialPayment ? PaymentStatus_1.PaymentStatus.PAID : PaymentStatus_1.PaymentStatus.PENDING, purchaseAmount: isLastPartialPayment ? orderAmount : amountToBePaid, paymentInfo: (paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.paymentInfo) || null }; } else { paymentStatus = { statusId: PaymentStatus_1.PaymentStatus.PENDING, purchaseAmount: amountToBePaid, paymentInfo: (paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.paymentInfo) || null }; } } } /**************** This block is for partial payments only (ENDS) ****************/ //console.log('paymentStatus', paymentStatus) orderModel = Object.assign({ id: txnOrderId === null || txnOrderId === void 0 ? void 0 : txnOrderId.split('-')[1], cardNo: null, orderNo: parseInt(txnOrderId === null || txnOrderId === void 0 ? void 0 : txnOrderId.split('-')[0]), orderAmount, paidAmount: !isCancelled ? paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.purchaseAmount : 0, balanceAmount: (paymentType === constants_2.PaymentSelectionType.PARTIAL) ? (orderAmount - partialAmount) : 0, isValid: true, status: !isCancelled ? paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.statusId : PaymentStatus_1.PaymentStatus.DECLINED, authCode: !isCancelled ? ((gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()) === ((_7 = PaymentMethodType_1.PaymentMethodType.PAYPAL) === null || _7 === void 0 ? void 0 : _7.toLowerCase())) ? (_8 = data === null || data === void 0 ? void 0 : data.extras) === null || _8 === void 0 ? void 0 : _8.token : paymentGatewayOrderTxnId : null, issuerUrl: null, paRequest: null, pspSessionCookie: JSON.stringify(Object.assign({}, rest)), pspResponseCode: null, pspResponseMessage: null, paymentGatewayId: paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.id, paymentGateway: paymentMethod === null || paymentMethod === void 0 ? void 0 : paymentMethod.systemName, token: null, payerId: null, cvcResult: null, avsResult: null, secure3DResult: null, cardHolderName: null, issuerCountry: null, info1: '', fraudScore: null, paymentMethod: gateway, cardType: null, operatorId: null, refStoreId: null, tillNumber: null, externalRefNo: null, expiryYear: null, expiryMonth: null, isMoto: false, upFrontPayment: false, upFrontAmount: '0.00', isPrePaid: !isCOD, isPartialPaymentEnabled, discountedTotal: (_9 = bankOfferDetails === null || bankOfferDetails === void 0 ? void 0 : bankOfferDetails.discountedTotal) !== null && _9 !== void 0 ? _9 : 0, externalPromoCode: (_10 = bankOfferDetails === null || bankOfferDetails === void 0 ? void 0 : bankOfferDetails.voucherCode) !== null && _10 !== void 0 ? _10 : null, externalVoucher: (bankOfferDetails === null || bankOfferDetails === void 0 ? void 0 : bankOfferDetails.voucherCode) ? { code: bankOfferDetails === null || bankOfferDetails === void 0 ? void 0 : bankOfferDetails.offerCode, additionalInfo1: bankOfferDetails === null || bankOfferDetails === void 0 ? void 0 : bankOfferDetails.value, additionalInfo2: bankOfferDetails === null || bankOfferDetails === void 0 ? void 0 : bankOfferDetails.status, } : null }, Object.assign(Object.assign({}, getPaymentInfoPayload((paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.paymentInfo) || ((_11 = data === null || data === void 0 ? void 0 : data.extras) === null || _11 === void 0 ? void 0 : _11.paymentInfo))), { paymentInfo9 })); } if (orderModel) { const paymentResponseInput = { model: orderModel, orderId: orderId, }; console.log('---- paymentResponseInput ----', JSON.stringify(paymentResponseInput)); await Logger_1.Logger.logPayment({ data: orderModel, message: `${gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()} | UpdatePaymentResponse API20 Request` }, { headers: {}, cookies: {} }); const { result: paymentResponseResult } = await Checkout_1.Checkout.updatePaymentResponse(paymentResponseInput, { headers: (_12 = data === null || data === void 0 ? void 0 : data.extras) === null || _12 === void 0 ? void 0 : _12.headers, cookies: (_13 = data === null || data === void 0 ? void 0 : data.extras) === null || _13 === void 0 ? void 0 : _13.cookies }); if (paymentResponseResult) { await Logger_1.Logger.logPayment({ data: paymentResponseResult, message: `${gateway === null || gateway === void 0 ? void 0 : gateway.toLowerCase()} | UpdatePaymentResponse API20 Response` }, { headers: {}, cookies: {} }); // Get order details const { result: orderResultPostPaymentResponse } = await Order_1.Order.get(orderId, { cookies: (_14 = data === null || data === void 0 ? void 0 : data.extras) === null || _14 === void 0 ? void 0 : _14.cookies }); console.log("---- orderResultPostPaymentResponse ----", orderResultPostPaymentResponse); return isCancelled ? PaymentStatus_1.PaymentStatus.DECLINED : ((paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.statusId) === PaymentStatus_1.PaymentStatus.INITIATED) ? PaymentStatus_1.PaymentStatus.INITIATED : (((paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.statusId) === PaymentStatus_1.PaymentStatus.PAID || (paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.statusId) === PaymentStatus_1.PaymentStatus.AUTHORIZED) || ((orderResultPostPaymentResponse === null || orderResultPostPaymentResponse === void 0 ? void 0 : orderResultPostPaymentResponse.id) && (orderResultPostPaymentResponse === null || orderResultPostPaymentResponse === void 0 ? void 0 : orderResultPostPaymentResponse.orderStatusCode) === OrderStatus_1.OrderStatus.APPROVED)) ? PaymentStatus_1.PaymentStatus.PAID : PaymentStatus_1.PaymentStatus.PENDING; /*return isCancelled ? PaymentStatus.DECLINED : ((gateway?.toLowerCase() === PaymentMethodType.PAYPAL?.toLowerCase() && paymentStatus?.statusId === PaymentStatus.PAID) || (orderResultPostPaymentResponse?.id && orderResultPostPaymentResponse?.orderStatusCode === OrderStatus.APPROVED)) ? PaymentStatus.PAID : PaymentStatus.PENDING;*/ } } } } } } catch (error) { await Logger_1.Logger.logPayment(error, { headers: {}, cookies: {} }); return { hasError: true, error: error }; } return null; } /** * Process the payment hook. * @param {IPaymentHookProcessingData} data The payment hook processing data. * @returns {Promise<any>} The promise of the processed payment hook result. */ async processPaymentHook(data) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r; try { await Logger_1.Logger.logPayment({ data, message: `Log | WebhookData | processPaymentHook` }, { headers: {}, cookies: {} }); let paymentNo, orderNo; let paymentGatewayOrderTxnId = constants_1.Defaults.String.Value; const { paymentMethodTypeId, paymentMethodType, data: hookData } = data; // Special handling for OmniCapital // ================================ // The UrlEncoded webhook data from Omnicapital doesn't handle encoded data, which is a bug at their end. // Therefore, use API key from config instead of webhook data // This fixes the URL decoding issue where '+' becomes ' ' in webhook data if (paymentMethodTypeId === constants_2.PaymentMethodTypeId.OMNICAPITAL) { if (constants_3.DEBUG_LOGGING_ENABLED) { // TODO: Debugging Log await Logger_1.Logger.logPayment({ data: { hookData }, message: `Log | hookData | ${hookData === null || hookData === void 0 ? void 0 : hookData.Status}` }, { headers: {}, cookies: {} }); } // Ensure BCEnvironment is properly initialized for OmniCapital webhooks // The extras are passed inside hookData.extras from the webhook handler const extras = hookData === null || hookData === void 0 ? void 0 : hookData.extras; if ((extras === null || extras === void 0 ? void 0 : extras.clientId) && (extras === null || extras === void 0 ? void 0 : extras.sharedSecret)) { console.log('--- Initializing BCEnvironment for OmniCapital webhook ---'); BCEnvironment_1.BCEnvironment.init(extras.clientId, extras.sharedSecret, extras.config, extras.authUrl, extras.baseUrl); // Also add extras to BCEnvironment for OmniCapitalEnvironment to use BCEnvironment_1.BCEnvironment.addExtras({ country: (extras === null || extras === void 0 ? void 0 : extras.country) || 'GB', currency: (extras === null || extras === void 0 ? void 0 : extras.currency) || 'GBP', language: (extras === null || extras === void 0 ? void 0 : extras.language) || 'en' }); } else { console.error('--- WARNING: Missing BCEnvironment credentials for OmniCapital webhook ---'); console.error('hookData.extras:', hookData === null || hookData === void 0 ? void 0 : hookData.extras); console.error('data structure:', { paymentMethodTypeId, paymentMethodType, dataKeys: Object.keys(data) }); } // Replace API key if needed if (hookData === null || hookData === void 0 ? void 0 : hookData.api_key) { const config = BCEnvironment_1.BCEnvironment.getConfig(); const configApiKey = (_b = (_a = config === null || config === void 0 ? void 0 : config.settings) === null || _a === void 0 ? void 0 : _a.find((x) => x.key === "Signature")) === null || _b === void 0 ? void 0 : _b.value; if (configApiKey) { console.log('--- Replacing OmniCapital API key from config ---'); hookData.api_key = configApiKey; } } } // Read transaction type from the incoming hook data. const paymentTransactionStatus = (0, payment_util_1.getPaymentTransactionStatus)(paymentMethodTypeId, hookData); console.log('--- paymentTransactionStatus ---', paymentTransactionStatus); if (constants_3.DEBUG_LOGGING_ENABLED) { // TODO: Debugging Log await Logger_1.Logger.logPayment({ data: { paymentTransactionStatus }, message: `Log | ${hookData === null || hookData === void 0 ? void 0 : hookData.Status}` }, { headers: {}, cookies: {} }); } // If web hook transaction is applicable for further processing. if (paymentTransactionStatus.toLowerCase() !== constants_1.PaymentTransactionStatus.NONE.toLowerCase()) { let orderId; if (paymentMethodTypeId === constants_2.PaymentMethodTypeId.PAYPAL) { const details = await (0, payment_util_1.getPaymentTransactionOrderId)(paymentMethodTypeId, hookData); console.log('--- details ---', details); if (details) { orderId = details === null || details === void 0 ? void 0 : details.split(',')[0]; const paymentNoDetails = details === null || details === void 0 ? void 0 : details.split(',')[1]; if (paymentNoDetails && ((_c = paymentNoDetails === null || paymentNoDetails === void 0 ? void 0 : paymentNoDetails.split('-')) === null || _c === void 0 ? void 0 : _c.length)) { orderNo = paymentNoDetails === null || paymentNoDetails === void 0 ? void 0 : paymentNoDetails.split('-')[0]; paymentNo = paymentNoDetails === null || paymentNoDetails === void 0 ? void 0 : paymentNoDetails.split('-')[1]; } } } else if (paymentMethodTypeId === constants_2.PaymentMethodTypeId.OMNICAPITAL) { orderId = await (0, payment_util_1.getPaymentTransactionOrderId)(paymentMethodTypeId, hookData); const retailerUniqueRef = hookData === null || hookData === void 0 ? void 0 : hookData["Identification[RetailerUniqueRef]"]; if (retailerUniqueRef) { const json = (0, parse_util_1.tryParseJson)(retailerUniqueRef); if ((json === null || json === void 0 ? void 0 : json.orderId) && ((_e = (_d = json === null || json === void 0 ? void 0 : json.orderId) === null || _d === void 0 ? void 0 : _d.split('-')) === null || _e === void 0 ? void 0 : _e.length)) { orderNo = (_f = json === null || json === void 0 ? void 0 : json.orderId) === null || _f === void 0 ? void 0 : _f.split('-')[0]; paymentNo = (_g = json === null || json === void 0 ? void 0 : json.orderId) === null || _g === void 0 ? void 0 : _g.split('-')[1]; } } } else { orderId = await (0, payment_util_1.getPaymentTransactionOrderId)(paymentMethodTypeId, hookData); } console.log('--- orderId ---', orderId); if (constants_3.DEBUG_LOGGING_ENABLED) { // TODO: Debugging Log await Logger_1.Logger.logPayment({ data: { orderId }, message: `Log | ${hookData === null || hookData === void 0 ? void 0 : hookData.Status} | orderId` }, { headers: {}, cookies: {} }); } if (orderId != constants_1.Defaults.Guid.Value) { const { result: orderResult } = await Order_1.Order.get(orderId, { headers: ((_h = data === null || data === void 0 ? void 0 : data.extras) === null || _h === void 0 ? void 0 : _h.headers) || {}, cookies: constants_1.Defaults.Object.Value }); console.log('--- orderResult ---', orderResult); if ((orderResult === null || orderResult === void 0 ? void 0 : orderResult.id) && (orderResult === null || orderResult === void 0 ? void 0 : orderResult.id) != constants_1.Defaults.Guid.Value) { if (paymentMethodTypeId === constants_2.PaymentMethodTypeId.CHECKOUT) { paymentGatewayOrderTxnId = (_j = hookData === null || hookData === void 0 ? void 0 : hookData.data) === null || _j === void 0 ? void 0 : _j.id; } else if (paymentMethodTypeId === constants_2.PaymentMethodTypeId.PAYPAL) { paymentGatewayOrderTxnId = (_m = (_l = (_k = hookData === null || hookData === void 0 ? void 0 : hookData.resource) === null || _k === void 0 ? void 0 : _k.supplementary_data) === null || _l === void 0 ? void 0 : _l.related_ids) === null || _m === void 0 ? void 0 : _m.order_id; } else if (paymentMethodTypeId === constants_2.PaymentMethodTypeId.OMNICAPITAL) { paymentGatewayOrderTxnId = hookData === null || hookData === void 0 ? void 0 : hookData.LoanApplicationId; } console.log('--- paymentGatewayOrderTxnId ---', paymentGatewayOrderTxnId); if (constants_3.DEBUG_LOGGING_ENABLED) { // TODO: Debugging Log await Logger_1.Logger.logPayment({ data: { paymentGatewayOrderTxnId }, message: `Log | ${hookData === null || hookData === void 0 ? void 0 : hookData.Status} | paymentGatewayOrderTxnId` }, { headers: {}, cookies: {} }); } const payments = orderResult === null || orderResult === void 0 ? void 0 : orderResult.payments; if (payments === null || payments === void 0 ? void 0 : payments.length) { const dbOrderAmount = ((_p = (_o = orderResult === null || orderResult === void 0 ? void 0 : orderResult.grandTotal) === null || _o === void 0 ? void 0 : _o.raw) === null || _p === void 0 ? void 0 : _p.withTax) || 0; // Call gateway specific SDK API to get the order/payment status. let paymentStatus = await this.getPaymentStatus(paymentMethodType, paymentGatewayOrderTxnId, true, dbOrderAmount, hookData); if (paymentMethodTypeId === constants_2.PaymentMethodTypeId.OMNICAPITAL) { paymentStatus = Object.assign(Object.assign({}, paymentStatus), { orderDetails: Object.assign(Object.assign({}, paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.orderDetails), { orderNo, paymentNo }) }); } console.log('--- paymentStatus ---', paymentStatus); if (constants_3.DEBUG_LOGGING_ENABLED) { // TODO: Debugging Log await Logger_1.Logger.logPayment({ data: { paymentStatus }, message: `Log | ${hookData === null || hookData === void 0 ? void 0 : hookData.Status} | ${paymentGatewayOrderTxnId}` }, { headers: {}, cookies: {} }); } if (paymentMethodTypeId !== constants_2.PaymentMethodTypeId.PAYPAL && paymentMethodTypeId !== constants_2.PaymentMethodTypeId.OMNICAPITAL) { paymentNo = (0, payment_util_1.getPaymentNo)(paymentMethodTypeId, paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.orderDetails); } console.log('--- paymentNo ---', paymentNo); if (constants_3.DEBUG_LOGGING_ENABLED) { // TODO: Debugging Log await Logger_1.Logger.logPayment({ data: { paymentNo }, message: `Log | ${hookData === null || hookData === void 0 ? void 0 : hookData.Status} | ${paymentGatewayOrderTxnId}` }, { headers: {}, cookies: {} }); } // Get all partial payments for this order. const orderPayments = (payments === null || payments === void 0 ? void 0 : payments.filter((x) => (x === null || x === void 0 ? void 0 : x.isPartialPaymentEnabled) && (x === null || x === void 0 ? void 0 : x.orderAmount) == dbOrderAmount)) || []; // Calculate the total partially paid amount for this order. const totalPartiallyPaidAmount = (orderPayments === null || orderPayments === void 0 ? void 0 : orderPayments.reduce((sum, x) => sum + x.paidAmount, 0)) || 0; console.log('totalPartiallyPaidAmount', totalPartiallyPaidAmount); if (constants_3.DEBUG_LOGGING_ENABLED) { // TODO: Debugging Log await Logger_1.Logger.logPayment({ data: { totalPartiallyPaidAmount }, message: `Log | ${hookData === null || hookData === void 0 ? void 0 : hookData.Status} | ${paymentGatewayOrderTxnId}` }, { headers: {}, cookies: {} }); } let isPartialPaymentEnabled = ((paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.paymentType) === constants_2.PaymentSelectionType.PARTIAL); // If payment type is FULL and there are any partial payments, then it is a last partial payment. if ((paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.paymentType) === constants_2.PaymentSelectionType.FULL && totalPartiallyPaidAmount > 0) { // This is a partial payment. isPartialPaymentEnabled = true; } if (paymentTransactionStatus.toLowerCase() === constants_1.PaymentTransactionStatus.ORDER_REFUNDED.toLowerCase()) { // Order Refunded } else { const processTxn = (paymentTransactionStatus.toLowerCase() === constants_1.PaymentTransactionStatus.TXN_CHARGED.toLowerCase() || paymentTransactionStatus.toLowerCase() === constants_1.PaymentTransactionStatus.TXN_FAILED.toLowerCase() || paymentTransactionStatus.toLowerCase() === constants_1.PaymentTransactionStatus.TXN_INITIATED.toLowerCase()); let statusId = PaymentStatus_1.PaymentStatus.DECLINED; const payment = payments === null || payments === void 0 ? void 0 : payments.find((x) => (x === null || x === void 0 ? void 0 : x.id) == paymentNo && ((x === null || x === void 0 ? void 0 : x.status) == PaymentStatus_1.PaymentStatus.PENDING || (x === null || x === void 0 ? void 0 : x.status) == PaymentStatus_1.PaymentStatus.INITIATED || (x === null || x === void 0 ? void 0 : x.status) == PaymentStatus_1.PaymentStatus.PROCESSING)); console.log('--- payment ---', payment); console.log('--- processTxn ---', `${processTxn}`); if (constants_3.DEBUG_LOGGING_ENABLED) { // TODO: Debugging Log await Logger_1.Logger.logPayment({ data: { processTxn, payment }, message: `Log | ${hookData === null || hookData === void 0 ? void 0 : hookData.Status} | ${paymentGatewayOrderTxnId}` }, { headers: {}, cookies: {} }); } if (payment && processTxn /*&& paymentStatus?.statusId === PaymentStatus.PENDING*/) { let result = constants_1.Defaults.Object.Value; const orderValue = paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.purchaseAmount; const paymentStatusId = paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.statusId; console.log('--- paymentStatusId ---', paymentStatusId); if (paymentStatusId === PaymentStatus_1.PaymentStatus.INITIATED || paymentStatusId === PaymentStatus_1.PaymentStatus.PAID) { console.log('--- SuccessUpdate ---'); const explicitOrderStatusId = (paymentStatusId === PaymentStatus_1.PaymentStatus.INITIATED) ? paymentStatusId : PaymentStatus_1.PaymentStatus.PENDING; const explicitPaidAmount = (paymentStatusId === PaymentStatus_1.PaymentStatus.INITIATED) ? paymentStatus.purchaseAmount : 0; result = await this.paymentHookOrderSuccessUpdate(paymentMethodType, paymentMethodTypeId, orderId, paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.orderDetails, statusId, orderValue, orderResult, { paymentNo, orderNo, hookData, paymentType: paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.paymentType, partialAmount: paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.partialAmount, isPartialPaymentEnabled, totalPartiallyPaidAmount, headers: (_q = data === null || data === void 0 ? void 0 : data.extras) === null || _q === void 0 ? void 0 : _q.headers, }, explicitOrderStatusId, explicitPaidAmount); } else if (paymentStatusId == PaymentStatus_1.PaymentStatus.DECLINED) { console.log('--- FailureUpdate ---'); result = await this.paymentHookOrderFailureUpdate(paymentMethodType, paymentMethodTypeId, orderId, paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.orderDetails, statusId, orderValue, orderResult, { paymentNo, orderNo, hookData, paymentType: paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.paymentType, partialAmount: paymentStatus === null || paymentStatus === void 0 ? void 0 : paymentStatus.partialAmount, isPartialPaymentEnabled, totalPartiallyPaidAmount, headers: (_r = data === null || data === void 0 ? void 0 : data.extras) === null || _r === void 0 ? void 0 : _r.headers, }); } return result; } } } } } } } catch (error) { await Logger_1.Logger.logPayment({ data: error, message: `Log | Error | processPaymentHook` }, { headers: {}, cookies: {} }); //await Logger.logPayment(error, { headers: {}, cookies: {} }) return { hasError: true, error: error }; } return null; } /** * Retrieves the payment status for a given payment gateway and transaction data. * * This method interacts with specific payment gateway SDKs to obtain the order or payment status. * It supports various payment gateways including PayPal, Checkout, Klarna, Stripe, and ClearPay. * The method determines the payment status based on the gateway-specific response and calculates * the purchase amount from the order details. * * @param gateway - The name of the payment gateway used for the transaction. * @param data - The transaction data required to fetch the payment status from the gateway. * @param returnOrderDetails - Flag indicating whether to return order details in the response. * @returns A promise that resolves to an object containing the status ID, purchase amount, and * optionally the order details if `returnOrderDetails` is true. */ async getPaymentStatus(gateway, data, returnOrderDetails = false, orderValue = 0, hookData = {}) { var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _