@tecafrik/africa-payment-sdk
Version:
A single SDK to integrate all african payment providers seamlessly
230 lines • 12 kB
JavaScript
"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());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const payment_provider_interface_1 = require("../payment-provider.interface");
const payment_events_1 = require("../payment-events");
const stripe_1 = __importDefault(require("stripe"));
const payment_error_1 = require("../payment-error");
const lodash_1 = require("lodash");
class StripePaymentProvider {
constructor(config) {
this.config = config;
this.stripe = new stripe_1.default(config.privateKey, {
apiVersion: "2023-08-16",
});
this.init().catch((error) => {
console.error("Error initializing stripe provider", error);
});
this.webhookSecret = config.webhookSecret;
}
init() {
return __awaiter(this, void 0, void 0, function* () {
if (this.config.webhookUrl) {
const existingWebhooks = yield this.stripe.webhookEndpoints.list();
const existingWebhook = existingWebhooks.data.find((webhook) => webhook.url === this.config.webhookUrl);
if (!existingWebhook) {
const installedWebhook = yield this.stripe.webhookEndpoints.create({
enabled_events: [
"checkout.session.completed",
"checkout.session.expired",
"checkout.session.async_payment_succeeded",
"checkout.session.async_payment_failed",
],
url: this.config.webhookUrl,
});
this.webhookSecret = installedWebhook.secret;
}
}
});
}
useEventEmitter(eventEmitter) {
this.eventEmitter = eventEmitter;
}
checkoutMobileMoney(options) {
return __awaiter(this, void 0, void 0, function* () {
throw new payment_error_1.PaymentError("Stripe does not support mobile money payments", payment_error_1.PaymentErrorType.UNSUPPORTED_PAYMENT_METHOD);
});
}
checkoutCreditCard(options) {
return __awaiter(this, void 0, void 0, function* () {
throw new payment_error_1.PaymentError("Stripe does not support credit card payments. Use credit card tokens instead", payment_error_1.PaymentErrorType.UNSUPPORTED_PAYMENT_METHOD);
});
}
checkoutRedirect(options) {
return __awaiter(this, void 0, void 0, function* () {
const checkoutSession = yield this.stripe.checkout.sessions.create({
customer_email: options.customer.email,
payment_method_types: options.paymentMethod === payment_provider_interface_1.PaymentMethod.CREDIT_CARD
? ["card"]
: undefined,
line_items: [
{
price_data: {
currency: options.currency,
product_data: {
name: options.description,
},
unit_amount: options.amount,
},
quantity: 1,
},
],
mode: "payment",
success_url: options.successRedirectUrl,
cancel_url: options.failureRedirectUrl,
metadata: Object.assign(Object.assign({}, (0, lodash_1.mapValues)(options.metadata, (value) => JSON.stringify(value))), { transactionId: options.transactionId }),
});
if (!checkoutSession.url) {
throw new payment_error_1.PaymentError("Stripe did not return a checkout URL", payment_error_1.PaymentErrorType.UNKNOWN_ERROR);
}
return {
transactionAmount: options.amount,
transactionCurrency: options.currency,
transactionId: options.transactionId,
transactionReference: checkoutSession.id,
transactionStatus: payment_provider_interface_1.TransactionStatus.PENDING,
redirectUrl: checkoutSession.url,
};
});
}
refund(options) {
return __awaiter(this, void 0, void 0, function* () {
const checkoutSession = yield this.stripe.checkout.sessions.retrieve(options.refundedTransactionReference);
if (!checkoutSession) {
throw new payment_error_1.PaymentError("No checkout session found with reference " +
options.refundedTransactionReference, payment_error_1.PaymentErrorType.UNKNOWN_ERROR);
}
if (!checkoutSession.payment_intent) {
throw new payment_error_1.PaymentError("No payment intent found for checkout session " + checkoutSession.id, payment_error_1.PaymentErrorType.UNKNOWN_ERROR);
}
const refund = yield this.stripe.refunds.create({
payment_intent: (0, lodash_1.isString)(checkoutSession.payment_intent)
? checkoutSession.payment_intent
: checkoutSession.payment_intent.id,
amount: options.refundedAmount,
reason: "requested_by_customer",
});
return {
transactionAmount: refund.amount,
transactionCurrency: refund.currency,
transactionId: options.transactionId,
transactionReference: refund.id,
transactionStatus: payment_provider_interface_1.TransactionStatus.SUCCESS,
};
});
}
payoutMobileMoney(options) {
throw new payment_error_1.PaymentError("Stripe does not support mobile money payouts", payment_error_1.PaymentErrorType.UNSUPPORTED_PAYMENT_METHOD);
}
handleWebhook(rawBody, options) {
var _a, _b, _c, _d, _e, _f, _g;
return __awaiter(this, void 0, void 0, function* () {
const signature = (_a = options.headers) === null || _a === void 0 ? void 0 : _a["stripe-signature"];
if (!signature) {
console.warn("No signature found in stripe webhook request");
return null;
}
if (!this.webhookSecret) {
console.warn("No stripe webhook secret found");
return null;
}
let event;
try {
event = this.stripe.webhooks.constructEvent(rawBody, signature, this.webhookSecret);
}
catch (error) {
console.warn("Error verifying stripe webhook signature", error);
return null;
}
const emitSuccessfulPayment = (session) => {
var _a, _b, _c;
if (!((_a = session.metadata) === null || _a === void 0 ? void 0 : _a.transactionId)) {
console.warn("No transaction ID found in stripe webhook");
return null;
}
const paymentSuccessfulEvent = {
type: payment_events_1.PaymentEventType.PAYMENT_SUCCESSFUL,
paymentMethod: payment_provider_interface_1.PaymentMethod.CREDIT_CARD,
transactionAmount: Number(session.amount_total),
transactionCurrency: session.currency,
transactionId: (_b = session.metadata) === null || _b === void 0 ? void 0 : _b.transactionId,
transactionReference: session.id,
metadata: parseMetadata(session.metadata),
paymentProvider: StripePaymentProvider.name,
};
(_c = this.eventEmitter) === null || _c === void 0 ? void 0 : _c.emit(payment_events_1.PaymentEventType.PAYMENT_SUCCESSFUL, paymentSuccessfulEvent);
return paymentSuccessfulEvent;
};
const parseMetadata = (metadata) => {
return (0, lodash_1.mapValues)(metadata, (value) => {
try {
return JSON.parse(value);
}
catch (error) {
return value;
}
});
};
if (event.type === "checkout.session.completed") {
const session = event.data.object;
if (!((_b = session.metadata) === null || _b === void 0 ? void 0 : _b.transactionId)) {
console.warn("No transaction ID found in stripe webhook");
return null;
}
const paymentInitiatedEvent = {
type: payment_events_1.PaymentEventType.PAYMENT_INITIATED,
paymentMethod: payment_provider_interface_1.PaymentMethod.CREDIT_CARD,
transactionAmount: Number(session.amount_total),
transactionCurrency: session.currency,
transactionId: (_c = session.metadata) === null || _c === void 0 ? void 0 : _c.transactionId,
transactionReference: session.id,
metadata: parseMetadata(session.metadata),
paymentProvider: StripePaymentProvider.name,
};
(_d = this.eventEmitter) === null || _d === void 0 ? void 0 : _d.emit(payment_events_1.PaymentEventType.PAYMENT_INITIATED, paymentInitiatedEvent);
if (session.payment_status === "paid") {
return emitSuccessfulPayment(session);
}
return paymentInitiatedEvent;
}
else if (event.type === "checkout.session.async_payment_succeeded") {
const session = event.data.object;
return emitSuccessfulPayment(session);
}
else if (event.type === "checkout.session.async_payment_failed") {
const session = event.data.object;
if (!((_e = session.metadata) === null || _e === void 0 ? void 0 : _e.transactionId)) {
console.warn("No transaction ID found in stripe webhook");
return null;
}
const paymentFailedEvent = {
type: payment_events_1.PaymentEventType.PAYMENT_FAILED,
paymentMethod: payment_provider_interface_1.PaymentMethod.CREDIT_CARD,
transactionAmount: Number(session.amount_total),
transactionCurrency: session.currency,
transactionId: (_f = session.metadata) === null || _f === void 0 ? void 0 : _f.transactionId,
transactionReference: session.id,
metadata: parseMetadata(session.metadata),
reason: "Payment failed",
paymentProvider: StripePaymentProvider.name,
};
(_g = this.eventEmitter) === null || _g === void 0 ? void 0 : _g.emit(payment_events_1.PaymentEventType.PAYMENT_FAILED, paymentFailedEvent);
return paymentFailedEvent;
}
return null;
});
}
}
exports.default = StripePaymentProvider;
//# sourceMappingURL=stripe.js.map