首页 > 解决方案 > 在注册/登录之前检查手机是否存在 - Flutter 手机身份验证

问题描述

我想在登录或注册用户之前检查电话是否存在。通过电子邮件注册,我使用了以下内容,并且能够判断电子邮件是否存在。

final url =
        'https://www.googleapis.com/identitytoolkit/v3/relyingparty/$verifyPassword?key={API_KEY}';

同样,对于电话号码,我使用了以下内容:

   final url ='https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPhoneNumber?key={API_KEY}';

       final response = await http.post(
        url,
        body: json.encode(
          {
            'phoneNumber': number
          },
        ),
      );

但是,我收到以下错误消息:

  Extracted data is {error: {code: 400, message: MISSING_SESSION_INFO, errors: [{message: MISSING_SESSION_INFO, domain: global, reason: invalid}]}}

我想知道为什么它适用于电子邮件而不适用于电话注册?另外,这是检查电话是否存在的正确方法吗?

这是我的完整代码:

  enum Status { Uninitialized, Authenticated, Authenticating, Unauthenticated }
    
    class AuthProvider with ChangeNotifier {
      FirebaseAuth _auth = FirebaseAuth.instance;
      User _user;
      Status _status = Status.Uninitialized;
      TextEditingController phoneNo;
      String smsOTP;
      String verificationId;
      String errorMessage = '';
      bool logedIn = false;
      bool loading = false;
       Status get status => _status;
    
      TextEditingController address = TextEditingController();
    
        AuthProvider.initialize() {
          readPrefs();
        }
    
      Future signOut() async {
        _auth.signOut();
        _status = Status.Unauthenticated;
        notifyListeners();
        return Future.delayed(Duration.zero);
      }
    
      Future<void> readPrefs() async {
        await Future.delayed(Duration(seconds: 3)).then((v) async {
          SharedPreferences prefs = await SharedPreferences.getInstance();
          logedIn = prefs.getBool('logedIn') ?? false;
          if (!logedIn) {
            print('User is not logged in');
            _status = Status.Unauthenticated;
          } else {
            print('User is logged in');
            _user = _auth.currentUser;
            _status = Status.Authenticated;
          }
          notifyListeners();
        });
      }
    
    
      Future<void> verifyPhone(BuildContext context, String number,String password) async {
        //To be used in the verifyPhone method
        final PhoneCodeSent smsOTPSent = (String verId, [int forceCodeResend]) {
          this.verificationId = verId;
          smsOTPDialog(context, number,password).then((value) {
            _status = Status.Authenticated;
          });
        };
        try {
          await _auth.verifyPhoneNumber(
              phoneNumber: number.trim(),  
              codeAutoRetrievalTimeout: (String verId) {
                //Starts the phone number verification process for the given phone number.
                //Either sends an SMS with a 6 digit code to the phone number specified, or sign's the user in and [verificationCompleted] is called.
                this.verificationId = verId;
              },
              codeSent: smsOTPSent,
            //  timeout: const Duration(seconds: 20),
              //If user is automatically verified (without having to type the code)
              verificationCompleted: (AuthCredential credential) async {
                Navigator.of(context).pop();
                UserCredential result =
                    await _auth.signInWithCredential(credential);
                User user = result.user;
                if (user != null) {
                  //TO DO:// Here you need to save the phone and password to DB
                  print('Adding user to DB'); 
                   final url = 'https://mobile-12.firebaseio.com/users/$number.json';
                      try {
                        await http.post(
                          url,
                          body: json.encode({
                            'password': password,
                            'phoneNumber':user.phoneNumber,
                          }),
                        );
                        _status = Status.Authenticated;
                      } catch (error) {
                        print(error);
                      }
                  Navigator.push(
                      context,
                      MaterialPageRoute(
                          builder: (context) => HomeScreen(
                              )));
                } else {
                  print("Error");
                }
              },
              verificationFailed: (FirebaseAuthException exceptio) {
                print('${exceptio.message} + something is wrong');
              });
        } catch (e) {
          handleError(e, context,number,password);
          errorMessage = e.toString();
          notifyListeners();
        }
        notifyListeners();
      }
    
      Future<bool> smsOTPDialog(BuildContext context,String number,String password) {
        return showDialog(
            context: context,
            barrierDismissible: false,
            builder: (BuildContext context) {
              return AlertDialog(
                title: Text('Enter SMS Code'),
                content: Container(
                  height: 85,
                  child: Column(children: [
                    TextField(
                      onChanged: (value) {
                        this.smsOTP = value;
                      },
                    ),
                    (errorMessage != ''
                        ? Text(
                            errorMessage,
                            style: TextStyle(color: Colors.red),
                          )
                        : Container())
                  ]),
                ),
                contentPadding: EdgeInsets.all(10),
                actions: <Widget>[
                  FlatButton(
                    child: Text("Confirm"),
                    textColor: Colors.white,
                    color: Colors.blue,
                    onPressed: () async {
                      final code = this.smsOTP.trim();
    
                      AuthCredential credential = PhoneAuthProvider.credential(
                          verificationId: verificationId, smsCode: code);
                      UserCredential result =
                          await _auth.signInWithCredential(credential);               
                      User user = result.user;
                      if (user != null) {
                        print('user already exist'); 
                      // //TO DO:// Save the phone number and password to DB 
                      print('Adding user to Db in the manual OTP route'); 
                       final url = 'https://mobile-12.firebaseio.com/users/$number.json';
                      try {
                        await http.post(
                          url,
                          body: json.encode({
                            'password': password,
                            'phoneNumber':user.phoneNumber,
                          }),
                        );
                      } catch (error) {
                        print('INSIDE ERROR'); 
                        print(error);
                      }
                      SharedPreferences prefs = await SharedPreferences.getInstance();
                      prefs.setBool("logedIn", true);
                      logedIn =  true;
                        Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => HomeScreen(
                                     
                                    )));
                        loading = false;
                        notifyListeners();
                      } else {
                        print("No OTP was added");
                        loading = true;
                        notifyListeners();
                        Navigator.of(context).pop();
                      }
                    },
                  )
                ],
              );
            });
      }
 

//Sign-In Method checks to see if a phone exists. 
      signIn(BuildContext context, String number, String password,AuthMode authMode) async {
        try {
          //Check to see if the phone number is available
          final url = 'https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyPhoneNumber?key=';
      
           final response = await http.post(
    url,
    body: json.encode(
      {
        'phoneNumber': number
      },
    ),
  );
           
           final extractedData = json.decode(response.body) as Map<String, dynamic>;
    
          print('Extracted data is ' + extractedData.toString()); 
       
          //Register and send OTP if new user
          if (extractedData == null && authMode == AuthMode.Signup) {
            print('Inside NULL no errors');
        //     //Verify phone
            verifyPhone(context, number, password);
          } 
          //If tries to login but phone not available 
          else if(extractedData == null && authMode == AuthMode.Login)
          {
            _showErrorDialog('Phone number does not exist. Please Sign Up', context);
          }
    
          else if (extractedData['error'] != null) {
           _showErrorDialog('Something went wrong! Please try again!', context);
          }
          
          //If someone signup but their phone already exist 
          else if(extractedData != null  && authMode == AuthMode.Signup) 
          { 
               _showErrorDialog('Your phone already exists. Please Login!', context);
          }
          //If available, proceed to homepage
          else {
            print('User found');
             Navigator.push(
                            context,
                            MaterialPageRoute(
                                builder: (context) => HomeScreen(
                                    )));
         }
        } catch (e) {
          handleError(e, context,number,password);
        }
      }
    
      handleError(error, BuildContext context,String number,String password) { 
        errorMessage = error.toString();
        print('ERROR IS ' + errorMessage);
        notifyListeners();
      }
      Future<bool> _showErrorDialog(String message,BuildContext context) {
       return  showDialog(
          context: context,
          builder: (ctx) => AlertDialog(
                title: Text('An Error Occurred!'),
                content: Text(message),
                actions: <Widget>[
                  FlatButton(
                    child: Text('Okay'),
                    onPressed: () {
                      Navigator.of(ctx).pop();
                    },
                  )
                ],
              ),
        );
      }
    }

标签: firebaseflutterfirebase-authentication

解决方案


推荐阅读