stripe-verify

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Stripe Verify

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.
证明集成确实可用。不是“看起来正常”——而是真正能正常工作。测试真实流程,验证真实状态变更,确认Webhook真实交付。

Process

流程

1. Configuration Verification
Before functional tests, verify all configuration:
bash
undefined
1. 配置验证
在功能测试前,验证所有配置:
bash
undefined

Env vars exist

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
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

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)"
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

Webhook URL accessible

curl -s -o /dev/null -w "%{http_code}" -I -X POST "$WEBHOOK_URL"
curl -s -o /dev/null -w "%{http_code}" -I -X POST "$WEBHOOK_URL"

Must be 4xx or 5xx, not 3xx

Must be 4xx or 5xx, not 3xx

Stripe CLI connected

Stripe CLI connected

stripe listen --print-json --latest

**2. Checkout Flow Test**

Create a real test checkout session:

```bash
stripe listen --print-json --latest

**2. 结账流程测试**

创建真实的测试结账会话:

```bash

Trigger checkout (via app or API)

Trigger checkout (via app or API)

Complete with Stripe test card: 4242 4242 4242 4242

Complete with Stripe test card: 4242 4242 4242 4242

Verify:

Verify:

- Session created successfully

- Session created successfully

- Redirect works

- Redirect works

- Success page loads

- Success page loads

- POST /api/stripe/checkout/confirm succeeds (or equivalent return-page sync)

- POST /api/stripe/checkout/confirm succeeds (or equivalent return-page sync)

- Webhook received (check logs)

- Webhook received (check logs)

- Subscription created in Stripe Dashboard

- Subscription created in Stripe Dashboard

- User state updated in database

- User state updated in database


**3. Webhook Delivery Test**

Verify webhooks are actually delivering:

```bash

**3. Webhook交付测试**

验证Webhook确实已交付:

```bash

Check pending webhooks

Check pending webhooks

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

Resend a recent event

Resend a recent event

stripe events resend <event_id> --webhook-endpoint <endpoint_id>
stripe events resend <event_id> --webhook-endpoint <endpoint_id>

Watch logs for delivery

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.
vercel logs <app> --json | grep webhook

所有近期事件的`pending_webhooks`值应为0。

**4. 订阅状态转换**

测试每种状态转换:

**新用户 → 试用**
- 创建账户
- 验证试用已开始
- 验证试用结束日期正确

**试用 → 活跃**
- 在试用期间完成结账
- 验证剩余试用时长已被尊重(trial_end已传递给Stripe)
- 验证本地状态已更新

**活跃 → 已取消**
- 取消订阅(通过客户门户或API)
- 验证访问权限持续到周期结束
- 验证状态已反映取消情况

**已取消 → 重新订阅**
- 取消后重新订阅
- 验证已创建新订阅
- 验证计费立即开始(无新试用)

**试用过期**
- 等待试用过期(或模拟)
- 验证访问权限已被撤销
- 验证已向用户发送正确提示信息

**5. 边缘情况测试**

**Webhook幂等性**
- 重复发送同一个Webhook事件两次
- 验证无重复处理
- 验证无状态损坏

**乱序Webhook**
- 若可能,模拟事件乱序到达
- 验证系统能优雅处理

**支付失败**
- 使用Stripe测试卡模拟支付失败:4000 0000 0000 0002
- 验证订阅进入past_due状态
- 验证past_due状态下的访问策略

**6. 访问控制验证**

测试访问控制是否真正有效:

- 活跃订阅用户 → 可访问功能
- 试用用户 → 可访问功能
- 试用过期 → 被阻止访问
- 已取消(在周期内) → 可访问
- 已取消(超过周期) → 被阻止访问
- 逾期未付 → 取决于策略(通常有宽限期)

**7. 业务模型合规性**

对照`business-model-preferences`验证:

- 是否为单一定价层级?(无多个选项)
- 升级时是否保留试用?(检查Stripe订阅是否包含trial_end)
- 无免费增值逻辑?(试用过期=无访问权限)

**8. 订阅管理用户体验**

对照`stripe-subscription-ux`要求验证:

**设置页面是否存在:**
- [ ] 设置页面包含订阅板块
- [ ] 显示当前套餐名称
- [ ] 订阅状态带视觉指示器
- [ ] 显示下一次计费日期
- [ ] 显示支付方式(品牌+后四位)

**Stripe门户集成:**
- [ ] 存在“管理订阅”按钮
- [ ] 按钮可创建门户会话并跳转
- [ ] 返回URL配置正确

**账单历史:**
- [ ] 显示过往发票
- [ ] 可下载发票PDF
- [ ] 显示支付状态

**特定状态用户体验:**
- [ ] 试用用户显示试用横幅
- [ ] 已取消状态显示周期结束日期
- [ ] 逾期未付状态显示更新支付的行动号召
- [ ] 活跃状态显示“一切正常”指示器

**这是硬性要求。** 如果缺少订阅管理用户体验,验证不通过。用户必须能够管理自己的账单。

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)
验证报告:
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
  • stripe-setup
    之后(新集成)
  • stripe-reconcile
    之后(已应用修复)
  • 生产部署前
  • 定期作为健康检查

Deep Mode

深度模式

This skill defaults to deep verification. Don't skip tests to save time. Billing bugs cost more than the time spent testing.
此技能默认启用深度验证。不要为了节省时间而跳过测试。计费漏洞的代价远高于测试所花的时间。