短信回调地址需通过GET校验并原样返回echostr,仅支持http/https默认端口,须校验来源与签名,做好幂等处理且快速响应200,SmsReport的success不表示用户已读。

短信接口的回调地址不是“填了就能用”,必须通过校验且符合协议规范,否则收不到上行短信(SmsUp)或下行状态报告(SmsReport)。
回调 URL 必须支持 GET 校验且原样返回 echostr
服务商(如极光、阿里云等)在你保存回调地址前,会发起一次 GET 请求,附带一个随机 8 位字符串参数 echostr。你的服务端必须:
- 监听该
GET请求,从 query string 中提取echostr值 - 不加任何修改、不带空格、不转义,直接写入 HTTP 响应体(
Response Body) - 返回状态码
200,且响应头Content-Type推荐设为text/plain; charset=utf-8
常见失败点:echostr 被 JSON 包裹、被日志中间件截断、响应里多了一个换行、用了 print_r() 或 var_dump() 导致输出多余字符。
http:// 或 https:// 开头,但端口不能自定义
几乎所有主流平台(极光、阿里云、腾讯云)都明确要求回调 URL 以 http:// 或 https:// 开头,且不支持显式指定端口(如 http://1.2.3.4:8080/callback 会被拒绝)。
- 若用
http,默认走 80;用https默认走 443 - 避免端口冲突:比如把
https://a.com改成https://a.com:4433,系统可能因前缀匹配误判为非法 - 内网调试可用公网 IP 直连,例如
http://112.53.67.22/callback,但需确保该 IP 对外可访问且防火墙放行
接收回调时,必须校验来源与完整性(尤其企业微信/政务类场景)
不是所有短信平台都强制签名,但像企业微信、部分政企通道,回调请求会携带 msg_signature、timestamp、nonce 等字段,并要求你用预设的 Token 和 EncodingAESKey 验证签名和解密内容。
- 漏做签名验证 → 可能被伪造请求注入垃圾数据
- 解密失败却直接解析明文 → 报错或读到乱码(如
\x01\x02...) -
EncodingAESKey是 43 位字符串,必须严格匹配,少一位或多一位都会解密失败
即使当前平台没强制要求,也建议在接收层统一做基础校验(如 User-Agent 是否含服务商标识、IP 是否在白名单),防患未然。
HTTP 批量推送模式下,别忽略重试与幂等设计
短信平台对回调失败会重试(通常 3–5 次,间隔递增),而你的服务可能因网络抖动、DB 锁、下游超时等短暂不可用。这意味着同一个 SmsUp 或 SmsReport 可能被推送多次。
- 不做幂等处理 → 同一条用户回复被重复计数、同一发送状态被反复更新,导致业务逻辑错乱
- 推荐用唯一 ID(如
request_id或短信平台返回的biz_id)做去重,缓存保留至少 24 小时 - 收到回调后,应尽快返回
200,耗时逻辑(如写 DB、发通知)务必异步执行
最常被忽略的一点:回调不是“确认送达”,而是“通知事件发生”。SmsReport 中的 status=success 仅表示运营商反馈“已下发至终端”,不代表用户已读——这点在做关键操作(如支付确认)时必须心里有数。










