Smart Stripe Integration Kit
Boost productivity with intelligent best practices for building payment integrations. Built for Claude Code with best practices and real-world patterns.
Stripe Integration Kit
Complete Stripe payment integration toolkit covering checkout sessions, subscriptions, webhooks, customer portal, metered billing, and payment element setup for SaaS and e-commerce applications.
When to Use This Skill
Choose Stripe Integration when:
- Adding payment processing to a web application
- Implementing subscription billing with plans and tiers
- Setting up Stripe webhooks for payment event handling
- Building customer self-service portals for billing management
- Implementing metered or usage-based billing
Consider alternatives when:
- Need crypto payments — use Coinbase Commerce
- Need invoicing only — use dedicated invoicing tools
- Need marketplace payments — consider Stripe Connect specifically
Quick Start
# Install Stripe SDK npm install stripe @stripe/stripe-js @stripe/react-stripe-js # Activate integration kit claude skill activate smart-stripe-integration-kit # Set up payments claude "Set up Stripe checkout for a SaaS subscription product"
Example: Subscription Checkout
// Backend: Create checkout session import Stripe from 'stripe'; const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!); export async function createCheckoutSession( customerId: string, priceId: string, successUrl: string, cancelUrl: string, ) { const session = await stripe.checkout.sessions.create({ customer: customerId, mode: 'subscription', payment_method_types: ['card'], line_items: [{ price: priceId, quantity: 1 }], success_url: `${successUrl}?session_id={CHECKOUT_SESSION_ID}`, cancel_url: cancelUrl, subscription_data: { trial_period_days: 14, metadata: { plan: 'pro' }, }, allow_promotion_codes: true, }); return session; } // Backend: Webhook handler export async function handleWebhook(req: Request) { const sig = req.headers.get('stripe-signature')!; const event = stripe.webhooks.constructEvent( await req.text(), sig, process.env.STRIPE_WEBHOOK_SECRET!, ); switch (event.type) { case 'checkout.session.completed': { const session = event.data.object as Stripe.Checkout.Session; await activateSubscription(session.customer as string, session.subscription as string); break; } case 'invoice.paid': { const invoice = event.data.object as Stripe.Invoice; await recordPayment(invoice); break; } case 'customer.subscription.deleted': { const subscription = event.data.object as Stripe.Subscription; await deactivateSubscription(subscription.customer as string); break; } } return new Response('OK', { status: 200 }); }
Core Concepts
Payment Flows
| Flow | Use Case | Stripe Feature |
|---|---|---|
| One-time Payment | E-commerce, digital products | Checkout Session (mode: payment) |
| Subscription | SaaS, membership | Checkout Session (mode: subscription) |
| Metered Billing | API usage, compute | Usage Records + Subscription |
| Pay-as-you-go | Credits, prepaid | Customer Balance |
| Marketplace | Multi-vendor payments | Stripe Connect |
| Invoicing | B2B billing | Invoices API |
Webhook Events
| Event | When It Fires | Action Required |
|---|---|---|
checkout.session.completed | Successful checkout | Provision access |
invoice.paid | Subscription renewal succeeds | Record payment, extend access |
invoice.payment_failed | Payment fails | Notify user, retry or suspend |
customer.subscription.updated | Plan change, trial end | Update user plan/features |
customer.subscription.deleted | Cancellation or non-payment | Revoke access |
charge.refunded | Refund processed | Adjust records |
// Frontend: Stripe Elements integration import { Elements, PaymentElement, useStripe, useElements } from '@stripe/react-stripe-js'; import { loadStripe } from '@stripe/stripe-js'; const stripePromise = loadStripe(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY!); function CheckoutForm() { const stripe = useStripe(); const elements = useElements(); const handleSubmit = async (e: React.FormEvent) => { e.preventDefault(); if (!stripe || !elements) return; const { error } = await stripe.confirmPayment({ elements, confirmParams: { return_url: `${window.location.origin}/payment/success`, }, }); if (error) { console.error(error.message); } }; return ( <form onSubmit={handleSubmit}> <PaymentElement /> <button type="submit" disabled={!stripe}> Subscribe </button> </form> ); } export default function PaymentPage({ clientSecret }: { clientSecret: string }) { return ( <Elements stripe={stripePromise} options={{ clientSecret }}> <CheckoutForm /> </Elements> ); }
Configuration
| Parameter | Description | Default |
|---|---|---|
api_version | Stripe API version | 2024-04-10 |
webhook_tolerance | Webhook signature tolerance (seconds) | 300 |
trial_days | Default trial period | 14 |
proration | Proration behavior on plan changes | create_prorations |
payment_methods | Accepted payment methods | ["card"] |
currency | Default currency | usd |
tax_collection | Automatic tax calculation | false |
Best Practices
-
Always verify webhook signatures — Use
stripe.webhooks.constructEvent()with your webhook secret to verify that events are genuinely from Stripe. Never process unverified webhook payloads, as attackers can forge event data to grant unauthorized access. -
Make webhook handlers idempotent — Stripe may send the same event multiple times. Use the event ID to deduplicate processing. Store processed event IDs and skip duplicates. Never assume a webhook fires exactly once.
-
Use Stripe Checkout for the payment flow, not custom forms — Stripe Checkout handles PCI compliance, 3D Secure, localization, and payment method display. Custom payment forms increase PCI scope and maintenance burden. Use Checkout for conversion-optimized, compliant payment flows.
-
Store Stripe customer IDs alongside your user records — Create a Stripe customer when a user signs up and store the customer ID. This enables pre-filling checkout, managing subscriptions, and viewing payment history without creating duplicate customers.
-
Test with Stripe CLI for local webhook development — Use
stripe listen --forward-to localhost:3000/api/webhooksto receive real webhook events locally. Test with Stripe's test clock feature for subscription lifecycle scenarios (trials, renewals, failures).
Common Issues
Webhook events arrive out of order. Stripe doesn't guarantee event ordering. Don't assume invoice.paid always follows checkout.session.completed. Design handlers to work independently — each handler should fetch the current resource state from Stripe rather than relying on previous events.
Subscription status gets out of sync between Stripe and your database. Rely on webhooks as the source of truth, not on redirect callbacks. The redirect after checkout confirms intent but not payment completion. Always use customer.subscription.updated and invoice.paid webhooks to update subscription status.
Test mode data contamination when switching between test and live modes. Use separate environments (staging and production) with different Stripe API keys. Never share a database between test and live Stripe modes. Prefix test user emails with test_ and filter them from production queries.
Reviews
No reviews yet. Be the first to review this template!
Similar Templates
Full-Stack Code Reviewer
Comprehensive code review skill that checks for security vulnerabilities, performance issues, accessibility, and best practices across frontend and backend code.
Test Suite Generator
Generates comprehensive test suites with unit tests, integration tests, and edge cases. Supports Jest, Vitest, Pytest, and Go testing.
Pro Architecture Workspace
Battle-tested skill for architectural, decision, making, framework. Includes structured workflows, validation checks, and reusable patterns for development.