【问题标题】:Stuck returning verificationId from Future<String> method Flutter卡住从 Future<String> 方法 Flutter 返回verificationId
【发布时间】:2021-02-06 10:43:36
【问题描述】:

我正在尝试使用手机对用户进行身份验证,当我使用 flutter_bloc 和 Repository 时,我所采用的方法是:

  1. 将带有电话号码的事件发送到 Bloc(OK)。
  2. 拨打verifyPhoneNumber,输入电话号码(OK)。
  3. 返回从codeAutoRetrievalTimeoutcodeSent 回调接收到的verificationId
  4. 将其从 BlocListener 发送到 UI 并带有状态。
  5. 更新 UI 以输入验证码。
  6. 将 smsCode 和 verifyId 发送到另一种方法以将手机 AuthCredential 链接到用户。

我的方法在调用回调之前返回,因为 verifyPhoneNumber 首先完成,所以它返回一个空字符串。

我做错了什么? 一如既往,非常感谢您的帮助。

Future<String> verifyPhoneNumber(String phoneNumber) async {
    print('verifyPhoneNumber() started');
    String verifyId;

    await _firebaseAuth
        .verifyPhoneNumber(
            phoneNumber: phoneNumber,
            timeout: Duration(minutes: 0),
            //error: Undefined class 'PhoneAuthCredential'.
//      verificationCompleted: (PhoneAuthCredential credential) async {
            verificationCompleted: (AuthCredential credential) {
            },
            //error: Undefined class 'FirebaseAuthException'.
//      verificationFailed: (FirebaseAuthException e) {
            verificationFailed: (AuthException e) {
              if (e.code == 'invalid-phone-number') {
                print(
                    'verifyPhoneNumber() -> verificationFailed -> The provided phone number is not valid.');
              } else {
                print(
                    'verifyPhoneNumber() -> verificationFailed :${e.message}');
              }

              // Handle other errors
            },
            codeAutoRetrievalTimeout: (String verificationId) {
              // Auto-resolution timed out...
//        verifyId = verificationId;
              print(
                  'verifyPhoneNumber() -> codeAutoRetrievalTimeout callback called');
            },
            //error: The argument type 'Null Function(String, int)' can't be assigned to the parameter type 'void Function(String, [int])'.
//      codeSent: (String verificationId, int resendToken)  {
            codeSent: (String verificationId, [int resendToken]) {
              verifyId = verificationId;
              print(
                  'verifyPhoneNumber() -> codeSent callback called : $verifyId'); // correct
              return verifyId;
            }
            )
        .then((value) {
      print('verifyId is $verifyId'); // null
//      return verifyId;
    }).whenComplete(() => print('Complete'));
    print('verifyPhoneNumber() ->returning verifyId: $verifyId');
    return verifyId; // without it method doesn't return, with it returns null
  }

【问题讨论】:

    标签: flutter future


    【解决方案1】:

    终于设法从 Bloc 正确使用它。

    方法有:

    用户存储库

    Future<void> verifyPhone(
          {@required String phoneNumber,
          @required Duration timeOut,
          @required PhoneVerificationFailed phoneVerificationFailed,
          @required PhoneVerificationCompleted phoneVerificationCompleted,
          @required PhoneCodeSent phoneCodeSent,
          @required PhoneCodeAutoRetrievalTimeout autoRetrievalTimeout}) async {
        _firebaseAuth.verifyPhoneNumber(
            phoneNumber: phoneNumber,
            timeout: timeOut,
            verificationCompleted: phoneVerificationCompleted,
            verificationFailed: phoneVerificationFailed,
            codeSent: phoneCodeSent,
            codeAutoRetrievalTimeout: autoRetrievalTimeout);
      }
    
      Future<AuthResult> verifyAndLinkAuthCredentials(
      {@required String verificationId, @required String smsCode}) async {
        AuthCredential authCredential = PhoneAuthProvider.getCredential(
            verificationId: verificationId, smsCode: smsCode);
    
    //    return _firebaseAuth.signInWithCredential(authCredential);
    
        FirebaseUser user = await _firebaseAuth.currentUser();
        return user.linkWithCredential(authCredential).catchError((e) {
          print('UserRepository.verifyAndLinkAuthCredentials() error: $e');
    //      return;
          });
      }
    

    回调在 bloc Streams 中定义:

    @override
      Stream<AuthenticationState> mapEventToState(
          AuthenticationEvent event) async* {
        // phone verification
        if (event is VerifyPhoneNumberEvent) {
          print('VerifyPhoneNumberEvent received');
          yield VerifyingState();
          yield* _mapVerifyPhoneNumberToState(event);
        } 
        if (event is PhoneCodeSentEvent) {
          print('PhoneCodeSentEvent received');
          yield OtpSentState();
        }
        if (event is VerificationCompletedEvent) {
          print('VerificationCompletedEvent received');
          yield VerificationCompleteState(firebaseUser: event.firebaseUser, isVerified: event.isVerified);
        }
        if (event is VerificationExceptionEvent) {
          print('VerificationExceptionEvent received');
          yield VerificationExceptionState(message: event.message);
        }
    
        if ( event is PhoneCodeAutoRetrievalTimeoutEvent){
          yield PhoneCodeAutoRetrievalTimeoutState(verificationId: event.verificationId);
        }
    
        if(event is SendVerificationCodeEvent) {
          yield VerifyingState();
          yield*_mapVerificationCodeToState(event);
        }
    
    
      }
      
      Stream<AuthenticationState> _mapVerifyPhoneNumberToState(VerifyPhoneNumberEvent event) async* {
        print('_mapVerifyPhoneNumberToState V2 started');
        final phoneVerificationCompleted = (AuthCredential authCredential) {
          print('_mapVerifyPhoneNumberToState PhoneVerificationCompleted');
          _userRepository.getCurrentUser().catchError((onError) {
            print(onError);
          }).then((user) {
            add(VerificationCompletedEvent(firebaseUser: user, isVerified:  true));
          });
        };
        final phoneVerificationFailed = (AuthException authException) {
          print('_mapVerifyPhoneNumberToState PhoneVerificationFailed');
          print(authException.message);
          add(VerificationExceptionEvent(onError.toString()));
        };
        final phoneCodeSent = (String verificationId, [int forceResent]) {
          print('_mapVerifyPhoneNumberToState PhoneCodeSent');
          this.verificationId = verificationId;
          add(PhoneCodeSentEvent());
        };
        final phoneCodeAutoRetrievalTimeout = (String verificationId) {
          print('_mapVerifyPhoneNumberToState PhoneCodeAutoRetrievalTimeout');
          this.verificationId = verificationId;
          add(PhoneCodeAutoRetrievalTimeoutEvent(verificationId: verificationId));
        };
    
        await _userRepository.verifyPhone(
            phoneNumber: event.phoneNumber,
            timeOut: Duration(seconds: 0),
            phoneVerificationFailed: phoneVerificationFailed,
            phoneVerificationCompleted: phoneVerificationCompleted,
            phoneCodeSent: phoneCodeSent,
            autoRetrievalTimeout: phoneCodeAutoRetrievalTimeout);
      }
    
    
      Stream<AuthenticationState> _mapVerificationCodeToState(SendVerificationCodeEvent event) async* {
        print('_mapVerificationCodeToState started');
          AuthResult result = await _userRepository.verifyAndLinkAuthCredentials(verificationId: verificationId, smsCode: event.smsCode)
              .catchError((e){
                print('verifyAndLinkAuthCredentials error: $e');
          });
          print(result);
    
          if (result != null) {
            yield VerificationCompleteState(firebaseUser: result.user, isVerified: true);
          } else {
            yield OtpExceptionState(message: "Invalid otp!", verificationId: verificationId);
          }
      }
    

    希望这对其他人有所帮助。 干杯。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-07-08
      • 2020-10-22
      • 2021-09-27
      • 1970-01-01
      • 2016-11-06
      • 2019-08-28
      • 2023-02-11
      • 1970-01-01
      相关资源
      最近更新 更多