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

Flutter/Dart中FCM HTTP v1发送通知失败,请求排查协助

FCM HTTP v1通知未送达问题排查与修复

首要问题:你用错了Bearer令牌

你当前通过getAccessToken()获取的是Firebase Auth用户的ID Token,但FCM v1 API要求的是服务账号的OAuth2访问令牌——用户ID Token只能用来验证用户身份,根本无权调用FCM的服务端API,这是导致通知发不出去的核心原因。

正确获取FCM令牌的方法

需要用Firebase服务账号生成专用的OAuth2令牌,步骤如下:

  1. 去Firebase控制台下载服务账号JSON文件(路径:项目设置 > 服务账号 > 生成新的私钥)
  2. 用Google Auth库生成令牌,Dart示例代码:
import 'package:googleapis_auth/auth_io.dart';
import 'package:http/http.dart' as http;

Future<String> getFcmAccessToken() async {
  // 注意:不要把服务账号JSON硬编码到代码里,建议从环境变量或安全配置文件读取
  final serviceAccountJson = {
    \"type\": \"service_account\",
    \"project_id\": \"你的项目ID\",
    \"private_key_id\": \"你的私钥ID\",
    \"private_key\": \"你的私钥内容\",
    \"client_email\": \"服务账号邮箱\",
    \"client_id\": \"服务账号ID\",
    \"auth_uri\": \"https://accounts.google.com/o/oauth2/auth\",
    \"token_uri\": \"https://oauth2.googleapis.com/token\",
    \"auth_provider_x509_cert_url\": \"https://www.googleapis.com/oauth2/v1/certs\",
    \"client_x509_cert_url\": \"服务账号证书URL\"
  };

  final credentials = ServiceAccountCredentials.fromJson(serviceAccountJson);
  // FCM所需的权限范围
  final scopes = ['https://www.googleapis.com/auth/firebase.messaging'];

  final client = await clientViaServiceAccount(credentials, scopes);
  final accessToken = client.credentials.accessToken.data;
  client.close();
  
  return accessToken;
}

其他排查方向

1. 验证Device Token是否有效

  • 先去FCM控制台的「发送测试消息」功能,直接用这个Device Token发测试通知,如果也收不到,说明Token无效(可能过期、应用已卸载,或者设备注册信息失效)
  • 确认Token格式正确:应该是一串约150字符的字符串

2. 检查API请求细节

  • 确认请求URL里的项目ID正确:把academy换成你实际的Firebase项目ID,格式是https://fcm.googleapis.com/v1/projects/[你的项目ID]/messages:send
  • 一定要打印API的响应内容,这是排查错误的关键!修改你的http.post代码,加上响应日志:
final response = await http.post(...);
print('FCM响应状态码: ${response.statusCode}');
print('FCM响应内容: ${response.body}');
// 不要只靠toast提示,日志能帮你看到具体错误(比如认证失败、Token无效等)

3. 权限与配置检查

  • 确保你的服务账号拥有「Firebase Messaging Admin」角色(去Google Cloud控制台 > IAM > 找到对应的服务账号 > 添加角色)
  • 确认客户端应用已经正确配置FCM:AndroidManifest.xml/Info.plist设置无误,google-services.json/GoogleService-Info.plist已添加到项目中

修复后的发送方法示例

static Future<void> sendNotificationForTesting(String deviceToken) async {
  try {
    String token = await getFcmAccessToken(); // 替换成正确的令牌获取方法

    final response = await http.post(
      Uri.parse('https://fcm.googleapis.com/v1/projects/[你的项目ID]/messages:send'),
      headers: <String, String>{
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $token'
      },
      body: jsonEncode(<String, dynamic>{
        \"message\": {
          \"token\": deviceToken,
          \"notification\": {
            \"title\": \"突发新闻\",
            \"body\": \"有新的新闻报道可用。\"
          },
          \"data\": {\"id\": \"1\"},
          \"android\": {
            \"notification\": {
              \"click_action\": \"FLUTTER_NOTIFICATION_CLICK\",
            },
          },
        }
      }),
    );

    if (response.statusCode == 200) {
      Fluttertoast.showToast(
        backgroundColor: Colors.green,
        msg: \"通知发送成功\",
        textColor: Colors.white,
      );
    } else {
      print('FCM错误详情: ${response.body}');
      Fluttertoast.showToast(
        backgroundColor: Colors.red,
        msg: \"发送失败: ${response.body}\",
        textColor: Colors.white,
      );
    }
  } catch (e) {
    print(\"发送测试通知失败: $e\");
    Fluttertoast.showToast(
      backgroundColor: Colors.red,
      msg: \"发送失败: ${e.toString()}\",
      textColor: Colors.white,
    );
  }
}

内容的提问来源于stack exchange,提问作者Templeton Meshack

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 15:21:06