| name | payments |
| description | Integrate payments into any web or mobile app. Sets up Stripe, LemonSqueezy, or Polar.sh for web; Superwall or RevenueCat for mobile. Covers products, webhooks, subscription portal, billing page, and a test-to-live checklist. Use when adding a paywall, subscription plan, or one-time purchase to an app. |
Payments
You are wiring up a complete payment integration. Work through each phase in order.
Billing model: {{args}}
Phase 1: Interview
Use AskUserQuestion for every question below — one call per question, not markdown. Ask questions one at a time and wait for each answer before proceeding.
Question 1: Platform (single select):
| Value | Description |
|---|
web | Web app |
mobile | Mobile app (iOS / Android) |
both | Both web and mobile |
Question 2a: Web payment provider (single select; skip if platform is mobile-only):
| Value | Description |
|---|
stripe | Stripe — direct card processing, full control, best ecosystem |
lemonsqueezy | LemonSqueezy — built-in VAT/tax handling, great for solo/EU |
polar | Polar.sh — open-source, OSS-friendly, built-in sponsorships & benefits |
Question 2b: Mobile payment provider (single select; skip if platform is web-only):
| Value | Description |
|---|
revenuecat | RevenueCat — abstracts App Store + Google Play; best cross-platform |
superwall | Superwall — dynamic paywalls without deploys; iOS-first |
Question 3: Products & billing — ask as free text:
Describe your plans/products (names, prices, billing intervals, trial periods, e.g. "Pro $9/mo with 7-day trial, Enterprise $49/mo").
Question 4: Gating & stack — ask as free text:
Which features are paywalled, and what is your framework / API layer / user model?
Confirm the product catalog and gating rules before proceeding.
Phase 2: Explore
Spawn 3 parallel subagents:
| Subagent | Focus |
|---|
| 1 | User model, auth flow, session handling |
| 2 | Existing API routes, middleware, webhook handling patterns |
| 3 | Frontend component patterns, routing, protected pages |
Synthesize: data model changes needed, API route plan, frontend gating strategy.
Phase 3: Plan
Define the full implementation surface based on provider:
Web (Stripe / LemonSqueezy / Polar.sh)
- Database changes: add
customer_id, subscription_status, plan fields to user model
- Stripe:
stripe_customer_id
- LemonSqueezy:
lemon_customer_id
- Polar.sh:
polar_customer_id
- API routes: checkout session, billing portal, webhook handler
- Webhook events:
- Stripe:
checkout.session.completed, customer.subscription.updated, customer.subscription.deleted, invoice.payment_failed
- LemonSqueezy:
subscription_created, subscription_updated, subscription_cancelled, subscription_payment_failed
- Polar.sh:
subscription.created, subscription.updated, subscription.canceled, order.created
- Frontend: pricing page, upgrade prompt, billing management page, plan-gated components
- Env vars: keys needed in dev and prod
Mobile (Superwall / RevenueCat)
- No backend billing routes needed: App Store / Google Play handle the transaction
- RevenueCat: configure entitlements and offerings in dashboard; sync user ID on login
- Superwall: create paywall templates in dashboard; register triggers in code
- Database changes: optionally mirror subscription state server-side via webhooks for backend gating
- Env vars: SDK API keys per platform
Present the plan and confirm before implementing.
Phase 4: Implement
First, detect the package manager so $PM is set for whichever provider subsection you follow:
command -v bun >/dev/null 2>&1 && PM=bun || (command -v pnpm >/dev/null 2>&1 && PM=pnpm || PM=npm)
Shell note: This snippet assumes a POSIX shell. On Windows, run it via the Bash tool / Git Bash (PowerShell cannot run command -v, >/dev/null 2>&1, or &&/|| as written). PowerShell equivalent:
$PM = if (Get-Command bun -ErrorAction SilentlyContinue) { "bun" } elseif (Get-Command pnpm -ErrorAction SilentlyContinue) { "pnpm" } else { "npm" }
Stripe (Web)
- Install:
$PM add stripe
- Create customer on signup (or lazily on first checkout)
- Checkout session endpoint: returns hosted checkout URL
- Billing portal endpoint: returns portal URL for plan changes/cancellation
- Webhook handler:
- Verify signature:
stripe.webhooks.constructEvent
- Handle events, update user record in DB
- Return
200 fast; do async work after acknowledging
- Middleware to protect gated routes: check
subscription_status === 'active'
LemonSqueezy (Web)
- Install:
$PM add @lemonsqueezy/lemonsqueezy.js
- Create checkout via
createCheckout() with variant ID
- Webhook handler: verify with
X-Signature header using HMAC-SHA256
- Handle
subscription_created / subscription_updated / subscription_cancelled
- Store
lemon_customer_id and subscription_status on user
Polar.sh (Web)
- Install:
$PM add @polar-sh/sdk
- Create checkout session via
polar.checkouts.create({ products: ['<productId>'] })
- Webhook handler: verify with
validateEvent() imported from @polar-sh/sdk/webhooks (throws WebhookVerificationError on a bad signature)
- Handle
subscription.created, subscription.updated, subscription.canceled, order.created
- Store
polar_customer_id and subscription state on user
- Use Polar's customer portal URL for billing management
- Optionally configure Benefits (e.g. license keys, Discord roles, downloads) in Polar dashboard: no extra code needed
RevenueCat (Mobile)
- Install:
$PM add react-native-purchases (or native pod/gradle)
- Configure with
Purchases.configure({ apiKey }) on app launch
- Identify user:
Purchases.logIn(userId) after auth
- Fetch offerings with
Purchases.getOfferings() and display in paywall UI
- Purchase:
Purchases.purchasePackage(package)
- Check entitlements:
customerInfo.entitlements.active['pro'] to gate features
- Set up RevenueCat webhooks to mirror subscription state to your backend (optional but recommended)
Superwall (Mobile)
- Install: for Expo (SDK 53+) use
npx expo install expo-superwall (the current recommended SDK); for bare React Native use the legacy @superwall/react-native-superwall
- Configure:
Superwall.configure({ apiKey }) on app launch
- Identify user:
Superwall.shared.identify(userId) after auth
- Register trigger:
Superwall.shared.register('campaign_trigger') at paywall entry points
- Handle purchase result via
SuperwallDelegate or subscription handler
- Paywalls are managed in Superwall dashboard: no app update needed to change copy/design/pricing
Frontend (Web)
- Pricing page with plan cards and CTA hitting checkout endpoint
- Upgrade prompt component for paywalled features
- Billing page (link to portal endpoint)
- Show current plan in account settings
Phase 5: Test Mode Verification
Stripe
LemonSqueezy
Polar.sh
RevenueCat
Superwall
Phase 6: Live Checklist
Web (all providers)
Mobile (RevenueCat / Superwall)
Completion Report
- Products and prices configured
- API routes / SDK integration created
- Webhook events handled and tested
- Frontend: pricing page, upgrade prompts, billing management
- Gating: which routes/features/screens are protected
- Env vars required (names only)