# 不止 Stripe：全球 SaaS 该怎么选支付通道

> 六个适配器、一份 Webhook 契约。Merchant of Record 到底改变了什么、哪些字段必须来自合同、以及不用六个沙箱账户怎么测。

- Author / publisher: make1day (company)
- Published: 2026-11-07
- Canonical: /blog/saas-billing-payment-gateways
- Category: Billing
- Tags: Creem Next.js boilerplate, PayPal SaaS starter, Waffo Pancake Next.js, Lemon Squeezy vs Stripe SaaS
- Language: zh

多数模板接完 Stripe 就停了。等你卖到卡不是默认支付方式的市场，或发现一个人算 VAT 等于第二份工作时，问题就来了。

## Merchant of Record 与支付处理商的区别

处理商（Stripe、PayPal、Waffo Acquiring）负责搬钱，税务计算、开票与合规仍归你。Merchant of Record（Waffo Pancake、Lemon Squeezy，部分配置下的 Creem）是法律意义上的卖方，负责销售税／VAT、发票，通常还有退款。对没有公司主体却要全球收款的独立开发者，这个差别就是选择它的全部理由。

## 六个适配器

本项目带 Waffo Pancake（默认，MoR）、Waffo Acquiring、Stripe、Creem、PayPal、Lemon Squeezy，另有 none 供自带计费。在 Builder 里选一个，其余适配器会从 ZIP 中剪掉。六个实现同一份接口：创建结账、创建客户门户会话、验签 Webhook。

合同字段一律由 env 提供，代码绝不代填：Waffo Acquiring 的商户号、return/notify URL、商品 id、签名模式都来自 WAFFO_ACQUIRING_* 变量，需从商户合同复制。缺任何一个，配置层会抛出指名变量的错误。

## 一份验签契约，六份实现

每个适配器在签名缺失、无效或格式损坏时都抛错，路由转成 400。返回空列表只表示「合法已验签但无需处理」，对应 200 加 ignored 标记。写 license 或套餐之前按事件 id 去重。早期版本在验签失败时也返回空列表，等于五个网关都用 200 接受了伪造请求；现在这份契约由离线探测脚本守着。

## 没有六个沙箱账户怎么测

四层：只报告缺失变量（不返回密钥）的配置自检；离线验签探测（npm run probe:webhook），对合法、缺失、篡改、损坏四类请求断言 400/200；逐网关沙箱对照；上线前一次真实小额购买。前两层完全不需要凭据，应该进 CI；后两层才要各家的沙箱密钥。完整矩阵见 docs/payment-testing.md。

## FAQ

### 支持哪些支付通道？

Waffo Pancake（默认 Merchant of Record）、Waffo Acquiring、Stripe、Creem、PayPal、Lemon Squeezy，以及 none。生成的 ZIP 只包含选中的那一个适配器。

### 全球收款必须有公司主体吗？

用 Merchant of Record 不必——Waffo Pancake 或 Lemon Squeezy 作为法律卖方处理税务。用普通处理商，税务、开票与合规由你自己承担。

### 代码会代填缺失的合同字段吗？

不会。商户号、价格 id、notify URL、签名模式必须来自 env 或商户合同。缺少必填变量时会抛出指名变量的错误，而不是塞一个看起来合理的占位值。

---

Source: make1day. See /llms.txt and /llms-full.txt for the full machine-readable product description.
