UNPKG

@wepublish/api

Version:
184 lines 8.43 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.StripePaymentProvider = void 0; const tslib_1 = require("tslib"); const payment_provider_1 = require("./payment-provider"); const stripe_1 = tslib_1.__importDefault(require("stripe")); const api_1 = require("../../../../utils-api/src"); const client_1 = require("@prisma/client"); function mapStripeEventToPaymentStatus(event) { switch (event) { case 'requires_payment_method': case 'requires_confirmation': case 'requires_action': return client_1.PaymentState.requiresUserAction; case 'processing': return client_1.PaymentState.processing; case 'succeeded': return client_1.PaymentState.paid; case 'canceled': return client_1.PaymentState.canceled; default: return null; } } class StripePaymentProvider extends payment_provider_1.BasePaymentProvider { constructor(props) { super(props); this.stripe = new stripe_1.default(props.secretKey, { apiVersion: '2020-08-27' }); this.webhookEndpointSecret = props.webhookEndpointSecret; } createStripeCustomer({ intent }) { var _a; return tslib_1.__awaiter(this, void 0, void 0, function* () { const customer = yield this.stripe.customers.create({ email: (_a = intent.metadata.mail) !== null && _a !== void 0 ? _a : '', payment_method: intent.payment_method, invoice_settings: { default_payment_method: intent.payment_method } }); return customer.id; }); } getWebhookEvent(body, signature) { return this.stripe.webhooks.constructEvent(body, signature, this.webhookEndpointSecret); } webhookForPaymentIntent(props) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const signature = props.req.headers['stripe-signature']; const event = this.getWebhookEvent(props.req.body, signature); if (!event.type.startsWith('payment_intent')) { return { status: 200, message: `Skipping handling ${event.type}` }; } const intent = event.data.object; const intentStates = []; const state = mapStripeEventToPaymentStatus(intent.status); if (state !== null && intent.metadata.paymentID !== undefined) { let customerID; if (intent.setup_future_usage === 'off_session' && intent.customer === null && intent.payment_method !== null) { customerID = yield this.createStripeCustomer({ intent }); } else { customerID = intent.customer; } intentStates.push({ paymentID: intent.metadata.paymentID, paymentData: JSON.stringify(intent), state, customerID }); } return { status: 200, paymentStates: intentStates }; }); } isCustomerDeleted(customer) { return !!customer.deleted; } createIntent({ customerID, invoice, saveCustomer, paymentID }) { var _a; return tslib_1.__awaiter(this, void 0, void 0, function* () { let paymentMethodID = null; if (customerID) { // For an off_session payment the default_payment_method or the default_source of the customer will be used. // If both are available the default_payment_method will be used. // If no user, deleted user, no default_payment_method or no default_source the intent will be created without an customer. const customer = yield this.stripe.customers.retrieve(customerID); if (this.isCustomerDeleted(customer)) { (0, api_1.logger)('stripePaymentProvider').warn('Provided customerID "%s" returns a deleted stripe customer', customerID); } else if (customer.invoice_settings.default_payment_method !== null) { paymentMethodID = customer.invoice_settings.default_payment_method; } else if (customer.default_source !== null) { paymentMethodID = customer.default_source; } else { (0, api_1.logger)('stripePaymentProvider').warn('Provided customerID "%s" has no default_payment_method or default_source', customerID); } } let intent; let errorCode; try { intent = yield this.stripe.paymentIntents.create(Object.assign(Object.assign(Object.assign(Object.assign({ amount: invoice.items.reduce((prevItem, currentItem) => prevItem + currentItem.amount * currentItem.quantity, 0) }, (customerID && paymentMethodID ? { confirm: true, customer: customerID, off_session: true, payment_method: paymentMethodID, payment_method_types: ['card'] } : {})), { currency: 'chf' }), (saveCustomer ? { setup_future_usage: 'off_session' } : {})), { metadata: { paymentID, mail: invoice.mail } })); } catch (err) { const error = err; (0, api_1.logger)('stripePaymentProvider').error(error, 'Error while creating Stripe Intent for paymentProvider %s', this.id); if (error.type === 'StripeCardError') { intent = error.raw.payment_intent; errorCode = error.raw.code; } else { intent = { id: 'unknown_error', error, state: client_1.PaymentState.requiresUserAction }; errorCode = 'unknown_error'; } } const state = mapStripeEventToPaymentStatus(intent.status); (0, api_1.logger)('stripePaymentProvider').info('Created Stripe intent with ID: %s for paymentProvider %s', intent.id, this.id); return { intentID: intent.id, intentSecret: (_a = intent.client_secret) !== null && _a !== void 0 ? _a : '', intentData: JSON.stringify(intent), state: state !== null && state !== void 0 ? state : client_1.PaymentState.submitted, errorCode }; }); } checkIntentStatus({ intentID }) { return tslib_1.__awaiter(this, void 0, void 0, function* () { const intent = yield this.stripe.paymentIntents.retrieve(intentID); const state = mapStripeEventToPaymentStatus(intent.status); if (!state) { (0, api_1.logger)('stripePaymentProvider').error('Stripe intent with ID: %s for paymentProvider %s returned with an unknown state %s', intent.id, this.id, intent.status); throw new Error('unknown intent state'); } if (!intent.metadata.paymentID) { (0, api_1.logger)('stripePaymentProvider').error('Stripe intent with ID: %s for paymentProvider %s returned with empty paymentID', intent.id, this.id); throw new Error('empty paymentID'); } let customerID; if (intent.setup_future_usage === 'off_session' && intent.customer === null && intent.payment_method !== null) { customerID = yield this.createStripeCustomer({ intent }); } else { customerID = intent.customer; } return { state, paymentID: intent.metadata.paymentID, paymentData: JSON.stringify(intent), customerID }; }); } } exports.StripePaymentProvider = StripePaymentProvider; //# sourceMappingURL=stripe-payment-provider.js.map