P PasteCode
Prompt

Prompt pour ajouter Stripe Checkout à une application Next.js

Prompt d'agent IA pour ajouter Stripe Checkout avec gestion des webhooks, portail client et statut d'abonnement à un projet Next.js App Router.

CursorClaude CodeCodexWindsurf Next.jsPostgreSQLTypeScript
.md .json Difficulté: Difficile Mis à jour 8 juin 2026

Donnez ce prompt à votre agent pour implémenter le flux de facturation Stripe complet — création de session de checkout, traitement des webhooks, portail client et gestion du statut d’abonnement — avec une vérification correcte de la signature des webhooks et aucun secret dans le code client.

Prompt principal

Main Prompt
You are working in a Next.js 15 App Router project with TypeScript and PostgreSQL.
Auth is already set up with a `getSession()` helper. The pricing page already defines
`PLANS` with Stripe Price IDs.
Task: wire up Stripe Checkout for subscription billing.
Requirements:
- Install `stripe` (server-only) and `@stripe/stripe-js` (client). Do NOT import `stripe` in
Client Components or expose `STRIPE_SECRET_KEY` to the browser.
- Create `src/lib/stripe.ts`: export a singleton Stripe client using `STRIPE_SECRET_KEY`.
- Create a Server Action `src/lib/actions/create-checkout.ts`:
- Get the current user session; return an error if not authenticated.
- Create a Stripe Checkout Session in `subscription` mode.
- Set `success_url` to `/dashboard?session_id={CHECKOUT_SESSION_ID}`.
- Set `cancel_url` to `/pricing`.
- Store the Stripe `customerId` in the `users` table (`stripe_customer_id` column).
- Return the Checkout Session URL.
- Create `src/app/api/stripe/webhook/route.ts`:
- Read the raw body using `request.text()`.
- Verify the signature using `stripe.webhooks.constructEvent(body, sig, STRIPE_WEBHOOK_SECRET)`.
- Handle events: `checkout.session.completed`, `customer.subscription.updated`,
`customer.subscription.deleted`.
- On each event, update the `users` table: set `subscription_status` and `subscription_tier`.
- Return `{ received: true }` with status 200.
- On signature failure, return 400.
- Create `src/lib/actions/create-portal.ts`: create a Stripe Customer Portal session and return the URL.
- Add a PostgreSQL migration `migrations/0011_add_stripe_columns.sql` adding
`stripe_customer_id TEXT`, `subscription_status TEXT`, `subscription_tier TEXT` to `users`.
- Add all Stripe keys to `.env.example`: `STRIPE_SECRET_KEY`, `STRIPE_WEBHOOK_SECRET`,
`NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY`.
- Do NOT use the deprecated `stripe.charges` API. Use Payment Intents / Checkout Sessions only.
Stop and list all planned file changes before writing any code.

Notes d’implémentation

  • La vérification de la signature du webhook nécessite le corps de la requête brut — si vous le parsez d’abord en JSON, la vérification de la signature échouera. Utilisez request.text() et non request.json().
  • Le gestionnaire de webhook doit être exclu des limites de taille du corps de Next.js via une configuration de route : export const config = { api: { bodyParser: false } } (Pages Router) — dans App Router, utilisez export const dynamic = 'force-dynamic' et lisez le flux directement.
  • Testez les webhooks localement avec la CLI Stripe : stripe listen --forward-to localhost:3000/api/stripe/webhook.
  • Stockez stripe_customer_id lors du premier checkout pour éviter de créer des clients Stripe en double.

Modifications de fichiers attendues

src/lib/stripe.ts (new)
src/lib/actions/create-checkout.ts (new — Server Action)
src/lib/actions/create-portal.ts (new — Server Action)
src/app/api/stripe/webhook/route.ts (new — Route Handler)
migrations/0011_add_stripe_columns.sql (new)
.env.example (edited)
package.json (edited)

Critères d’acceptation

  • Cliquer sur un CTA de tarification redirige vers Stripe Checkout pour le plan correct.
  • Effectuer un checkout de test met à jour subscription_status = 'active' dans PostgreSQL.
  • Le lien du portail client Stripe redirige vers le portail hébergé par Stripe.
  • Envoyer un événement de test customer.subscription.deleted via la CLI Stripe définit subscription_status = 'canceled'.
  • Un webhook avec une signature invalide renvoie HTTP 400.

Commandes de test

Terminal window
bun add stripe @stripe/stripe-js
psql "$DATABASE_URL" -f migrations/0011_add_stripe_columns.sql
bun run typecheck
bun run dev &
stripe listen --forward-to localhost:3000/api/stripe/webhook
stripe trigger checkout.session.completed
# verify users table updated
psql "$DATABASE_URL" -c "SELECT stripe_customer_id, subscription_status FROM users LIMIT 5;"

Erreurs courantes des IA

  • Importer stripe (SDK serveur) dans un composant client, exposant STRIPE_SECRET_KEY.
  • Parser le corps du webhook en JSON avant la vérification de la signature, ce qui fait échouer toutes les validations du webhook.
  • Créer un nouveau client Stripe à chaque checkout au lieu de réutiliser stripe_customer_id.
  • Utiliser stripe.charges.create (obsolète) au lieu de stripe.checkout.sessions.create.

Prompt de correction

Fix Prompt
Webhook signature verification fails with `No signatures found matching the expected signature`.
Fix in order:
1. In the webhook route, replace `await request.json()` with `const body = await request.text()`.
2. Ensure `stripe.webhooks.constructEvent(body, sig, process.env.STRIPE_WEBHOOK_SECRET!)` receives
the raw string body, not a parsed object.
3. Add `export const dynamic = 'force-dynamic'` at the top of the route file.
Show only the corrected route handler diff.