Stripe Integration mit Claude Code: Payments, Subscriptions & Webhooks 2026

Stripe ist die mächtigste Payment-Plattform — aber auch eine der komplexesten zu integrieren. Checkout Sessions, Subscription-Lifecycle, Proration, Webhooks, Customer Portal: Claude Code generiert jeden Teil korrekt und erklärt die Fallstricke.

Der Stripe-Integration-Flow

  • Stripe-Kunde anlegen bei Registration — Stripe Customer ID in DB speichern
  • Checkout Session erstellen — Nutzer zur Stripe-Seite leiten
  • Webhook empfangen: checkout.session.completed → Subscription aktivieren
  • Subscription-Lifecycle managen: Upgrade, Downgrade, Cancel, Reaktivierung
  • Customer Portal: Self-Service für Nutzer (Zahlungsmethode, Kündigung)
  • Rechnungen und Invoices: automatisch, konfigurierbar
Claude Code Prompt-Strategie: Stripe-Integrationen sind komplex weil viele Randfälle existieren. Prompt-Tipp: "Implementiere Stripe Subscriptions. Berücksichtige: failed payments, dunning, trial periods, proration bei Plan-Wechsel, und Webhook-Idempotency." So bekommt man produktionsreife Code.

Checkout Session: One-Time und Subscription

CheckoutSession erstellen

# Prompt: "Erstelle Stripe Checkout für Subscription mit Trial" import Stripe from 'stripe'; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY); export async function createCheckoutSession({ customerId, priceId, userId, successUrl, cancelUrl }) { const session = await stripe.checkout.sessions.create({ customer: customerId, mode: 'subscription', line_items: [{ price: priceId, quantity: 1 }], // 14-Tage-Trial subscription_data: { trial_period_days: 14, metadata: { userId } }, // Success: nach Checkout weiterleiten success_url: `${successUrl}?session_id={CHECKOUT_SESSION_ID}`, cancel_url: cancelUrl, // Automatische Steuern (Stripe Tax) automatic_tax: { enabled: true }, // Metadata für Webhook metadata: { userId } }); return session.url; } # One-Time Payment (statt Subscription): # mode: 'payment' statt 'subscription' # line_items: [{ price: oneTimePriceId, quantity: 1 }]

Webhook-Handler: Der kritische Teil

WebhooksAlle relevanten Events abfangen

# Die wichtigsten Stripe-Webhook-Events für SaaS:
Event Wann Action
checkout.session.completed Kauf abgeschlossen Plan in DB aktivieren
customer.subscription.updated Plan-Wechsel, Trial-Ende Plan + Status updaten
customer.subscription.deleted Kündigung wirksam Auf FREE downgraden
invoice.payment_failed Zahlung fehlgeschlagen User informieren, Dunning
invoice.paid Rechnung bezahlt Zugang verlängern
# Webhook-Handler (Next.js App Router) export async function POST(req) { const body = await req.text(); const sig = req.headers.get('stripe-signature'); let event; try { event = stripe.webhooks.constructEvent( body, sig, process.env.STRIPE_WEBHOOK_SECRET ); } catch (err) { return Response.json({ error: 'Invalid signature' }, { status: 400 }); } // Idempotency: Events können mehrfach kommen! const processed = await db.webhookEvents.findUnique({ where: { stripeEventId: event.id } }); if (processed) return Response.json({ received: true }); await db.webhookEvents.create({ data: { stripeEventId: event.id } }); switch (event.type) { case 'customer.subscription.updated': case 'customer.subscription.created': { const sub = event.data.object; await syncSubscription(sub); break; } case 'customer.subscription.deleted': await cancelSubscription(event.data.object); break; case 'invoice.payment_failed': await handleFailedPayment(event.data.object); break; } return Response.json({ received: true }); }
Webhook-Idempotency ist Pflicht! Stripe kann dasselbe Event mehrfach senden (Netzwerkfehler, Retries). Immer prüfen ob das Event bereits verarbeitet wurde — sonst wird der User doppelt upgegraded oder downgraded.

Subscription-Management

SubscriptionPlan-Wechsel mit Proration

# Upgrade von BASIC zu PRO — anteilige Abrechnung async function upgradeSubscription(subscriptionId, newPriceId) { const subscription = await stripe.subscriptions.retrieve(subscriptionId); const updated = await stripe.subscriptions.update(subscriptionId, { items: [{ id: subscription.items.data[0].id, price: newPriceId }], // Sofort upgraden, anteilig berechnen proration_behavior: 'create_prorations', // Alternativ: 'none' (keine Proration) oder 'always_invoice' (sofort Rechnung) }); return updated; } # Kündigung zum Periodenende (nicht sofort): async function cancelAtPeriodEnd(subscriptionId) { return stripe.subscriptions.update(subscriptionId, { cancel_at_period_end: true }); // User behält Zugang bis Abo-Ende → dann subscription.deleted Event }

Customer Portal: Self-Service

PortalStripe Customer Portal einbinden

# Customer Portal: Stripe managed UI für Zahlungen, Pläne, Kündigung # Setup: Stripe Dashboard → Billing → Customer Portal → Configure export async function createPortalSession(customerId, returnUrl) { const session = await stripe.billingPortal.sessions.create({ customer: customerId, return_url: returnUrl // Wohin nach Portal-Exit }); return session.url; } # In der App: Button → redirect zu Portal # User kann selbst: Zahlungsmethode ändern, Abo kündigen, Plan wechseln # Du bekommst Webhook-Events für alle Änderungen → syncSubscription()
Customer Portal = Pflicht für SaaS. Ohne Portal musst du jeden Support-Case manuell bearbeiten. Mit Portal: User löst 90% selbst. Setup dauert 10 Minuten, spart Stunden pro Woche.

Testing: Stripe CLI und Test-Karten

# Stripe CLI: Webhooks lokal testen stripe listen --forward-to localhost:3000/api/webhooks/stripe # Webhook-Secret für lokale Tests: # STRIPE_WEBHOOK_SECRET=whsec_xxx (aus stripe listen Output) # Test-Karten: # Erfolg: 4242 4242 4242 4242 # Declined: 4000 0000 0000 0002 # 3D-Secure: 4000 0025 0000 3155 # SCA: 4000 0027 6000 3184 # Events triggern ohne echten Checkout: stripe trigger payment_intent.succeeded stripe trigger customer.subscription.deleted

Payment-Integration im Kurs

Im Claude Code Mastery Kurs: vollständige Stripe-Integration mit Checkout, Webhooks, Customer Portal, Subscription-Lifecycle und Testing — direkt in eine funktionierende SaaS-App eingebaut.

14 Tage kostenlos testen →