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
JavaScript
"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, _