接码 API 的收码超时和重试怎么设计:先分清是请求超时还是短信没来

2026-09-22 4 0

接码 API 对接里最容易写错的一段,就是超时处理。很多人把它当成一个问题,结果写出一个循环:等不到码就重新下单,再等不到再下单——号池、并发配额和余额一起被烧掉,日志里还看不出到底哪一步坏了。

先给判断:接码 API 里的“超时”是两件不同的事,必须用两套逻辑。

  • 接口通信超时:连接超时、读取超时、408、502/503/504。请求本身没走通或网关抖了一下,和短信无关。要重试的是同一个请求
  • 业务收码超时:接口正常返回 200,状态一直停在“等待短信”(各平台叫法不同,常见是 WAIT_CODE 一类)。这说明通信没问题,是短信没到。这时候重试的不是请求,而是换号码、换国家或换号码类型

把第二种误判成第一种,就会出现前面说的死循环。下面分开说。

接口层退避重试与业务层轮询、结单、阶梯换号的分流流程图

接口通信超时:退避、抖动、幂等

只对可安全重试的错误重试。 连接/读取超时、408、429、502、503、504 可以重试;余额不足、参数非法、无可用号码、鉴权失败这类明确的 4xx 业务错误重试没有意义,只会把限流额度耗掉。

退避要带抖动。 0.5s → 1s → 2s → 4s,每次叠加一个随机偏移(比如 ±30%),上限 3 到 4 次。不加抖动的话,多个并发任务会在同一毫秒集体重试,把刚恢复的接口再打下去。

写请求的重试必须先解决幂等。 取号(下单)会真实占用号码并扣费,请求超时不等于没有执行——很可能服务端已经成功,只是响应丢了。所以重试之前要有办法确认上一次的结果:

  • 平台支持幂等键的,带上自己生成的唯一键;
  • 不支持的,重试前先查一次“活跃订单/进行中订单”列表,确认没有刚刚创建出来的订单,再决定是否重发。

跳过这一步的典型后果是:一次业务操作拿到两个号、扣两笔钱,而程序只认其中一个,另一个挂在那里占配额直到过期。

取号、查码、结单这三步的完整调用顺序,可以对照短信接码 API 怎么对接:取号、收码、结单的完整调用链来看,本文只讲其中的异常分支。

业务收码:轮询节奏和总等待窗口

别写无间隔的死循环轮询。 高频空转最常见的结果是撞上 API 网关的 429,把自己限流,反而更慢拿到码。

一个可直接用的起点:

  • 前 30 秒:每 3–5 秒查一次。 大多数验证码落在这个区间。
  • 30 秒之后:间隔拉到 8–10 秒。 过了头 30 秒还没来,多半不是“差一点”,提高频率没有收益。
  • 总等待窗口:2–3 分钟。

窗口为什么是 2–3 分钟,而不是越长越好?因为它要和目标平台那边验证码的生效期对齐。有些平台的码 5–10 分钟过期,有些 60 秒后就允许你点重发并让旧码失效。窗口比码的有效期还长没有意义:等到了也可能已经作废,你还白占着号码和并发。反过来,如果你对接的目标平台以路由慢著称,把窗口放宽到 4 分钟也是合理的——按平台调,不要用一个全局常量。

如果你用的平台提供 webhook 或长轮询,优先用它替代主动轮询,能同时省掉限流和延迟这两个麻烦。具体是否支持、怎么配置,以该平台的开发者文档为准。

超时后的第一个动作:显式结单

达到等待窗口还没收到码,不要直接丢下这张订单去下一单。要显式调用取消/释放接口,把订单推进到终态。

三个原因:

  1. 费用。 未产出验证码的订单,多数接码平台不扣费或退回额度——但通常需要你主动结单才触发。遗弃的订单往往要等它自然过期,资金在此之前是锁着的。
  2. 配额。 没结单的订单继续占用你的并发/活跃订单上限。批量任务跑上几十轮,新的取号请求就会因为“达到并发上限”而失败,看起来像平台故障。
  3. 归因。 终态明确,日志才有分析价值:这个号等了多久、以什么状态结束,是后面判断“换国家还是换号码类型”的唯一依据。

取消接口的具体端点路径和字段名各平台不同(订单标识叫 order_id 还是 id、取消后返回什么状态),照你实际对接的平台文档写,不要抄别家的示例代码

收不到码,通常不是接码平台坏了

这是阶梯式重试的前提。同一个号码在窗口内什么都没收到,最常见的原因是目标平台静默拒发:它在发码之前就判定了这条线路的类型,直接不发,前端只显示“已发送”。其次是运营商路由延迟或跨国链路丢弃。

所以重试要按阶梯推进,每一级换掉一个不同的变量:

第一级:同国家重新取号,上限 2–3 次。 换掉“这一个号码碰巧不好”的可能性。连着两三个号都静默,基本可以排除运气因素。

第二级:切换备选国家。 有些目标平台对特定国家的号段收紧,换一个国家的节点往往立刻通。

第三级:换号码类型,升级到真实运营商本土号码。 如果目标平台拒的是虚拟落地号段,前两级怎么试都不会通,因为变量没变。这一层要换的是号码的线路属性,不是号码本身。两者的区别,可以看真实运营商本土号码和虚拟落地号有什么区别;如果你对接的目标站是 ChatGPT 这类在发码前就查线路类型的平台,VoIP 虚拟号码为什么注册不了 ChatGPT里的那套判定逻辑就是你重试失败的直接原因。

落到选号这一步:NexSMS 的短效普通号码按量计费、有效期很短、一次验证用完即止,适合放在第一、二级做低成本试探;长效精品号码是真实运营商本土号码(实体卡与 eSIM),可续费,有效期内不限次接码,适合做第三级的兜底,也适合那些之后还要复收的账号——换绑、二次验证、找回密码都要用同一个号。如果你的重试逻辑本身就是因为“下次还要再收一次码”才被迫反复取号,那问题不在重试代码里,而在号码类型选错了,可以先过一遍短效号码和长效精品号码怎么选。需要注意:能否通过某个平台的验证,由该平台当时的规则决定;长效号也要在到期前续费才继续持有。

还有一种情况换号解决不了:同一个出口 IP、同一个浏览器环境反复提交,触发的是目标平台的环境风控,它会连续对你静默拒发,你换十个号也一样。这属于出口和环境的范畴(NexIP、NexBrowser),不是收码这一段能修的——判断依据很简单:换号无效、换环境立刻好。

熔断:给重试装上限

自动化任务一定要有硬性上限,否则目标站整体加严风控的那天,程序会安安静静地烧掉一整天的余额。

  • 单任务号码上限:最多换 3 个号。 超过就标记失败退出,交给人工判断。
  • 花费上限。 按任务和按小时各设一个。
  • 失败率熔断。 同一目标平台连续 N 次(比如 10 次)任务全部超时,暂停整个队列,而不是继续排队。这通常意味着对方规则变了,不是你的重试不够努力。
  • 归因字段落库。 至少记录:目标平台、国家、号码类型、实际等待时长、终态原因。有了这四项,你才能分辨“是这个国家不行”“是虚拟号段不行”还是“这个平台今天整体不行”,下次重试才有依据换对变量。

三个容易漏掉的细节

回填也要幂等。 重试解决的是拿到码,但同一个业务动作只能成功提交一次。收到码后写回业务侧的那一步也要去重,否则重试链路上会出现重复提交。

码要先校验再用。 按预期长度和字符集(多数是 4–8 位纯数字)校验一次再回填,避免把同期到达的营销短信或欢迎短信里的数字当成验证码提交,白白消耗目标平台的尝试次数。

别在目标平台上疯狂点“重新发送”。 平台侧的重发接口普遍有节流,短时间内多次请求会被直接丢弃,且新码可能让旧码失效——你反而更收不到。停手等待的具体判断顺序,提交号码后一直没收到短信:按四层漏斗排查验证码延迟怎么办里讲得更细,自动化任务里同样适用:两次重发请求之间至少留足平台自己的冷却时间。

一句话版本

接口超时 → 带抖动退避重试同一请求,写请求先保证幂等;收码超时 → 3–5 秒起轮询、2–3 分钟封顶、到点显式结单,然后按“同国家换号 → 换国家 → 换成真实运营商长效号”换变量,全程压在号码数和花费的熔断线之内。

如果你正在决定这次用哪种号码、哪个国家来跑重试,可以先在按应用看接码说明里找到对应的目标平台,再回到号码类型和续费条件上做选择。

相关文章

短信接码 API 怎么对接:取号、收码、结单的完整调用链

评论(0)

暂无评论

发布评论