簡體   English   中英

使用 firebase 和 flutter 進行電話身份驗證

[英]Phone authentication with firebase and flutter

我正在編寫一個使用電話身份驗證的 flutter 應用程序。 我目前正在 iPhone 12 模擬器上運行該應用程序,當我測試該應用程序並實施電話號碼時,我沒有按計划從 firebase 收到 6 位代碼。 我認為是因為其中一個提到了共鳴。

    1. Firebase 無法將代碼發送到帶有假號碼的模擬器。
    1. 我需要更改 firebase/flutter 項目的一些設置,以便它按預期工作。
    1. 我還需要發送帶有區號的電話號碼。
    1. 我的代碼是錯誤的或沒有做我想做的事。

(我還沒有蘋果開發者賬戶,所以我給了一個測試號碼和代碼 firebase 所以當我輸入假號碼時,我仍然會得到應用程序的代碼(不是推送通知))。

應用程序的一些點:

如果需要,我可以在真實設備上測試該應用程序。
我現在不需要收到推送通知,我只需將驗證碼打印到控制台,這樣我就能看到代碼是否有效。
我想在將電話號碼發送到此頁面(驗證頁面)后立即開始驗證過程
現在我使用的是沒有區號的完整號碼。

我可以為模擬器使用假號碼嗎? 或者我需要一個真正的?

謝謝,希望您能幫助我解決問題。

這是我的代碼(只有驗證部分):

// imports are here

enum Status { waiting, error }

class VerificationCode extends StatefulWidget {
  const VerificationCode({Key? key, this.number}) : super(key: key);
  final number;
  @override
  _VerificationCodeState createState() => _VerificationCodeState(number);
}

class _VerificationCodeState extends State<VerificationCode> {
  late final phoneNumber;
  final _verKey = GlobalKey<FormState>();
  late String _verCode;
  late double _formHeight;
  final FirebaseAuth _auth = FirebaseAuth.instance;
  var _verificationId;
  var _status = Status.waiting;
  _VerificationCodeState(this.phoneNumber); // storing the phone number from other page

  @override
  void initState() {
    super.initState();
    _verifyPhoneNumber();
  }

  Future _verifyPhoneNumber() async {
    _auth.verifyPhoneNumber(
        phoneNumber: phoneNumber,
        verificationCompleted: (phonesAuthCredentials) async {},
        verificationFailed: (verificationFailed) async {},
        codeSent: (verificationId, reseningToken) async {
          setState(() {
            _verificationId = verificationId;
            print(_verificationId); // here I am printing the opt code so I will know what it is to use it
          });
        },
        codeAutoRetrievalTimeout: (verificationId) async {});
  }

  Future _sendCodeToFirebase({String? code}) async {
    if (_verificationId != null) {
      var credential = PhoneAuthProvider.credential(
        verificationId: _verificationId,
        smsCode: code!,
      );

      await _auth
          .signInWithCredential(credential)
          .then((value) {
            print("auth complete!");
          })
          .whenComplete(() {})
          .onError((error, stackTrace) {
            setState(() {
              _verKey.currentState!.reset();
              _status = Status.error;
            });
          });
    }
  }

  @override
  Widget build(BuildContext context) {
    Size size = MediaQuery.of(context).size;
    if (size.height <= 736) {
      _formHeight = (size.height * .05) + 6;
    } else {
      _formHeight = size.height * .048;
    }
    return Scaffold(
      body: SafeArea(
        child: GestureDetector(
          onTap: () => FocusScope.of(context).requestFocus(
            FocusNode(),
          ),
          child: SingleChildScrollView(
            child: ConstrainedBox(
              constraints: BoxConstraints(
                minHeight: size.height - 90,
              ),
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.stretch,
                children: [
                  Stack(
                    alignment: Alignment.topLeft,
                    children: [
                      GestureDetector(
                        onTap: () {
                          Navigator.pop(context);
                        },
                        child: Padding(
                          padding: EdgeInsets.only(
                            top: size.height * .006,
                            left: size.width * .03,
                          ),
                          child: SvgPicture.asset(
                            "assets/arrow-back.svg",
                          ),
                        ),
                      ),
                    ],
                  ),
                  Padding(
                    padding: EdgeInsets.only(
                      top: size.height * .18,
                    ),
                    child: Center(
                      child: Text(
                        "AppName",
                        style: TextStyle(
                          fontSize: size.width * .096,
                          letterSpacing: size.width * .026,
                          fontWeight: FontWeight.w300,
                        ),
                      ),
                    ),
                  ),
                  Padding(
                    padding: EdgeInsets.only(top: size.height * .015),
                    child: Center(
                      child: Container(
                        margin: EdgeInsets.symmetric(
                          horizontal: size.width * .045,
                        ),
                        height: _formHeight,
                        child: Form(
                          key: _verKey,
                          child: TextFormField(
                            style: TextStyle(
                              fontSize: size.width * .035,
                            ),
                            decoration: InputDecoration(
                              counterText: "",
                              contentPadding:
                                  const EdgeInsets.fromLTRB(0, 10, 0, 0),
                              hintText: 'Verification Code',
                              enabledBorder: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(7.0),
                                borderSide: const BorderSide(
                                  color: Colors.black,
                                  width: 1.25,
                                ),
                              ),
                              focusedBorder: OutlineInputBorder(
                                borderRadius: BorderRadius.circular(7.0),
                                borderSide: const BorderSide(
                                  color: Colors.black,
                                  width: 1.5,
                                ),
                              ),
                            ),
                            autofocus: false,
                            keyboardType: TextInputType.number,
                            cursorColor: Colors.black,
                            textAlign: TextAlign.center,
                            onChanged: (input) async {
                              if (input.length == 6) {
                                _verCode = input;
                                _sendCodeToFirebase(code: _verCode);
                              }
                            },
                            maxLength: 6,
                          ),
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Firebase iOS 上的電話身份驗證需要文檔中提到的一些設置步驟 它提到您需要啟用推送通知的步驟需要驗證請求是否來自您的應用程序,它被稱為“靜默 APNs 通知”,因為它在用戶沒有意識到的情況下靜默發生,但在測試的情況下,使用reCAPTCHA 驗證,請閱讀官方 Firebase iOS 文檔中有關此步驟的更多信息。

但是,為了在模擬器上進行測試,您確實可以使用您在 Firebase 控制台中電話身份驗證登錄方法下定義的假號碼和短信代碼。

首先,您需要根據 Firebase SDK 的要求為 iOS 設置 reCAPTCHA 驗證

其次,添加本地測試Phone Auth的測試號碼

  1. 在 Firebase 控制台上,select 是“電話”身份驗證提供程序,然后單擊“測試電話號碼”下拉菜單。
  2. 輸入新的電話號碼(例如 +44 7444 555666)和測試代碼(例如 123456)。

添加測試編號需要注意以下事項:

  1. 一旦您在 Firebase 控制台中將號碼添加到您的測試列表中,即使它們是真實的,您也不會收到關於它們的短信代碼,您可以使用您已經在控制台中定義的代碼。
  2. 如果您已經有一個使用與您嘗試添加以測試的相同電話號碼的注冊帳戶,它會給出一個錯誤,說明無法添加,請確保刪除與該號碼關聯的帳戶或選擇另一個。

至於Firebase接受的電話號碼格式,必須有國家代碼,並且遵循E.164標准, +開頭,國家代碼,電話號碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM