StableOps
概念

Webhooks

签名、重试、死信与重放机制。

Webhook 让你的应用在 StableOps 中发生事件(例如支付被检测、确认、最终化)时实时收到通知。

总览

不必轮询 API 查支付状态,事件发生时 StableOps 会直接 HTTP POST 到你的服务。好处:

  • 实时:到账立刻知道。
  • 节省调用:不必持续轮询。
  • 可靠投递:失败自动指数退避重试。
  • 可回放:所有投递都有日志,可在 dashboard 重放。

工作流

┌─────────────┐         ┌─────────────┐         ┌─────────────┐
│   区块链     │────────▶│  StableOps  │────────▶│   你的应用   │
└─────────────┘         └─────────────┘         └─────────────┘
    支付发出                 检测到事件              派发 Webhook
  1. 某个事件发生(例如链上检测到支付)
  2. StableOps 创建一条 Webhook 投递
  3. 向你的端点发 HTTP POST
  4. 你的服务处理后返回 200 OK
  5. 投递失败则指数退避重试

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:

  1. 进入 DevelopersWebhooks
  2. Add Endpoint
  3. 填入你的 Webhook URL(生产必须 HTTPS)
  4. 勾选订阅的事件类型(创建时省略 enabled_events 表示订阅全部事件)
  5. 保存 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):

第几次间隔
130 秒
260 秒
35 分钟
430 分钟
52 小时
6+DLQ

投递记录字段

webhook-deliveries 上你能查到的关键字段:

字段说明
attemptsHTTP 已尝试的次数
response_status最近一次下游返回的状态码
response_duration_ms最近一次耗时
error_message最近一次失败的简短原因
next_retry_at下次重试时间;进入终态时为 null
statuspending / succeeded / failed / dead_letter

Replay

三个重放接口(endpoint replay、单条 delivery replay、批量 replay dead letters) 都是新建一条 delivery 记录进行投递,原审计日志保持不变。Dashboard 的 "replay" 按钮就是调用这些接口。

最佳实践

  1. 始终验证签名

  2. 尽快返回 200

  3. 按 X-Event-Id 幂等处理

  4. 验签必须用 raw body

  5. 处理全部相关事件类型

  6. 详尽记录日志

  7. 监控投递健康度

下一步

本页内容