配置 Webhook#
在 TLY Pay 后台, 打开 集成 > Webhook > 添加 Webhook. 填写 端点 URL 并提交, 将 保存此签名密钥 中的凭据保存到接收器服务端. Webhook 列表和详情不显示已有签名密钥. 在 Webhook 详情中使用 编辑 Webhook 修改 URL 或投递状态.API 方式用于自动化集成配置: 使用具备 webhook:bootstrap 作用域的 API 密钥调用 POST /v1/webhook-endpoints, 提交 Idempotency-Key 和 {"url":"https://merchant.example/webhooks/tly"}. 此 URL 仅用于示例. 实际配置必须使用已登记的 HTTPS 域名和 443 端口, 不包含凭据, 查询参数或片段. 发送方不跟随重定向.你的账户可以配置一个 Webhook. 在后台和 API 配置方式中选择一种, 不要创建第二个 Webhook. 使用 API 配置时, 安全保存返回的 resource_id 和仅返回一次的 secret. 重复配置的响应可能省略 secret. 请保留已保存的签名密钥. 如果重试未返回签名密钥, 且你此前没有保存, 请先在后台轮换签名密钥, 再使用该 Webhook. 使用 POST /v1/webhook-endpoints/{webhook_endpoint_id}/verify 和 {"secret":"<WEBHOOK_SECRET>"} 校验通过 API 配置并保存的凭据.secret_kind 表示签名密钥为 active 或 pending. 轮换时, 在 集成 > Webhook 打开 Webhook 详情, 选择 轮换密钥 > 生成新 Secret 并保存新签名密钥. 先更新接收器以接受 pending 签名密钥, 再选择 启用轮换后的 Secret > 启用 Secret. 显式切换前旧签名密钥保 持 active; 切换后发送方只使用新 active 签名密钥. 接收器可以在有界的重叠窗口内接收仍在传输中的旧签名请求.先验签, 再解析和处理#
TLY Pay 发送的事件 JSON 对象包含 schema_version, event_id, event_type, occurred_at 和 data. 事件类型为 payment.updated; 创建 Payment, 首次激活 Checkout 和关闭 Checkout 访问不会生成该事件. 更新, 已接受金额变化, 支付结果, 过期, 取消和审核可以生成该事件.签名输入为时间戳的原始 ASCII 字节, 一个句点字节和原始 HTTP 请求体字节. 使用完整且可信的 Webhook 签名密钥, 按保存的原值使用, 作为 HMAC-SHA256 密钥. 不得通过解析未验签的请求体选择签名密钥, 不得在验签前重新序列化 JSON.在接收器配置中确定 max_skew_secs, 并将当前可信的 Unix 时间作为 now_secs 传入. HTTP 框架应正确读取不区分大小写的请求头.验签成功后, 持久记录或入队事件, 按 event_id 去重, 并仅将 data.status_version 与同一 Payment 已保存的版本比较. 重复或旧事实不得覆盖新事实. 接收器承担事件处理责任后返回 2xx. 此示例仅验证消息, 不实现持久化存储或订单履约.完成持久接收后, 投递确认和业务处理可以分别进行. HTTP 2xx 只确认投递, 不表示订单已支付. 缺失支付事实时使用权威 Payment 查询恢复.投递和恢复#
重试保持 Event ID 和事件内容不变, 使用新的投递时间戳和签名. HTTP 2xx 表示投递已确认. 网络故障, 408, 425, 429 和 5xx 会触发有限次数的重试; 其它非 2xx 响应属于永久失败. 重定向不表示确认.通知缺失时, 使用具备 payment:read 作用域的 API 密钥查询 GET /v1/payments/{payment_id}. 查询不会改变投递状态. 打开 集成 > Webhook 日志, 选择一条投递查看状态和尝试记录. 具备权限的操作人员可以通过 重放交付 > 排队重放 再次投递. 重放为 active Webhook 重新排队同一事件, 保留 Event ID 和原始事件内容. 新投递尝试生成新的时间戳和签名. 重放入队不表示接收器已经接受事件.使用已验证的 Webhook 签名密钥, Payment ID, 订单引用, 原始计价金额和状态版本, 将事件关联到当前集成. 不得仅通过 Webhook 投递成功推断支付成功.