使用PHP调用FCM HTTP v1 API时遇非法/格式错误请求问题
问题根源与解决方案
你的核心问题是Authorization请求头的用法完全错误——FCM HTTP v1 API要求的Bearer令牌是通过服务账号私钥生成的OAuth2访问令牌,不是直接把私钥文件的内容填进去。
推荐解决方案:使用Firebase Admin PHP SDK(最省心)
- 先安装SDK:
composer require kreait/firebase-php
- 替换你的代码为以下正确实现:
<?php require __DIR__.'/vendor/autoload.php'; use Kreait\Firebase\Factory; use Kreait\Firebase\Messaging\CloudMessage; use Kreait\Firebase\Messaging\Notification; $serviceAccountKeyFile = 'C:\Users\Yaz\Downloads\<projectName>-f8312-65996b5966ea.json'; // 初始化Firebase实例,SDK会自动处理令牌生成 $factory = (new Factory)->withServiceAccount($serviceAccountKeyFile); $messaging = $factory->createMessaging(); // 构建推送消息 $message = CloudMessage::withTarget('token', 'fH8TwZfXQniUvF6aYqbTOu:APA91bH-uLHe3-e9-3N_Szu6bHwKbA4voAog1mzTVbOyFDUGjwZpZe8XUB2-FF0YD2StieCdvU1gtmNN4cg-ILyb6DFh1SrZhBfHZkMQUcPc6FsINaE38iLq8xhG-ankRPE0ifVmEDij') ->withNotification(Notification::create('Your Notification Title', 'Your Notification Body')); // 发送通知并处理结果 try { $response = $messaging->send($message); echo "通知发送成功:{$response}"; } catch (Exception $e) { echo "发送失败:{$e->getMessage()}"; }
手动生成令牌方案(适合理解原理,不推荐)
如果不想依赖SDK,需要自己完成令牌生成流程:
- 从私钥JSON文件中提取
client_email和private_key字段 - 用RS256算法生成JWT,Payload需包含:
iss: 上述client_emailscope:https://www.googleapis.com/auth/firebase.messagingaud:https://oauth2.googleapis.com/tokenexp: 当前时间戳 + 3600(令牌有效期1小时)iat: 当前时间戳
- 向
https://oauth2.googleapis.com/token发送POST请求,请求体为grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&assertion=生成的JWT,获取返回的access_token - 将该
access_token作为Bearer值填入Authorization头,再请求FCM发送接口
为什么你之前的尝试无效?
- Guzzle报错是因为Authorization头里塞的是私钥文件内容,不是合法的OAuth2令牌,导致请求头格式非法
- 新建服务账号无法解决问题,因为错误根源不是私钥本身,而是你完全误解了私钥的使用方式——私钥是生成令牌的凭证,不是令牌本身
内容的提问来源于stack exchange,提问作者sigma lab
相关产品推荐
相关产品推荐

