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的两种方式
- 自动验证场景:
verificationCompleted回调直接返回PhoneAuthCredential,通过FirebaseVerificationCompleted状态传递给UI层。 - 手动验证场景:用户输入验证码后,触发
FirebaseVerifyOtp事件,Bloc内部用保存的verificationId和验证码生成PhoneAuthCredential,再通过FirebaseVerificationCompleted状态传递。
四、常见问题排查
- 若
verificationCompleted始终不触发,确认设备是否满足自动验证条件,不满足则走手动验证流程即可。 - 确保手机号格式正确(需带国家码,比如
+8613xxxxxxxxx)。 - 检查Firebase控制台是否已启用手机号登录方式,且应用的SHA-1/SHA-256指纹已正确配置。
内容的提问来源于stack exchange,提问作者Rizki Okto S
相关产品推荐
相关产品推荐

