You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase重发OTP时重复发送旧验证码且验证失败问题

Firebase Auth OTP重发验证失败问题解决方案

问题核心原因

  1. 重发OTP后未更新验证用的confirmObj(即signInWithPhoneNumber返回的会话对象),导致验证时仍使用旧的verificationId,与新发送的OTP不匹配。
  2. 首次OTP会话过期(Firebase默认有效期约5分钟),旧verificationId失效,新OTP对应新会话,代码未同步更新会话信息。
  3. 全局window.recaptchaVerifier被重复覆盖,可能导致实例冲突。

解决方案

1. 重发OTP时更新验证会话对象

在组件状态中维护confirmObj,重发OTP时将新获取的会话对象赋值给它,确保验证时使用最新会话:

const handleReSendOtp = async () => {
    setOtp("");
    setOtpError(false);
    setIsSubmitting(true);

    try {
        // 获取新的OTP会话对象
        const newConfirmObj = await setUpRecaptcha(
            "another-reCaptcha-container",
            userMobileNo
        );
        if (newConfirmObj?.verificationId) {
            // 更新组件中的会话对象状态
            setConfirmObj(newConfirmObj);
            setMinutes(0);
            setSeconds(45);
            openSnackbarFunction(dispatch, "验证码已重新发送", "info");
            grecaptcha?.reset();
            setIsSubmitting(false);
        }
    } catch (error: any) {
        console.log(error);
        if (error?.code === "auth/too-many-requests") {
            openSnackbarFunction(dispatch, "请求次数过多,请稍后再试", "error");
        } else {
            openSnackbarFunction(dispatch, String(error), "error");
        }
        setIsSubmitting(false);
        navigate(Paths.WELCOME);
    }
};

2. 优化reCAPTCHA实例管理

避免全局变量冲突,每次创建新实例前销毁旧实例:

export const setUpRecaptcha = async (
    recaptchaContainer: string,
    number: string
) => {
    // 清理旧的reCAPTCHA实例
    if (window.recaptchaVerifier) {
        window.recaptchaVerifier.clear();
    }
    // 创建新实例
    const recaptchaVerifier = new RecaptchaVerifier(
        recaptchaContainer,
        {
            size: "invisible",
        },
        auth
    );
    const verificationToken = await recaptchaVerifier.verify();
    if (verificationToken) {
        return signInWithPhoneNumber(auth, number, recaptchaVerifier);
    }
};

3. 新增会话过期错误处理

在OTP验证逻辑中捕获auth/session-expired错误,明确提示用户重新获取OTP:

catch (error: any) {
    console.log(error, "error message");
    if (error?.code === "auth/invalid-verification-code") {
        openSnackbarFunction(
            dispatch,
            "输入的验证码不正确",
            "error"
        );
    } else if (error?.code === "auth/session-expired") {
        openSnackbarFunction(
            dispatch,
            "验证码会话已过期,请重新获取",
            "error"
        );
    } else if (error?.code === "auth/invalid-app-credential") {
        openSnackbarFunction(
            dispatch,
            "出现错误,请重试",
            "error"
        );
        navigate(Paths.WELCOME);
    } else {
        openSnackbarFunction(dispatch, String(error), "error");
    }
    setOtpError(true);
    setIsSubmitting(false);
}

关键注意事项

  • 每次请求OTP(首次/重发)必须使用返回的新confirmObj验证,每个verificationId仅对应一次有效会话。
  • Firebase OTP会话默认有效期约5分钟,过期后旧会话无法验证任何OTP,必须重新请求。
  • 重发OTP时确保reCAPTCHA实例正确重置,避免旧实例干扰新请求。

内容的提问来源于stack exchange,提问作者Shubham Chaudhary

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 03:34:58