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

React Native Firebase手机号认证:自动验证时CODE_SENT提前触发导致流程被打断的问题

React Native Firebase手机号认证:自动验证时CODE_SENT提前触发导致流程被打断的问题

首先明确:这种情况是Firebase Phone Auth的预期行为。因为CODE_SENT状态是Firebase发送验证码后的第一个反馈状态——不管后续是否会触发自动验证,这个状态都会被优先触发。你的问题核心在于:原代码在CODE_SENT时就直接resolve了Promise,这会让上层UI逻辑(比如导航到OTP页面)立刻执行,而后续的AUTO_VERIFIED状态虽然会在几秒后触发,但此时Promise已经完成,对应的resolve不会被上层代码处理,导致自动验证的流程被完全跳过。

原代码的核心问题

Promise的特性是一旦被resolve/reject就不会再响应后续的状态变化。你在CODE_SENT时就resolve了,相当于提前终止了状态监听的有效流程,后续的AUTO_VERIFIED逻辑即使执行,也无法影响已经完成的Promise。

解决方案:调整状态监听的逻辑,延迟resolve直到确定最终状态

我们需要修改逻辑:不直接在CODE_SENT时resolve,而是先保存verificationId,等待后续状态判断——如果触发AUTO_VERIFIED,就直接完成登录并resolve;如果触发AUTO_VERIFY_TIMEOUT,再resolve到需要手动输入OTP的状态。这样就能保证自动验证的流程能完整执行,不会被提前打断。

修改后的完整代码

import auth from '@react-native-firebase/auth';
import { db } from './firebaseConfig';
import { addDoc, collection, serverTimestamp } from 'firebase/firestore';

export const phoneAuth = (formattedPhoneNumber) => {
  return new Promise((resolve, reject) => {
    // 提前声明变量,用于保存CODE_SENT时的verificationId
    let verificationId;
    try {
      auth()
        .verifyPhoneNumber(formattedPhoneNumber)
        .on(
          'state_changed',
          async (phoneAuthSnapshot) => {
            switch (phoneAuthSnapshot.state) {
              case auth.PhoneAuthState.CODE_SENT:
                // 只保存verificationId,不resolve,等待后续状态
                verificationId = phoneAuthSnapshot.verificationId;
                console.log('验证码已发送,等待自动验证或超时...');
                break;

              case auth.PhoneAuthState.AUTO_VERIFIED:
                // 自动验证完成,直接完成登录流程
                try {
                  const { code } = phoneAuthSnapshot;
                  const credential = auth.PhoneAuthProvider.credential(
                    verificationId,
                    code
                  );
                  const userCredential = await auth().signInWithCredential(credential);
                  resolve({
                    status: 'autoVerified',
                    userCredential,
                    phoneAuthSnapshot,
                  });
                } catch (err) {
                  reject({
                    status: 'autoVerifyFailed',
                    error: err.message,
                  });
                }
                break;

              case auth.PhoneAuthState.AUTO_VERIFY_TIMEOUT:
                // 自动验证超时,需要用户手动输入OTP
                resolve({
                  status: 'sent',
                  verificationId: verificationId,
                  phoneAuthSnapshot,
                });
                break;

              case auth.PhoneAuthState.ERROR:
                reject({
                  status: 'error',
                  error: phoneAuthSnapshot.error?.message || '手机号认证出现异常',
                });
                break;

              default:
                resolve({ status: phoneAuthSnapshot.state });
            }
          },
          (error) => {
            reject({
              status: 'failed',
              error: error?.message || 'OTP验证请求失败',
            });
          }
        );
    } catch (error) {
      reject({
        status: 'exception',
        error: error?.message || '发起手机号认证失败',
      });
    }
  });
};

关键修改点说明

  1. 延迟resolve时机:不再在CODE_SENT时立刻resolve,而是仅保存verificationId,等待后续状态:
    • 如果触发AUTO_VERIFIED:直接完成登录并返回自动验证成功的状态
    • 如果触发AUTO_VERIFY_TIMEOUT:才resolve到需要手动输入OTP的'sent'状态
  2. 变量作用域调整:把verificationId提到switch外部,确保AUTO_VERIFIED状态能获取到正确的验证ID

额外注意事项

  • 自动验证仅在特定场景生效:设备插入了对应号码的SIM卡(安卓),或设备系统支持自动读取短信验证码(iOS/安卓都需要开启对应权限)
  • 部分地区/运营商可能不支持自动验证,此时会走到AUTO_VERIFY_TIMEOUT状态,需要正常处理手动输入OTP的流程
  • 测试时建议使用真实设备(模拟器的自动验证支持有限)

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 11:08:05