Waffo Pancake
如何设置和使用 Waffo Pancake 处理支付和订阅
MkSaaS 支持使用 Waffo Pancake 处理一次性支付和订阅 支付。Waffo 是一家 Merchant of Record(MoR,记录商), 可以代您处理全球税务计算、代收、合规和结算。
该集成使用官方 @waffo/pancake-ts SDK, 并使用 Waffo 托管的结账页面和消费者门户。卡信息不会经过您的应用服务器。
设置
MkSaaS 默认包含免费计划、月度和年度专业版订阅计划,以及终身一次性支付计划。
创建 Waffo 账户
在 pancake.waffo.ai 注册 Waffo 账户,并在引导过程中创建商店。基础设置可以参考 Waffo 快速入门。
获取 API 凭据
在 Waffo 控制台打开 API & Development,点击 Create API Key,复制
Merchant ID 和私钥,并将它们保存为 WAFFO_MERCHANT_ID 和
WAFFO_PRIVATE_KEY。
WAFFO_MERCHANT_ID 是 Merchant ID,不是 storeId,也不是从 URL 中复制
的商店标识。API 密钥在创建时绑定测试或生产环境,因此请为每个环境创建
独立的密钥。
私钥只能存放在服务端。将 PEM 私钥保存到环境变量时,使用转义的 \n 保留
换行:
WAFFO_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEv...\n-----END PRIVATE KEY-----"配置 Webhook
在 Waffo 控制台 > Settings > Webhooks 中点击 Add Webhook,并配置:
- 负载格式:Raw。只有这种格式会携带验签所需的
X-Waffo-Signature请求头。 - URL:
https://YOUR-DOMAIN.com/api/webhooks/waffo - 事件:保留Webhook 事件一节列出的支付、订阅和退款事件。
Waffo 不需要 Webhook 签名密钥环境变量。@waffo/pancake-ts SDK 内置验证
公钥,并通过 verifyWebhook() 验证原始请求体。
创建产品
Waffo 结账使用以 PROD_ 开头的 Product ID,而不是 Stripe 风格的价格 ID:
- 创建月度 Subscription 产品,将产品 ID 保存为
NEXT_PUBLIC_WAFFO_PRODUCT_PRO_MONTHLY。 - 创建年度 Subscription 产品,将产品 ID 保存为
NEXT_PUBLIC_WAFFO_PRODUCT_PRO_YEARLY。 - 创建 One-time 产品,将产品 ID 保存为
NEXT_PUBLIC_WAFFO_PRODUCT_LIFETIME。 - 如果启用了积分购买,再为积分套餐创建对应产品。
新产品默认处于测试模式。接收真实支付前,需要先发布到生产环境;发布是单向 操作。详情请参考 Waffo 订阅指南 和发布产品。
添加环境变量
在 .env 中设置支付提供商和 Waffo 凭据:
NEXT_PUBLIC_PAYMENT_PROVIDER=waffo
# 仅服务端使用的凭据
WAFFO_MERCHANT_ID=MER_...
WAFFO_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEv...\n-----END PRIVATE KEY-----"
# 可选:在生产构建中接受沙盒 Webhook,仅用于冒烟测试
# WAFFO_DEBUG=true
# 产品 ID
NEXT_PUBLIC_WAFFO_PRODUCT_PRO_MONTHLY=PROD_...
NEXT_PUBLIC_WAFFO_PRODUCT_PRO_YEARLY=PROD_...
NEXT_PUBLIC_WAFFO_PRODUCT_LIFETIME=PROD_...
# 可选的积分套餐产品 ID
NEXT_PUBLIC_WAFFO_PRODUCT_CREDITS_BASIC=PROD_...
NEXT_PUBLIC_WAFFO_PRODUCT_CREDITS_STANDARD=PROD_...
NEXT_PUBLIC_WAFFO_PRODUCT_CREDITS_PREMIUM=PROD_...
NEXT_PUBLIC_WAFFO_PRODUCT_CREDITS_ENTERPRISE=PROD_...配置价格
保留 src/config/website.tsx 中现有的 price.plans 配置,但在 Waffo
启用时,让其中的 priceId 使用 Waffo 产品 ID。金额、货币、周期、积分和计划
元数据必须与 Waffo 中创建的产品保持一致。
price: {
plans: {
pro: {
id: 'pro',
prices: [
{
type: PaymentTypes.SUBSCRIPTION,
priceId: process.env.NEXT_PUBLIC_WAFFO_PRODUCT_PRO_MONTHLY!,
amount: 990,
currency: 'USD',
interval: PlanIntervals.MONTH,
},
{
type: PaymentTypes.SUBSCRIPTION,
priceId: process.env.NEXT_PUBLIC_WAFFO_PRODUCT_PRO_YEARLY!,
amount: 9900,
currency: 'USD',
interval: PlanIntervals.YEAR,
},
],
isFree: false,
isLifetime: false,
},
},
},核心功能
- 月度和年度周期订阅
- 终身一次性支付
- 托管结账,无需在服务端处理卡信息
- 处理支付、订阅和退款事件的 Webhook
- Waffo 负责税务、合规和结算
- 支持 Magic Link 登录的消费者门户
- 与支付提供商无关的价格、结账、积分和账单组件
开发环境
本地开发时,Waffo 必须能够访问您的 Webhook 端点。请通过 HTTPS 隧道暴露本地 服务器:
ngrok http 3000
# 或
cloudflared tunnel --url http://localhost:3000将隧道 URL 作为测试环境 Webhook,例如
https://xxxx.ngrok-free.app/api/webhooks/waffo。不要把临时隧道 URL 配置为生产
Webhook。不要使用 localtunnel,因为它可能会剥离 X-Waffo-Signature 请求头。
模板提供 Waffo 沙盒 E2E 测试套件:
pnpm e2e:waffo沙盒结账不会产生真实扣款。在托管结账页选择 Credit/Debit Card,使用 Quick
Fill 的 Success 选项,或使用下方的测试卡。运行本地 E2E helper 时,可以通过
设置 WAFFO_ENV_FILE 复用被忽略的 MkFast Template 环境变量文件。
生产环境
- 完成 Waffo 商店审核 / KYB,启用生产支付。
- 将订阅和一次性产品从测试环境发布到生产环境。
- 创建生产环境 API 凭据,并将
WAFFO_MERCHANT_ID和WAFFO_PRIVATE_KEY替换为生产凭据。 - 将
https://YOUR-DOMAIN.com/api/webhooks/waffo注册为生产 Webhook。 - 不要设置
WAFFO_DEBUG,或将其设置为false。生产构建不能让沙盒事件授予真实 权限。
消费者门户
Waffo 提供共享的消费者门户:
https://pancake.waffo.ai/consumer/portal/login。客户使用购买时填写的邮箱和
一次性 Magic Link 登录,可以查看订阅和发票、取消或重新激活订阅、更新账单信息并
申请退款。
Webhook 事件
为 /api/webhooks/waffo 配置以下事件:
| 事件 | 描述 |
|---|---|
order.completed | 一次性订单支付成功 |
subscription.activated | 订阅首次支付成功 |
subscription.payment_succeeded | 订阅续费支付成功 |
subscription.updated | 订阅产品变更 |
subscription.canceling | 已申请取消,当前周期结束前仍有效 |
subscription.uncanceled | 撤回取消申请 |
subscription.canceled | 订阅终止 |
subscription.past_due | 续费失败,Waffo 正在重试 |
refund.succeeded | 退款完成并撤销访问权限 |
refund.failed | 退款失败 |
Waffo 会将测试和生产事件发送到同一个端点,每个负载都包含 mode 字段。MkSaaS
会拒绝与当前运行环境不匹配的事件。
测试卡
在 Waffo 测试模式中使用任意未来有效期和任意三位 CVC:
| 卡号 | 类型 | 结果 |
|---|---|---|
4576 7500 0000 0110 | Visa Credit | 成功 |
2226 9000 0000 0110 | Mastercard Credit | 成功 |
4576 7500 0000 0220 | Visa Credit | 拒绝 |
最佳实践
- 只在服务端保存
WAFFO_PRIVATE_KEY和WAFFO_MERCHANT_ID。 - 使用 Raw Webhook 格式,确保
X-Waffo-Signature请求头不丢失。 - 使用与运行环境匹配的测试或生产凭据。
- 上线前在沙盒中完成一次完整的结账和 Webhook 往返流程。
MkSaaS文档