Stripe
stripePayments32 lines
Card payments, subscriptions and billing for web checkout.
Current — as published in v1.3.2. Written by hand for Stripe, not generated.
The rule
Trust boundary
- Never take an amount, price or currency from the client. Look the price up server-side from an id you control. A forged request body is trivial.
- The secret key is server-side only. The publishable key is the only one that may reach a browser.
- Landing on the success page is not proof of payment.
Webhooks are the source of truth
- Verify every webhook signature against the raw body. A parsed body breaks the check; an unverified endpoint accepts forged "payment succeeded" events from anyone.
- Idempotency is required, not optional. Stripe retries and delivers at-least-once: record the event id and ignore duplicates, or a retry grants access twice.
- Handle the subscription lifecycle —
updatedanddeleted— not only checkout completion.
Money
- Amounts are integers in the smallest currency unit. Never use floats.
- Store the Stripe customer and subscription ids against your own user.
Never
- Never log a full card number, secret key or webhook payload containing personal data.
- Never use Stripe for digital goods inside a mobile app — the stores reject it.
- Never grant access from client state alone; re-check server-side.
As each tool receives it
The same guidance, in the shape each editor reads. Cursor and Claude Code are written separately by hand; the rest are derived from the Cursor rule.
.cursor/rules/stripe.mdc
---
description: Stripe conventions
globs: ["server/**", "api/**", "app/api/**", "src/services/payments/**"]
alwaysApply: false
---
# Stripe
## Trust boundary
- **Never take an amount, price or currency from the client.** Look the price up
server-side from an id you control. A forged request body is trivial.
- The secret key is server-side only. The publishable key is the only one that
may reach a browser.
- Landing on the success page is not proof of payment.
## Webhooks are the source of truth
- Verify every webhook signature against the **raw** body. A parsed body breaks
the check; an unverified endpoint accepts forged "payment succeeded" events
from anyone.
- **Idempotency is required**, not optional. Stripe retries and delivers
at-least-once: record the event id and ignore duplicates, or a retry grants
access twice.
- Handle the subscription lifecycle — `updated` and `deleted` — not only
checkout completion.
## Money
- Amounts are integers in the smallest currency unit. Never use floats.
- Store the Stripe customer and subscription ids against your own user.
## Never
- Never log a full card number, secret key or webhook payload containing
personal data.
- Never use Stripe for digital goods inside a mobile app — the stores reject it.
- Never grant access from client state alone; re-check server-side.
What else this module writes
Selecting Stripe contributes more than a rule file — all of it merged with every other module you pick, with conflicts resolved rather than duplicated.
Environment
STRIPE_SECRET_KEYrequiredServer-side API key. Never ship in a client bundle.STRIPE_WEBHOOK_SECRETrequiredVerifies webhook signatures. The endpoint is public without it.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEYoptionalBrowser-side key for Stripe.js. Safe to expose.Dependencies
stripe^22.4.0@stripe/stripe-js^9.13.0
Folders
server/payments/src/features/billing/
Checklists
checklists/payments-web.md
Related
Put this in your repo
Adds Stripe to a project this tool generated, without starting over. Files you have hand-edited are left alone.