checkout_url 填卡付款「建 checkout」= 为这一次购买,向 Creem 申领一个带上下文的一次性收银台;跳转拿结果只当 UX,webhook 才是记账依据;API Key 永远只待在服务端。
接入总览:三步
OverviewCreem 是托管收银台(Merchant of Record),接入的核心链路只有三步:
- 拿 API Key — 注册后在 dashboard 的 Developers 区复制,塞进服务端环境变量
CREEM_API_KEY。先用测试模式开发,不产生真实扣款。 - 建 checkout — 后端调 API 创建结账会话,拿回
checkout_url,把用户重定向过去付款。 - 处理支付成功 — 用户付完会跳回
success_url;生产环境必须再挂 webhook,可靠地接收支付事件。
也可以纯无代码:在 dashboard 建好产品,点 Share 拿到支付链接直接发出去,就能收钱。代价是链接不带上下文(见下方「支付链接怎么认人」)。
「建 checkout」到底是什么
Checkout Session它是一次 checkout session(结账会话)——让 Creem 临时为你生成一个专属付款页,拿到地址后把用户送过去付钱。后端调一次:
# POST /v1/checkouts { "product_id": "prod_xxx", "success_url": "https://yoursite.com/success" }
返回一个一次性付款页地址:
{
"id": "ch_1Qy...",
"checkout_url": "https://checkout.creem.io/ch_1Qy...",
"status": "pending"
}
然后把用户丢过去:window.location.href = checkout_url。他在 Creem 托管的页面填卡付款,付完跳回你的 success_url。
它和「支付链接」的区别
| 维度 | 支付链接(静态) | checkout session(动态) |
|---|---|---|
| 生成方式 | 产品建好即固定,一个 URL 一个产品 | 每次下单动态生成 |
| 能否带上下文 | 基本不能(只能靠 URL 参数) | 可带订单号、metadata、预填邮箱、专属成功页 |
| 适用 | 无代码、快速开卖 | 需要追踪、动态定价、订阅等 |
因为创建 checkout 要用 API Key,而 Key 只能在服务端。所以流程一定是:前端点按钮 → 请求你后端 → 后端建 checkout → 返回 URL → 前端跳转。
怎么把「我的订单号」传给 Creem
request_id vs metadata两个字段,看你想在哪一步读回来:
request_id
就是一个订单号,会原样回传到 success 跳转的 query,也能在 checkout 对象上读回来。
- 只要一个订单标识 → 用它
- 适合靠跳转或 webhook 认单
metadata
用户 ID、活动来源等多个自定义字段,会进 webhook 事件,也能通过 API 查回来。
- 要带多项内部信息 → 用它
- 生产推荐用 webhook 读取
// TypeScript SDK const checkout = await creem.checkouts.create({ productId: "prod_xxx", requestId: "order_123", // ← 你的订单号 metadata: { userId: "u_123", source: "campaign_x" }, successUrl: "https://yoursite.com/success", });
跳转 URL 里出现的是 request_id,别和 Creem 自己生成的 order_id 搞混。metadata 不保证出现在跳转 URL,建议走 webhook 读取。两者都别放敏感信息——会回传、会进事件。
靠 success 跳转拿,和靠 webhook 有啥区别
Redirect vs Webhook跳转是给用户看的,webhook 是给你服务器记账的。
| 维度 | success 跳转 | webhook |
|---|---|---|
| 触发方 | 用户浏览器 | Creem 服务器直推你服务器 |
| 依赖 | 用户得成功跳回来(关页/断网/跳转失败就丢) | 不依赖用户,支付成功即推 |
| 时效 | 立刻,但只在浏览器配合时 | 略有延迟,但有重试(30s / 5min / 30min / 6h,共 5 次) |
| 覆盖范围 | 只有「这一次」checkout | 全生命周期:续费、取消、退款、争议、逾期…… |
| 验证 | signature 参数(SHA-256),要自己验 | creem-signature HMAC 验签,服务端可信 |
| 重复 | 一般不会 | 会重复投递,处理必须幂等 |
为什么生产要用 webhook
- 不丢单:用户付完直接关页面,跳转就没了——你这边「不知道人家付了」,但钱已经收了。webhook 不受用户行为影响。
- 不可伪造:跳转 URL 在用户可控的浏览器里,不验
signature就能手工拼一个「成功」骗你的发货逻辑;webhook 有 HMAC 验签。 - 只有 webhook 管后续:续费、退订、退款、拒付根本没有「跳转」,只能靠 webhook。做订阅制是刚需。
- 权威性:发货 / 开权限 / 改数据库只信 webhook;跳转只负责「谢谢购买」的 UI。
跳转当 UX,webhook 当账本。两边都用同一个 request_id / metadata.orderId 去重对上;如果非要从跳转读东西,务必验签(参数按 URL 出现顺序拼 + salt={apiKey},空值排除)。
API Key 用在哪
Where the key lives只有一个场景:你后端去调 Creem API 的凭证,同时兼作跳转签名的 salt。
- 所有服务端请求的 header:
x-api-key: ***,建 checkout、查产品、管订阅都靠它认证。 - 验 success 跳转签名的 salt:
sha256("k1=v1|k2=v2|...|salt={apiKey}")。
① 只放服务端,绝不进前端代码 / 公开仓库 / 日志——谁拿到就能以你的身份调 API;② 测试 Key ≠ 生产 Key,两者不通用;③ 别和 CREEM_WEBHOOK_SECRET(whsec_...)搞混——那是验签 Creem 来调你用的。
支付链接怎么知道谁付款了
Payment link attribution静态支付链接本身不带你的用户身份,谁点都长一样。三条路:
- 靠用户付款填的邮箱——Creem 侧记录 customer,dashboard 和
checkout.completed事件都能看到。缺点:这个邮箱不一定等于你系统里的账号邮箱。 - 给每人发带参数的链接——追加
?metadata[userId]=u_123,会进 webhook 事件。但要为每人单独拼链接,批量起来和自己调 API 差不多。 - 要真·可靠 → 用 checkout session——带
request_id/metadata,每次购买自动对上你的订单,还能动态设成功页。
群发同一个链接只能靠邮箱认人;想认准人,要么给每人发带 metadata 的专属链接,要么直接走 checkout API(推荐)。无论哪种,都建议挂 webhook。
内容整理自 Creem 官方文档 · docs.creem.io/getting-started/quickstart
测试卡号:4111 1111 1111 1111(任意未来有效期 + 任意 CVC)
测试域名 https://test-api.creem.io | 生产域名 https://api.creem.io