你至少要写三个接口
商户订单要存什么
至少这些字段,不然出问题时排查不了:1. 创建订单和 Session
服务端也可以用
@clink-ai/clink-typescript-sdk,它替你处理认证请求头和类型定义。上面直接调 API 的写法是为了让你看清每个字段的位置。- 金额从数据库取。前端传过来的价格一律不信,否则客户改个请求就能一块钱买走会员。
- 金额是主货币单位,不是分。19.99 美元传
19.99。传1999会被当成 1999 美元,扣款差 100 倍。日元、韩元、印尼盾这类零小数位币种只能传整数。 - 别用浮点直接乘金额。JavaScript 里
0.1 * 3等于0.30000000000000004,而 Clink 会精确比对商品明细之和与总额,这点误差就会被拒。价格按整数分存,乘完数量再转回主单位;金额结构复杂时用 decimal 类库。 merchantReferenceId填你自己的订单号。Clink 不拿它做幂等——同一个值调两次会得到两个 Session。防重复下单是你自己的事。referenceCustomerId填你系统里的用户 ID。以后再给同一个客户创建 Session,Clink 能自动关联到同一个 Clink 客户。
2. 回跳页面
客户付完款跳回successUrl。这个页面要做的事只有一件:查你自己后端的订单状态,把结果显示出来。
pending。这时候显示「支付确认中」,隔几秒再查一次,别直接显示失败。
如果一直是 pending,你的后端可以主动查一次 GET /checkout/session/{id} 补上状态。
3. 接收 Webhook
这是整个接入里最要紧的一段。付款结果以这里为准。验签
Clink 用 HMAC SHA-256 签名,签的是时间戳 + "." + 原始请求体。
Node 环境直接用 SDK 就行,不用自己写:
其他语言:自己算 HMAC
其他语言:自己算 HMAC
签名规则很简单,任何语言都好实现:三个请求头:
X-Clink-Timestamp 是时间戳,X-Clink-Signature 是签名,X-Clink-SignType 目前固定为 SHA256。完整的处理器
refund.* 的对象里没有 merchantReferenceId,只有 orderId 和 refundMerchantOrderId。所以要用付款时存下的 clinkOrderId 反查本地订单。
这五件事一件都不能少
1
验签
用原始请求体算 HMAC SHA-256,比对
X-Clink-Signature。签名对不上就返回 401。2
按事件 ID 去重
投递失败 Clink 会重试,同一个事件你会收到多遍。用
event.id 去重,重复的直接返回 200。3
双重匹配订单
同时校验
merchantReferenceId 和 sessionId。只对上一个就当异常处理,别更新状态。4
容忍乱序
Clink 不保证事件按发生顺序到达。已经是
paid 或 refunded 的订单,不能被后到的旧事件改回 pending。5
写库成功后再返回 2xx
返回 200 表示”我处理完了”。还没落库就返回 200,这个事件就永远丢了。
订阅哪些事件
一次性支付至少订阅这几个:
做订阅业务的话,订阅和账单事件另有一套,见 订阅支付。完整事件列表见 Webhook 参考,也可以调
GET /webhook/events 查当前支持的事件名。
订阅时要写完整的事件名。
subscription.* 这类通配符不是能提交给 API 的值。本地怎么调
Webhook 地址必须是公网可达的 HTTPS,localhost、回环地址和内网 IP 都会被拒绝。 如果你已经有可用的公网地址(预览环境、Vercel/Netlify 之类的部署地址、自己的域名),直接用那个。纯本地开发才需要隧道:--protocol http2 重试。
隧道地址每次重启都会变,换了地址记得回后台更新 Webhook 端点。
不刷卡也能调验签
隧道加真实付款能验证端到端,但反复调验签逻辑时,每次都刷一遍卡太慢。自己造一个带签名的请求打到本地就行:谁负责什么
常见错误
在回跳页面发货。successUrl 是个普通地址,客户手动敲一遍也能打开。发货只能由验过签的 Webhook 触发。
Webhook 收到就发货,不去重。 Clink 会重试,同一个事件你会收到好几遍。不去重的话客户下单一次收到三件货。
pending 当成失败,让客户重新付。 pending 是”还不知道”。这时候重新扣款,很可能扣两次。等 Webhook,或者查 GET /order/{id}。
用 express.json() 解析 Webhook 请求。 解析过的 body 再序列化回去,签名对不上,所有事件都会验签失败。
Secret Key 出现在前端代码里。 拿到它的人可以用你的账户发起收款和退款。前端只能拿 Publishable Key。
接下来
密钥与 Webhook 配置
密钥轮换、IP 限制、投递重试规则。
上线检查
切生产前要验的场景清单。