Payment Expert

The Payment Expert agent specializes in payment processing, subscription management, Stripe integration, and billing systems for SaaS applications.

Expertise Areas#

  • Stripe Integration - SDK setup and configuration
  • Checkout Sessions - One-time and subscription payments
  • Webhook Handling - Payment event processing
  • Customer Portal - Self-service billing management
  • Usage-Based Billing - Metered subscription tracking
  • Subscription Management - Plan changes, cancellations
  • Pricing Components - UI for pricing pages

Usage Examples#

Stripe Setup#

Use the payment-expert agent to set up Stripe integration for a SaaS with multiple pricing tiers.

Response includes:

  • SDK configuration
  • Price ID management
  • Customer creation
  • Checkout flow

Webhook Handler#

Use the payment-expert agent to implement a comprehensive Stripe webhook handler for subscription events.

Response includes:

  • Signature verification
  • Event type handling
  • Database synchronization
  • Error handling

Billing Portal#

Use the payment-expert agent to add a customer billing portal for subscription management.

Response includes:

  • Portal session creation
  • Return URL handling
  • UI integration
  • Permission checking

Best Practices Applied#

1. Payment Processing#

  • Secure API key handling
  • Webhook signature verification
  • Idempotent event processing
  • Error recovery patterns

2. Subscription Management#

  • Database synchronization
  • Status tracking
  • Grace period handling
  • Dunning management

3. User Experience#

  • Clear pricing display
  • Smooth checkout flow
  • Self-service portal
  • Invoice access

4. Security#

  • PCI compliance via Stripe
  • Secure webhook endpoints
  • Proper authentication
  • Audit logging

Common Patterns#

Stripe Setup#

1// lib/stripe.ts 2import Stripe from 'stripe'; 3 4export const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, { 5 apiVersion: '2024-12-18.acacia', 6 typescript: true, 7}); 8 9export const PLANS = { 10 FREE: { priceId: null, name: 'Free', price: 0 }, 11 PRO: { 12 priceId: process.env.STRIPE_PRO_PRICE_ID!, 13 name: 'Pro', 14 price: 29, 15 }, 16 TEAM: { 17 priceId: process.env.STRIPE_TEAM_PRICE_ID!, 18 name: 'Team', 19 price: 99, 20 }, 21} as const;

Checkout Session#

1// app/api/checkout/route.ts 2import { stripe } from '@/lib/stripe'; 3import { auth } from '@/lib/auth'; 4 5export async function POST(req: Request) { 6 const session = await auth(); 7 if (!session?.user) { 8 return Response.json({ error: 'Unauthorized' }, { status: 401 }); 9 } 10 11 const { priceId } = await req.json(); 12 13 const checkoutSession = await stripe.checkout.sessions.create({ 14 customer: customerId, 15 mode: 'subscription', 16 payment_method_types: ['card'], 17 line_items: [{ price: priceId, quantity: 1 }], 18 success_url: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard?success=true`, 19 cancel_url: `${process.env.NEXT_PUBLIC_APP_URL}/pricing?canceled=true`, 20 subscription_data: { 21 metadata: { userId: session.user.id }, 22 }, 23 }); 24 25 return Response.json({ url: checkoutSession.url }); 26}

Webhook Handler#

1// app/api/webhooks/stripe/route.ts 2import { stripe } from '@/lib/stripe'; 3import { headers } from 'next/headers'; 4import Stripe from 'stripe'; 5 6export async function POST(req: Request) { 7 const body = await req.text(); 8 const signature = headers().get('stripe-signature')!; 9 10 let event: Stripe.Event; 11 12 try { 13 event = stripe.webhooks.constructEvent( 14 body, 15 signature, 16 process.env.STRIPE_WEBHOOK_SECRET! 17 ); 18 } catch (err) { 19 return Response.json({ error: 'Invalid signature' }, { status: 400 }); 20 } 21 22 switch (event.type) { 23 case 'checkout.session.completed': 24 await handleCheckoutComplete(event.data.object); 25 break; 26 case 'customer.subscription.updated': 27 await handleSubscriptionUpdate(event.data.object); 28 break; 29 case 'customer.subscription.deleted': 30 await handleSubscriptionCanceled(event.data.object); 31 break; 32 case 'invoice.payment_failed': 33 await handlePaymentFailed(event.data.object); 34 break; 35 } 36 37 return Response.json({ received: true }); 38}

Customer Portal#

1// app/api/portal/route.ts 2import { stripe } from '@/lib/stripe'; 3import { auth } from '@/lib/auth'; 4 5export async function POST() { 6 const session = await auth(); 7 if (!session?.user) { 8 return Response.json({ error: 'Unauthorized' }, { status: 401 }); 9 } 10 11 const customerId = await getStripeCustomerId(session.user.id); 12 if (!customerId) { 13 return Response.json({ error: 'No subscription' }, { status: 400 }); 14 } 15 16 const portalSession = await stripe.billingPortal.sessions.create({ 17 customer: customerId, 18 return_url: `${process.env.NEXT_PUBLIC_APP_URL}/dashboard`, 19 }); 20 21 return Response.json({ url: portalSession.url }); 22}

Sample Prompts#

TaskPrompt
Stripe setup"Set up Stripe integration with multiple pricing tiers"
Checkout"Implement checkout flow for subscription purchases"
Webhooks"Create webhook handler for subscription lifecycle events"
Portal"Add customer billing portal integration"
Usage billing"Implement usage-based billing with metered subscriptions"

Configuration#

1// bootspring.config.js 2module.exports = { 3 agents: { 4 customInstructions: { 5 'payment-expert': ` 6 - Use Stripe for payment processing 7 - Implement comprehensive webhook handling 8 - Set up customer portal for self-service 9 - Track subscription status in database 10 - Handle failed payments gracefully 11 `, 12 }, 13 }, 14 payments: { 15 provider: 'stripe', 16 plans: ['free', 'pro', 'team', 'enterprise'], 17 }, 18};