电话验证 API 与号码校验:OTP 应该放在哪里?
产品经理要求在注册环节接入电话验证 API。在选择供应商之前,先确定你需要回答哪个问题:这个号码是什么、对方能否在该号码上收到消息、还是这个人是谁。这是三种不同的证明。本文对三者进行比较,用本地合成示例演示一个假设的注册流程,列出精确的 fixture 输出,说明失败处理,并给出验收清单。本地示例不发送 OTP,也不发起任何网络调用。
curl https://gridzen.ai/console/api/quickstart/trial \
-H 'Content-Type: application/json' \
-d '{"task": "signup_phone", "scenario": "success"}'问题:一个词,三种证明
“验证手机号”可能指三件事。号码校验描述号码本身的属性:格式是否正确、是否有效、可能属于哪种线路类型。OTP 发送测试的是渠道访问能力:正在输入的人此刻能否在该渠道上收到验证码。身份验证核实的是一个人的声明,通常通过托管的证件与活体检测流程完成。三者互不替代。有效的手机号不能证明归属,收到验证码不能证明对方是谁,身份结果 Approved 也不等于无条件授权。你需要决定的是:注册任务真正需要哪种证明,以及每种证明由哪个组件负责。
每种证明回答什么,GridZen 目前覆盖什么
号码属性:面向符合条件企业的免费 Basic Lookup 路线只是应用的辅助手段。它不请求线路类型、归属、可达性或 OTP 发送,并适用每分钟 60 次请求的技术速率限制。渠道访问:本地示例不支持 OTP 发送,当前免费路线也不包含这一能力。如果你的任务需要证明某人能收到验证码,请保留或选择你自己已获授权的 OTP 供应商。身份:托管身份引导是一项独立任务,有自己的合成示例和单独的注册流程。在设计中应把它们视为三个组件、三个负责方,而不是一次返回“已验证”的调用。
假设场景:一个小型 B2B 注册流程
设想一个假设的团队,其注册表单要求填写工作电话。他们提议的设计是:先调用号码检查,再把结果交给自己的策略处理,只有当策略要求渠道证明时,才通过现有的 OTP 供应商发送验证码。如果日后需要向卖家付款,再单独走身份引导流程。这是提议的应用设计,并非 GridZen 已实现的行为。已实现的是 delivery.py 中的本地四分支电话 fixture,它为每个分支返回下一步,让团队在任何真实查询之前接好处理逻辑。它需要 Python 3.10 或更高版本,无需凭据,也不访问网络。
各分支的预期 fixture 输出
所有分支都返回 mode synthetic_fixture、otp_sent false 和 live_line_type_available false。normal 分支返回 state simulated、valid true、line_type mobile 和 next continue_customer_policy;其中 mobile 是合成值,不代表任何真实线路。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。otp 分支返回 state unsupported、valid null、line_type null 和 next customer_otp_provider。最后这个值指的是你必须自行提供的组件,不会发送任何消息。无法识别的分支会抛出 UNSUPPORTED_FIXTURE。请注意,这个可下载的四分支示例与匿名的三场景 HTTP 试用是两回事。
由你的应用负责的失败处理
不要把 unknown 或 provider_failure 合并为无效号码。unknown 表示检查无法给出答案,应转入人工审核或你已在运行的 OTP 步骤。provider_failure 表示调用失败,应进行有上限的重试,然后转入审核。unsupported 表示该路线上不存在所请求的证明,应交给你自己的 OTP 供应商,而不是等待验证码。永远不要把 valid true 理解为归属或可达性。如果以后加入身份引导,请注意其 fixture 只接受合成的 fixture_callback 事件,不接受真实签名;其 recover 步骤只在本地将会话标记为过期,不会轮询任何供应商。fixture 中的权限记录也不是真实的业务权限。
验收清单
在认定集成可以提交沙盒请求之前,请确认:四个分支均可在本地运行,且输出与上文一致;每个结果中 otp_sent 都为 false,没有任何界面在等待来自这个 fixture 的验证码;unknown 和 provider_failure 分别进入不同的处理逻辑,而不是直接拒绝;customer_otp_provider 映射到一个由你控制、已获授权且明确命名的 OTP 供应商,或者该任务本就不需要渠道证明;任何文案或日志都不会根据号码检查声称归属、可达性或身份;身份需求被界定为单独的任务;任何真实路线都需单独确认,因为合成结果和匿名试用都不等于生产批准。测试只覆盖模拟的状态转换,不能证明生产环境中的成功。
运行已检查的模拟示例
下载并解压 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/phone-otp-identity/ https://gridzen.ai/guides/current-capabilities/ 依据已检查的来源快照与本地模拟;建议的业务规则属于设计建议,不代表已证明的生产行为。内容使用 AI 辅助写作,并经过独立审稿。
下载不等于运行成功;本地示例与在线沙盒分别测试。