All the parts

Build · Add powers

Payments

How do I take money from customers?

What it is

You never handle card numbers yourself. A payment provider shows the card form on its own page, charges the card, and tells your app the result. Your job is to start the checkout and then wait for a confirmation message called a webhook.

It is a card reader on a shop counter: the machine takes the card, and you only get told whether it was paid.

Add it when You charge for a product, a subscription or a donation.

It can wait when Your app is free, or you collect payment outside the app for now.

1 Which one should I pick?

Answer what you can. The ranking updates as you go, and you can ignore it if you disagree.

Where are your customers?
Who should handle sales tax?
What matters most right now?

Most people start with

2 Side by side

Three pips is strong, one is weak. Pick a row to read about it below.

OptionQuick to set upCheap while smallEasy to leaveRoom to growPrice
Pay a percentage and a fixed fee per payment
Pay a percentage per payment
Pay a larger percentage per sale
Pay a percentage and a fixed fee per payment

3 Look closer, then wire it in

Managed service

Stripe

The most common payment platform, with hosted checkout and subscriptions.

Pick it when You want the best docs and tools for one-off payments or subscriptions.

Skip it if You do not want to deal with sales tax yourself. Stripe has tax tools, but you stay the seller.

  • Hosted checkout page, no card form to build
  • Excellent docs and test mode
  • Subscriptions and invoices built in
  • You are the seller, so tax rules are your job
  • Not available in every country
Quick to set up
Cheap while small
Easy to leave
Room to grow

PricePay a percentage and a fixed fee per payment

How to connect it

  1. Create an account and copy your test keys.
  2. Create a checkout session on the server with the price and your return URLs.
  3. Redirect the user to the session URL.
  4. Receive the webhook, verify its signature, and mark the order as paid.
Put these in your .env file
  • STRIPE_SECRET_KEY
  • NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
  • STRIPE_WEBHOOK_SECRET
checkout.ts
import Stripe from "stripe";

const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!);

const session = await stripe.checkout.sessions.create({
  mode: "payment",
  line_items: [{ price: "price_123", quantity: 1 }],
  success_url: "https://yourapp.com/thanks",
  cancel_url: "https://yourapp.com/cart",
});
// send the user to session.url

4 Watch it work

Press play, or step through one message at a time.

Press Play to watch it run · 8 steps

The provider takes the card. The webhook, not the redirect, tells you it was paid.

A payment, step by stepThe provider takes the card. The webhook, not the redirect, tells you it was paid.Click BuyCreate checkout sessionSession URLRedirect to the checkout pageEnter card and payRedirect back to your thank-you pageWebhook: payment succeeded (signed)Verify signature, mark order paid
  • Client
  • Service
  • External API
  • Database
Text description
  1. Browser → Your app: Click Buy
  2. Your app → Payment provider: Create checkout session
  3. Payment provider replies to Your app: Session URL
  4. Your app replies to Browser: Redirect to the checkout page
  5. Browser → Payment provider: Enter card and pay
  6. Payment provider replies to Browser: Redirect back to your thank-you page
  7. Payment provider → Your app: Webhook: payment succeeded (signed)
  8. Your app → Your database: Verify signature, mark order paid

5 Mistakes to skip

  • Trusting the redirect back to your thank-you page.

    Anyone can open that URL. Mark an order paid only when the signed webhook arrives.

  • Not verifying webhook signatures.

    Check the signature with your webhook secret so nobody can fake a payment message.

  • Storing card numbers.

    Never touch them. Use the provider's hosted checkout and keep only their customer and payment ids.

See where it sits in a whole app

The stack builder draws your product with payments in it and animates a request through it.

Open the stack builder

Works closely with