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

Flutter Bloc:如何触发FirebaseVerificationCompletedEvent并获取Credential值?

解决FirebaseVerificationCompleted触发及Credential获取问题

一、触发FirebaseVerificationCompleted的条件

verificationCompleted回调仅在以下场景自动触发:

  • 当前设备是待验证手机号的所属设备(比如用自己的手机验证本人号码),Firebase Auth会跳过手动输入步骤,直接完成验证。
  • 设备支持SMS Retriever API,且应用已配置该功能,Firebase能自动读取短信中的验证码并完成验证。

若你的场景不符合上述条件,流程会停在codeSent状态,此时需通过手动输入验证码获取Credential。

二、修正Bloc代码,覆盖自动+手动验证场景

你当前代码仅处理了自动验证分支,缺少codeSent状态处理和手动验证逻辑,修改后代码如下:

class FirebaseOtpBloc extends Bloc<FirebaseOtpEvent, FirebaseOtpState> {
  // 存储codeSent返回的verificationId,用于手动验证
  String? _verificationId;

  FirebaseOtpBloc() : super(FirebaseOtpInitial()) {
    on<FirebaseVerifyPhoneNumber>(_onFirebaseVerifyPhoneNumber);
    // 添加手动验证验证码的事件处理
    on<FirebaseVerifyOtp>(_onFirebaseVerifyOtp);
  }

  void _onFirebaseVerifyPhoneNumber(
      FirebaseVerifyPhoneNumber event, Emitter<FirebaseOtpState> emit) async {
    try {
      emit(FirebaseCodeSending()); // 可选:添加验证码发送中状态
      await FirebaseAuth.instance.verifyPhoneNumber(
        phoneNumber: event.phoneNumber,
        verificationCompleted: (PhoneAuthCredential credential) {
          // 自动验证触发,直接发送完成状态
          emit(FirebaseVerificationCompleted(credential));
        },
        verificationFailed: (FirebaseAuthException e) {
          emit(FirebaseVerificationFailed(e.toString()));
        },
        codeSent: (String verificationId, int? resendToken) {
          // 保存verificationId,用于后续手动验证
          _verificationId = verificationId;
          // 发送验证码已发送状态,提示用户输入验证码
          emit(FirebaseCodeSent(verificationId: verificationId));
        },
        codeAutoRetrievalTimeout: (String verificationId) {
          _verificationId = verificationId;
          emit(FirebaseCodeTimeout(verificationId: verificationId));
        },
      );
    } catch (e) {
      emit(FirebaseVerificationFailed(e.toString()));
    }
  }

  void _onFirebaseVerifyOtp(
      FirebaseVerifyOtp event, Emitter<FirebaseOtpState> emit) async {
    if (_verificationId == null) {
      emit(FirebaseVerificationFailed("请先获取验证码"));
      return;
    }
    try {
      // 用verificationId和用户输入的验证码生成Credential
      PhoneAuthCredential credential = PhoneAuthProvider.credential(
        verificationId: _verificationId!,
        smsCode: event.otpCode,
      );
      emit(FirebaseVerificationCompleted(credential));
    } catch (e) {
      emit(FirebaseVerificationFailed(e.toString()));
    }
  }
}

// 补充对应的事件和状态类示例:
abstract class FirebaseOtpEvent {}
class FirebaseVerifyPhoneNumber extends FirebaseOtpEvent {
  final String phoneNumber;
  FirebaseVerifyPhoneNumber(this.phoneNumber);
}
class FirebaseVerifyOtp extends FirebaseOtpEvent {
  final String otpCode;
  FirebaseVerifyOtp(this.otpCode);
}

abstract class FirebaseOtpState {}
class FirebaseOtpInitial extends FirebaseOtpState {}
class FirebaseCodeSending extends FirebaseOtpState {}
class FirebaseCodeSent extends FirebaseOtpState {
  final String verificationId;
  FirebaseCodeSent({required this.verificationId});
}
class FirebaseCodeTimeout extends FirebaseOtpState {
  final String verificationId;
  FirebaseCodeTimeout({required this.verificationId});
}
class FirebaseVerificationCompleted extends FirebaseOtpState {
  final PhoneAuthCredential credential;
  FirebaseVerificationCompleted(this.credential);
}
class FirebaseVerificationFailed extends FirebaseOtpState {
  final String message;
  FirebaseVerificationFailed(this.message);
}

三、获取Credential的两种方式

  1. 自动验证场景:verificationCompleted回调直接返回PhoneAuthCredential,通过FirebaseVerificationCompleted状态传递给UI层。
  2. 手动验证场景:用户输入验证码后,触发FirebaseVerifyOtp事件,Bloc内部用保存的verificationId和验证码生成PhoneAuthCredential,再通过FirebaseVerificationCompleted状态传递。

四、常见问题排查

  • 若verificationCompleted始终不触发,确认设备是否满足自动验证条件,不满足则走手动验证流程即可。
  • 确保手机号格式正确(需带国家码,比如+8613xxxxxxxxx)。
  • 检查Firebase控制台是否已启用手机号登录方式,且应用的SHA-1/SHA-256指纹已正确配置。

内容的提问来源于stack exchange,提问作者Rizki Okto S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 07:13:11