Overview

Stripe payment integration in Plainform with checkout sessions, subscriptions, customer portal, and webhooks

Plainform uses Stripe for payment processing, providing secure checkout, subscription management, and webhook integration out of the box.

What is Stripe?

Stripe is a complete payment platform that handles:

  • One-time payments and subscriptions
  • Checkout sessions with hosted payment pages
  • Webhook events for payment status updates
  • Manual payment capture for order verification
  • Automatic tax calculation
  • Coupon and promotion codes
  • Customer portal for subscription management

How Plainform Uses Stripe

Plainform integrates Stripe at three key points:

  1. Checkout Flow (app/api/stripe/checkout/) - Creates checkout sessions for one-time prices and recurring subscription prices
  2. Customer Portal (app/api/stripe/portal/) - Sends logged-in customers to Stripe Billing Portal to manage subscriptions
  3. Webhooks (app/api/webhooks/stripe/) - Routes Stripe events to focused handlers for payments, subscriptions, products, and coupons
  4. Product Display (lib/stripe/) - Fetches products, prices, coupons, customers, and sessions for the UI

For detailed information about Stripe's payment processing, security features, and advanced capabilities, see the official Stripe documentation.

Key Features in Plainform

Checkout Sessions

Pre-configured checkout with:

  • Hosted payment page (no PCI compliance needed)
  • Automatic tax calculation
  • Manual capture for order verification
  • Success/cancel URL redirects
  • Requires a signed-in Clerk user before checkout
  • Creates or reuses a Stripe customer linked to the Clerk user

Manual Payment Capture

Plainform uses manual capture mode for one-time payments:

  • Payment is authorized but not charged immediately
  • Allows order verification before capturing funds
  • Can cancel authorization if order is invalid
  • Capture or cancel via Stripe Dashboard or API

Webhook Integration

Real-time payment event processing:

  • checkout.session.completed - Delegates to one-time or subscription checkout handlers
  • customer.subscription.created - Subscription started
  • customer.subscription.updated - Subscription renewed, changed, or scheduled for cancellation
  • customer.subscription.deleted - Subscription fully ended
  • product.* and coupon.* - Pricing and event cache revalidation
  • Cache revalidation for products and coupons

Product & Pricing Display

Dynamic pricing section:

  • Fetches products from Stripe API
  • Displays prices with currency formatting
  • Shows active coupons and discounts
  • Cached with Next.js revalidation tags

Subscription Support

Full subscription lifecycle:

  • Create subscription plans in Stripe Dashboard
  • Automatic recurring billing
  • Customer portal for plan management
  • Webhook events for subscription changes
  • Local User table stores Stripe customer and subscription state
  • Product metadata can drive app-specific plan keys and feature limits

Customer Portal

Logged-in users can manage billing from the user menu. The menu posts to /api/stripe/portal, which creates a Stripe Billing Portal session for the current user's stripeCustomerId. If the user has no Stripe customer yet, they are redirected back to the pricing section.

Environment Variables

Required Stripe configuration in .env:

.env
# Publishable key
STRIPE_PUBLISHABLE_KEY=pk_test_...

# Secret key (server-side only)
STRIPE_SECRET_KEY=sk_test_...

# Webhook secret (for signature verification)
STRIPE_WEBHOOK_SECRET=whsec_...

Never expose STRIPE_SECRET_KEY or STRIPE_WEBHOOK_SECRET in client-side code. These are server-only secrets.

Payment Flow

One-Time Payment

User clicks "Buy Now"

User must be signed in

POST /api/stripe/checkout

Create or reuse Stripe customer linked to Clerk user

Stripe Checkout Session created (manual capture)

User completes payment

Webhook: checkout.session.completed

Order saved to database (payment authorized)

Manual review/verification

Capture payment via Stripe Dashboard

Checkout session metadata updated

Confirmation email sent

Subscription Payment

User selects subscription plan

User must be signed in

POST /api/stripe/checkout (mode: subscription)

Create or reuse Stripe customer linked to Clerk user

Stripe Checkout Session created

User completes payment

Webhook: customer.subscription.created

Subscription saved to database

Automatic recurring billing

User manages plan in Stripe Billing Portal

Security Features

  • PCI Compliance - Stripe handles all payment data
  • Webhook Signature Verification - Validates webhook authenticity
  • Rate Limiting - Prevents checkout abuse (5 requests per 10 seconds)
  • Manual Capture - Review orders before charging
  • HTTPS Only - All API calls over secure connection

Performance Considerations

  • Cached Product Data - Products fetched with force-cache and revalidation tags
  • Server-Side Only - Stripe client initialized with 'server-only' directive
  • Webhook Optimization - Fast event processing with targeted cache invalidation
  • Minimal Client JS - Checkout redirects to Stripe-hosted page

How is this guide ?

Last updated on

On this page