复制 Skill
打开 Skill 原始文件,将完整内容复制到剪贴板。
下载 Skill (.md)
下载 Skill 文件,添加到你的 AI 编程助手或 IDE 中。
@waffo/pancake-ts 是 Waffo Pancake 的服务端 TypeScript SDK。它处理请求签名、收银台会话创建、Webhook 验证和 GraphQL 查询。
常见陷阱 — 先读这里
这些是导致集成失败的常见错误。写代码之前先过一遍。| 陷阱 | 为什么会出问题 | 解决方法 |
|---|---|---|
| 以 JSON 方式读取 Webhook body | request.json() 会重新序列化 body,改变空白字符。签名验证对比的是原始字节。 | 始终使用 request.text()(App Router / Hono)或 express.raw()(Express)。 |
| 使用 localtunnel 做 Webhook 隧道 | localtunnel 会丢弃自定义 HTTP header。X-Waffo-Signature 根本到不了你的处理程序。 | 改用 cloudflared tunnel --url http://localhost:3000。 |
忘记调用 .publish() | 产品默认创建在 test 环境。为未发布产品创建生产收银台会话会静默失败。 | 上线前调用 client.onetimeProducts.publish({ id }) 或 client.subscriptionProducts.publish({ id })。 |
访问 result 而非 result.data(GraphQL) | GraphQL 客户端返回 { data: T | null, errors?: [...] }。字段嵌套在 .data 下。 | 始终解构:const stores = result.data?.stores ?? []。 |
| 传入美元金额而非美分 | 所有金额使用最小货币单位。$29.00 = 2900,¥1000 = 1000(JPY 无小数)。 | 再三确认:创建 $9.99 的产品时传入 999,不是 9.99。 |
GraphQL 变量使用 $id: ID! | 后端使用 $id: String!,不是 $id: ID!。类型错误会静默返回 null。 | ID 变量始终声明为 String!。 |
产品组更新中的 productIds 是完整替换 | 调用 subscriptionProductGroups.update({ productIds: [...] }) 会替换整个列表,而不是追加。 | 始终传入完整的目标列表,而不是只传新增项。 |
使用场景
Waffo Pancake 是一个 merchant-of-record 支付平台。以下项目类型适合使用 SDK:- SaaS 订阅计费 — 月付/年付计划,支持升降级(例如:Free/Pro/Team 层级)
- 数字商品销售 — 电子书、模板、课程、许可证的一次性购买
- 按次付费 — 按下载、API 调用或生成报告等操作收费
- 混合模式 — 订阅 + 一次性购买组合
- 多币种定价 — 按币种设置价格,自动处理税务
| 项目类型 | 付费模式 | 需要创建的产品 |
|---|---|---|
| AI Skills 市场 | 按次下载 + Pro 订阅 | 1 个一次性产品($0.99/次下载)+ 2 个订阅产品(月付/年付) |
| 在线课程平台 | 按课程一次性购买 | 每门课程 1 个一次性产品(199) |
| SaaS 工具(Starter/Pro/Enterprise) | 订阅层级 | 3 个订阅产品 + 1 个产品组用于计划切换 |
| 设计模板商店 | 按模板一次性购买 | 每个模板 1 个一次性产品,或 1 个共享产品配合 priceSnapshot 覆盖价格 |
| API 服务(用量额度) | 额度包 + 订阅 | 每个额度包 1 个一次性产品 + 订阅提供月度配额 |
安装与配置
PEM 私钥处理
转义换行符(最简单):快速开始:从零创建
快速开始:使用已有产品
如果产品已在 Dashboard 中创建,复制 Product ID 直接创建收银台会话:API 参考
商店
一次性产品
digital_goods | saas | software | ebook | online_course | consulting | professional_service
订阅产品
订阅产品组
产品组支持共享试用期和订阅计划之间的切换。收银台会话
取消订阅
GraphQL 查询
只读查询。ID 变量使用String!(不是 ID!)。
Webhook 验证
SDK 内置 test 和 prod 两个环境的公钥。验证只需一次函数调用。Next.js App Router
Express
Hono
验证选项
事件类型
| 事件 | 触发条件 |
|---|---|
order.completed | 一次性支付成功 |
subscription.activated | 首次订阅支付成功 |
subscription.payment_succeeded | 续费支付成功 |
subscription.canceling | 发起取消(当前周期结束前仍有效) |
subscription.uncanceled | 撤回取消 |
subscription.updated | 计划变更(升级/降级) |
subscription.canceled | 订阅完全终止 |
subscription.past_due | 续费支付失败 |
refund.succeeded | 退款完成 |
refund.failed | 退款失败 |
事件结构
配置 Webhook URL
错误处理
errors[0] 是根本原因(最深层),errors[n] 是最外层调用者。
开发提示
- Webhook 隧道 — 使用
cloudflared,不要用 localtunnel(见陷阱表)。
-
幂等性自动处理 — SDK 根据
merchantId + path + body自动生成确定性键。重试是安全的。 -
Test → Prod 工作流 — 产品默认创建在 test 环境。使用
.publish()发布到生产环境。Webhook 事件包含mode: "test" | "prod",你的处理程序可以据此区分。
快速上手清单
npm install @waffo/pancake-ts- 配置
WAFFO_MERCHANT_ID和WAFFO_PRIVATE_KEY环境变量 - 初始化
new WaffoPancake({ merchantId, privateKey }) - 创建或引用商店
- 创建或引用产品
- 创建收银台:
client.checkout.createSession(...)→ 重定向到checkoutUrl - 处理 Webhook:
verifyWebhook(rawBody, sig)— 必须使用request.text() - 配置 Webhook URL:
client.stores.update({ webhookSettings: ... })