电话号码验证 API:区分“未知”结果与服务商故障
注册表单调用电话号码验证 API,得到的结果既不是有效也不是无效。示例中有两个分支会产生这种结果:unknown 和 provider_failure,二者都返回 state unknown 且 valid 为 null,只有 next 字段能区分它们。本文使用经过检查的四分支合成示例,说明为什么代码应当对二者采取不同路径、示例的精确输出是什么,以及 Basic Lookup 永远无法证明的内容:号码的持有、归属或 OTP 的送达。
curl https://gridzen.ai/console/api/quickstart/trial \
-H 'Content-Type: application/json' \
-d '{"task": "signup_phone", "scenario": "success"}'问题:两个含义不同的空值
你的注册处理程序收到一个电话检查结果,其中 valid 为 null,line_type 也为 null。你需要决定的是:正在表单上等待的用户接下来会怎样。常见的捷径是把所有空值都当作拒绝,但这把两种情况混为一谈。第一种情况下,检查确实执行了,却无法对号码给出有用的结论;第二种情况下,对服务商的调用本身失败了,因此什么都没有得到。在第二种情况下拒绝用户,等于因为服务中断而惩罚用户;而在任何一种情况下盲目放行,又等于假装做过一次实际上没有发生的检查。可下载的示例通过 next 字段把这种差别明确表达出来,你的应用也应当保持这种明确区分,不要在后续处理中把它抹掉。
两个模糊分支的精确示例输出
本地示例的每个分支都返回 mode synthetic_fixture、otp_sent false 以及 live_line_type_available false。unknown 分支返回 state unknown、valid null、line_type null,next 为 review_or_existing_otp。provider_failure 分支返回 state unknown、valid null、line_type null,next 为 bounded_retry_then_review。作为对照,normal 分支返回 state simulated、valid true、line_type mobile,next 为 continue_customer_policy;otp 分支返回 state unsupported、valid null、line_type null,next 为 customer_otp_provider。传入不受支持的分支名会抛出 UNSUPPORTED_FIXTURE。请注意,仅凭 state 无法区分 unknown 与 provider_failure;如果你的代码只根据 state 做判断,这一区别就已经丢失了。normal 分支中的 line_type mobile 是合成值:当前免费的 Basic Lookup 路线并不请求线路类型,这正是所有分支中 live_line_type_available 均为 false 的原因。
一个假设场景
设想一个小型 B2B 团队,其注册表单收集一个用于账户联系的电话号码。这是一个假设的设计,并不描述任何真实部署。用户提交了号码。在测试中,团队先运行 unknown 分支:拟议的处理程序保存这次尝试,让注册继续进入人工审核队列,并且在团队已有 OTP 流程的情况下可选地触发该流程。接着运行 provider_failure 分支:拟议的处理程序以较短的间隔进行有限次数的重试,如果仍然没有结果,就把这次尝试转入审核,而不是直接拒绝。最后运行 otp 分支,确认界面不会等待验证码,因为 otp_sent 为 false,示例从不发送任何消息。重试次数、间隔和审核规则都由团队自行决定;示例只负责给出下一步的名称,不替你执行任何动作。
已实现的部分与需要你设计的部分
已实现:一个无依赖的 Python 函数,把分支名映射为固定的字典,不进行网络调用、不需要凭据,并附带单元测试。未实现:任何重试循环、审核队列、OTP 发送或真实的服务商适配器,这些都由调用方负责。匿名 HTTP 试用是另一个独立的三场景检查,不应与这个可下载的四分支示例混淆。符合条件的企业注册后可以使用 Basic Lookup,它只是一个辅助信号,技术速率限制为每分钟 60 次请求;它不能确认号码的持有、归属、可达性或 OTP 送达。如果你需要证明用户能够收到验证码,应使用你自己的 OTP 服务商;如果你需要确认身份,那是完全不同的另一类检查,不能用电话检查代替。
值得保留的故障处理规则
重试必须有上限:无限重复的服务商故障会让注册流程一直挂起。记录每个决定是由哪个分支产生的,这样日后的审核人员能够看出某个空值来自故障而不是结论。绝不要把 unknown 或 provider_failure 自动转为拒绝。在测试中,对无法识别的分支或错误要像 UNSUPPORTED_FIXTURE 一样直接停止。不要让合成的 valid true 解锁任何真实功能;示例结果不是真实的业务许可。人们对电话号码验证 API 的搜索兴趣,也不能证明某个具体设计对你的用户有效,它只是一个需要继续观察的信号。
验收清单
在决定沙盒集成是否适合你的任务之前,请逐项确认:四个分支都能在本地运行,并且与上文输出逐字段一致;处理程序使用 next 而不是 state 来区分 unknown 与 provider_failure;provider_failure 有重试上限,并以审核作为兜底;没有任何分支仅因 valid 为 null 就导致自动拒绝;当 otp_sent 为 false 时,界面绝不等待验证码;没有任何代码路径从真实的 Basic Lookup 结果中读取 line_type;日志记录 mode synthetic_fixture,避免测试数据被误认为生产数据;团队以书面形式确认电话检查既不能证明号码持有、归属,也不能证明身份。如果全部满足,下一步是可选地保存一个沙盒请求,而不是直接上线到生产环境。
运行已检查的模拟示例
下载并解压 https://gridzen.ai/downloads/verification-delivery.zip,进入 verification_delivery,用 Python 3.10+ 运行。此本地示例不联网;独立身份实验请使用新的数据库。
python3 delivery.py phone --branch unknown
python3 delivery.py phone --branch provider_failure来源与范围
https://gridzen.ai/guides/signup-phone-check/ https://gridzen.ai/guides/current-capabilities/ 依据已检查的来源快照与本地模拟;建议的业务规则属于设计建议,不代表已证明的生产行为。内容使用 AI 辅助写作,并经过独立审稿。
下载不等于运行成功;本地示例与在线沙盒分别测试。