Firebase电话验证:一些用户不使用';我没有收到OTP
我面临着一个奇怪的问题,一些电话号码没有收到OTP而没有收到任何错误,只是什么都没有发生。除了极少数用户外,几乎所有用户都能很好地收到OTP。如何调试该问题?Firebase Auth是否有错误日志?我的代码遗漏了什么吗 以下是发送OTP的代码(在颤振中)Firebase电话验证:一些用户不使用';我没有收到OTP,firebase,flutter,firebase-authentication,Firebase,Flutter,Firebase Authentication,我面临着一个奇怪的问题,一些电话号码没有收到OTP而没有收到任何错误,只是什么都没有发生。除了极少数用户外,几乎所有用户都能很好地收到OTP。如何调试该问题?Firebase Auth是否有错误日志?我的代码遗漏了什么吗 以下是发送OTP的代码(在颤振中) sendOtp(String number, BuildContext context) async { print("Sending OTp"); state = ViewState.Busy;
sendOtp(String number, BuildContext context) async {
print("Sending OTp");
state = ViewState.Busy;
await auth.verifyPhoneNumber(
phoneNumber: '+966$number',
timeout: Duration(seconds: 30),
verificationCompleted: (AuthCredential credential) {
print("Verified");
signInWCredential(credential, context, number);
},
verificationFailed: (FirebaseAuthException e) {
print("verification error code is: ${e.code}");
print("verification error message is: ${e.message}");
if (e.code == "too-many-requests") {
Dialogs.dialog(
context,
"${Localization.of(context).error}!",
Localization.of(context).tooManyOtpRequestsError,
Localization.of(context).ok,
isDoublePop: true)
.then((value) {
if (value == ConfirmAction.ACCEPT) {
Navigator.of(context).pop();
}
});
} else {
FirebaseCrashlytics.instance.recordError(e, StackTrace.current);
print("Error is: $e");
Dialogs.dialog(
context,
"${Localization.of(context).error}!",
Localization.of(context).errorSendingOtp,
Localization.of(context).ok,
isDoublePop: true);
}
},
codeSent: (String verificationId, [int resendToken]) {
print("Code sent");
print("verification ID is: $verificationId");
setVerificationId(verificationId);
print("Resend token is: $resendToken");
state = ViewState.Idle;
},
codeAutoRetrievalTimeout: (String verificationId) {},
);
}
import'package:firebase_auth/firebase_auth.dart';
进口“包装:颤振/cupertino.dart”;
进口“包装:颤振/材料.省道”;
类Demo扩展StatefulWidget{
@凌驾
_DemoState createState();
}
类_DemoState扩展了状态{
TextEditingController _controller=TextEditingController();
Future\u showMyDialog()异步{
返回显示对话框(
上下文:上下文,
barrierDismissible:false,//用户必须点击按钮!
生成器:(BuildContext上下文){
返回警报对话框(
标题:文本(“AlertDialog标题”),
内容:SingleChildScrollView(
子:列表体(
儿童:[
Text('这是一个演示警报对话框'),
文本字段(
控制器:_控制器,
)
],
),
),
行动:[
文本按钮(
子项:文本('Approve'),
已按下:(){
Navigator.of(context.pop();
},
),
],
);
},
);
}
void sendOTP()异步{
等待FirebaseAuth.instance.verifyPhoneNumber(
电话号码:“您的号码”,
验证已完成:(PhoneAuthCredential凭据)异步{
打印(“验证完成”);
等待FirebaseAuth.instance.signInWithCredential(凭证);
},
验证失败:(FireBaseAuth异常){
打印(“FirebaseAuthException”);
打印(电子代码);
},
codeSent:(字符串验证ID,int标记)异步{
打印(“代码发送”);
等待_showMyDialog();
PhoneAuthCredential PhoneAuthCredential=PhoneAuthProvider.credential(
verificationId:verificationId,smsCode:_controller.text);
等待FirebaseAuth.instance.signInWithCredential(phoneAuthCredential);
打印(“已完成”);
},
codeAutoRetrievalTimeout:(字符串验证ID){
打印($verificationID);
},
超时:常数持续时间(秒:60),
);
}
@凌驾
小部件构建(构建上下文){
返回脚手架(
正文:中(
孩子:扁平按钮(
子:文本(
“发送otp”),
onPressed:sendOTP,
),
),
);
}
}
这是我使用firebase进行电话身份验证的代码,它对许多手机号码都很有效我遇到了这个问题,通过搜索互联网发现firebase的电话身份验证不适用于将号码从一个网络传输到另一个网络的用户。我还发现其他电话认证SDK(Firebase除外)也存在同样的问题。唯一的解决方案是让您的用户可以选择使用电子邮件和密码登录,或者使用电话身份验证以外的其他登录方法。提供这两个选项将保证用户可以登录。我已联系GCP支持部门调查此问题。他们向我报告,我的客户所在地区的短信发送成功率为85%-90%。他们正在与短信提供商合作解决这个问题
我提出了一个新的功能请求,如果短信发送失败,我将返回一条错误消息。同时,我通过创建自己的自定义身份验证API并通过另一家服务提供商发送短信解决了这个问题。你明白了吗?我正在考虑将我的手机认证改为电子邮件和密码认证。
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
class Demo extends StatefulWidget {
@override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
TextEditingController _controller = TextEditingController();
Future<void> _showMyDialog() async {
return showDialog<void>(
context: context,
barrierDismissible: false, // user must tap button!
builder: (BuildContext context) {
return AlertDialog(
title: Text('AlertDialog Title'),
content: SingleChildScrollView(
child: ListBody(
children: <Widget>[
Text('This is a demo alert dialog.'),
TextField(
controller: _controller,
)
],
),
),
actions: <Widget>[
TextButton(
child: Text('Approve'),
onPressed: () {
Navigator.of(context).pop();
},
),
],
);
},
);
}
void sendOTP() async {
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: "your number",
verificationCompleted: (PhoneAuthCredential credential) async {
print("verificationCompleted");
await FirebaseAuth.instance.signInWithCredential(credential);
},
verificationFailed: (FirebaseAuthException e) {
print("FirebaseAuthException");
print(e.code);
},
codeSent: (String verificationID, int token) async {
print("codeSent");
await _showMyDialog();
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.credential(
verificationId: verificationID, smsCode: _controller.text);
await FirebaseAuth.instance.signInWithCredential(phoneAuthCredential);
print("completed");
},
codeAutoRetrievalTimeout: (String verificationID) {
print("$verificationID");
},
timeout: const Duration(seconds: 60),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: FlatButton(
child: Text(
"send otp"),
onPressed: sendOTP,
),
),
);
}
}