Creem
Next.js 模板的 Creem 结账与 Webhook 提供商。
Creem 是默认提供商。它在
src/lib/payment/providers/creem.ts 中实现共享的
PaymentProvider 接口:创建托管结账、校验 webhook 签名,
并处理若干生命周期事件。
配置
| 变量 | 用途 |
|---|---|
NEXT_PUBLIC_PAYMENT_PROVIDER | 设为 creem(默认)以选择该提供商。 |
CREEM_SERVER_IDX | 选择 Creem 服务器(沙箱 vs. 正式)。默认 0。 |
CREEM_API_KEY | 创建结账的服务端密钥。 |
CREEM_WEBHOOK_SECRET | 校验 webhook 签名的 HMAC 密钥。 |
NEXT_PUBLIC_CREEM_PRODUCT_PRO_MONTHLY / _PRO_YEARLY / _LIFETIME | Pro 月付、Pro 年付与终身方案的公开 Creem 产品 ID。 |
见 环境变量。
价格 vs. 产品 ID
src/config/price-config.ts 保存展示价格与方案元数据。每个方案的 productId
来自某个 NEXT_PUBLIC_CREEM_PRODUCT_* 变量,那才是 Creem 实际收费所依据的。展示金额
与 Creem 产品彼此独立 —— 需你自行保持一致。
创建路由以 price-config.ts 中的展示金额插入 payment 行,而真实收费由 Creem
产品决定。若你依赖存储的 amount/currency,请与 Creem 产品对账。
结账
createCheckout 为请求的 productId 构建 Creem 结账并返回其 URL。创建路由将浏览器
导向该地址,成功 URL 为 {origin}/pay-success?orderId={orderNo}。
Webhook
- 路径:
POST /api/payment/notify/creem(由共享的/api/payment/notify/[provider]路由提供)。 - 签名: 使用
CREEM_WEBHOOK_SECRET对原始请求体做 HMAC-SHA256,并与十六进制的creem-signature请求头以恒定时间比较。缺少/无效签名时路由返回400。 - 已处理事件:
checkout.completed—— 将匹配的payment行标记为success,并保存 Creem 的 订单/客户 ID。- 订阅生命周期 ——
subscription.active、subscription.paid、subscription.update、subscription.trialing、subscription.paused、subscription.past_due、subscription.scheduled_cancel、subscription.canceled与subscription.expired会将用户的subscription行 upsert 到对应的状态、周期与取消时间戳。 refund.created—— 将匹配的payment行标记为refunded。
本地测试
- 使用 Creem 沙箱服务器(
CREEM_SERVER_IDX)与沙箱产品 ID。 - 用隧道工具(如
cloudflared/ngrok)暴露本地 webhook,并在 Creem 中注册https://<tunnel>/api/payment/notify/creem。 - 确认在
checkout.completed后payment行翻转为success。
生产注意事项
- 切换到正式 Creem 服务器与正式产品 ID(公开的
NEXT_PUBLIC_*ID 需重新构建才能生效)。 - webhook 可能被重试;处理器不具备幂等性,若你为其增加非终态副作用,请添加事件 ID 去重。
验证
- 定价 CTA 创建结账并跳转到 Creem。
- 在沙箱支付后,成功页显示该订单。
- Webhook 将
payment行标记为success。 - 订阅类产品会创建/更新
subscription行。
