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

React项目Firebase OTP认证reCaptcha无效错误求助

解决Firebase手机号OTP认证的auth/invalid-app-credential错误

问题根源分析

你遇到的auth/invalid-app-credential错误,主要由以下原因导致:

  • 每次点击发送OTP时,通过innerHTML重置recaptcha容器,导致之前初始化的RecaptchaVerifier关联DOM元素被销毁,生成的验证令牌直接失效。
  • 未等待RecaptchaVerifier完成初始化与验证流程,就直接调用signInWithPhoneNumber,此时recaptcha尚未生成有效令牌。
  • 隐形recaptcha(size:'invisible')需要正确触发验证流程,直接调用登录方法会跳过核心验证步骤。

修复步骤

  1. 避免重复创建recaptcha容器:仅在组件挂载时初始化一次容器,不要每次点击按钮都重置。
  2. 复用RecaptchaVerifier实例:将verifier实例存入useRef,避免重复初始化。
  3. 确保recaptcha完成验证:调用verifier的verify()方法手动触发隐形recaptcha验证,确保令牌有效后再发送OTP请求。
  4. 检查Firebase配置:确认Firebase控制台已添加当前项目域名到「授权域名」列表,否则recaptcha令牌会被判定无效。

修改后的完整代码

import React, { useState, useRef, useEffect } from "react";
import firebase from "../firebase";

const Auth = () => {
    const [phoneNumber, setPhoneNumber] = useState('');
    const [verificationID, setVerificationID] = useState('');
    const recaptchaRef = useRef(null);
    const verifierRef = useRef(null); // 存储verifier实例,避免重复初始化

    useEffect(() => {
        // 组件挂载时一次性初始化recaptcha容器与verifier
        if (recaptchaRef.current && !verifierRef.current) {
            const container = document.createElement('div');
            container.id = 'recaptcha-container';
            recaptchaRef.current.appendChild(container);

            verifierRef.current = new firebase.auth.RecaptchaVerifier('recaptcha-container', {
                size: 'invisible',
                callback: () => console.log('Recaptcha验证成功'),
                'expired-callback': () => {
                    // 验证过期时重置verifier,下次点击重新初始化
                    verifierRef.current = null;
                }
            });
        }
    }, []);

    const handleSendOtp = async () => {
        if (!verifierRef.current) {
            console.log('Recaptcha未初始化完成');
            return;
        }

        try {
            // 手动触发隐形recaptcha验证
            await verifierRef.current.verify();
            // 验证通过后发送OTP
            const confirmationResult = await firebase.auth().signInWithPhoneNumber(phoneNumber, verifierRef.current);
            setVerificationID(confirmationResult.verificationId);
            console.log('OTP发送成功');
        } catch (error) {
            console.log('Error sending OTP:', error);
            // 验证失败时重置verifier与容器
            verifierRef.current = null;
            if (recaptchaRef.current) recaptchaRef.current.innerHTML = '';
        }
    };

    return(
        <div>
            <h1>Phone OTP Authentication</h1>
            <div ref={recaptchaRef}></div>
            <input 
                type="tel" 
                placeholder="+91 9999999999"
                value={phoneNumber}
                onChange={e => setPhoneNumber(e.target.value)}
            />
            <button onClick={handleSendOtp}>Send OTP</button>
        </div>
    );
};

export default Auth;

额外注意事项

  • 确认../firebase配置文件中的apiKey、authDomain等参数完全正确,且authDomain对应的域名已添加到Firebase控制台「Authentication」→「设置」→「授权域名」列表。
  • 本地测试时,需将localhost加入授权域名列表。
  • 可给发送按钮添加禁用状态,防止频繁点击触发重复请求。

内容的提问来源于stack exchange,提问作者Hardik Chawhan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 22:29:50