php - 为 Firebase 云消息传递 PHP 生成 OAUTH 令牌
问题描述
我有一个 PHP 页面,我用来向我开发的移动应用程序的用户发送通知,这个页面直到上个月都可以正常工作,然后它给了我这个错误
{"multicast_id":5174063503598899354,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"InvalidRegistration"}]}
我尝试使用此链接 https://firebase.google.com/docs/cloud-messaging/auth-server#node.js中的文档生成 OAUTH 令牌, 但它需要 NODE.JS 服务器并且我的服务器不支持 Node .Js ,我尝试使用 Firebase Admin SDK 但找不到任何东西。这是页面的PHP代码
<?php
//Includes the file that contains your project's unique server key from the Firebase Console.
require_once("serverKeyInfo.php");
//Sets the serverKey variable to the googleServerKey variable in the serverKeyInfo.php script.
$serverKey = $googleServerKey;
//URL that we will send our message to for it to be processed by Firebase.
$url = "https://fcm.googleapis.com/fcm/send";
//Recipient of the message. This can be a device token (to send to an individual device)
//or a topic (to be sent to all devices subscribed to the specified topic).
$recipient = $_POST['rec'];
//Structure of our notification that will be displayed on the user's screen if the app is in the background.
$notification =array(
'title' => $_POST['title'],
'body' => $_POST['body'],
'sound' => 'default'
);
//Structure of the data that will be sent with the message but not visible to the user.
//We can however use Unity to access this data.
$dataPayload =array(
"powerLevel" => "9001",
"dataString" => "This is some string data"
);
//Full structure of message inculding target device(s), notification, and data.
$fields =array(
'to' => $recipient,
'notification' => $notification,
'data' => $dataPayload
);
//Set the appropriate headers
$headers = array(
'Authorization: key=' . $serverKey,
'Content-Type: application/json'
);
//Send the message using cURL.
$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_SSL_VERIFYPEER, false );
curl_setopt( $ch,CURLOPT_POSTFIELDS, json_encode( $fields ) );
$result = curl_exec($ch );
curl_close( $ch );
//Result is printed to screen.
echo $result;
?>
谁能给我一个例子,我该怎么做(我是PHP的初学者)提前谢谢
*更新:我也尝试将代码中的 $url 更改为
$url = "https://fcm.googleapis.com/v1/projects/notifications-9ccdd/messages:send";
但它给了我这个错误
"error": { "code": 401, "message": "请求具有无效的身份验证凭据。预期的 OAuth 2 访问令牌、登录 cookie 或其他有效的身份验证凭据。请参阅https://developers.google.com/identity/sign -in/web/devconsole-project。” , "status": "UNAUTHENTICATED" } 块引用
解决方案
对于仍在寻找答案的任何人(2021 年),为了通过您自己的 PHP 系统向 Firebase 消息系统发送推送消息,您需要来自 Google 凭据的访问令牌。下面是如何做到这一点 - 请注意我只在 PHP Laravel 中完成了这个,而不是原始 PHP。但是您应该能够通过修改步骤以适应此问题(也与 Code Igniter 和其他 PHP 库相同)
在http://console.firebase.google.com的 project->settings->service accounts 下找到 Firebase 服务帐户。生成新的私钥并下载 json 文件。将其存储在用户无法访问的服务器上。
安装谷歌 API 客户端。对于 Laravel,这是:
composer require google/apiclient --with-all-dependencies
打开 composer.json,并添加到自动加载数组。对于 Laravel,这是:
"classmap": [ "vendor/google/apiclient/src/Google" ],
创建一个新的服务类(如果是原生 PHP,则创建一个新的类),并添加以下方法来检索访问令牌:
private function getGoogleAccessToken(){ $credentialsFilePath = 'the-folder-and-filename-of-your-downloaded-service-account-file.json'; //replace this with your actual path and file name $client = new \Google_Client(); $client->setAuthConfig($credentialsFilePath); $client->addScope('https://www.googleapis.com/auth/firebase.messaging'); $client->refreshTokenWithAssertion(); $token = $client->getAccessToken(); return $token['access_token']; }
现在创建一个通过 CURL 将所有消息信息发送到 Firebase 的方法:
public function sendMessage(){ $apiurl = 'https://fcm.googleapis.com/v1/projects/your-project-id/messages:send'; //replace "your-project-id" with...your project ID $headers = [ 'Authorization: Bearer ' . $this->getGoogleAccessToken(), 'Content-Type: application/json' ]; $notification_tray = [ 'title' => "Some title", 'body' => "Some content", ]; $in_app_module = [ "title" => "Some data title (optional)", "body" => "Some data body (optional)", ]; //The $in_app_module array above can be empty - I use this to send variables in to my app when it is opened, so the user sees a popup module with the message additional to the generic task tray notification. $message = [ 'message' => [ 'notification' => $notification_tray, 'data' => $in_app_module, ], ]; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $apiurl); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($message)); $result = curl_exec($ch); if ($result === FALSE) { //Failed die('Curl failed: ' . curl_error($ch)); } curl_close($ch); }
Google 建议您仅在无法将 JSON 文件作为环境变量直接添加到服务器上时才使用此方法。我不知道为什么谷歌没有关于这个主题的更好的 PHP 文档,它似乎更喜欢 node.js、Go、Java 和 C++。
推荐阅读
- c# - 如何在 WPF 应用程序中设置线程的 DPI_AWARENESS_CONTEXT?
- asp.net - WCF MessageContract 的参数未从 SSRS 正确发送
- android - 非ui线程的领域使用
- python - PyQt5 - 为每个按钮点击打开新的图像窗口
- reactjs - 根据标签大小设置材质UI选择的宽度
- python - 将参数和变量从装饰器传递给 Python 中的函数
- python - 为什么我的 for 循环运行次数超过我指定的次数?
- php - 无法让 Zend 在 Windows 7 上使用 PHP
- c++ - C ++将两个不同类型的向量的属性连接到新向量中
- javascript - 无法使用 jquery 重定向到页面