跳转到正文
OmniChannels.ai

消息API对接指南:REST、SMPP与Webhook

面向开发者的消息API对接指南:详解REST、SMPP与Webhook的区别,覆盖鉴权、幂等键、送达回执(DLR)、失败重试、限流处理与沙箱测试,帮助出海团队稳定接入WhatsApp、短信和邮件等渠道,帮助团队少走弯路、更快完成上线并稳定运行。

更新于 9 分钟阅读

作者: OmniChannels.ai Editorial Team · 审阅: BroadNet Messaging Solutions Team

集成

简短回答

应用程序发送消息用REST API;只有在已经具备电信级基础设施的高并发短信场景才选SMPP;接收送达回执和用户回复则用Webhook。每次调用都要鉴权,每次发送都带上幂等键,避免重试造成重复发送;把送达状态视为异步结果;遇到HTTP 429和5xx时退避重试;上线前先在沙箱中测试各种失败路径。

本页内容
  1. 该选REST、SMPP还是Webhook?
  2. 应该如何鉴权?
  3. 如何安全地发送一条消息?
  4. 为什么幂等性很重要?
  5. 送达回执是如何工作的?
  6. 如何处理重试和限流?
  7. 上线前应该如何测试?
  8. 实战示例:验证码与订单通知服务
  9. 常见的集成错误有哪些?
  10. OmniChannels.ai 如何提供帮助

要点速览

  • REST适合大多数应用集成;SMPP是为消息系统之间的短信吞吐量设计的持久二进制协议。
  • 发送请求被接受,只代表消息已进入队列,并不代表已送达;最终状态稍后通过Webhook或SMPP送达回执返回。
  • HTTP 429 Too Many Requests 在RFC 6585中定义;客户端应放慢速度,并遵守Retry-After响应头。
  • 幂等键可以让您在发送超时后安全重试,而不会让客户收到两条相同的消息。
  • Meta会对WhatsApp Cloud API的Webhook签名,接收方因此可以验证事件确实来自Meta。

本指南面向需要把应用接入WhatsApp、短信或邮件消息服务商的后端开发者、解决方案架构师和CTO。文中说明应选用哪种接口,以及如何处理鉴权、幂等性、送达回执、重试、限流和测试,并附有请求与响应的示意结构。如果您想把会话同步到CRM,请参阅配套文章:用Webhook连接CRM。

该选REST、SMPP还是Webhook?

发送用REST,接收用Webhook;SMPP只用于您已经在运行SMPP的高并发短信场景。三者是互补而不是竞争关系:大多数集成都是出站用REST调用、回传用Webhook。

对比项 REST API SMPP Webhook
方向 您的应用 → 服务商 单一会话内双向 服务商 → 您的应用
传输方式 HTTPS请求/响应 持久TCP会话,二进制PDU 向您的端点发起HTTPS POST
支持渠道 WhatsApp、短信、邮件等 仅短信 所有渠道的事件
典型用途 发送消息、管理模板、查询状态 消息系统之间的批量短信 送达状态、用户回复
优势 简单、对防火墙友好、载荷丰富 吞吐量高、有窗口机制、电信行业标准 实时、无需轮询
注意事项 限流、超时 会话管理、bind、保活 重试、重复、安全性

SMPP(Short Message Peer-to-Peer)会话以bind开始(transmitter、receiver或transceiver),用submit_sm发送消息,通过deliver_sm接收送达回执和上行短信,并用enquire_link保持连接。它效率高,但运维成本比HTTPS更重。

应该如何鉴权?

使用服务商提供的最强方式,不要把密钥写进代码,并且双向都要鉴权。

  • **出站调用:**通过TLS,在Authorization头中发送API密钥或OAuth 2.0 bearer token。把它们存放在密钥管理器中,定期轮换,人员变动后也要轮换。
  • **SMPP:**bind时使用system ID和密码,通常限制为白名单IP,如服务商支持,再叠加TLS。
  • **入站Webhook:**对每个事件都验证签名。Meta使用您的应用密钥,对WhatsApp Cloud API的Webhook载荷计算HMAC-SHA256签名,放在X-Hub-Signature-256头中;其他服务商通常也有类似机制。请在解析之前,基于原始请求体计算签名。

每个环境使用独立的凭证,这样泄露的测试密钥就无法发送生产流量。

如何安全地发送一条消息?

通过队列发送,带上幂等键,并把响应理解为“已接受”而不是“已送达”。

发送请求示例

下面的结构是用于说明的伪JSON,并非某家服务商的真实API。

POST /v1/messages
Authorization: Bearer <token>
Idempotency-Key: 7f3c9a2e-order-55821-shipped

{
  "channel": "whatsapp",
  "to": "+9715XXXXXXXX",
  "template": {
    "name": "order_shipped",
    "language": "ar",
    "variables": ["Layla", "55821", "15 March"]
  },
  "client_reference": "order-55821",
  "callback_url": "https://api.example.com/webhooks/messaging"
}

响应示例

202 Accepted

{
  "message_id": "msg_01HZX...",
  "status": "accepted",
  "client_reference": "order-55821",
  "created_at": "2026-10-09T12:00:00Z"
}

请立即把message_id与您自己的业务引用一并保存。此后发生的一切都会异步返回。

为什么幂等性很重要?

因为网络超时往往发生在服务端已经处理请求之后。如果发送请求超时而您盲目重试,客户可能收到两条验证码或两条发货通知。幂等键能让服务端识别出这是一次重试,并返回第一次的结果。

行之有效的规则:

  1. 幂等键应由业务事件生成(例如订单ID加事件类型),而不是每次尝试都生成随机值。
  2. 同一次发送的每次重试都使用同一个键。
  3. 键的保留时间要覆盖您的重试窗口。
  4. 如果服务商不支持幂等键,请在发送之前自行去重。

IETF的Idempotency-Key头草案把这一模式标准化到了HTTP API中;各服务商的实现并不相同,请阅读其文档。

送达回执是如何工作的?

送达状态会以事件形式稍后返回:WhatsApp和大多数REST API通过Webhook,SMPP则通过deliver_sm回执。各状态的含义因渠道而异;我们的消息送达状态指南对此逐一说明。

状态Webhook示例

POST /webhooks/messaging
X-Signature: sha256=<hmac>

{
  "event_id": "evt_9c1...",
  "type": "message.status",
  "message_id": "msg_01HZX...",
  "client_reference": "order-55821",
  "status": "delivered",
  "timestamp": "2026-10-09T12:00:04Z",
  "error": null
}

请以防御性的方式处理状态事件:

  • **去重:**按event_id,或按消息ID加状态去重。
  • **不要回退:**事件乱序到达时,不要把消息从已读退回已送达。
  • 快速返回2xx,再从队列中异步处理。
  • **记录错误码:**对失败的消息,判断哪些错误可以重试。
  • **允许缺失:**部分短信线路只返回有限的回执,已读状态则取决于渠道和用户设置。

如何处理重试和限流?

只重试有可能成功的请求,采用带抖动的指数退避,并遵从服务端发出的信号。

响应 含义 处理方式
2xx 已接受 保存ID,等待状态
400 / 422 请求无效(号码、模板、变量) 不要重试,修正数据
401 / 403 鉴权或权限问题 不要重试,触发告警
409 冲突,常见于重复的幂等键 获取第一次的结果
429 请求过多(RFC 6585) 等待Retry-After时间或退避
5xx / 超时 服务端或网络错误 使用同一幂等键并退避重试

RFC 9110定义了Retry-After头,其值可以是秒数或日期。请在发送前加一层客户端限流器,使发送速率始终低于服务商公布的限制,而不是靠错误响应来摸索限制。WhatsApp在Meta侧还限制了您能触达的独立客户数量,详见消息限额与质量评级。

上线前应该如何测试?

不仅要测顺利路径,更要测失败路径。

上线前检查清单

  1. 用真实长度的变量值发送每个模板,包括阿拉伯语文本。
  2. 人为制造超时,确认重试不会造成重复发送。
  3. 向无效号码发送,确认错误被处理且不会重试。
  4. 把同一个Webhook重放两次并打乱顺序,确认最终只有一个状态。
  5. 发送一个签名错误的Webhook,确认被拒绝。
  6. 如果允许,对沙箱做压测以触发429。
  7. 轮换一次API密钥,确认没有停机。
  8. 检查日志里有消息ID,但没有完整的消息正文或验证码。
  9. 在每个渠道上用内部号码做小规模生产试点。

沙箱很难完全还原运营商和Meta的行为,所以上线后的最初几周请持续监控。

实战示例:验证码与订单通知服务

“Qafilah Logistics”(虚构)是沙特阿拉伯的一家包裹物流公司,通过WhatsApp发送订单更新、以短信作为备用,并发送身份验证验证码。

  • **架构:**订单事件进入队列;发送worker以shipment-id:event作为幂等键调用REST API。
  • **备用:**如果WhatsApp对非WhatsApp用户返回失败状态,worker会用新的键shipment-id:event:sms发送短信。
  • **验证码:**验证码有效期很短,因此过了有效期不再重试发送;由用户重新申请新验证码。参见OTP验证消息指南。
  • **回执:**Webhook接收端校验签名、去重,并更新一个永不回退的状态表。
  • **限流:**令牌桶限流器把每个渠道的发送速率限制在公布的上限之下。

常见的集成错误有哪些?

  • 把“已接受”当作“已送达”。
  • 每次重试都换一个新的幂等键。
  • 在Webhook请求内部做繁重处理。
  • 跳过Webhook的签名校验。
  • 反复循环重试4xx校验错误。
  • 把验证码和完整消息内容写入日志。
  • 在测试环境使用生产凭证。

OmniChannels.ai 如何提供帮助

OmniChannels.ai由BroadNet Technologies提供技术支持,提供公开文档化的REST/JSON API,配有OpenAPI 3.1规范和TypeScript SDK,覆盖SMS、WhatsApp、RCS、Messenger、Instagram、Telegram、邮件和推送,其中包括支持一键、零点击和复制验证码OTP的WhatsApp身份验证模板。Webhook以统一规范的格式回传送达状态,SMPP 3.4通过TLS服务高并发短信,MCP服务器则可连接AI Agent。带筛选和CSV导出的送达报告,有助于您对账集成实际发出的消息。请从开发者文档和快速入门开始。

常见问题

对接消息服务商应该选REST还是SMPP?

几乎所有应用场景都建议选REST:它基于HTTPS,安全配置简单,并且支持WhatsApp等富媒体渠道。如果您发送的短信量很大、已经在运行SMPP客户端,并且需要带窗口机制的持久连接,再选SMPP。SMPP只适用于短信;WhatsApp、邮件和社交渠道都使用HTTP API。

消息API中的幂等键是什么?

幂等键是您的系统随请求一起发送的唯一值,服务端据此识别重复请求。如果发送请求超时,您用同一个键重试,服务商会返回第一次的结果,而不是再发一条消息。IETF已有Idempotency-Key HTTP头的草案标准,但各服务商的实现方式不同,请以其文档为准。

为什么送达回执有时会乱序到达?

状态事件由运营商、Meta和服务商等不同系统产生,并通过带重试的网络传递。已读事件可能先于已送达事件到达,重复事件也属正常。请连同时间戳一起保存每个状态,不要让消息从较新的状态退回较早的状态,并按消息ID和状态去重。

应用应该如何应对限流?

先阅读服务商公布的限制,把待发送消息放入队列,而不是直接在用户请求中发送,并在自己一侧使用令牌桶等限流器。收到HTTP 429时暂停,按Retry-After头给出的时间重试,或采用带抖动的指数退避。不要重试4xx类的校验错误。

在消息沙箱中应该测试什么?

测试鉴权失败、无效手机号、模板变量错误、带幂等重试的超时、重复和乱序的Webhook、限流响应、长文本和阿拉伯语消息,以及Webhook签名校验。随后用真实号码做小规模生产试点,因为沙箱很难完全还原运营商或Meta的真实行为。

资料来源

  1. Cloud API Webhook文档 — Meta for Developers
  2. RFC 6585:附加HTTP状态码(429 Too Many Requests)
  3. RFC 9110:HTTP语义
  4. Idempotency-Key HTTP头字段 — IETF草案
  5. SMPP协议规范资源 — SMPP.org