← 所有文章
教程

UnifyPort Webhook 事件筛选:用 subscribed_events 还是通配符?

单一用途的生产处理器应明确列出 subscribed_events;如果端点是完整事件采集器,或者你还在确认工作流需要哪些事件,则使用 ["*"]。通配符涵盖所有公开标准事件,但不包含内部原始事件。对于跨境团队的消息收件箱,可先订阅 message.received,只有当同一服务也负责连接状态时,再加入账号生命周期事件。

关键结论

  • subscribed_events 接受准确的公开事件名,或单独使用 ["*"] 订阅完整公开目录。
  • 创建或更新端点时,未知事件名会被拒绝。
  • 订阅成功不代表每个渠道都会产生该事件,仍需查看渠道事件矩阵。
  • message.received 可能是入站或出站消息,必须检查 data.message.direction
  • 事件筛选、HMAC 签名、成功确认和重试是四项独立控制。

subscribed_events 控制什么

UnifyPort 会把 subscribed_events 选中的事件通过 HTTP POST 发送到 Webhook 端点。标准信封始终包含 idtypeprovideraccount_idoccurred_at 和因事件而异的 data。可接受的名称与载荷结构见标准事件目录

最小的收件订阅如下:

{
  "subscribed_events": ["message.received"]
}

处理器仍要判断消息方向:

if (
  event.type === 'message.received' &&
  event.data?.message?.direction === 'inbound'
) {
  await storeInboundMessage(event);
}

该事件表示连接的消息账号观察到一条消息,并不保证它一定是入站消息。

通配符写法是:

{
  "subscribed_events": ["*"]
}

应把它作为完整选择使用,不要把 "*" 与具体事件名混在同一个数组里。它会选择全部公开标准事件,但不会开放内部原始事件。

三种实用筛选方案

1. 只做入站收件箱

适合只负责存储和分发客户来信的服务:

{
  "subscribed_events": ["message.received"]
}

只处理 data.message.directioninbound 的记录。以后确实需要编辑、删除、表情反应或回执时,再加入对应的准确事件名,并先定义它们如何更新已存状态。

2. 入站收件箱加账号健康状态

如果同一服务还要提示授权失效或运行连接断开,可使用:

{
  "subscribed_events": [
    "message.received",
    "account.status.updated",
    "account.started",
    "account.auth.required",
    "account.auth.succeeded",
    "account.auth.failed"
  ]
}

不要把每个状态事件都当成重启指令。先同步 auth_statusruntime_status,再核对账号当前状态后采取动作。消息账号运行状态恢复手册说明了何时 refresh、reconnect、start 或重新认证。

3. 完整事件采集器

如果端点是统一接入边界,后续才按消费者分发,则使用 ["*"]。这样可以让 WhatsApp、Telegram、LINE、TikTok、Zalo 和 X 共用一个已签名队列,而消息、回执、群组与账号状态由不同消费者处理。

通配符采集器仍要为未来新增的公开事件准备默认分支:先安全存储标准信封并返回成功确认,无法识别的类型进入可观察的隔离队列,不要假设每个事件都是消息。

用明确筛选条件创建端点

真实 API 路由是 POST /v1/webhook-endpoints。以下请求创建一个启用签名的活动端点,接收消息和账号状态:

curl -X POST https://api.unifyport.ai/v1/webhook-endpoints \
  -H "X-Api-Key: $UNIFYPORT_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"url\": \"https://inbox.example.com/webhooks/unifyport\",
    \"status\": \"active\",
    \"subscribed_events\": [
      \"message.received\",
      \"account.status.updated\",
      \"account.auth.required\"
    ],
    \"signing_secret\": \"$WEBHOOK_SIGNING_SECRET\",
    \"retry_policy\": { \"max_attempts\": 3 }
  }"

请求字段以创建 Webhook 端点参考为准。retry_policy.max_attempts 表示首次发送之后的重试次数;文档默认值 3 代表首次请求之外最多再重试三次,允许范围是 05

以后需要修改筛选条件时,调用文档中的 PATCH /v1/webhook-endpoints/{endpoint_id} 并提交新的 subscribed_events;创建和更新使用相同的名称校验规则。

把筛选与传输安全分开

筛选条件决定 UnifyPort 发送什么;signing_secret 决定发送是否带有 X-Device-TimestampX-Device-Signature。启用签名后,应在解析 JSON 之前,按“时间戳、英文句点、原始请求体”的顺序计算十六进制 HMAC-SHA256 并校验。

任何 2xx 都会确认发送成功。连接错误以及 HTTP 4084295xx 可按配置重试,其他 4xx 不会重试。发送采用至少一次语义,因此普通事件的重试必须幂等处理。

完整实现请参考Webhook 发送与签名校验和更深入的HMAC 防重放与幂等教程

添加事件名前先核对渠道支持

公开目录定义了合法事件名,但不同渠道解析器并不支持全部事件。message.received 与关键账号事件覆盖较广,而回执、消息编辑、会话变化和群组更新会因渠道而异。

让消费者依赖某个事件前,先查看各渠道 Webhook 事件差异。合法订阅只是筛选条件,不保证上游账号一定产生该事件。

如果你正在搭建自动化而不是通用采集器,可继续阅读n8n WhatsApp 已签名 Webhook 教程,了解为什么签名校验和可靠入库应位于 AI 工作流之前。

限制与取舍

明确事件列表能减少噪声并划清服务职责,但新增需求出现时,必须先更新配置。通配符不会漏掉新的公开类型,却要求消费者能够接纳更多事件以及未来扩展。

UnifyPort 没有通用 REST 消息历史读取 API,也不保证补发所有遗漏载荷。应先注册接收端点,再连接生产消息账号,并在事件到达时保存所需数据。有限的 WhatsApp 历史同步只用于连续性,不替代你自己的事件存储。

UnifyPort 提供非官方接口。如果项目必须走官方平台认证路径,或需要矩阵之外的渠道专属能力,应选择对应平台的官方 API。

常见问题

应该订阅 message.received 还是 ["*"]

专用收件箱处理器用 message.received;存储并分发全部公开标准事件的通用采集器用 ["*"]

message.received 是否只包含入站消息?

不是。工作流只处理来信时,必须检查 data.message.direction 是否为 inbound

能订阅渠道内部事件吗?

不能。subscribed_events 只接受公开标准名称,通配符也不会开放内部原始事件。

事件名拼错会怎样?

创建或更新请求会拒绝未知名称,不会静默保存一个永远匹配不到事件的配置。

["*"] 是否保证每个渠道都产生所有事件?

不保证。它选择全部公开标准类型,但实际渠道支持和上游可用性仍有差异。

下一步

打开创建 Webhook 端点参考,从上述三种筛选方案中选择一种,并在连接生产消息账号前完成接收端注册。

资料来源

核对日期:2026 年 8 月 19 日。