Flutter调用Firebase手机号登录接口失败如何排查解决
Firebase 手机号登录流程执行失败修复方案
问题说明
实现Firebase手机号登录功能时流程中断无法完成,暂未定位到明确错误点,核心实现代码如下:
var phoneNumber = myPhone.text; phoneNumber = '+62' + int.parse(phoneNumber).toString(); _auth.verifyPhoneNumber( phoneNumber: phoneNumber, timeout: Duration(seconds: 60), verificationCompleted: (AuthCredential auth) async { phoneStatus.value = 'Auto retrieving verification code'; debugPrint('step 1'); //_authCredential = auth; await _auth.signInWithCredential(auth).then((value) async { if (value.user != null) { User user = value.user!; updateUserData(user); Get.offAll(Root()); await getUserData(user.uid); // TODO: Save token if notification service is added. _saveDeviceToken(user.uid); //onAuthenticationSuccessful(); } else { phoneStatus.value = 'Invalid code/invalid authentication'; } }).catchError((error) { phoneStatus.value = 'Something has gone wrong, please try later.'; }); debugPrint('step 3 : ' + phoneStatus.string); // if (phoneStatus.toString() == 'Authentication successful') { // Get.offAll(Root()); // } Get.snackbar('Phone Login', phoneStatus.toString(), snackPosition: SnackPosition.BOTTOM, colorText: Colors.white, backgroundColor: kPrimary); },
错误截图:
根因定位
代码存在4个核心问题,直接导致登录失败且无法捕获有效错误日志:
- 手机号格式处理逻辑错误:用
int.parse处理用户输入的手机号会自动丢弃开头的前置0(印尼本地手机号常以0开头),如果用户输入带分隔符、空格还会直接抛出格式转换异常,最终拼接出的手机号不符合E.164规范,Firebase无法识别。 verifyPhoneNumber回调缺失:仅实现了verificationCompleted自动验证回调,漏写了verificationFailed验证失败、codeSent验证码下发、codeAutoRetrievalTimeout自动验证超时三个必选回调,Firebase返回的所有原生错误全被吞,根本看不到具体报错原因。- 从错误截图的
missing-client-identifier报错可以判断,Firebase控制台配置缺失:没有把应用的SHA1/SHA256签名指纹配置到Firebase项目中,或者没有开启Play Integrity(原SafetyNet)校验,安卓设备无法通过Firebase的设备合法性校验。 - 执行逻辑顺序错误:
signInWithCredential成功后直接执行Get.offAll(Root())跳转根页面,后面的getUserData、_saveDeviceToken逻辑会因为页面销毁被中断,容易出现状态异常。
修复步骤
- 替换手机号格式处理逻辑,不要用数字转换处理字符串类型的手机号:
// 去掉用户输入手机号开头的前置0,再拼接国家码 String rawPhone = myPhone.text.trim(); if (rawPhone.startsWith('0')) { rawPhone = rawPhone.substring(1); } String phoneNumber = '+62$rawPhone'; // 校验手机号格式,过滤非法字符 assert(RegExp(r'^\+62[0-9]{9,12}$').hasMatch(phoneNumber), '手机号格式不符合E.164规范'); - 补全
verifyPhoneNumber的全部回调,打印错误日志方便后续排查:_auth.verifyPhoneNumber( phoneNumber: phoneNumber, timeout: const Duration(seconds: 60), verificationCompleted: (AuthCredential credential) async { phoneStatus.value = '自动校验验证码中'; try { final userCred = await _auth.signInWithCredential(credential); final user = userCred.user; if (user != null) { phoneStatus.value = '登录成功'; // 先执行完所有数据拉取、存储逻辑再跳转页面 updateUserData(user); await getUserData(user.uid); _saveDeviceToken(user.uid); Get.offAll(Root()); } } catch (e) { debugPrint('自动登录失败: $e'); phoneStatus.value = '验证失败,请稍后重试'; } Get.snackbar('手机号登录', phoneStatus.value, snackPosition: SnackPosition.BOTTOM, colorText: Colors.white, backgroundColor: kPrimary); }, verificationFailed: (FirebaseAuthException e) { // 核心错误捕获入口 debugPrint('验证流程失败: ${e.code} ${e.message}'); phoneStatus.value = '验证失败:${e.message}'; Get.snackbar('手机号登录', phoneStatus.value, snackPosition: SnackPosition.BOTTOM, colorText: Colors.white, backgroundColor: Colors.red); }, codeSent: (String verificationId, int? resendToken) { phoneStatus.value = '验证码已下发'; // 存储verificationId,等用户输入验证码后拼接为AuthCredential完成登录 }, codeAutoRetrievalTimeout: (String verificationId) { phoneStatus.value = '自动验证超时,请手动输入验证码'; }, ); - 补全Firebase控制台配置:
- 提取安卓应用debug、release签名对应的SHA1、SHA256指纹,添加到Firebase项目「设置-我的应用-安卓应用」的指纹配置项中
- 打开Firebase控制台「Authentication-设置-手机号」,开启Play Integrity校验开关;如果是国内测试设备无法连接Google服务,调试阶段可以把测试手机号、测试验证码配置到Firebase测试白名单中,绕过设备校验
- 重新下载
google-services.json配置文件放到项目android/app目录下,重新编译运行
内容的提问来源于stack exchange,提问作者Dendimuhmd
相关产品推荐
相关产品推荐

