ReactJS 中使用 Firebase Auth 无法重发 OTP 的问题求解
如何使用Firebase Authentication重发OTP?
问题根源
你遇到的报错是由以下几个原因导致的:
- 从登录页跳转到OTP页后,登录页的
#sign-in-buttonDOM元素随组件卸载被销毁,你第一次初始化的recaptchaVerifier实例绑定的容器已经不存在,无法完成二次验证 - 首次调用signInWithPhoneNumber后,原有的reCAPTCHA验证已经被消费,无法复用在重发OTP的请求中
- 若使用SPA框架的路由跳转,存储在window上的旧recaptcha实例已经失效,无法正常调用
解决方案
步骤1:修改OTP页JSX,新增reCAPTCHA容器
在OTP页的代码中新增一个隐藏的reCAPTCHA绑定容器,确保重发OTP时可以初始化新的验证实例:
<form> <input type="text" placeholder="请输入OTP" /> <div onClick={resendOTP}>重发OTP?</div> <!-- 新增隐藏的reCAPTCHA容器,无需展示给用户 --> <div id="resend-otp-recaptcha" style={{display: 'none'}}></div> </form>
步骤2:重写resendOTP函数,每次请求重新初始化验证实例
不要复用登录页存储的旧recaptcha实例,每次点击重发按钮时重新初始化验证:
const resendOTP = () => { // 绑定OTP页的新容器,重新初始化不可见reCAPTCHA window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('resend-otp-recaptcha', { 'size': 'invisible', 'callback': (response) => { console.log("reCAPTCHA验证通过") }, defaultCountry: "IN" }) // 格式化手机号,确保和首次提交的格式一致 const phoneNumber = `+91${userDetails.phoneNumber.replace(/^\+91/, '')}` const appVerifier = window.recaptchaVerifier firebase.auth().signInWithPhoneNumber(phoneNumber, appVerifier) .then((confirmationResult) => { // 更新全局的confirmationResult,用于后续OTP校验 window.confirmationResult = confirmationResult console.log("OTP已重发") // 此处可添加60秒倒计时逻辑,禁止用户短时间重复点击 }).catch((error) => { console.log("OTP重发失败", error) // 请求失败时重置reCAPTCHA,方便下次点击重新触发验证 window.recaptchaVerifier.render().then(widgetId => { grecaptcha.reset(widgetId) }) }) }
额外注意事项
- 确保登录页的手机号已经通过路由参数、全局状态或者localStorage传递到OTP页,避免
userDetails.phoneNumber为空 - 若多次重发失败,可以打印
error.code排查具体错误,比如是reCAPTCHA无效、手机号格式错误还是Firebase短信配额不足 - 生产环境建议增加重发频率限制,避免被恶意刷接口
内容的提问来源于stack exchange,提问作者Arihant Jain
相关产品推荐
相关产品推荐

