帮助用户处理通过短信接收的动态密码
什么是 WebOTP API?
如今,世界上大多数人都拥有移动设备,开发者通常会使用电话号码作为其服务用户的标识符。
验证电话号码的方法有很多种,但通过短信发送随机生成的动态密码 (OTP) 是最常见的方法之一。将此代码发送回开发者的服务器,即可证明您对相应电话号码的控制权。
此理念已在许多场景中部署,以实现以下目标:
- 作为用户标识符的电话号码。注册新服务时,某些网站会要求您提供电话号码(而不是电子邮件地址),并将其用作账号标识符。
- 两步验证。登录时,网站除了要求提供密码或其他知识因素外,还会要求提供通过短信发送的一次性验证码,以提高安全性。
- 付款确认。当用户付款时,要求用户提供通过短信发送的一次性验证码有助于验证用户的意图。
当前流程会给用户带来不便。在短信中查找一次性密码,然后将其复制并粘贴到表单中,这种做法非常麻烦,会降低关键用户体验历程中的转化率。许多全球最大的开发者一直以来都希望能够简化此流程。Android 有一个专门用于执行此操作的 API。iOS 和 Safari 也是如此。
借助 WebOTP API,您的应用可以接收与应用网域绑定的特殊格式的消息。这样一来,您就可以通过编程方式从短信消息中获取 OTP,并更轻松地验证用户的电话号码。
实例展示
假设某用户想通过某个网站验证自己的电话号码。网站通过短信向用户发送一条短信,用户输入该短信中的动态密码,以验证电话号码的所有权。
借助 WebOTP API,用户只需点按一下即可完成这些步骤,如视频所示。收到短信后,系统会弹出底部工作表,提示用户验证其电话号码。在底部工作表中点击验证按钮后,浏览器会将 OTP 粘贴到表单中,然后提交表单,而无需用户按继续。
下图展示了整个流程。
亲自试用演示版。它不会要求您提供电话号码,也不会向您的设备发送短信,但您可以从其他设备发送短信,只需复制演示中显示的文字即可。之所以可行,是因为在使用 WebOTP API 时,发件人是谁并不重要。
- 在 Android 设备上,使用 Chrome 84 或更高版本前往 https://chrome.dev/web-otp-demo。
- 通过另一部手机向您的手机发送以下短信。
Your OTP is: 123456.
@chrome.dev #123456
您是否收到了短信,并看到提示您在输入区域中输入验证码? 这就是 WebOTP API 的用户体验。
使用 WebOTP API 包含三个部分:
- 正确添加了注释的
<input>标记 - Web 应用中的 JavaScript
- 通过短信发送的格式化消息文本。
我将先介绍 <input> 标记。
为 <input> 标记添加注释
WebOTP 本身无需任何 HTML 注释即可正常运行,但为了实现跨浏览器兼容性,我强烈建议您向用户输入 OTP 的 <input> 标记添加 autocomplete="one-time-code"。
这样一来,即使 Safari 14 或更高版本不支持 WebOTP,当用户收到格式如设置短信格式中所述的短信时,Safari 14 或更高版本也会建议用户使用 OTP 自动填充 <input> 字段。
HTML
<form>
<input autocomplete="one-time-code" required/>
<input type="submit">
</form>
使用 WebOTP API
由于 WebOTP 非常简单,只需复制并粘贴以下代码即可。无论如何,我都会向您介绍正在发生的情况。
JavaScript
if ('OTPCredential' in window) {
window.addEventListener('DOMContentLoaded', e => {
const input = document.querySelector('input[autocomplete="one-time-code"]');
if (!input) return;
const ac = new AbortController();
const form = input.closest('form');
if (form) {
form.addEventListener('submit', e => {
ac.abort();
});
}
navigator.credentials.get({
otp: { transport:['sms'] },
signal: ac.signal
}).then(otp => {
input.value = otp.code;
if (form) form.submit();
}).catch(err => {
console.log(err);
});
});
}
功能检测
功能检测与其他许多 API 相同。监听 DOMContentLoaded 事件将等待 DOM 树准备好进行查询。
JavaScript
if ('OTPCredential' in window) {
window.addEventListener('DOMContentLoaded', e => {
const input = document