使用PHP发送Firebase推送通知时遭遇401认证错误求助
解决FCM推送401认证错误问题
错误原因
你当前使用的是FCM v1 API端点,但错误地将Firebase Server Key作为Bearer令牌使用。FCM v1 API不支持这种认证方式,它要求使用OAuth2访问令牌;而旧版Legacy FCM API才支持直接用Server Key认证。
解决方案1:切换到Legacy FCM API(快速实现)
修改代码如下,适配Legacy API的认证规则和消息格式:
<?PHP if ($_SERVER['REQUEST_METHOD'] === 'POST') { // 获取表单数据 $topic = $_POST['topic']; $title = $_POST['title']; $body = $_POST['body']; $imageURL = $_POST['image_url']; // 数据验证 if (empty($topic) || empty($title) || empty($body)) { die('错误:所有必填字段不能为空。'); } // Firebase Server Key $serverKey = 'your_server_key'; // Legacy FCM API端点 $url = 'https://fcm.googleapis.com/fcm/send'; // 构造Legacy API格式的消息 $message = [ 'to' => "/topics/{$topic}", // 话题格式需改为/topics/xxx 'notification' => [ 'title' => $title, 'body' => $body, ], ]; // 添加图片数据(如果存在) if (!empty($imageURL)) { $message['data']['image_url'] = $imageURL; } // 修改认证头格式 $headers = [ 'Authorization: key=' . $serverKey, // 改为key=前缀 'Content-Type: application/json', ]; // 初始化cURL $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message)); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // 执行请求并输出响应 $response = curl_exec($ch); curl_close($ch); echo $response; } else { header('Location: index.php'); exit(); } ?>
解决方案2:使用FCM v1 API并正确认证(推荐)
若要继续使用FCM v1 API,需通过Firebase服务账号生成合法的OAuth2访问令牌,步骤如下:
- 登录Firebase控制台,进入项目→项目设置→服务账号→点击「生成新的私钥」,下载JSON密钥文件。
- 使用Google API客户端库生成访问令牌,示例代码如下:
首先安装依赖:
composer require google/apiclient
修改后的PHP代码:
<?PHP require_once __DIR__ . '/vendor/autoload.php'; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $topic = $_POST['topic']; $title = $_POST['title']; $body = $_POST['body']; $imageURL = $_POST['image_url']; if (empty($topic) || empty($title) || empty($body)) { die('错误:所有必填字段不能为空。'); } // 加载服务账号密钥文件 $client = new Google_Client(); $client->setAuthConfig('path/to/your-service-account-file.json'); $client->addScope('https://www.googleapis.com/auth/firebase.messaging'); $client->refreshTokenWithAssertion(); $accessToken = $client->getAccessToken(); // FCM v1 API端点 $projectId = 'your_project_id'; $url = "https://fcm.googleapis.com/v1/projects/{$projectId}/messages:send"; // 构造FCM v1格式的消息 $message = [ 'message' => [ 'topic' => $topic, 'notification' => [ 'title' => $title, 'body' => $body, ], ], ]; if (!empty($imageURL)) { $message['message']['data']['image_url'] = $imageURL; } $headers = [ 'Authorization: Bearer ' . $accessToken['access_token'], 'Content-Type: application/json', ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message)); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); curl_close($ch); echo $response; } else { header('Location: index.php'); exit(); } ?>
内容的提问来源于stack exchange,提问作者Ibrahim Tinku
相关产品推荐
相关产品推荐

