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

FCM V1 API网页推送通知收不到问题及API Key生成代码需求

FCM V1 API返回200但设备无通知问题排查 + 服务账号令牌生成代码

一、设备收不到通知的核心原因及修复

你当前的代码只发送了data类型消息,而Firebase控制台发送的是notification类型消息,两者的处理逻辑完全不同:

  • notification消息:由FCM SDK自动处理,系统会直接弹出通知,无需客户端额外代码
  • data消息:需要客户端代码手动解析并构建通知,否则不会自动显示

修复后的发送代码

修改$notifMessage结构,添加notification字段即可:

<?php
function sendFCM() {
  $url = 'https://fcm.googleapis.com/v1/projects/nanagroup/messages:send';
  // 注意:OAuth2 Playground的令牌是临时的,建议用服务账号生成长期令牌(见第二部分)
  $apiKey = "ya29.a0AfB_byB3orl0ZHoWQl_KYGObHiytKRj3WeMDmlYOuuUBVKlqHsploLlrxBExC2w5_Ux7-YgwUioFgw_F5VbQjouCDtUOGuB2y65ikUmCaMsMyYC1C8nBD4wAuSIhFSDx120BtCiSashwGC0AHZe2b9kP7lTVJc3H4WPlaCgYKATASARISFQHGX2MiX-xa0oLOMvIAiYH3thEf6w0171";

  $headers = array (
    'Authorization:Bearer ' . $apiKey,
    'Content-Type:application/json'
  );

  $notifData = [
    'title' => "Test Title",
    'body' => "Test notification body",
  ];

  // 添加notification字段,让系统自动展示通知
  $notifMessage = [
    'token' => "elGCwBHhSK2roeM-VysEIm:APA91bFma3hQgndwueeyIfd91acHonvGSo-T8u_VfQAfSgMGdgBYP0HTX5c9JIbvHQjMZVPv9XD0y1liuXli0K3KG6CQVbqcZrbGuM19atV2CDNvFInsxnpEkeDxJNtAQauLpS9MmgOC",
    'notification' => $notifData,
    'data' => $notifData, // 可选,保留data字段供客户端自定义逻辑使用
  ];

   $apiBody = [
    'message' => $notifMessage
  ];

  $ch = curl_init();
  curl_setopt ($ch, CURLOPT_URL, $url);
  curl_setopt ($ch, CURLOPT_POST, true);
  curl_setopt ($ch, CURLOPT_HTTPHEADER, $headers);
  curl_setopt ($ch, CURLOPT_RETURNTRANSFER, true);
  curl_setopt ($ch, CURLOPT_POSTFIELDS, json_encode($apiBody));

  $result = curl_exec($ch);
  print($result);
  curl_close($ch);

  return $result;
}
sendFCM();
?>

二、从Firebase服务账号JSON生成OAuth2令牌的代码

你当前用的OAuth2 Playground令牌是临时的,有效期仅1小时左右,生产环境建议用Firebase控制台下载的服务账号JSON生成长期可刷新的令牌。以下提供两种实现方式:

方法1:使用Google Client库(推荐)

先通过Composer安装依赖:

composer require google/apiclient:^2.0

然后编写代码:

<?php
require __DIR__ . '/vendor/autoload.php';

// 生成FCM访问令牌
function getFCMAccessToken() {
    $serviceAccountPath = 'path/to/your/service-account.json'; // 替换成你的JSON文件路径
    $client = new Google_Client();
    $client->setAuthConfig($serviceAccountPath);
    $client->addScope('https://www.googleapis.com/auth/firebase.messaging');
    $client->fetchAccessTokenWithAssertion();
    return $client->getAccessToken()['access_token'];
}

// 发送FCM消息
function sendFCM() {
    $url = 'https://fcm.googleapis.com/v1/projects/nanagroup/messages:send';
    $apiKey = getFCMAccessToken();

    $headers = [
        'Authorization:Bearer ' . $apiKey,
        'Content-Type:application/json'
    ];

    $notifData = [
        'title' => "Test Title",
        'body' => "Test notification body",
    ];

    $notifMessage = [
        'token' => "elGCwBHhSK2roeM-VysEIm:APA91bFma3hQgndwueeyIfd91acHonvGSo-T8u_VfQAfSgMGdgBYP0HTX5c9JIbvHQjMZVPv9XD0y1liuXli0K3KG6CQVbqcZrbGuM19atV2CDNvFInsxnpEkeDxJNtAQauLpS9MmgOC",
        'notification' => $notifData,
        'data' => $notifData,
    ];

    $apiBody = [
        'message' => $notifMessage
    ];

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($apiBody));

    $result = curl_exec($ch);
    print($result);
    curl_close($ch);

    return $result;
}

sendFCM();
?>

方法2:手动生成JWT令牌(无需第三方库)

如果不想依赖Composer,可以手动实现JWT签名和令牌请求:

<?php
// 从服务账号JSON生成FCM访问令牌
function generateFCMAccessToken($serviceAccountPath) {
    $serviceAccount = json_decode(file_get_contents($serviceAccountPath), true);
    $privateKey = $serviceAccount['private_key'];
    $clientEmail = $serviceAccount['client_email'];
    $tokenUri = $serviceAccount['token_uri'];

    // 构建JWT载荷
    $iat = time();
    $exp = $iat + 3600; // 令牌有效期1小时
    $payload = [
        'iss' => $clientEmail,
        'scope' => 'https://www.googleapis.com/auth/firebase.messaging',
        'aud' => $tokenUri,
        'iat' => $iat,
        'exp' => $exp
    ];

    // 生成JWT签名
    $header = json_encode(['alg' => 'RS256', 'typ' => 'JWT']);
    $base64Header = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($header));
    $base64Payload = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode(json_encode($payload)));
    $signatureInput = $base64Header . '.' . $base64Payload;
    openssl_sign($signatureInput, $signature, $privateKey, 'SHA256');
    $base64Signature = str_replace(['+', '/', '='], ['-', '_', ''], base64_encode($signature));
    $jwt = $base64Header . '.' . $base64Payload . '.' . $base64Signature;

    // 请求获取访问令牌
    $ch = curl_init($tokenUri);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query([
        'grant_type' => 'urn:ietf:params:oauth:grant-type:jwt-bearer',
        'assertion' => $jwt
    ]));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    $response = json_decode(curl_exec($ch), true);
    curl_close($ch);

    return $response['access_token'];
}

// 使用示例
$serviceAccountPath = 'path/to/your/service-account.json';
$apiKey = generateFCMAccessToken($serviceAccountPath);

// 后续发送FCM的代码参考第一部分,记得添加notification字段
?>

内容的提问来源于stack exchange,提问作者Witchaya Eungphinij

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:09:55