卡住了从Future <String>方法Flutter返回的VerificationId

时间:2020-10-23 11:04:08

标签: flutter future

我正在尝试通过电话对用户进行身份验证,并且在使用flutter_bloc和存储库时,我使用的方法是:

  1. 将带有电话号码的事件发送到Bloc(确定)。
  2. 拨打verifyPhoneNumber并输入电话号码(确定)。
  3. 返回从verificationIdcodeAutoRetrievalTimeout回调中收到的codeSent
  4. 将它与状态从BlocListener发送到UI。
  5. 更新用户界面以输入验证码。
  6. 将smsCode和VerificationId发送到另一种将电话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
  }

1 个答案:

答案 0 :(得分:0)

最终设法从Bloc正确使用了它。

方法是:

UserRepository

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;
      });
  }

回调是在整体流中定义的:

@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);
      }
  }

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