如何在PHP中使用FCM HTTP v1 API及获取对应权限的访问令牌?
PHP 对接 FCM HTTP v1 API:获取访问令牌全流程指南
我完全懂你的困扰——FCM从旧版转到v1 API后,官方文档确实有点零散,尤其是结合PHP的Google API Client Library来获取权限令牌的部分,我之前帮团队做迁移的时候也卡过好久。下面把我亲测可行的完整步骤拆解给你:
一、先搞定服务账号密钥(核心前提)
首先得在Google Cloud控制台生成服务账号密钥:
- 打开你的Firebase项目对应的Google Cloud控制台,找到「IAM与管理」→「服务账号」
- 创建一个新的服务账号(或者用现有账号),给它分配「Firebase Cloud Messaging Admin」角色(这个权限是发送FCM消息的核心)
- 点击服务账号的「密钥」→「添加密钥」→「创建新密钥」,选择JSON格式下载,把这个文件存到你的PHP项目里(注意别提交到代码仓库!)
二、用Google API Client获取访问令牌
首先确保你已经通过Composer安装了Google API Client:
composer require google/apiclient
接下来是核心代码,重点是指定FCM对应的权限范围https://www.googleapis.com/auth/firebase.messaging:
<?php require __DIR__ . '/vendor/autoload.php'; // 替换成你的服务账号密钥文件路径 $keyFilePath = '/path/to/your-service-account-key.json'; // FCM v1 API要求的权限范围 $scope = 'https://www.googleapis.com/auth/firebase.messaging'; $client = new Google_Client(); $client->setAuthConfig($keyFilePath); $client->addScope($scope); // 设置为离线模式,支持获取可刷新的令牌(FCM令牌有效期1小时,建议做缓存) $client->setAccessType('offline'); // 获取访问令牌 try { $token = $client->fetchAccessTokenWithAssertion()['access_token']; // 建议把令牌缓存起来,比如存Redis或本地文件,避免每次请求都生成(有效期3600秒) // 示例:file_put_contents('fcm_token.cache', json_encode(['token' => $token, 'expires' => time() + 3600])); echo "获取令牌成功:" . $token; } catch (Exception $e) { die("获取令牌失败:" . $e->getMessage()); }
这里要注意:
- 权限范围绝对不能错,用其他范围会导致后续发送消息时权限不足
- 令牌有效期是1小时,一定要做缓存,不然频繁请求Google的认证服务会被限流
三、用令牌发送FCM消息示例
拿到令牌后,就可以调用FCM v1 API发送消息了,这里用curl做个简单示例:
<?php // 假设已经从缓存中拿到了令牌 $token = '你的访问令牌'; // FCM v1 API的端点,替换成你的项目ID $fcmEndpoint = 'https://fcm.googleapis.com/v1/projects/你的项目ID/messages:send'; // 构建消息体(这里是发送到单个设备的示例) $message = [ 'message' => [ 'token' => '目标设备的FCM令牌', 'notification' => [ 'title' => '测试标题', 'body' => '测试内容' ], 'data' => [ 'custom_key' => 'custom_value' ] ] ]; $ch = curl_init($fcmEndpoint); curl_setopt($ch, CURLOPT_HTTPHEADER, [ 'Authorization: Bearer ' . $token, 'Content-Type: application/json' ]); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); var_dump(json_decode($response, true));
四、我踩过的几个坑
- 服务账号权限不够:一开始只给了普通的Editor角色,结果发送消息时返回403,必须要给「Firebase Cloud Messaging Admin」角色
- 密钥文件权限问题:服务器上PHP进程没有读取密钥文件的权限,导致认证失败,记得给文件设置合理的权限(比如
chmod 600) - 令牌缓存失效:一开始没做缓存,频繁生成令牌被Google限流,后来加了Redis缓存就解决了
内容的提问来源于stack exchange,提问作者Jude Fernandes
相关产品推荐
相关产品推荐

