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

Flutter启用App Check与Play Integrity后Firebase onCall验证及推送异常

Firebase App Check 与 Play Integrity 集成问题

已在Firebase中启用App Check和Play Integrity,但调用Callable函数时遇到两个问题:

  • 应用验证未执行(详见Firebase函数日志);
  • onCall函数内的推送通知未触发。

错误信息

客户端日志报错:

W/FirebaseContextProvider(25810): Error getting App Check token. Error: com.google.firebase.FirebaseException: Too many attempts.

Google Cloud函数日志摘要:

functionName158nxe4tcyx4 Callable request verification passed
jsonPayload: {
    message: "Callable request verification passed"
    verifications: {
    auth: "VALID"
    app: "MISSING" // 问题核心:应用验证缺失
    }
}

关键现象

移除以下两段代码后,推送通知可正常接收:

  1. 云函数的App Check强制验证配置:
.runWith({
        enforceAppCheck: true
    })
  1. 云函数内的App Check校验逻辑:
if (context.app == undefined) {
     throw new functions.https.HttpsError(
        'failed-precondition',
        'The function must be called from an App Check verified app.')
 }

相关代码

Flutter 端 Firebase 初始化

import 'package:firebase_app_check/firebase_app_check.dart';

 Future<void> initFirebase() async {
    WidgetsFlutterBinding.ensureInitialized();
    await Firebase.initializeApp();
    await FirebaseAppCheck.instance.activate(
      webRecaptchaSiteKey: 'recaptcha-v3-site-key',
      androidProvider: AndroidProvider.playIntegrity, // 模拟器用'debug'枚举,真机用'playIntegrity'
);

Flutter 端 Callable 函数调用

HttpsCallable callable =
          FirebaseFunctions.instanceFor(region: 'my-area')
              .httpsCallable('functionName');
      await callable.call<String, dynamic>({
        'token': pushToken,
        'username': '$userName',
  });

Firebase 云函数代码

exports.functionName = functions
    .region('my-area')
    .runWith({
        enforceAppCheck: true
    })
    .https.onCall(async (data, context) => {
        
        if (context.app == undefined) {
            throw new functions.https.HttpsError(
                'failed-precondition',
                'The function must be called from an App Check verified app.')
        }
        // 推送通知任务未执行(问题2)
        const token = data.token;
        const isApproved = data.isApproved;
        const payLoad = {
            data: { 'type': 'approvalStatus' },
            notification: {
                title: `Approval Status Update`,
                body: isApproved ? `Some description Text here`,
                clickAction: 'FLUTTER_NOTIFICATION_CLICK'
            }
        };
        return fcm.sendToDevice(token, payLoad);
    });

解决步骤

1. 修复App Check Token获取失败(Too many attempts)

  • 真机Play Integrity配置检查:
    • 确认已在Google Play Console为应用启用Play Integrity API,并将生成的API密钥配置到Firebase控制台的App Check设置(对应Android应用的Play Integrity提供方)。
    • 测试真机必须安装正式签名的应用包,debug包使用Play Integrity会验证失败,需配置debug签名的Play Integrity豁免规则。
  • 调整重试逻辑:
    App Check默认重试可能因网络或验证失败触发频繁请求,可在Flutter端手动捕获错误并添加指数退避重试:
    try {
      // 主动获取Token验证是否能正常获取
      await FirebaseAppCheck.instance.getToken(true);
    } catch (e) {
      await Future.delayed(Duration(seconds: 2));
      // 再次尝试获取Token
      await FirebaseAppCheck.instance.getToken(true);
    }
    

2. 修复云函数端App Check验证缺失

  • 配置云函数权限:
    在Google Cloud IAM中,为云函数默认服务账号添加Firebase App Check Token Verifier角色,确保其拥有firebaseappcheck.verifyToken权限。
  • 调试验证逻辑:
    在云函数中添加日志打印,确认context.app的具体内容:
    console.log('App Check上下文信息:', context.app);
    
  • 检查语法错误:
    云函数推送Payload中的body字段使用三元运算符但缺少else分支,会直接导致函数崩溃,这也是推送未执行的潜在原因,需补全:
    body: isApproved ? `已通过审核` : `审核未通过`,
    

3. 推送通知恢复逻辑

推送未执行本质是App Check验证失败导致函数提前抛出错误,解决App Check验证问题后,推送逻辑会自动执行。额外确认:

  • 云函数中fcm已正确初始化(如const fcm = admin.messaging();)。
  • 推送Token是有效的设备Token。

内容的提问来源于stack exchange,提问作者Neil-NotNeo

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 23:25:18