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 || '发起手机号认证失败', }); } }); };
关键修改点说明
- 延迟resolve时机:不再在
CODE_SENT时立刻resolve,而是仅保存verificationId,等待后续状态:- 如果触发
AUTO_VERIFIED:直接完成登录并返回自动验证成功的状态 - 如果触发
AUTO_VERIFY_TIMEOUT:才resolve到需要手动输入OTP的'sent'状态
- 如果触发
- 变量作用域调整:把
verificationId提到switch外部,确保AUTO_VERIFIED状态能获取到正确的验证ID
额外注意事项
- 自动验证仅在特定场景生效:设备插入了对应号码的SIM卡(安卓),或设备系统支持自动读取短信验证码(iOS/安卓都需要开启对应权限)
- 部分地区/运营商可能不支持自动验证,此时会走到
AUTO_VERIFY_TIMEOUT状态,需要正常处理手动输入OTP的流程 - 测试时建议使用真实设备(模拟器的自动验证支持有限)
内容来源于stack exchange
相关产品推荐
相关产品推荐

