Implements Stripe payments, subscriptions, and webhooks so billing state stays correct - Checkout Sessions, signature-verified idempotent webhook handlers, dunning, and SCA handling. Use when someone asks "add Stripe subscriptions to my app", "why is my webhook signature verification failing", "my database says subscribed but Stripe says canceled", "how do I avoid double-charging on retries", or "how should I handle failed payments". Do NOT use for choosing price points, tiers, or packaging - use saas-pricing instead; for general-purpose webhook receiver hardening beyond Stripe, use webhook-receiver-hardener; for idempotency patterns outside payments, use idempotency-enforcer.
Click to play with sound.
---
name: Stripe Expert
description: Implements Stripe payments, subscriptions, and webhooks so billing state stays correct - Checkout Sessions, signature-verified idempotent webhook handlers, dunning, and SCA handling. Use when someone asks "add Stripe subscriptions to my app", "why is my webhook signature verification failing", "my database says subscribed but Stripe says canceled", "how do I avoid double-charging on retries", or "how should I handle failed payments". Do NOT use for choosing price points, tiers, or packaging - use saas-pricing instead; for general-purpose webhook receiver hardening beyond Stripe, use webhook-receiver-hardener; for idempotency patterns outside payments, use idempotency-enforcer.
---
# Stripe Expert
Billing bugs are the most expensive class of bug: an unverified webhook is an open door to fake "payment succeeded" events, a non-idempotent handler double-provisions on Stripe's at-least-once delivery, and state inferred from a client redirect grants free access to anyone who can type a URL. This skill wires Stripe so money moves correctly and your database never disagrees with Stripe about who has paid.
## Core principle
Stripe is the source of truth for billing state. Your database is a mirror, updated only by verified webhooks. Never grant access from a client-side success callback or redirect - the redirect can be spoofed, dropped, or replayed; the webhook cannot.
## Operating procedure
### Step 1: Gather inputs
1. Billing model - one-time purchase, flat subscription, per-seat, or usage-based? Default for SaaS: flat subscription via Checkout.
2. Existing user model - is there a `stripe_customer_id` column? One Stripe customer per user, created lazily on first purchase.
3. Access-gating point - the exact code path that checks "is this user paid?". It must read your mirrored subscription status, nowhere else.
4. Dunning policy - how many days of grace on `past_due` before access is cut? Default: 7 days with email notices.
### Step 2: Build the purchase flow (Checkout)
1. Create the Checkout Session server-side. Never trust amounts or price IDs from the client - accept only an internal plan identifier and resolve the Stripe price ID server-side.… install to load the full skill