You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Firebase短信验证请求OTP时打开浏览器,未上架Play无法用Play Integrity求助

Firebase Auth手机号验证问题(Unity)解决方案

一、Play Integrity API不用上架也能跑

别被误导了,Play Integrity API不需要游戏上架Google Play商店就能用,但得满足这几个条件:

  • 必须用签名后的APK/AAB包测试,Unity编辑器直接跑或者未签名的调试包不行
  • Google Cloud控制台要配置对:
    • 确认Firebase项目和Google Cloud项目是关联的(Firebase后台「项目设置」里能看到关联状态)
    • 给你的应用包名开了Play Integrity API,而且最新的google-services.json已经替换到Unity项目的Assets根目录
    • 签名用的SHA-256密钥,既要加到Firebase项目,也要加到Google Play Console的「应用签名」里(哪怕没上架,先在Play Console创建个空应用就行)

二、OTP请求跳浏览器?这么搞定

Firebase Auth跳浏览器是因为没法自动完成验证/短信检索,按步骤修复:

1. 补全短信检索依赖

在Unity的Assets/Plugins/Android文件夹里,确保有play-services-auth-api-phone和play-services-sms-retriever的aar包。可以用Firebase Unity SDK的依赖管理器自动导入,也能手动添加。

2. 修改AndroidManifest.xml

在Assets/Plugins/Android/AndroidManifest.xml里添加这些权限和服务:

<!-- 短信相关权限 -->
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.SEND_SMS" />

<!-- 短信检索接收器 -->
<receiver android:name="com.google.firebase.auth.api.phone.internal.SmsRetriever"
          android:exported="true">
  <intent-filter>
    <action android:name="com.google.android.gms.auth.api.phone.SMS_RETRIEVED" />
  </intent-filter>
</receiver>

3. 优化验证代码

几个关键细节:

  • 手机号必须带国家码(比如+86),否则验证大概率失败
  • 补全登录逻辑,打印完整错误信息方便排查
  • 保存会话ID和重发令牌,支持手动验证和重发验证码

修改后的代码:

using Firebase;
using Firebase.Auth;
using TMPro;
using UnityEngine;

// 修正类名拼写:FIrebaseAuth → FirebaseAuth
public class FirebaseAuth : MonoBehaviour
{
    public TMP_InputField phoneNumberInputField;
    public TMP_InputField codeInputField; // 新增验证码输入框

    private FirebaseAuth auth;
    private uint timeOut = 60 * 1000;
    private string verificationId;
    private PhoneAuthProvider.ForceResendingToken resendToken;

    private void Start()
    {
        FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
        {
            if (task.Exception != null)
            {
                Debug.LogError("Firebase初始化失败: " + task.Exception);
                return;
            }
            auth = FirebaseAuth.DefaultInstance;
        });
    }

    public void SendVerificationCode()
    {
        string phoneNumber = phoneNumberInputField.text;
        // 强制添加国家码,根据目标地区调整
        if (!phoneNumber.StartsWith("+"))
        {
            phoneNumber = "+86" + phoneNumber;
        }

        PhoneAuthProvider provider = PhoneAuthProvider.GetInstance(auth);
        provider.VerifyPhoneNumber(phoneNumber, timeOut, resendToken, verificationCompleted: (credential) =>
        {
            // 自动验证成功,直接登录
            auth.SignInWithCredentialAsync(credential).ContinueWith(signTask =>
            {
                if (signTask.IsCompletedSuccessfully)
                {
                    Debug.Log("用户登录成功");
                    // 此处跳转游戏主界面
                }
                else
                {
                    Debug.LogError("登录失败: " + signTask.Exception);
                }
            });
        }, verificationFailed: (error) =>
        {
            // 打印完整错误信息,精准排查问题
            Debug.LogError("验证失败: " + error.DebugDescription);
        }, codeSent: (id, token) =>
        {
            Debug.Log("验证码已发送,会话ID: " + id);
            verificationId = id;
            resendToken = token;
            // 显示验证码输入UI
            codeInputField.gameObject.SetActive(true);
        }, codeAutoRetrievalTimeOut: (id) =>
        {
            Debug.Log("自动收验证码超时,请手动输入");
            // 显示验证码输入UI
            codeInputField.gameObject.SetActive(true);
        });
    }

    // 手动输入验证码后的验证方法
    public void VerifyInputCode()
    {
        string inputCode = codeInputField.text.Trim();
        if (string.IsNullOrEmpty(inputCode) || string.IsNullOrEmpty(verificationId)) return;

        PhoneAuthCredential credential = PhoneAuthProvider.GetCredential(verificationId, inputCode);
        auth.SignInWithCredentialAsync(credential).ContinueWith(task =>
        {
            if (task.IsCompletedSuccessfully)
            {
                Debug.Log("手动验证成功,用户登录");
                // 此处跳转游戏主界面
            }
            else
            {
                Debug.LogError("验证码错误或验证失败: " + task.Exception);
            }
        });
    }
}

4. 签名配置必须匹配

Unity打包时,一定要用和Firebase后台添加的SHA密钥一致的签名文件。调试包用调试签名的SHA-1/SHA-256,正式包用发布签名的,两类密钥都要提前加到Firebase后台。

三、Play Integrity API没生效?按顺序排查

如果开了API还是不行,按以下步骤检查:

  1. 去Google Cloud控制台,搜索「Play Integrity API」,确认状态是「已启用」
  2. 检查Firebase后台「项目设置」→「应用」,包名、SHA-1/SHA-256都要完全匹配,且google-services.json是最新下载的
  3. 打包用Release模式(Debug也可以,但必须签名),用真实设备测试,模拟器可能不支持自动检索功能
  4. 查看verificationFailed回调里的完整错误日志,比如有没有API未启用、密钥不匹配的明确提示

内容的提问来源于stack exchange,提问作者Prashant Khandelwal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:22:55