transport: ['sms'] 是唯一有效值,必须显式声明为数组;其他写法(如字符串、多通道、省略)均导致凭证获取失败,且浏览器不报错而返回 null。

transport: ['sms'] 是唯一可用值,不能省略或写错
WebOTP API 的 transport 参数目前只支持 ['sms'],且必须显式声明。漏掉这个字段,navigator.credentials.get() 会直接返回 null,而不是报错——容易误以为 API 失效,实际是配置缺失。
常见错误包括:
- 写成
transport: 'sms'(字符串而非数组) - 写成
transport: ['sms', 'email'](多通道不支持,浏览器忽略) - 完全 omit 该字段(结果始终为
undefined,凭证获取失败)
正确写法只有一种:{ otp: { transport: ['sms'] } }。其他 transport 类型(如 email、webauthn)尚未被任何浏览器实现,W3C 规范也未定义。
为什么 transport 不支持 email 或 push?
WebOTP 是为「运营商短信通道」设计的受控机制,依赖系统级短信收件箱的可信路径。email 没有统一、可验证、用户授权的读取接口;push 通知无内容结构约束,无法保证验证码格式和来源可靠性。
立即学习“前端免费学习笔记(深入)”;
将调研报告、方案对比、数据分析、需求梳理、会议纪要、设计说明、代码评审、学习笔记等任务产物输出为可在浏览器直接打开的单文件 HTML,替代 Markdown 作为最终交付物。Markdown 在信息密度、视觉清晰度和可分享性上已跟不上 AI 产物的丰富度,HTML 能同时承载排版、表格、SVG 等。
这意味着:
- 即使你用 SendGrid 发送含
@example.com #123456的邮件,浏览器也不会触发 WebOTP 填充 - Android 的 SMS Retriever API 和 iOS 的 SMS autofill 都只监听系统短信应用,不介入邮件或 IM
- 所谓“WebOTP 支持 email”是常见误解,源于混淆了 autocomplete 属性和 credentials API
transport: ['sms'] 在不同平台的实际行为差异
transport: ['sms'] 表面一致,但底层触发逻辑因平台而异:
- Chrome(Android/iOS):监听系统短信数据库,匹配后弹出底部提示条,用户点“填充”才执行
- Edge(Android):行为同 Chrome;Edge(Windows)不支持 WebOTP
- Safari:完全忽略
transport字段,仅靠autocomplete="one-time-code"+ 短信格式自动填充(不走navigator.credentials.get) - Firefox:不支持 WebOTP,调用
navigator.credentials.get会直接 reject
因此,不要在 Safari 或 Firefox 中尝试捕获 otp.code——它们压根不会返回该字段,但 Safari 仍可能自动填值到 input 框中。
transport 字段不影响短信格式校验,只控制通道意图
transport: ['sms'] 并不改变浏览器对短信内容的匹配规则。它只是告诉浏览器:“我期望从短信渠道获取 OTP”,真正的格式校验仍由以下条件决定:
- 短信必须含
@yourdomain.com(域名需与当前页面 origin 完全一致) - 验证码必须是纯数字,建议 6 位,前后有空格或 U+200E 等分隔符
- 不能含 emoji、换行、多个
@或多余标点(如 “验证码:123456” 中的冒号会破坏匹配)
也就是说,transport 写对了,不代表短信就能被识别;格式不对,哪怕 transport 正确,浏览器也静默跳过——这是最常被忽略的调试盲点。


















