Advanced / CODE NOTE
Back to SnippetsStripe: metadata that makes your receipts and ops clean
A compact metadata convention for linking payments → intakes → people without mystery or manual cleanup.
StripeWebhooksOps
Receipt: every payment knows what it paid for.
What this is
Your webhook is only as useful as your metadata.
Use it
- Attach stable IDs (intakeId / productId) on the PaymentIntent metadata.
- Include “what” (purpose) and “who” (email) so ops can search quickly.
- Never trust client values as authoritative for price/scope.
Make it yours
- Use stable IDs and a bounded purpose enum that match your server-owned catalog.
Reuse contract
Supported environments
- Stripe Payment Intents API
- Server-side Stripe SDK
Security notes
- Never accept price, currency, entitlement, or fulfillment authority from client-supplied metadata.
- Verify Stripe signatures before processing webhook events and make handlers idempotent.
Code
Language: ts
// Server (authoritative)
const intent = await stripe.paymentIntents.create({
amount: amountCents,
currency: 'usd',
automatic_payment_methods: { enabled: true },
metadata: {
purpose: 'deposit',
intakeId,
customerEmail,
source: 'cilc_site',
// optional:
sprintId: sprintId ?? '',
},
});
// Webhook: payment_intent.succeeded
// 1) read metadata.intakeId
// 2) mark intake status = 'paid'
// 3) write paidAt + stripePaymentIntentId