Skip to content
Back to skills

Stripe Subscriptions

ASecurity

Stripe subscription lifecycle patterns: checkout sessions, webhook verification (raw body gotcha), customer portal, usage-based billing, proration, and trial management.

  • 6 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 27, 2026
developmenttypescriptgoexpress

Works with

  • cli

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add KevinZai/commander --skill stripe-subscriptions --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Stripe Subscriptions?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Stripe Subscriptions
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/kevinzai-stripe-subscriptions/badge)](https://www.skillsdirectory.com/skills/kevinzai-stripe-subscriptions)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: stripe-subscriptions
description: "Stripe subscription lifecycle patterns: checkout sessions, webhook verification (raw body gotcha), customer portal, usage-based billing, proration, and trial management."
category: payments
risk: critical
source: custom
tags: [stripe, billing, subscriptions, webhooks, saas]
---

# Stripe Subscription Lifecycle

## When to Use
- Implementing Stripe Checkout for subscriptions
- Building webhook handlers (CRITICAL: raw body verification)
- Managing subscription lifecycle (create, upgrade, cancel, pause)
- Implementing usage-based billing or metered pricing
- Building customer billing portal
- Handling failed payments and dunning

## Critical: Webhook Raw Body Gotcha
```typescript
// ❌ WRONG — parsed body breaks signature verification
app.use(express.json());
app.post('/webhook', (req, res) => {
  stripe.webhooks.constructEvent(req.body, sig, secret); // FAILS
});

// ✅ CORRECT — use raw body for verification
app.post('/webhook',
  express.raw({ type: 'application/json' }),
  (req, res) => {
    const event = stripe.webhooks.constructEvent(
      req.body, // raw Buffer
      req.headers['stripe-signature'],
      process.env.STRIPE_WEBHOOK_SECRET
    );
  }
);
```

## Subscription Flow
```
Checkout Session → customer.subscription.created →
invoice.payment_succeeded → subscription active →
[upgrade/downgrade] → customer.subscription.updated →
[cancel] → customer.subscription.deleted
```

## Key Webhook Events
- `checkout.session.completed` — new subscription
- `invoice.payment_succeeded` — renewal
- `invoice.payment_failed` — payment issue (start dunning)
- `customer.subscription.updated` — plan change
- `customer.subscription.deleted` — cancellation
- `customer.subscription.trial_will_end` — 3 days before trial ends

## Best Practices
- Idempotent webhook handlers (use event.id for dedup)
- Store Stripe customer ID on your user model
- Use Stripe Customer Portal for self-service billing
- Implement proper proration for mid-cycle upgrades
- Handle `past_due` status gracefully (don't hard-lock immediately)
- Test with Stripe CLI: `stripe listen --forward-to localhost:3000/webhook`

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…