laravel-billing

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Laravel Billing (Cashier)

Laravel 账单系统(Cashier)

Agent Workflow (MANDATORY)

Agent 工作流(必须遵循)

Before ANY implementation, use
TeamCreate
to spawn 3 agents:
  1. fuse-ai-pilot:explore-codebase - Check existing billing setup, User model
  2. fuse-ai-pilot:research-expert - Verify latest Cashier docs via Context7
  3. mcp__context7__query-docs - Query specific patterns (Stripe/Paddle)
After implementation, run fuse-ai-pilot:sniper for validation.

在进行任何实现之前,使用
TeamCreate
生成3个Agent:
  1. fuse-ai-pilot:explore-codebase - 检查现有账单设置、User模型
  2. fuse-ai-pilot:research-expert - 通过Context7验证最新的Cashier文档
  3. mcp__context7__query-docs - 查询特定模式(Stripe/Paddle)
实现完成后,运行fuse-ai-pilot:sniper进行验证。

Overview

概述

Laravel Cashier provides subscription billing with Stripe or Paddle. Choose based on your needs:
ProviderPackageBest For
Stripe
laravel/cashier
Full control, high volume, complex billing
Paddle
laravel/cashier-paddle
Tax handling, compliance, global sales
Laravel Cashier 提供基于Stripe或Paddle的订阅账单服务。可根据需求选择:
支付服务商包名称适用场景
Stripe
laravel/cashier
完全控制、高交易量、复杂账单场景
Paddle
laravel/cashier-paddle
税务处理、合规要求、全球销售场景

Key Difference: MoR vs Payment Processor

核心差异:支付处理器 vs 代收款商

AspectStripePaddle
TypePayment ProcessorMerchant of Record
TaxesYou manage (or Stripe Tax)Paddle manages automatically
InvoicesYour company namePaddle + your name
ComplianceYour responsibilityPaddle handles
Fees~2.9% + $0.30~5% + $0.50 (all-inclusive)

对比项StripePaddle
类型支付处理器代收款商(Merchant of Record)
税务处理自行管理(或使用Stripe Tax)Paddle自动处理
发票显示显示您的公司名称显示Paddle + 您的名称
合规责任由您负责Paddle负责
手续费~2.9% + $0.30~5% + $0.50(全包价)

Critical Rules

重要规则

  1. Use webhooks - Never rely on client-side confirmations
  2. Handle grace periods - Allow access until subscription ends
  3. Never store card details - Use payment tokens/methods
  4. Test with test keys - Always before production
  5. Verify webhook signatures - Prevent spoofing attacks
  6. Handle incomplete payments - 3D Secure requires user action

  1. 使用Webhook - 绝不依赖客户端确认
  2. 处理宽限期 - 允许用户在订阅结束前继续访问
  3. 绝不存储银行卡信息 - 使用支付令牌/支付方式
  4. 使用测试密钥测试 - 上线前必须完成
  5. 验证Webhook签名 - 防止伪造攻击
  6. 处理未完成支付 - 3D Secure需要用户操作

Architecture

架构

app/
├── Http/
│   ├── Controllers/
│   │   └── Billing/              ← Billing controllers
│   │       ├── SubscriptionController.php
│   │       ├── CheckoutController.php
│   │       └── InvoiceController.php
│   └── Middleware/
│       └── EnsureSubscribed.php  ← Subscription check
├── Models/
│   └── User.php                  ← Billable trait
├── Listeners/
│   └── StripeEventListener.php   ← Webhook handling
└── Services/
    └── BillingService.php        ← Business logic

config/
├── cashier.php                   ← Stripe/Paddle config
└── services.php                  ← API keys

routes/
└── web.php                       ← Webhook routes (excluded from CSRF)

app/
├── Http/
│   ├── Controllers/
│   │   └── Billing/              ← 账单控制器
│   │       ├── SubscriptionController.php
│   │       ├── CheckoutController.php
│   │       └── InvoiceController.php
│   └── Middleware/
│       └── EnsureSubscribed.php  ← 订阅状态检查中间件
├── Models/
│   └── User.php                  ← 引入Billable trait
├── Listeners/
│   └── StripeEventListener.php   ← Webhook事件处理
└── Services/
    └── BillingService.php        ← 业务逻辑层

config/
├── cashier.php                   ← Stripe/Paddle配置
└── services.php                  ← API密钥配置

routes/
└── web.php                       ← Webhook路由(排除CSRF验证)

FuseCore Integration

FuseCore 集成

When working in a FuseCore project, billing follows the modular structure:
FuseCore/
├── Core/                         # Infrastructure (priority 0)
│   └── App/Contracts/
│       └── BillingServiceInterface.php  ← Billing contract
├── User/                         # Auth module (existing)
│   └── App/Models/User.php       ← Add Billable trait here
├── Billing/                      # Billing module (new)
│   ├── App/
│   │   ├── Http/
│   │   │   ├── Controllers/
│   │   │   │   ├── SubscriptionController.php
│   │   │   │   ├── CheckoutController.php
│   │   │   │   └── WebhookController.php
│   │   │   └── Middleware/
│   │   │       └── EnsureSubscribed.php
│   │   ├── Listeners/
│   │   │   └── HandleWebhookEvents.php
│   │   └── Services/
│   │       └── BillingService.php
│   ├── Config/
│   │   └── cashier.php           ← Module-level config
│   ├── Database/Migrations/
│   ├── Routes/
│   │   ├── web.php               ← Webhooks (no CSRF)
│   │   └── api.php               ← Subscription management
│   └── module.json               # dependencies: ["User"]
FuseCore项目中,账单模块遵循以下模块化结构:
FuseCore/
├── Core/                         # 基础设施层(优先级0)
│   └── App/Contracts/
│       └── BillingServiceInterface.php  ← 账单服务契约
├── User/                         # 认证模块(已存在)
│   └── App/Models/User.php       ← 在此引入Billable trait
├── Billing/                      # 账单模块(新增)
│   ├── App/
│   │   ├── Http/
│   │   │   ├── Controllers/
│   │   │   │   ├── SubscriptionController.php
│   │   │   │   ├── CheckoutController.php
│   │   │   │   └── WebhookController.php
│   │   │   └── Middleware/
│   │   │       └── EnsureSubscribed.php
│   │   ├── Listeners/
│   │   │   └── HandleWebhookEvents.php
│   │   └── Services/
│   │       └── BillingService.php
│   ├── Config/
│   │   └── cashier.php           ← 模块级配置
│   ├── Database/Migrations/
│   ├── Routes/
│   │   ├── web.php               ← Webhook路由(无CSRF验证)
│   │   └── api.php               ← 订阅管理API
│   └── module.json               # 依赖:["User"]

FuseCore Billing Checklist

FuseCore 账单检查清单

  • Billing code in
    /FuseCore/Billing/
    module
  • Billable trait on User model in
    /FuseCore/User/
  • Webhook routes in
    /FuseCore/Billing/Routes/web.php
  • Exclude webhook from CSRF in
    VerifyCsrfToken
  • Declare
    "User"
    dependency in
    module.json
→ See fusecore skill for complete module patterns.

  • 账单代码位于
    /FuseCore/Billing/
    模块
  • /FuseCore/User/
    的User模型上引入Billable trait
  • Webhook路由位于
    /FuseCore/Billing/Routes/web.php
  • VerifyCsrfToken
    中排除Webhook路由
  • module.json
    中声明
    "User"
    依赖
→ 查看 fusecore skill 获取完整模块模式。

Decision Guide

决策指南

Stripe vs Paddle

Stripe vs Paddle

Selling to businesses (B2B)? → Stripe
├── Need OAuth for third-party apps? → Stripe Connect
└── Selling to consumers (B2C) globally?
    ├── Want to handle taxes yourself? → Stripe + Stripe Tax
    └── Want tax compliance handled? → Paddle
面向企业客户(B2B)? → Stripe
├── 需要为第三方应用提供OAuth? → Stripe Connect
└── 面向全球消费者(B2C)?
    ├── 希望自行处理税务? → Stripe + Stripe Tax
    └── 希望由服务商处理税务合规? → Paddle

Subscription vs One-Time

订阅制 vs 一次性支付

Recurring revenue? → Subscription
├── Fixed plans? → Single-price subscription
└── Usage-based? → Metered billing (Stripe) or quantity-based
Single purchase? → One-time charge
├── Digital product? → Checkout session
└── Service fee? → Direct charge

 recurring收入? → 订阅制
├── 固定套餐? → 单一价格订阅
└── 按使用量计费? → 计量计费(Stripe)或按数量计费
一次性购买? → 一次性收费
├── 数字产品? → 结账会话
└── 服务费? → 直接收费

Key Concepts

核心概念

ConceptDescriptionReference
BillableTrait that enables billing on a modelstripe.md
SubscriptionRecurring billing cyclesubscriptions.md
Price IDStripe/Paddle price identifierstripe.md
Grace PeriodTime after cancellation with accesssubscriptions.md
WebhookServer-to-server payment notificationswebhooks.md
Customer PortalSelf-service billing managementcheckout.md

概念描述参考文档
Billable为模型启用账单功能的Traitstripe.md
Subscriptionrecurring账单周期subscriptions.md
Price IDStripe/Paddle的价格标识符stripe.md
Grace Period取消订阅后仍可访问的宽限期subscriptions.md
Webhook服务器到服务器的支付通知webhooks.md
Customer Portal自助式账单管理门户checkout.md

Reference Guide

参考指南

Concepts (WHY & Architecture)

基础概念(设计思路与架构)

TopicReferenceWhen to Consult
Stripe Cashierstripe.mdStripe setup, configuration
Paddle Cashierpaddle.mdPaddle setup, differences
Subscriptionssubscriptions.mdCreate, cancel, swap, pause
Webhookswebhooks.mdWebhook security, handling
Invoicesinvoices.mdPDF generation, receipts
Payment Methodspayment-methods.mdCards, wallets, updates
Checkoutcheckout.mdHosted checkout, portal
Testingtesting.mdTest cards, webhook testing
主题参考文档适用场景
Stripe Cashierstripe.mdStripe设置、配置
Paddle Cashierpaddle.mdPaddle设置、差异对比
订阅管理subscriptions.md创建、取消、切换、暂停订阅
Webhookwebhooks.mdWebhook安全、事件处理
发票管理invoices.mdPDF生成、收据
支付方式payment-methods.md银行卡、钱包、更新支付方式
结账流程checkout.md托管结账、客户门户
测试testing.md测试银行卡、Webhook测试

Advanced SaaS Features

高级SaaS功能

TopicReferenceWhen to Consult
Metered Billingmetered-billing.mdUsage-based pricing (API, storage)
Team Billingteam-billing.mdOrganization billing, per-seat
Dunningdunning.mdFailed payment recovery
Feature Flagsfeature-flags.mdPlan-based feature access
主题参考文档适用场景
计量计费metered-billing.md按使用量定价(API、存储)
团队账单team-billing.md组织账单、按席位计费
催缴管理dunning.md失败支付恢复
功能开关feature-flags.md基于套餐的功能访问控制

Templates (Complete Code)

模板(完整代码)

TemplateWhen to Use
UserBillable.php.mdUser model with Billable trait
SubscriptionController.php.mdCRUD subscription operations
WebhookController.php.mdCustom webhook handling
CheckoutController.php.mdStripe Checkout + Portal
InvoiceController.php.mdInvoice download
BillingRoutes.php.mdComplete route definitions
SubscriptionTest.php.mdPest tests for billing
MeteredBillingController.php.mdUsage tracking and reporting
TeamBillable.php.mdTeam model with seat management
DunningService.php.mdPayment recovery automation
FeatureFlags.php.mdLaravel Pennant per-plan features

模板适用场景
UserBillable.php.md引入Billable trait的User模型
SubscriptionController.php.md订阅操作的CRUD控制器
WebhookController.php.md自定义Webhook处理
CheckoutController.php.mdStripe结账 + 客户门户
InvoiceController.php.md发票下载
BillingRoutes.php.md完整路由定义
SubscriptionTest.php.md账单功能的Pest测试
MeteredBillingController.php.md使用量跟踪与报告
TeamBillable.php.md带席位管理的团队模型
DunningService.php.md支付恢复自动化
FeatureFlags.php.md基于Laravel Pennant的套餐功能控制

Quick Reference

快速参考

Check Subscription Status

检查订阅状态

php
// Has active subscription?
$user->subscribed('default');

// Subscribed to specific price?
$user->subscribedToPrice('price_premium', 'default');

// On trial?
$user->onTrial('default');

// Cancelled but still active?
$user->subscription('default')->onGracePeriod();
php
// 是否有活跃订阅?
$user->subscribed('default');

// 是否订阅了特定价格?
$user->subscribedToPrice('price_premium', 'default');

// 是否处于试用期?
$user->onTrial('default');

// 是否已取消但仍在宽限期?
$user->subscription('default')->onGracePeriod();

Create Subscription

创建订阅

php
// Simple subscription
$user->newSubscription('default', 'price_monthly')
    ->create($paymentMethodId);

// With trial
$user->newSubscription('default', 'price_monthly')
    ->trialDays(14)
    ->create($paymentMethodId);
php
// 简单订阅
$user->newSubscription('default', 'price_monthly')
    ->create($paymentMethodId);

// 带试用期的订阅
$user->newSubscription('default', 'price_monthly')
    ->trialDays(14)
    ->create($paymentMethodId);

Manage Subscription

管理订阅

php
$subscription = $user->subscription('default');

// Change plan
$subscription->swap('price_yearly');

// Cancel at period end
$subscription->cancel();

// Cancel immediately
$subscription->cancelNow();

// Resume cancelled subscription
$subscription->resume();
php
$subscription = $user->subscription('default');

// 切换套餐
$subscription->swap('price_yearly');

// 到期时取消
$subscription->cancel();

// 立即取消
$subscription->cancelNow();

// 恢复已取消的订阅
$subscription->resume();

Billing Portal

账单门户

php
// Redirect to customer portal (Stripe)
return $user->redirectToBillingPortal(route('dashboard'));

// Get portal URL
$url = $user->billingPortalUrl(route('dashboard'));

php
// 重定向到客户门户(Stripe)
return $user->redirectToBillingPortal(route('dashboard'));

// 获取门户URL
$url = $user->billingPortalUrl(route('dashboard'));

Best Practices

最佳实践

DO

建议

  • Use webhooks for payment confirmation
  • Implement grace periods for cancelled subscriptions
  • Set up webhook signature verification
  • Handle
    IncompletePayment
    exceptions
  • Test with Stripe CLI locally
  • Prune old data regularly
  • 使用Webhook确认支付
  • 为已取消订阅的用户提供宽限期
  • 配置Webhook签名验证
  • 处理
    IncompletePayment
    异常
  • 本地使用Stripe CLI测试
  • 定期清理旧数据

DON'T

禁忌

  • Trust client-side payment confirmations
  • Store card numbers (PCI compliance)
  • Skip webhook verification
  • Ignore failed payment webhooks
  • Forget to handle 3D Secure
  • Hardcode prices (use env or config)
  • 信任客户端的支付确认
  • 存储银行卡号(违反PCI合规)
  • 跳过Webhook验证
  • 忽略失败支付的Webhook
  • 未处理3D Secure验证
  • 硬编码价格(使用环境变量或配置文件)