首页 > 解决方案 > 为 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" } 块引用

标签: phpfirebaseoauthfirebase-cloud-messagingtoken

解决方案


对于仍在寻找答案的任何人(2021 年),为了通过您自己的 PHP 系统向 Firebase 消息系统发送推送消息,您需要来自 Google 凭据的访问令牌。下面是如何做到这一点 - 请注意我只在 PHP Laravel 中完成了这个,而不是原始 PHP。但是您应该能够通过修改步骤以适应此问题(也与 Code Igniter 和其他 PHP 库相同)

  1. http://console.firebase.google.com的 project->settings->service accounts 下找到 Firebase 服务帐户。生成新的私钥并下载 json 文件。将其存储在用户无法访问的服务器上。

  2. 安装谷歌 API 客户端。对于 Laravel,这是:

      composer require google/apiclient --with-all-dependencies
    
  3. 打开 composer.json,并添加到自动加载数组。对于 Laravel,这是:

     "classmap": [
         "vendor/google/apiclient/src/Google"
     ],
    
  4. 创建一个新的服务类(如果是原生 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'];
    }
    
  5. 现在创建一个通过 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++。


推荐阅读