Payments

Stripe integration, subscription handling, and webhooks

Payments

SaaS Pack includes a complete Stripe integration for handling payments and subscriptions.

Features

  • Stripe Checkout integration
  • Subscription management
  • Webhook handling
  • Customer portal
  • Invoice generation
  • Payment method management

Configuration

Environment Variables

STRIPE_PUBLIC_KEY=pk_test_...
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...

Stripe Dashboard Setup

  1. Create a new Stripe account or use existing
  2. Add your products and pricing plans
  3. Configure webhooks endpoint: https://yourdomain.com/api/webhooks/stripe
  4. Copy webhook signing secret

Creating a Checkout Session

// Create a checkout session
const session = await $fetch('/api/stripe/checkout', {
  method: 'POST',
  body: {
    priceId: 'price_xxx',
    successUrl: '/success',
    cancelUrl: '/pricing'
  }
})

// Redirect to Stripe Checkout
window.location.href = session.url

Subscription Management

// Get current subscription
const subscription = await $fetch('/api/stripe/subscription')

// Cancel subscription
await $fetch('/api/stripe/subscription', {
  method: 'DELETE'
})

// Update subscription
await $fetch('/api/stripe/subscription', {
  method: 'PATCH',
  body: {
    priceId: 'price_new_plan'
  }
})

Webhook Handling

// server/api/webhooks/stripe.post.ts
export default defineEventHandler(async (event) => {
  const signature = getHeader(event, 'stripe-signature')
  const body = await readRawBody(event)
  
  const stripeEvent = stripe.webhooks.constructEvent(
    body,
    signature,
    process.env.STRIPE_WEBHOOK_SECRET
  )
  
  switch (stripeEvent.type) {
    case 'checkout.session.completed':
      // Handle successful checkout
      break
    case 'customer.subscription.updated':
      // Handle subscription update
      break
    case 'customer.subscription.deleted':
      // Handle subscription cancellation
      break
  }
})

Customer Portal

Allow customers to manage their subscriptions:

// Create portal session
const portalSession = await $fetch('/api/stripe/portal', {
  method: 'POST'
})

// Redirect to portal
window.location.href = portalSession.url

Testing

Use Stripe test cards for development:

  • Success: 4242 4242 4242 4242
  • Requires authentication: 4000 0025 0000 3155
  • Declined: 4000 0000 0000 9995

Next Steps