如何用PHP和cURL通过FCM v1 API向多设备推送通知?
FCM v1 批量推送通知(PHP + cURL 实现)
FCM v1 API 不再支持旧版的 register_ids 参数,也没有直接的多Token批量字段,但可以通过HTTP批量请求实现一次性向多个设备发送推送,避免循环调用API。以下是具体实现方案:
1. 前置准备
- 从 Firebase 控制台下载服务账号 JSON 文件(项目设置 > 服务账号 > 生成新的私钥)
- 确保服务器能正常访问 Google 的 OAuth2 和 FCM API 端点
2. 核心实现代码
步骤1:获取 FCM v1 所需的 OAuth2 访问令牌
FCM v1 要求使用 Bearer 令牌认证,不再支持旧版 Server Key。以下函数通过服务账号生成临时令牌:
function getFcmAccessToken(string $serviceAccountPath): string { $serviceAccount = json_decode(file_get_contents($serviceAccountPath), true); $jwtHeader = base64_encode(json_encode(['alg' => 'RS256', 'typ' => 'JWT'])); $jwtPayload = base64_encode(json_encode([ 'iss' => $serviceAccount['client_email'], 'scope' => 'https://www.googleapis.com/auth/firebase.messaging', 'aud' => 'https://oauth2.googleapis.com/token', 'exp' => time() + 3600, 'iat' => time() ])); $signature = ''; openssl_sign($jwtHeader . '.' . $jwtPayload, $signature, $serviceAccount['private_key'], 'SHA256'); $jwt = $jwtHeader . '.' . $jwtPayload . '.' . base64_encode($signature); $ch = curl_init('https://oauth2.googleapis.com/token'); 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']; }
步骤2:构造批量推送请求并发送
将多个单设备推送请求打包成一个批量请求,每个请求用自定义分隔符分割:
function sendBatchFcmNotifications(string $accessToken, array $deviceTokens, array $notificationPayload): void { // 自定义批量请求分隔符,确保不会出现在请求内容中 $boundary = 'fcm-batch-boundary-' . uniqid(); $batchContent = ''; foreach ($deviceTokens as $token) { // 构造单个推送请求的合法结构 $singleRequest = [ 'message' => [ 'token' => $token, 'notification' => $notificationPayload, // 可选:添加自定义数据字段 // 'data' => ['order_id' => '123', 'status' => 'paid'] ] ]; // 拼接批量请求的单个部分 $batchContent .= "--{$boundary}\r\n"; $batchContent .= "Content-Type: application/http\r\n"; $batchContent .= "Content-Transfer-Encoding: binary\r\n\r\n"; $batchContent .= "POST /v1/projects/YOUR_PROJECT_ID/messages:send HTTP/1.1\r\n"; $batchContent .= "Content-Type: application/json\r\n\r\n"; $batchContent .= json_encode($singleRequest) . "\r\n\r\n"; } // 结束批量请求的边界标记 $batchContent .= "--{$boundary}--"; // 发送批量请求 $ch = curl_init('https://fcm.googleapis.com/batch'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, [ "Authorization: Bearer {$accessToken}", "Content-Type: multipart/mixed; boundary={$boundary}" ]); curl_setopt($ch, CURLOPT_POSTFIELDS, $batchContent); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $response = curl_exec($ch); // 处理响应(可根据需求添加错误判断) if (curl_errno($ch)) { echo 'CURL Error: ' . curl_error($ch); } else { // 批量响应包含每个请求的独立结果,可解析后处理失败的推送 echo 'Batch Response: ' . $response; } curl_close($ch); }
步骤3:调用示例
// 替换为你的服务账号文件路径 $serviceAccountPath = '/path/to/your/service-account.json'; // 替换为你的 Firebase 项目ID $projectId = 'your-firebase-project-id'; // 目标设备Token列表 $deviceTokens = [ 'token_xxxxxx1', 'token_xxxxxx2', 'token_xxxxxx3' ]; // 推送通知内容 $notification = [ 'title' => '批量推送测试', 'body' => '这是FCM v1批量推送的消息内容' ]; $accessToken = getFcmAccessToken($serviceAccountPath); sendBatchFcmNotifications($accessToken, $deviceTokens, $notification);
3. 常见问题解决
- Schema错误:确保每个单请求的
message结构符合FCM v1规范,必须包含token字段,notification的title/body不能为空,避免JSON语法错误(比如逗号遗漏、引号不匹配)。 - 批量请求限制:FCM批量请求最多包含500个单推送请求,如果Token数量超过500,需要将列表分批处理。
- 令牌过期:访问令牌有效期为1小时,建议缓存令牌,避免每次请求都重新生成。
内容的提问来源于stack exchange,提问作者labu77
相关产品推荐
相关产品推荐

