概念
Webhooks
签名、重试、死信与重放机制。
Webhook 让你的应用在 StableOps 中发生事件(例如支付被检测、确认、最终化)时实时收到通知。
总览
不必轮询 API 查支付状态,事件发生时 StableOps 会直接 HTTP POST 到你的服务。好处:
- 实时:到账立刻知道。
- 节省调用:不必持续轮询。
- 可靠投递:失败自动指数退避重试。
- 可回放:所有投递都有日志,可在 dashboard 重放。
工作流
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 区块链 │────────▶│ StableOps │────────▶│ 你的应用 │
└─────────────┘ └─────────────┘ └─────────────┘
支付发出 检测到事件 派发 Webhook- 某个事件发生(例如链上检测到支付)
- StableOps 创建一条 Webhook 投递
- 向你的端点发 HTTP POST
- 你的服务处理后返回 200 OK
- 投递失败则指数退避重试
Webhook 事件
支付相关事件
payment_order.created
新订单创建时发送。
{
"type": "payment_order.created",
"data": {
"id": "po_abc123",
"merchant_order_id": "order_123",
"scenario": "checkout",
"amount": "10.00",
"settlement_asset": "USDC",
"status": "created",
"expires_at": "2024-01-01T12:30:00Z",
"metadata": {
"user_id": "user_456"
},
"created_at": "2024-01-01T12:00:00Z",
"accepted_assets": [
{ "chain": "base", "asset": "USDC" }
],
"payment_instructions": [
{ "chain": "base", "asset": "USDC", "address": "0x1234..." }
]
}
}payment.detected
链上首次看到对应转账(0 确认)时发送。
动作:把 UI 切换到「支付已收到,确认中…」。
注意:此时不要履约,交易仍有可能被回滚。
payment.finalized
支付达到 finality、不再可回滚时发送。
动作:可以安全履约 —— 资金已经稳定。
这是推荐用来触发履约的事件。
接入 Webhook
1. 创建端点
在 StableOps dashboard:
- 进入 Developers → Webhooks
- 点 Add Endpoint
- 填入你的 Webhook URL(生产必须 HTTPS)
- 勾选订阅的事件类型(创建时省略
enabled_events表示订阅全部事件) - 保存 Webhook secret
secret 字段只在创建与 rotate 时返回一次,Dashboard 不会再展示,请安全保存。
调用 rotate-secret 后,旧 secret 仍保留 24 小时与新 secret 同时有效,便于
你平滑地把验签 key 切换到新值,不会丢投递。
2. 验证签名
始终验证签名,确保请求来自 StableOps。
import { SIGNATURE_HEADER, verifySignature } from '@stableops/api-sdk/webhooks'
const result = verifySignature({
secrets: [webhookSecret],
header: request.headers.get(SIGNATURE_HEADER) ?? undefined,
rawBody,
})
if (!result.ok) {
console.error('Invalid signature:', result.reason)
// 拒绝请求
}投递、重试与死信
成功判定
任何 2xx 响应都算成功。其它状态码、网络错误、或者超过 10 秒 没返回,都按
失败处理。
重试退避
失败后按下表延迟重排,第 6 次仍失败转入 DLQ(dead letter queue):
| 第几次 | 间隔 |
|---|---|
| 1 | 30 秒 |
| 2 | 60 秒 |
| 3 | 5 分钟 |
| 4 | 30 分钟 |
| 5 | 2 小时 |
| 6+ | DLQ |
投递记录字段
webhook-deliveries 上你能查到的关键字段:
| 字段 | 说明 |
|---|---|
attempts | HTTP 已尝试的次数 |
response_status | 最近一次下游返回的状态码 |
response_duration_ms | 最近一次耗时 |
error_message | 最近一次失败的简短原因 |
next_retry_at | 下次重试时间;进入终态时为 null |
status | pending / succeeded / failed / dead_letter |
Replay
三个重放接口(endpoint replay、单条 delivery replay、批量 replay dead letters) 都是新建一条 delivery 记录进行投递,原审计日志保持不变。Dashboard 的 "replay" 按钮就是调用这些接口。
最佳实践
-
始终验证签名
-
尽快返回 200
-
按 X-Event-Id 幂等处理
-
验签必须用 raw body
-
处理全部相关事件类型
-
详尽记录日志
-
监控投递健康度