Payments Preflight · Check 6 of 15
Never trust prices or amounts from the client
Create Checkout Sessions and PaymentIntents on the server using Price IDs from your own config. Never accept an amount, price or plan from the browser.
What it is
The browser should send what the customer wants (a product or plan key). Your server decides the price and creates the Checkout Session or PaymentIntent.
Why it matters
Anything the client sends can be edited. If your API accepts amount or a Price ID straight from the request, a user can pay one cent for your top plan.
How to check
- Open the route that creates the Checkout Session or PaymentIntent. Does it read
amount,unit_amountorpricefrom the request body? - In devtools, change the request body and see if the session total changes.
- Check that access is granted from a verified webhook or a server-side retrieve, not from the success page URL.
How to fix it
- Map an allowed plan key to a Price ID on the server and reject anything else.
- Grant access in fulfillment, after retrieving the Checkout Session and checking
payment_status. - Treat the success URL as a page to show, not proof of payment.
const PRICES = { pro: process.env.PRICE_PRO!, team: process.env.PRICE_TEAM! } as const;
const plan = (await req.json()).plan as keyof typeof PRICES;
if (!PRICES[plan]) return new Response("Unknown plan", { status: 400 });
const session = await stripe.checkout.sessions.create({
mode: "subscription",
line_items: [{ price: PRICES[plan], quantity: 1 }],
success_url: `${origin}/billing?session_id={CHECKOUT_SESSION_ID}`,
});Prompt for your AI coding tool
Paste into Cursor, Claude Code, Lovable or similar. Review the diff before you accept it.
Check my Stripe checkout code. The client must only send a plan or product key. The server must map it to a Price ID from an allowlist, reject anything else, and never read amount, unit_amount or price from the request. Grant access only after a verified webhook or after retrieving the Checkout Session server-side and checking payment_status. Show the diff.
Sources
- Fulfill orders Stripe docs
- How products and prices work Stripe docs
Related checks
Sponsor this page: get in touch.