S

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.

SkillCommunitydevelopmentv1.0.0MIT
0 views0 copies

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

FlowUse CaseStripe Feature
One-time PaymentE-commerce, digital productsCheckout Session (mode: payment)
SubscriptionSaaS, membershipCheckout Session (mode: subscription)
Metered BillingAPI usage, computeUsage Records + Subscription
Pay-as-you-goCredits, prepaidCustomer Balance
MarketplaceMulti-vendor paymentsStripe Connect
InvoicingB2B billingInvoices API

Webhook Events

EventWhen It FiresAction Required
checkout.session.completedSuccessful checkoutProvision access
invoice.paidSubscription renewal succeedsRecord payment, extend access
invoice.payment_failedPayment failsNotify user, retry or suspend
customer.subscription.updatedPlan change, trial endUpdate user plan/features
customer.subscription.deletedCancellation or non-paymentRevoke access
charge.refundedRefund processedAdjust 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

ParameterDescriptionDefault
api_versionStripe API version2024-04-10
webhook_toleranceWebhook signature tolerance (seconds)300
trial_daysDefault trial period14
prorationProration behavior on plan changescreate_prorations
payment_methodsAccepted payment methods["card"]
currencyDefault currencyusd
tax_collectionAutomatic tax calculationfalse

Best Practices

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. Test with Stripe CLI for local webhook development — Use stripe listen --forward-to localhost:3000/api/webhooks to 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.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates