晚上十一点,值班同学在群里发了一句:“注册短信全挂了,接口一直报错。”大家第一反应是平台出故障了,结果翻日志一看,返回的是余额不足。充值的事情早在一周前就有人提醒过,只是没人接。

短信接口调用失败,真正是平台故障的情况其实不多。大部分时候,返回码已经把原因写得很清楚,只是没人认真看,或者代码里把所有错误都打成了一句“发送失败”。这篇按类别讲一遍常见的返回码,以及每一类该怎么处理。

需要说明:各家平台的具体码值和文字描述不一样,下面只按类别讲,具体以你所用平台的接口文档为准。

先分清两种“失败”

很多人把这两件事混在一起:接口调用失败和短信发送失败。

调用失败,是你的请求根本没被平台接受,接口当场返回错误,短信压根没发出去。发送失败,是平台接受了请求、短信也提交给了运营商,但最后没送到用户手机,这个结果要看后面的状态回执。

本文讲的是前一种。判断方法很简单:看短信接口同步返回的结果,如果有平台分配的消息编号,说明请求已经被接受,后面的问题去查回执;如果没有编号、直接返回了错误码,那就是调用这一步出了问题。

短信接口返回值状态码的五大类

平时遇到的短信接口报错,基本可以归到下面五类:

类别 常见描述 先查什么
鉴权失败 密钥错误、签名校验不通过、IP不在白名单 密钥是否对应当前环境,服务器出口IP是否已添加
账户问题 余额不足、账户冻结、套餐到期 后台余额和账户状态
签名模板 签名未审核、模板不存在、内容与模板不符 模板编号是否写对,变量是否匹配
参数错误 手机号格式不对、缺少必填参数、编码异常 请求体原文,字符编码
频率超限 同号码请求过于频繁、并发超出限制 调用来源是否异常,有没有被刷

短信接口鉴权失败最常见的三个原因

一是测试环境的密钥被带到了生产环境,或者反过来。二是服务器换了机房、换了出口IP,白名单没跟着改。三是签名算法里用到时间戳,服务器时间不准,请求被判定为过期。第三种最难查,因为代码一行没动,某天突然就不行了。

模板类错误往往是上线流程的问题

新模板还在审核,代码已经先发布了;或者运营在后台删掉了一个“看着没用”的旧模板,结果线上还在调用它。建议把模板编号放进配置文件,改模板之前在群里同步一声,别让开发和运营各干各的。

哪些错误能重试,哪些千万别重试

这一点很多团队写短信接口的调用代码时没想清楚。

网络超时、连接被重置、平台临时繁忙,这类错误可以重试,但要有间隔和次数上限,比如隔几秒试一次,试两三次还不行就停下来告警。鉴权失败、参数错误、模板未审核、余额不足,重试一万次结果也一样,反而会把日志刷满,甚至因为请求过多触发频控。

还有个坑:超时不等于没发出去。有时请求已经到了平台,只是响应没及时回来,你这边一重试,用户就收到两条短信验证码。所以重试时最好带上业务侧的唯一编号,让短信接口或者你自己的服务能识别重复请求。

日志和告警怎么做才有用

短信接口出了问题能不能快速定位,取决于平时日志记了什么。我们给客户做对接时,一般要求记下这几项:请求时间、手机号(可脱敏)、模板编号、短信接口返回的原始码值和描述、平台返回的消息编号、耗时。

告警不要只盯“失败了多少条”,可以按类别设:

  • 鉴权类错误一出现就告警,说明配置被动过;
  • 余额低于某个阈值提前提醒,别等到报错才知道;
  • 频率超限突然增多,要检查是不是接口被人恶意刷;
  • 调用耗时明显变长,可能是网络或平台侧有波动。

自己排查不动时,怎么找平台

把这几样东西准备好再联系技术支持:出错的时间段、请求原文(密钥打码)、返回的完整报文、你的账号和服务器出口IP。信息给全了,对方几分钟就能查到原因;只说一句“接口调不通”,来回问半天。

结论

短信接口调用失败,先看有没有返回消息编号,分清是调用失败还是送达失败。再按鉴权、账户、签名模板、参数、频率这五类去对照返回码,能重试的有限重试,不能重试的直接修配置。日志记全、告警分类,后面排查会轻松很多。蔚岚科技的短信服务提供完整的接口文档和技术支持,对接或排障遇到问题,可以打 18720919319 找我们的技术同事。

常见问题

短信接口返回成功,为什么用户没收到?

返回成功只代表平台接受了请求。有没有送到要看状态回执,可能是号码停机、被手机拦截,或者运营商侧失败。

返回码文档找不到怎么办?

找平台要最新版短信接口文档,或者让技术支持把你遇到的码值解释一下,不要凭字面猜。

余额不足会影响已经提交的短信吗?

一般不影响已经被接受的请求,新的请求会被拒绝。具体规则以平台说明为准,最好设置余额提醒。

同一套代码,测试能发,正式环境报鉴权失败?

先核对正式环境用的密钥和账号,再看服务器出口IP有没有加进白名单,这两项能解决大部分情况。

被刷验证码导致频率超限,怎么处理?

前端加图形验证和倒计时,后端按手机号和IP限制次数。同时联系平台确认账号状态,再回头查一遍是哪个页面在被反复调用。