最快定位单条发送结果应先查短信服务商控制台日志,阿里云、腾讯云等平台保留7–30天原始记录,含手机号、模板id、状态及失败码;注意“成功”仅表示进入运营商通道,终端触达需依赖已开通的dlr回执日志。

直接查控制台日志:最快定位单条发送结果
如果你只是想确认某次验证码有没有发出去、失败原因是什么,别折腾代码或 API,先去短信服务商控制台看原生日志。阿里云、腾讯云、环信等平台都默认保留 7–30 天的原始发送记录,含手机号、模板 ID、发送时间、状态(成功/失败)、失败码(如 405 表示密钥错误,407 表示内容含敏感词)。
常见坑:别只看“状态=成功”就以为用户收到了——它仅代表短信已进入运营商通道,不保证终端送达。真正要判断是否触达,得结合回执日志(DLR),而这个功能需单独开通且部分平台默认关闭。
- 阿里云:进「短信服务控制台 → 业务统计 → 短信日志分析」,首次使用需主账号授权
AliyunServiceRoleForDysmsLog角色 - 腾讯云:在「短信控制台 → 操作记录 → 发送记录」筛选时间+手机号,失败详情里会带具体错误描述
- 注意:RAM 用户若查不到日志,大概率是没被授予
dybase:QuerySendDetails类权限
用 API 拉取日志:适合批量分析与系统集成
当你要做运营复盘、异常监控或把发送数据同步到内部 BI 系统时,靠手动翻页肯定不行,得调用日志查询接口。主流平台都提供类似 DescribeSmsSendDetails(阿里云)、GetSmsSendStatus(腾讯云)这样的接口。
关键点在于参数组合:时间范围必须精确到分钟级(部分平台要求起止时间差 ≤ 30 天),且 PhoneNumber 和 SendDate 通常为必填项;漏传会导致返回空数组,你以为没数据,其实是参数错了。
- 阿里云接口返回字段含
Code(业务状态码)、Message(中文提示)、Fee(计费条数)、ReceiptTime(回执时间) - 腾讯云返回的
result是数字码(0=成功),但真正要看的是errmsg字段,比如"invalid mobile" - 调用前务必检查
SecretId和SecretKey是否过期,尤其是用了自动轮换密钥的企业账号
本地调试时埋点日志:避免线上问题复现难
开发阶段遇到“本地能发、测试环境报 405”,十有八九是配置没对齐。这时候光看平台日志不够,得在自己服务里打日志——但不能简单 console.log(),否则高并发下日志串行、无法归属到具体请求。
推荐做法:用上下文 ID(如 X-Request-ID)贯穿整个请求链路,在调用短信接口前后,把请求体(含 TemplateID、PhoneNumber)、响应体(含 StatusCode、body)、耗时全记下来。Koa/Express 中可用中间件 + ctx.state.logMessages 实现隔离,但切记不要全局共享数组,否则 A 请求的日志混进 B 请求里。
- 重点记三类信息:原始入参(防模板 ID 写错)、HTTP 状态码(区分网络层失败)、响应 body 的
code字段(业务层失败) - 别记录完整手机号,脱敏成
138****1234,否则审计过不了 - 预发环境和生产共用同一套数据库?那预发查到的日志才最接近真实情况——本地连的测试库根本查不到真实发送记录
日志分析进阶:从“查得到”到“看得懂”
开通日志服务(如阿里云 SLS)后,默认建好 sms-log-{AccountID} Project 和 sms-log Logstore,但这只是起点。真正有用的分析往往需要写查询语句,比如查“近 24 小时模板通过率低于 95% 的签名”:
* | SELECT SignName, COUNT(*) as total, COUNT_IF(Status = 'success') * 100.0 / COUNT(*) as rate | WHERE __date__ > ago(24h) | GROUP BY SignName | HAVING rate < 95
容易忽略的细节:专属 Logstore 不允许写入其他日志,所以别想着把它当通用日志池;另外,如果用了按写入量计费模式,日志里塞太多调试字段(比如完整 request body)会快速推高费用。
还有个隐形门槛:平台提供的“短信发送统计”仪表盘是只读的,改不了字段逻辑。真要按业务维度(比如活动 ID、渠道来源)归因,得在调用接口时主动把 Extend 或 SessionContext 字段带上,否则日志里根本没这列数据可分组。










