discipline/rounds/round-11-paddle-payment.md
📑 本页目录
轮次记录 · Round 11 · Paddle 支付打通(L5 变现落地)
1. 目标与选题
- 用户指令:我是中国个人开发者,海外收费用 Paddle 是否最简便?请把支付途径打通。
- 调研结论:是。Stripe 不支持大陆个人主体;Paddle 是 Merchant of Record(MoR), 替你处理全球税务合规,注册主体支持 Individual,提现走 Payoneer (Paddle 的 PayPal 提现已于 2026-02-28 停止)。
- 本轮完成标准 = 支付代码就绪(沙盒可测)+ 审核落地页完整 + 用户侧分步指南; 不伪造付费(未配密钥前保持 waitlist,webhook 验签后才置 active)。
2. 背景与相关文献
- 学科资产:09-value-chain.md §6 变现纪律(付费点绑定 L4 价值、订阅率 = 价值代理)、 Round 9 订阅状态机(waitlist→active→canceled)、06-evidence.md 先注册后计分。
- 支付参考(官方文档核验,2026-04 版):
- 创建 Checkout:
POST /transactions(Authorization: Bearer <api_key>), body{"items":[{"price_id":"pri_...","quantity":1}], "custom_data":{...}}→ 响应data.checkout.url;custom_data贯穿所有 webhook 事件并复制到订阅。 - Webhook 验签:
Paddle-Signature: ts=<unix>;h1=<hex>;HMAC-SHA256(secret, f"{ts}:{raw_body}")与 h1 比较;必须用原始 request body (不能 JSON.parse 后重序列化);5 分钟时间戳容忍防重放;每个 notification destination 有独立 secret(pdl_ntfset_...)。 - 事件:
transaction.completed(付款确认,开始履约)、subscription.created/subscription.activated(授予访问)、subscription.updated、subscription.canceled。
3. 框架变更(Decision)
| # | 决策 | 落点 |
|---|---|---|
| D50 | 支付从 Stripe 迁移 Paddle:pro.paddle 配置段(api_key/webhook_secret 环境变量、sandbox 开关、沙盒/生产 API 地址、月付/年付价格 ID);pro.stripe 标记为历史遗留 |
config/forecast.yaml |
| D51 | checkout 走 Paddle:创建交易时写 custom_data(email/sid/plan)贯穿事件;未配密钥返回 503;waitlist 模式不伪造支付 |
app/pro_api.py |
| D52 | webhook 重写为 Paddle:HMAC 验签(ts:rawBody、5 分钟防重放)+ event_id 幂等去重(paddle-events.jsonl 追加式)+ 事件→状态机(completed/activated/created→active,canceled→canceled) |
app/pro_api.py、watchlist.cancel_subscriber |
| D53 | 审核落地页补齐:新增 /terms 服务条款(含支付/退款/取消政策),首页/英文页/Pro 页页脚加链接 |
app/static/terms.html、app/main.py |
| D54 | 用户侧分步指南:注册(Individual/护照一致/企业域名邮箱)→ API key → 价格 → webhook → Payoneer → 沙盒 → 上线 | PAYMENT_SETUP.md |
4. 实践产物与结果
config/forecast.yaml:pro.mode: waitlist(默认)→ 配置密钥后改paddle;pro.paddle含 sandbox/live 地址、price_id_monthly/yearly、success/cancel URL。app/pro_api.py:checkout 调 Paddle 创建交易并返回checkout.url; webhook 验签 + 幂等 + 状态机更新;subscribe_success事件带 provider=paddle。app/forecasting/watchlist.py:新增cancel_subscriber(active→canceled)。/terms页面上线(服务条款 + 支付/退款/取消政策);页脚链接齐备。PAYMENT_SETUP.md:中国个人开发者从注册到收款的七步清单(含 Payoneer 提现、 沙盒测试卡、上线切换)。- 验证:webhook 验签(正确签名→active、错签名→400、过期→400、重复 event_id→ 幂等跳过)、链接审计全 200(见 Round 11 验证脚本)。
5. 评估
- 达标:支付链路代码就绪且沙盒可测;落地页满足 Paddle 审核基本要求; 付费状态仍由支付确认驱动(不伪造);用户指南可照做。
- 未达标(需外部凭据,诚实列入清单):真实 Paddle 账号/密钥未配置,
pro.mode保持 waitlist;Payoneer 绑定与首笔提现需用户操作(见 PAYMENT_SETUP.md)。
6. 未决问题
- Q24 年付入口:checkout 目前只走月付价格 ID;年付按钮与 plan 切换待页面支持。
- Q25 token 投递:生产接入邮件后改为 magic link(Round 9 Q19 延续)。
- Q26 续费/退款处理:webhook 已能处理 renew(completed 幂等激活),
退款(
transaction.refunded)与取消策略页面已就绪、代码侧退款状态待补。
7. 下一轮建议(Round 12 候选)
- 英文产品 UI 化:趋势雷达/预测看板双语(承接 /en 流量,延续 Round 10 候选 1)。
- 年付 + 取消/退款代码侧:Q24/Q26 落地,把支付状态机补完整。
- Paddle 沙盒实测:用户按 PAYMENT_SETUP.md 配好密钥后,跑通一笔沙盒订单 并回填验证记录(依赖外部凭据)。
8. 版本号与 changelog
- 版本:v0.10 → v0.11。Changelog 见 rounds/README.md。