2026-07-08 · 实现计划 · 门面自建 + USDT 收款 + 激活码自动发货 · 基于已就绪的 server/internal/codes
POST /webhook/store/codes(HMAC + 时间戳 + nonce 防重放)、用户兑换 POST /v1/redeem(JWT)、批次生成/导出/作废都在 server/internal/codes。所以方案 A 的工作量集中在门面(独角数卡)+ 一小段发货胶水 + 运维,不是重写后端。
POST /webhook/store/codes发卡店卖出一个码后调它,把该码登记为 pangolin 的有效激活码。挂在 /v1 之外、无需 JWT,靠三重校验。
POST /webhook/store/codes # 无 JWT
Headers:
X-Pangolin-Signature: sha256=<hex> # HMAC-SHA256(raw body, secret)
X-Pangolin-Timestamp: <unix> # ±5 分钟窗口
X-Pangolin-Nonce: <唯一串> # Redis 去重,防重放
Body:
{ "code": "<明文激活码>", # 必须是 pangolin 格式合法码(见下)
"plan": "pro", # free | pro | team
"duration_days": 365,
"note": "dujiaoka #订单号" } # 可选备注
→ 201 {"status":"created"}
→ 200 {"status":"already_exists"} # code_hash 已存在,幂等
→ 200 {"status":"duplicate_ignored"} # nonce 重复,幂等
→ 400 / 401 # 校验失败
仅存 hash(明文不落库)。secret 走 Bitwarden,配到 server.env。
POST /v1/redeemPOST /v1/redeem (JWT)
Body: { "code": "PGL-XXXX-..." }
→ 200 { "idempotent":false, "plan":"pro", "duration_days":365,
"expires_at":"2027-07-08T00:00:00Z" }
错误码: CODE_NOT_FOUND / CODE_REDEEMED / CODE_VOID / INVALID_CODE / RATE_LIMITED / ACCOUNT_LOCKED
已含幂等(同用户同码重放返回 idempotent=true)+ 限频 + 账户锁。用户中心/客户端只要有"输码兑换"入口即可。
server/cmd/codegen 生成一批合法码(Crockford Base32、75-bit、带校验位、可 Canonicalize 纠错),export.go 导出明文,VoidBatch 批量作废未使用码。码格式带校验位——第三方要产出合法码不能乱编(见下模型 B 的待补点)。
| 模型 A · 预充卡密库存 最快 MVP | 模型 B · webhook JIT 登记 更安全 | |
|---|---|---|
| 怎么做 | codegen 生成一批 → 导出明文 → 充进独角数卡卡密库 → 发货直接给码 | 独角数卡发货后调 /webhook/store/codes 才把码登记为有效 |
| 码何时有效 | 生成即有效(在 codes 表 status=unused) | 付款+发货后才有效 |
| 泄漏风险 | 独角数卡库被脱 → 码可被无票兑换 | 未售出的码无效,脱库也没用 优 |
| 要写的胶水 | 几乎零(导入卡密即可) | 发货 hook 签 HMAC 调 webhook + 解决"码由谁生成" |
| webhook | 不用 | 用 /webhook/store/codes |
GenerateCode 生成算法;(2) 给 pangolin 加一个受保护的 POST /internal/codes/mint(HMAC 同款)让发卡网"先领一个合法码再发货登记"。推荐 (2),格式单源、不重复实现。
独角数卡里每个商品 = 一个套餐档,映射到 webhook 的 plan + duration_days:
| 独角数卡商品 | plan | duration_days |
|---|---|---|
| Pro · 月 | pro | 30 |
| Pro · 年 | pro | 365 |
| Team · 月 / 年 | team | 30 / 365 |
档位/定价对齐 design/CLAUDE.md §7 与官网 Pricing;SKU 表落进配置,别散在代码里。
X-Pangolin-Signature(HMAC)+时间戳+nonce,POST /webhook/store/codes。独角数卡支持"自动发货 API 商品/webhook",写个小中间脚本或插件即可。server.env 与独角数卡侧。POST /internal/codes/mint:受 HMAC 保护,返回一个合法码给发卡网。需新增codegen 生成一批 → 导出 → 充进独角数卡卡密库。此步即可开卖。/internal/codes/mint + 发货 hook 调 webhook,切到"售出才有效"。/v1/redeem→订阅生效、全端同步。/internal/codes/mint。