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 / _LIFETIMEPro 月付、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.activesubscription.paidsubscription.updatesubscription.trialingsubscription.pausedsubscription.past_duesubscription.scheduled_cancelsubscription.canceledsubscription.expired 会将用户的 subscription 行 upsert 到对应的状态、周期与取消时间戳。
    • refund.created —— 将匹配的 payment 行标记为 refunded

本地测试

  • 使用 Creem 沙箱服务器(CREEM_SERVER_IDX)与沙箱产品 ID。
  • 用隧道工具(如 cloudflared / ngrok)暴露本地 webhook,并在 Creem 中注册 https://<tunnel>/api/payment/notify/creem
  • 确认在 checkout.completedpayment 行翻转为 success

生产注意事项

  • 切换到正式 Creem 服务器与正式产品 ID(公开的 NEXT_PUBLIC_* ID 需重新构建才能生效)。
  • webhook 可能被重试;处理器不具备幂等性,若你为其增加非终态副作用,请添加事件 ID 去重。

验证

  • 定价 CTA 创建结账并跳转到 Creem。
  • 在沙箱支付后,成功页显示该订单。
  • Webhook 将 payment 行标记为 success
  • 订阅类产品会创建/更新 subscription 行。

On this page