Skip to content

注册 Webhook

用于创建、列出和删除通知 webhook 的端点。


创建 Webhook

POST /api/external/webhooks

请求头

类型必填描述
AuthorizationStringApiKey {client_id}:{client_secret}
Content-TypeStringapplication/json
hmacStringbody 的 HMAC-SHA512 签名(了解详情

请求体

字段类型必填默认描述
urlString--接收通知的 URL(默认 HTTPS)
eventsArray--要订阅的事件列表。必须是非空数组,至少包含下表中的一个有效事件。省略该字段返回 400 {"errors": {"events": ["can't be blank"]}}
secretString自动生成用于投递的 HMAC-SHA256 签名密钥。如省略,自动生成随机值。
descriptionStringnullwebhook 的自由描述,用于内部识别
allow_insecureBooleanfalse允许 HTTP(非 HTTPS)URL。数据安全由客户负责。

可用事件(仅 PIX — 今天其他产品不在 Owem 范围内):

事件状态 body描述触发
pix.charge.createdcreatedQR 码已生成或 cash-in 已启动激活
pix.charge.paidpaidPIX 已接收并结算激活
pix.charge.expiredexpiredQR 码在未付款情况下过期(worker 每 5 分钟)激活
pix.charge.cancelledcancelledQR 码在付款前取消已注册,尚未触发
pix.payout.queuedqueued已发送的 PIX 由于速率限制(每 merchant 的 ClientLimiter 或 DICT BACEN bucket)入队激活
pix.payout.processingprocessingPIX 已发送,等待确认激活
pix.payout.confirmedsettledPIX 已发送并确认(终止激活
pix.payout.failedrejectedPIX 已发送,被拒绝(终止激活
pix.payout.returnedreturned已发送的 PIX 已退回激活
pix.refund.requestedrequested收到退款请求(BACEN 违规);在客户余额上创建预防性封锁激活
pix.refund.completedsettled / completed抗辩分析完成,退款已执行(或已释放)激活
pix.return.receivedsettled收到 PIX 退款(贷记)激活
pix.infraction.createdACKNOWLEDGED对方通过 BACEN DICT 报告 PIX 违规激活
pix.infraction.resolvedCLOSED / CANCELLED违规已解决(admin 关闭、auto-deny 或对方取消)激活
pix.infraction.defense_submitteddefense_submittedmerchant 已提交抗辩激活
webhook.testtest手动测试。仅通过 Admin/Merchant portal 可用 — External API 不提供触发端点手动触发

pix.charge.cancelled 尚未触发

该事件存在于有效订阅枚举中,但今天生产中没有代码触发此类通知(QR 码取消流程未实现)。您可以将其包含在 events 数组中 — API 接受 — 但在流程实现之前,您的端点不会收到通知。

该表之外的任何事件都会被拒绝

创建 webhook 时,后端的 validate_events 对照枚举 @valid_events(schema Fluxiq.Schemas.Webhooks.Webhook)验证每一项。未知事件(boleto.paidaccount.createdsta.file.* 等)返回 400,错误为 events: contains invalid events: ...。在 session 163 之前,这些名称作为愿望保留在枚举中 — 已移除,因为代码中没有 dispatcher。

每个事件的载荷

每个事件的完整载荷示例见 Webhook 载荷

示例

bash
BODY='{"url":"https://seusite.com.br/webhook","events":["pix.charge.paid","pix.payout.confirmed"]}'
HMAC=$(echo -n "$BODY" | openssl dgst -sha512 -hmac "$CLIENT_SECRET" | awk '{print $2}')

curl -X POST https://api.owem.com.br/api/external/webhooks \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/json" \
  -H "hmac: $HMAC" \
  -d "$BODY"

成功响应 (201)

json
{
  "worked": true,
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "url": "https://seusite.com.br/webhook",
  "events": ["pix.charge.paid", "pix.payout.confirmed"],
  "secret": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
  "description": null,
  "is_active": true,
  "created_at": "2026-03-07T15:30:00Z"
}

id 的格式

webhook 的 id 是规范的 UUID v4(36 个字符,带连字符)。直接在 DELETE /api/external/webhooks/:id 中使用该值。

错误响应 (422)

json
{
  "worked": false,
  "detail": "URL deve utilizar HTTPS"
}

默认仅 HTTPS

webhook URL 必须使用 HTTPS。HTTP URL 将被拒绝,除非在注册中发送 allow_insecure: true

重要 — Webhook Secret

在注册响应中返回的 secret 字段是用于签名 webhook 投递的密钥(HMAC-SHA256)。请在收到后安全存储此值 — 它用于验证通知确实来自 Owem Pay。

不要与 client_secret 混淆:

  • client_secret = 您对 API 请求的身份验证(Authorization 头)
  • webhook secret = 验证收到的投递的签名(X-Owem-Signature 头)

如果您不在注册中发送 secret 字段,将自动生成随机值并在响应中返回。

参见 Webhook 验证 了解如何验证签名的示例。

之后恢复 secret

secretPOST /api/external/webhooks(创建)以及 GET /api/external/webhooksGET /api/external/webhooks/:id(查询)中都返回。如果您丢失了该值,只需通过 GET 再次查询 webhook。

在未来版本中,此行为可能受到限制(仅在创建时显示);我们建议在注册时将 secret 存储在托管的 secret 中(vault、SSM 等)。

HTTP URL

默认情况下,webhook 要求 HTTPS 以确保传输中数据的安全。要使用 HTTP,请在 webhook 注册中发送 allow_insecure: true

注意

HTTP URL 以明文方式传输数据。传输信息的安全性和保密性完全由客户负责。Owem Pay 正常投递 webhook,但对未加密连接上的数据拦截或泄漏不承担责任。

私有 URL 始终被阻止

即使使用 allow_insecure: true,指向私有/内部地址的 URL 也会被拒绝:

  • localhost / 127.x.x.x
  • RFC1918:10.x.x.x192.168.x.x172.16-31.x.x
  • 内部 TLD:.local.internal

Webhook 必须指向互联网可访问的公共 URL。


列出 Webhook

GET /api/external/webhooks

请求头

类型必填描述
AuthorizationStringApiKey {client_id}:{client_secret}

示例

bash
curl -X GET https://api.owem.com.br/api/external/webhooks \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"

成功响应 (200)

返回对象数组(不包装在 {"worked": true} 中)。每项包含与注册相同的字段,包括 secret

json
[
  {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "url": "https://seusite.com.br/webhook",
    "events": ["pix.charge.paid", "pix.payout.confirmed"],
    "description": null,
    "account_id": 10014,
    "is_active": true,
    "allow_insecure": false,
    "status": "active",
    "secret": "a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4",
    "created_at": "2026-03-07T15:30:00",
    "updated_at": "2026-03-07T15:30:00"
  }
]
字段类型描述
idstring (UUID)webhook 标识符
urlstring目标 URL
eventsarray订阅的事件
descriptionstring 或 null可选描述
account_idinteger 或 null关联的账户。null = API key 的全局 webhook(如果支持)
is_activebooleanfalse = webhook 暂停,无投递
allow_insecurebooleantrue = 接受 HTTP URL
statusstringis_active 派生 — "active""inactive"
secretstring用于签名投递的 HMAC-SHA256 密钥。在 LIST 中返回以允许客户端在丢失原始值时恢复
created_at / updated_atstring ISO 8601UTC 时间戳,NaiveDateTime 格式(无 Z 后缀,例:"2026-03-07T15:30:00")。与 webhook 载荷中的其他日期字段(paid_atreturned_atexpired_at)不同,它们使用带 Z 后缀的 DateTime ISO 8601。始终假设 webhook 对象字段为 UTC

删除 Webhook

DELETE /api/external/webhooks/:id

请求头

类型必填描述
AuthorizationStringApiKey {client_id}:{client_secret}

路径参数

参数类型必填描述
idString (UUID)webhook ID(创建端点返回的 UUID v4)

示例

bash
curl -X DELETE https://api.owem.com.br/api/external/webhooks/a1b2c3d4-e5f6-7890-abcd-ef1234567890 \
  -H "Authorization: ApiKey $CLIENT_ID:$CLIENT_SECRET"

成功响应 (204)

HTTP 204 No Content — 空 body。webhook 已成功移除;不会触发待处理的投递。

第一次调用:204。后续:404

第一次成功调用返回 204 No Content。相同 id 的后续调用返回 404 { "errors": { "not_found": "webhook not found" } } — webhook 已被移除。这不是严格的 HTTP 幂等性(每次调用都返回 204)— 这是资源不再存在时 DELETE 的标准行为。请编写您的集成以同时接受 204404 作为"webhook 不再激活"。

错误响应 (400)

无效的 id 格式(不是 UUID):

json
{
  "errors": {
    "bad_request": "id must be a valid UUID"
  }
}

错误响应 (404)

webhook 不存在或不属于您的账户:

json
{
  "errors": {
    "not_found": "webhook not found"
  }
}

Owem Pay Instituição de Pagamento — ISPB 37839059