Agent Skills: Stripe Verify

|

UncategorizedID: phrazzld/claude-config/stripe-verify

Install this agent skill to your local

pnpm dlx add-skill https://github.com/phrazzld/claude-config/tree/HEAD/skills/stripe-verify

Skill Files

Browse the full folder contents for stripe-verify.

Download Skill

Loading file tree…

skills/stripe-verify/SKILL.md

Skill Metadata

Name
stripe-verify
Description
|

Stripe Verify

Comprehensive end-to-end verification. Go deep — billing bugs are expensive.

Objective

Prove the integration works. Not "looks right" — actually works. Test real flows, verify real state changes, confirm real webhook delivery.

Process

1. Configuration Verification

Before functional tests, verify all configuration:

# Env vars exist
bunx convex env list | rg "^(STRIPE_|CONVEX_WEBHOOK_TOKEN=)"
bunx convex env list --prod | rg "^(STRIPE_|CONVEX_WEBHOOK_TOKEN=)"
vercel env ls --environment=production 2>/dev/null | rg "^(STRIPE_|CONVEX_WEBHOOK_TOKEN=)" || true

# Token parity (Next/Vercel ↔ Convex) - P0 invariant
vercel env pull .env.vercel-parity-check --environment=production --yes >/dev/null
vercel_token=$(rg "^CONVEX_WEBHOOK_TOKEN=" .env.vercel-parity-check | head -n1 | cut -d= -f2-)
rm -f .env.vercel-parity-check
convex_token=$(bunx convex env get --prod CONVEX_WEBHOOK_TOKEN 2>/dev/null || true)
[ -n "$vercel_token" ] && [ -n "$convex_token" ] && [ "$vercel_token" = "$convex_token" ] && echo "✓ CONVEX_WEBHOOK_TOKEN parity (prod)" || echo "✗ CONVEX_WEBHOOK_TOKEN parity failed (prod)"

# Webhook URL accessible
curl -s -o /dev/null -w "%{http_code}" -I -X POST "$WEBHOOK_URL"
# Must be 4xx or 5xx, not 3xx

# Stripe CLI connected
stripe listen --print-json --latest

2. Checkout Flow Test

Create a real test checkout session:

# Trigger checkout (via app or API)
# Complete with Stripe test card: 4242 4242 4242 4242

# Verify:
# - Session created successfully
# - Redirect works
# - Success page loads
# - POST /api/stripe/checkout/confirm succeeds (or equivalent return-page sync)
# - Webhook received (check logs)
# - Subscription created in Stripe Dashboard
# - User state updated in database

3. Webhook Delivery Test

Verify webhooks are actually delivering:

# Check pending webhooks
stripe events list --limit 5 | jq '.data[] | {id, type, pending_webhooks}'

# Resend a recent event
stripe events resend <event_id> --webhook-endpoint <endpoint_id>

# Watch logs for delivery
vercel logs <app> --json | grep webhook

All recent events should have pending_webhooks: 0.

4. Subscription State Transitions

Test each state transition:

New → Trial

  • Create account
  • Verify trial starts
  • Verify trial end date correct

Trial → Active

  • Complete checkout during trial
  • Verify remaining trial honored (trial_end passed to Stripe)
  • Verify local state updated

Active → Canceled

  • Cancel subscription (via customer portal or API)
  • Verify access continues until period end
  • Verify state reflects cancellation

Canceled → Resubscribed

  • Resubscribe after cancellation
  • Verify new subscription created
  • Verify billing starts immediately (no new trial)

Trial Expired

  • Let trial expire (or simulate)
  • Verify access revoked
  • Verify proper messaging to user

5. Edge Case Testing

Webhook Idempotency

  • Resend the same webhook event twice
  • Verify no duplicate processing
  • Verify no state corruption

Out-of-Order Webhooks

  • If possible, simulate events arriving out of order
  • Verify system handles gracefully

Payment Failure

  • Use Stripe test card for decline: 4000 0000 0000 0002
  • Verify subscription goes to past_due
  • Verify access policy for past_due state

6. Access Control Verification

Test that access control actually works:

  • Active subscriber → can access features
  • Trial user → can access features
  • Expired trial → blocked
  • Canceled (in period) → can access
  • Canceled (past period) → blocked
  • Past due → depends on policy (usually grace period)

7. Business Model Compliance

Verify against business-model-preferences:

  • Single pricing tier? (no multiple options)
  • Trial honored on upgrade? (check Stripe subscription has trial_end)
  • No freemium logic? (expired trial = no access)

8. Subscription Management UX

Verify against stripe-subscription-ux requirements:

Settings Page Exists:

  • [ ] Settings page has subscription section
  • [ ] Current plan name displayed
  • [ ] Subscription status with visual indicator
  • [ ] Next billing date shown
  • [ ] Payment method displayed (brand + last4)

Stripe Portal Integration:

  • [ ] "Manage Subscription" button exists
  • [ ] Button creates portal session and redirects
  • [ ] Return URL configured correctly

Billing History:

  • [ ] Past invoices displayed
  • [ ] Invoice PDFs downloadable
  • [ ] Payment statuses shown

State-Specific UX:

  • [ ] Trial banner shows for trialing users
  • [ ] Canceled state shows period end date
  • [ ] Past due state shows payment update CTA
  • [ ] Active state shows "all good" indicator

This is a hard requirement. If subscription management UX is missing, verification fails. Users must be able to manage their billing.

Output

Verification report:

STRIPE VERIFICATION REPORT
=========================

CONFIGURATION
✓ All env vars present
✓ Webhook URL responds correctly
✓ Stripe CLI connected

CHECKOUT FLOW
✓ Session creates
✓ Payment succeeds
✓ Webhook received
✓ State updated

SUBSCRIPTION STATES
✓ Trial → Active
✓ Active → Canceled
✓ Canceled → Resubscribed
⚠ Trial expiration: not tested (would require waiting)

EDGE CASES
✓ Idempotent webhook handling
✓ Payment decline handled
✗ Out-of-order webhooks: not testable

ACCESS CONTROL
✓ Active: access granted
✓ Trial: access granted
✓ Expired: access denied
✓ Canceled in-period: access granted

BUSINESS MODEL
✓ Single tier
✓ Trial completion on upgrade
✓ No freemium

SUBSCRIPTION MANAGEMENT UX
✓ Settings page has subscription section
✓ Plan name and status displayed
✓ Next billing date shown
✓ Payment method displayed
✓ Manage Subscription button works
✓ Billing history accessible
✓ Trial banner for trialing users
✓ Canceled state messaging
⚠ Past due state: not tested

---
STATUS: VERIFIED (with minor gaps)

When to Run

  • After stripe-setup (new integration)
  • After stripe-reconcile (fixes applied)
  • Before production deployment
  • Periodically as health check

Deep Mode

This skill defaults to deep verification. Don't skip tests to save time. Billing bugs cost more than the time spent testing.