Prompt zum Hinzufügen von Stripe Checkout zu einer Next.js App
KI-Agent-Prompt zum Hinzufügen von Stripe Checkout mit Webhook-Handling, Kundenportal und Abonnementstatus zu einem Next.js App Router-Projekt.
CursorClaude CodeCodexWindsurf Next.jsPostgreSQLTypeScript
Geben Sie diesen Prompt Ihrem Agenten, um den vollständigen Stripe-Abrechnungsablauf zu implementieren — Checkout-Sitzungserstellung, Webhook-Verarbeitung, Kundenportal und Abonnementstatus-Beschränkung — mit ordnungsgemäßer Webhook-Signaturverifikation und ohne Geheimnisse im Client-Code.
Haupt-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.Implementierungshinweise
- Die Webhook-Signaturverifikation erfordert den rohen Anfragekörper — wenn Sie ihn zuerst als JSON parsen, schlägt die Signaturprüfung fehl. Verwenden Sie
request.text()nichtrequest.json(). - Der Webhook-Handler muss über eine Routenkonfiguration von den Next.js-Größenbeschränkungen für den Körper ausgenommen werden:
export const config = { api: { bodyParser: false } }(Pages Router) — im App Router verwenden Sieexport const dynamic = 'force-dynamic'und lesen Sie den Stream direkt. - Testen Sie Webhooks lokal mit der Stripe-CLI:
stripe listen --forward-to localhost:3000/api/stripe/webhook. - Speichern Sie
stripe_customer_idbeim ersten Checkout, um die Erstellung doppelter Stripe-Kunden zu vermeiden.
Erwartete Dateiänderungen
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)Akzeptanzkriterien
- Ein Klick auf einen Preis-CTA leitet zu Stripe Checkout für den richtigen Plan weiter.
- Das Abschließen eines Test-Checkouts aktualisiert
subscription_status = 'active'in PostgreSQL. - Der Stripe-Kundenportal-Link leitet zum von Stripe gehosteten Portal weiter.
- Das Senden eines Test-
customer.subscription.deleted-Ereignisses über die Stripe-CLI setztsubscription_status = 'canceled'. - Ein Webhook mit einer ungültigen Signatur gibt HTTP 400 zurück.
Testbefehle
bun add stripe @stripe/stripe-jspsql "$DATABASE_URL" -f migrations/0011_add_stripe_columns.sqlbun run typecheckbun run dev &stripe listen --forward-to localhost:3000/api/stripe/webhookstripe trigger checkout.session.completed# verify users table updatedpsql "$DATABASE_URL" -c "SELECT stripe_customer_id, subscription_status FROM users LIMIT 5;"Häufige KI-Fehler
- Importieren von
stripe(Server-SDK) in eine Client-Komponente, wodurchSTRIPE_SECRET_KEYoffengelegt wird. - Parsen des Webhook-Körpers als JSON vor der Signaturverifikation, wodurch alle Webhook-Validierungen fehlschlagen.
- Erstellen eines neuen Stripe-Kunden bei jedem Checkout anstatt
stripe_customer_idwiederzuverwenden. - Verwenden von
stripe.charges.create(veraltet) anstelle vonstripe.checkout.sessions.create.
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.