Skip to content

Take payments

This guide wires Stripe in test mode and ends with a real checkout from your own paywall. How the money moves:

Payment flow: the user hits a paywall, pays in a Stripe Checkout tab, the webhook writes entitlements on the server, the background mirrors them into storage, and the wall unlocks. The extension never decides who paid. The server does.User hitspaywallStripe Checkout(browser tab)Webhook →entitlements (server)storage mirrorwall unlocks /credits appearthe extension never decides who paid. The server does.

Run everything from backend/functions/, after firebase use <your-project-id>. No Stripe CLI needed. Keep the order; the webhook must exist before the first deploy (why).

Terminal window
cp .env.example .env # non-secret knobs (return URLs, trial days)
firebase functions:secrets:set STRIPE_SECRET_KEY # sk_test_…
pnpm seed:stripe # creates the catalog by lookup_key (idempotent)
pnpm stripe:webhook # registers the webhook + stores its signing secret
pnpm firebase:deploy # ONE deploy: the api function + rules
pnpm doctor # verifies the whole chain, points at any fix

Then point the extension at your backend in apps/extension/.env:

Terminal window
WXT_API_URL=https://us-central1-<project>.cloudfunctions.net/api
VITE_PREMIUM=true

Restart pnpm dev and reload the extension.

  1. In the popup, trigger the paywall (the Try a premium feature demo button, or your own gated feature).
  2. Click the wall’s upgrade button. Stripe Checkout opens in a tab.
  3. Pay with the test card 4242 4242 4242 4242 (any future expiry/CVC).
  4. Back in the popup: the wall clears and the Account tab shows your plan, no reload needed. The webhook recorded your payment server-side and the extension picked it up.

If anything is red, pnpm doctor names the broken link in the chain. Deeper checks (Firestore docs, webhook deliveries, emulator loop): Payments guide.

To sell a credit allowance with top-up packs instead, enable the credits model: same setup, plus metering.

Next: 4. Build your feature.