Skip to main content

Stripe Live Checkout + Webhook Provisioning

critical path   Property: ChurchWiseAI   Category: Onboarding Tier: any Persona: pastor-admin Touchpoint: /checkout

Preconditions

  • Use Stripe test card 4242 4242 4242 4242, any future expiry, any CVC
  • No existing premium_churches row for the test email
  • Stripe webhook endpoint registered and reachable

Steps

#ActionExpected Result
1Navigate to /pricingAll tier cards render with correct prices matching pricing.yaml
2Click 'Get Started' on any paid tierRedirected to Stripe Checkout with correct price_id for selected plan
3Complete payment with test card 4242 4242 4242 4242Stripe Checkout completes, redirected to /onboarding or success page
4Check stripe_webhook_inbox table within 30 secondscheckout.session.completed event row present with status=pending
5Wait for cron/process-stripe-webhooks to fire (up to 60s)Webhook inbox row status changes to processed
6Check Supabase premium_churches tableNew row with correct plan, status=active or preview, church_id set
7Complete onboarding formRedirected to /admin/[token] dashboard — dashboard loads with correct tier entitlements
8Verify magic link emailEmail with subject 'Your ChurchWiseAI dashboard' arrives within 2 min

Known Failure Modes

  • Webhook not received — check Stripe dashboard webhook log for delivery failures
  • premium_churches row created but plan wrong — check process-stripe-webhooks handler
  • Onboarding redirects back to /pricing — subscription not provisioned
  • stripe_webhook_inbox row stuck at pending — check cron is running

References

Cleanup

  • Cancel the test subscription in Stripe test dashboard
  • Delete the test premium_churches row (or set status=cancelled)

Notes

CRITICAL PATH. Any PR touching linked_code_files must produce a green Playwright run before merge — see CLAUDE.md rule #10 and registry.yaml entry stripe-live-checkout. The webhook now uses inbox pattern (2026-04-14): thin ack → stripe_webhook_inbox → cron processes async. Do NOT inline provisioning in the webhook handler again.