examples/storefront Public
// The payment provider, behind the two calls checkout needs. Stripe in production; tests pass// their own Payments.import Stripe from "stripe";export type Charge = { order_id: string; amount_cents: number; currency: string; email: string };export type Intent = { id: string; client_secret: string };export interface Payments { // Creates the PaymentIntent the shopper pays in the browser. Calling it again for the same // order returns the same intent. createIntent(charge: Charge): Promise<Intent>; // True when the intent is cancelled, false when it can no longer be (it succeeded, or a // payment is processing). In that case the webhook settles the order. cancelIntent(intentId: string): Promise<boolean>;}export function stripePayments(secretKey: string, fetchFn?: typeof fetch): Payments { const stripe = new Stripe(secretKey, { httpClient: Stripe.createFetchHttpClient(fetchFn), maxNetworkRetries: 2, timeout: 10_000, }); return { async createIntent(c) { const intent = await stripe.paymentIntents.create( { amount: c.amount_cents, currency: c.currency, receipt_email: c.email, automatic_payment_methods: { enabled: true }, metadata: { order_id: c.order_id }, }, { idempotencyKey: `order-${c.order_id}` }, ); if (!intent.client_secret) throw new Error(`PaymentIntent ${intent.id} has no client_secret`); return { id: intent.id, client_secret: intent.client_secret }; }, async cancelIntent(intentId) { try { await stripe.paymentIntents.cancel(intentId); return true; } catch (e) { if (e instanceof Stripe.errors.StripeInvalidRequestError && e.code === "payment_intent_unexpected_state") return false; throw e; } }, };}