UNPKG

@tecafrik/africa-payment-sdk

Version:

A single SDK to integrate all african payment providers seamlessly

280 lines 14.6 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.TaarihTransactionStatus = void 0; const libphonenumber_js_1 = require("libphonenumber-js"); const payment_provider_interface_1 = require("../payment-provider.interface"); const apisauce_1 = require("apisauce"); const payment_error_1 = require("../payment-error"); const lodash_1 = require("lodash"); const payment_events_1 = require("../payment-events"); var TaarihTransactionStatus; (function (TaarihTransactionStatus) { TaarihTransactionStatus["PENDING"] = "PENDING"; TaarihTransactionStatus["COMPLETED"] = "COMPLETED"; TaarihTransactionStatus["FAILED"] = "FAILED"; })(TaarihTransactionStatus || (exports.TaarihTransactionStatus = TaarihTransactionStatus = {})); var TaarihCreditCardPaymentProcessor; (function (TaarihCreditCardPaymentProcessor) { TaarihCreditCardPaymentProcessor["CINETPAY"] = "CINETPAY"; TaarihCreditCardPaymentProcessor["STRIPE"] = "STRIPE"; })(TaarihCreditCardPaymentProcessor || (TaarihCreditCardPaymentProcessor = {})); class TaarihPaymentProvider { constructor(config) { this.config = config; this.api = (0, apisauce_1.create)({ baseURL: config.mode === "test" ? "https://api-dev.taarih.com/api" : "https://api.taarih.com/api", headers: { "Content-Type": "application/json", }, }); this.api.addResponseTransform((response) => { if (!response.ok) { const defaultErrorMessage = "Taarih error: " + response.problem + ". Status: " + response.status + ". Data: " + JSON.stringify(response.data); console.error(response); throw new payment_error_1.PaymentError(response.data && (0, lodash_1.isObject)(response.data) ? "message" in response.data ? String(response.data.message) : "response_text" in response.data ? String(response.data.response_text) : defaultErrorMessage : defaultErrorMessage); } }); } useEventEmitter(eventEmitter) { this.eventEmitter = eventEmitter; } getTaarihPaymentMethod(paymentMethod, processor) { switch (paymentMethod) { case payment_provider_interface_1.PaymentMethod.WAVE: return "WAVE"; case payment_provider_interface_1.PaymentMethod.ORANGE_MONEY: return "OM"; case payment_provider_interface_1.PaymentMethod.CREDIT_CARD: if (!processor || !Object.values(TaarihCreditCardPaymentProcessor).includes(processor)) { throw new payment_error_1.PaymentError("Taarih error: Invalid or missing credit card processor", payment_error_1.PaymentErrorType.UNSUPPORTED_PAYMENT_METHOD); } return processor; default: throw new payment_error_1.PaymentError("Invalid payment method: " + paymentMethod); } } login() { return __awaiter(this, void 0, void 0, function* () { const signEndUserResponse = yield this.api.post("/auth/signin-end-user", { callingCode: this.config.callingCode, phoneNumber: this.config.phoneNumber, authMode: "SMS", visitorId: this.config.visitorId, password: this.config.password, }); if (signEndUserResponse.data && "otpRequired" in signEndUserResponse.data) { throw new payment_error_1.PaymentError("Taarih error: " + signEndUserResponse.data.message); } if (signEndUserResponse.data && "invalidData" in signEndUserResponse.data) { throw new payment_error_1.PaymentError("Taarih error: " + signEndUserResponse.data.message + " " + signEndUserResponse.data.invalidData ? JSON.stringify(signEndUserResponse.data.invalidData) : ""); } if (signEndUserResponse.data && "token" in signEndUserResponse.data) { return signEndUserResponse.data; } throw new payment_error_1.PaymentError("Taarih error: No token in response"); }); } checkout(options) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { let operationCode = ""; if (!("operationCode" in options)) { operationCode = options.paymentMethod === payment_provider_interface_1.PaymentMethod.WAVE ? "PAY_WITH_WAVE" : "PAY_WITH_OM"; } else if ("operationCode" in options && options.operationCode) { operationCode = options.operationCode; } else { throw new payment_error_1.PaymentError("Taarih error: operation code is required", payment_error_1.PaymentErrorType.INVALID_OPERATION_CODE); } if (options.currency !== payment_provider_interface_1.Currency.XOF) { throw new payment_error_1.PaymentError("Taarih does not support the currency: " + options.currency, payment_error_1.PaymentErrorType.UNSUPPORTED_PAYMENT_METHOD); } const isMobileMoney = options.paymentMethod === payment_provider_interface_1.PaymentMethod.WAVE || options.paymentMethod === payment_provider_interface_1.PaymentMethod.ORANGE_MONEY; const isCreditCard = options.paymentMethod === payment_provider_interface_1.PaymentMethod.CREDIT_CARD; const user = yield this.login(); const companyId = user.legalEntityId; let taarihCheckoutResponse; taarihCheckoutResponse = yield this.api.post("/transaction/pos-payment", { companyId, amount: options.amount, countryCode: this.config.callingCode, mobileNumber: options.customer.phoneNumber, paymentMethod: this.getTaarihPaymentMethod(options.paymentMethod, (_a = options.metadata) === null || _a === void 0 ? void 0 : _a.processor), operationCode, firstName: options.customer.firstName, lastName: options.customer.lastName, currency: options.currency, externalTransactionId: options.transactionId, accountNumber: options.accountNumber || "", employeeId: options.employeeId }, { headers: Object.assign(Object.assign({}, this.api.headers), { "x-access-token": user.token }), }); if (isMobileMoney) { const parsedCustomerPhoneNumber = (0, libphonenumber_js_1.parsePhoneNumber)(options.customer.phoneNumber, "SN"); if (!parsedCustomerPhoneNumber.isValid()) { throw new payment_error_1.PaymentError("Invalid phone number: " + options.customer.phoneNumber, payment_error_1.PaymentErrorType.INVALID_PHONE_NUMBER); } if (!parsedCustomerPhoneNumber.isPossible()) { throw new payment_error_1.PaymentError("Phone number is not possible: " + options.customer.phoneNumber, payment_error_1.PaymentErrorType.INVALID_PHONE_NUMBER); } } if (!taarihCheckoutResponse) { throw new payment_error_1.PaymentError("Taarih error: no payment response data"); } if (isCreditCard) { taarihCheckoutResponse.data = (_b = taarihCheckoutResponse.data.results) === null || _b === void 0 ? void 0 : _b[0]; } if (taarihCheckoutResponse.data && "externalId" in taarihCheckoutResponse.data && "internalId" in taarihCheckoutResponse.data && "payment_link" in taarihCheckoutResponse.data) { const result = { transactionAmount: options.amount, transactionCurrency: options.currency, transactionId: taarihCheckoutResponse.data.internalId, transactionReference: taarihCheckoutResponse.data.externalId, transactionStatus: payment_provider_interface_1.TransactionStatus.PENDING, redirectUrl: taarihCheckoutResponse.data.payment_link, }; return result; } throw new payment_error_1.PaymentError("Taarih error: response data is not valid"); }); } checkoutMobileMoney(options) { return __awaiter(this, void 0, void 0, function* () { return this.checkout(options); }); } checkoutCreditCard(options) { return __awaiter(this, void 0, void 0, function* () { return this.checkout(options); }); } checkoutRedirect(options) { return __awaiter(this, void 0, void 0, function* () { throw new payment_error_1.PaymentError("Taarih redirect checkout not yet implemented", payment_error_1.PaymentErrorType.UNSUPPORTED_PAYMENT_METHOD); }); } refund(options) { return __awaiter(this, void 0, void 0, function* () { throw new payment_error_1.PaymentError("Taarih refund not yet implemented", payment_error_1.PaymentErrorType.UNSUPPORTED_PAYMENT_METHOD); }); } payoutMobileMoney(options) { return __awaiter(this, void 0, void 0, function* () { throw new payment_error_1.PaymentError("Taarih payout not yet implemented", payment_error_1.PaymentErrorType.UNSUPPORTED_PAYMENT_METHOD); }); } handleWebhook(rawBody) { var _a, _b; return __awaiter(this, void 0, void 0, function* () { if ((0, lodash_1.isBuffer)(rawBody) || (0, lodash_1.isString)(rawBody)) { console.error("Paydunya webhook body must be a parsed object, not the raw body"); return null; } const body = rawBody; const taarihTransactionStatusResponse = yield this.callback(body.transactionId, body.timeInterval || 5000, body.maxAttempts || 20); if (taarihTransactionStatusResponse.status === TaarihTransactionStatus.COMPLETED) { const paymentSuccessfulEvent = { type: payment_events_1.PaymentEventType.PAYMENT_SUCCESSFUL, paymentMethod: "", transactionAmount: taarihTransactionStatusResponse.amount, transactionCurrency: payment_provider_interface_1.Currency.XOF, transactionId: body.transactionId, transactionReference: body.transactionId, paymentProvider: TaarihPaymentProvider.name, }; (_a = this.eventEmitter) === null || _a === void 0 ? void 0 : _a.emit(payment_events_1.PaymentEventType.PAYMENT_SUCCESSFUL, paymentSuccessfulEvent); return paymentSuccessfulEvent; } const paymentFailedEvent = { type: payment_events_1.PaymentEventType.PAYMENT_FAILED, paymentMethod: "", transactionAmount: taarihTransactionStatusResponse.amount, transactionCurrency: payment_provider_interface_1.Currency.XOF, transactionId: body.transactionId, transactionReference: body.transactionId, reason: "Payment failed", paymentProvider: TaarihPaymentProvider.name, }; (_b = this.eventEmitter) === null || _b === void 0 ? void 0 : _b.emit(payment_events_1.PaymentEventType.PAYMENT_FAILED, paymentFailedEvent); return paymentFailedEvent; }); } callback(internalId, timeInterval = 3000, maxAttempts = 4) { return __awaiter(this, void 0, void 0, function* () { const user = yield this.login(); let attempts = 0; while (true) { const taarihTransactionStatusResponse = yield this.api.get(`/transaction/verify-transaction-status/${internalId}`, {}, { headers: Object.assign(Object.assign({}, this.api.headers), { "x-access-token": user.token }), }); if (taarihTransactionStatusResponse.data && "invalidData" in taarihTransactionStatusResponse.data) { throw new payment_error_1.PaymentError("Taarih error: " + taarihTransactionStatusResponse.data.message); } const { data } = taarihTransactionStatusResponse; if (!data) { throw new payment_error_1.PaymentError("Taarih error: no transaction status data"); } const status = data.status; if (status !== TaarihTransactionStatus.PENDING) { return (0, lodash_1.pick)(data, [ "status", "amount", "currency", "bankAccountSender", ]); } attempts++; if (attempts >= maxAttempts) { return (0, lodash_1.pick)(data, [ "status", "amount", "currency", "bankAccountSender", ]); } yield new Promise((resolve) => setTimeout(resolve, timeInterval)); } }); } } exports.default = TaarihPaymentProvider; //# sourceMappingURL=taarih.js.map