php Firebase HTTP v1 API不再批量发送?

6l7fqoea  于 2023-06-28  发布在  PHP
关注(0)|答案(1)|浏览(183)

我收到一封来自Google的电子邮件,通知我以下服务正在停用:
“将多个发送请求包含在发送给FCM的单个HTTP请求中,称为批量发送。”
建议的方法是:

  • 通过HTTP v1 API发送消息,该API已针对扇出性能进行了优化。*

在此页面上:
https://firebase.google.com/support/faq#fcm-23-deprecation
其中提到:
https://fcm.googleapis.com/batch
“* 对端点的请求将在2024年6月21日之后开始失败。*”
建议采取的行动是:

  • 迁移到标准HTTP v1 API发送方法,该方法支持HTTP/2进行多路复用。*

关于这件事我有个问题。
目前,我通过www.example.com使用PHP和cURL发送FCM消息fcm.googleapis.com/batch。由于明年将不再工作,我已经停止使用这种方法,现在我已经将消息发送过程放在foreach(while)循环中。这意味着,例如,如果我发送400条FCM消息,我将连续/行触发或联系以下URL 400次:
https://fcm.googleapis.com/v1/projects/my-app/messages:send
这是预期的行为而不是问题吗?我的项目已经使用HTTP/2。我只是想知道这是否是正确的方法,因为我无法想象它比分批或一次性发送更好。谢谢你的澄清。
如果你需要任何进一步的帮助,请告诉我。
下面是我的foreach代码:

foreach ($deviceTokens as $token) {
  $data = json_encode(array(
    "message" => array(
      "token" => $token,
      "notification" => array(
        "message_title" => "Test",
        "message_body" => "Test", 
        "website_link" => "example.com", 
        "notification_type" => "message",
        "image" => "example.com/test.jpg"
      )      
    )
  ));

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://fcm.googleapis.com/v1/projects/my-app/messages:send',
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => '',
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 0,
  CURLOPT_FOLLOWLOCATION => true,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => 'POST',
  CURLOPT_POSTFIELDS => $request,
  CURLOPT_HTTPHEADER => array(
    'Content-Type: multipart/mixed; boundary="subrequest_boundary"',
    'Authorization: Bearer ' . $accessToken 
  ),
));

$response = curl_exec($curl);
echo $response . '<br />';

curl_close($curl);
}
ubbxdtey

ubbxdtey1#

如果你想继续处理原始的cURL请求,你可以看看异步的curl_multi_*函数--说实话,我已经有一段时间没有直接使用cURL了,所以我只参考PHP docs,它也提供了一个使用示例,你可以把它用作模板。
但是,我建议采用的方法是使用google/auth PHP库,Guzzle HTTP Client进行身份验证并将请求发送到FCM API,Guzzle Promises异步执行请求。
为了使事情变得“更糟”,您不仅必须使用HTTP V1端点,还必须使用HTTP V1 FCM消息格式。下面的代码显示了您原始帖子中的消息将如何更改。
所以,下面是我如何在Composer的帮助下在一个脚本中从头开始:

# Initialize the project
mkdir myproject
cd myproject
composer require google/auth
<?php
# run.php

# This example uses Google Application Credentials exposed via the
# `GOOGLE_APPLICATION_CREDENTIALS` environment variable
# See https://github.com/googleapis/google-auth-library-php/blob/main/README.md
# for more alternative ways to authenticate requests

declare(strict_types=1);

require 'vendor/autoload.php';

use Google\Auth\ApplicationDefaultCredentials;
use GuzzleHttp\Client;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Promise;

### Create a Guzzle client that authenticates requests to the FCM API Endpoints

putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/credentials.json');

// https://developers.google.com/identity/protocols/oauth2/scopes#fcm
$scopes = [
    'https://www.googleapis.com/auth/cloud-platform',
    'https://www.googleapis.com/auth/firebase.messaging',
];

// create middleware
$middleware = ApplicationDefaultCredentials::getMiddleware($scopes);
$stack = HandlerStack::create();
$stack->push($middleware);

$client = new Client([
  'handler' => $stack,
  'auth' => 'google_auth'
]);

### Setup the messages

$deviceTokens = [/* ... */];
$messages = [];

foreach ($deviceTokens as $token) {
    $messages[] = [
        'token' => $token,
        'notification' => [
            'title' => 'Notification Title',
            'body' => 'Notification Body',
            'image' => 'https://example.com/test.jpg',
        ],
        'webpush' => [
            'fcm_options' => [
                'link' => 'https://example.com'
            ],
        ],
    ];
}

### Create message request promises

$promises = function() use ($client, $messages) {
    foreach ($messages as $message) {
        yield $client->requestAsync('POST', 'https://fcm.googleapis.com/v1/projects/my-app/messages:send', [
            'json' => ['message' => $message],
        ]);
    }
};

### Create response handler

$handleResponses = function (array $responses) {
    foreach ($responses as $response) {
        if ($response['state'] === Promise\PromiseInterface::FULFILLED) {
            // $response['value'] is an instance of \Psr\Http\Message\RequestInterface
            echo $response['value']->getBody();
        } elseif ($response['state'] === Promise\PromiseInterface::REJECTED) {
            // $response['reason'] is an exception
            echo $response['reason']->getMessage();
        }
    }
};

Promise\Utils::settle($promises())
    ->then($handleResponses)
    ->wait();

我用一个有效的和一个无效的注册令牌测试了这个脚本,得到了以下结果:

❯ php run.php
Client error: `POST https://fcm.googleapis.com/v1/projects/beste-firebase/messages:send` resulted in a `400 Bad Request` response:
{
  "error": {
    "code": 400,
    "message": "The registration token is not a valid FCM registration token",
    "stat (truncated...)
{
  "name": "projects/beste-firebase/messages/e39032c2-866d-4263-83e6-b1ce3770dfe6"
}

或者,如果您不想手动完成所有这些操作,也可以使用(非官方的)Firebase Admin PHP SDK,它在其最新的7.5.0版本中切换到这种方法。(免责声明:我是维护者,显然有偏见):

# Initialize the project
mkdir myproject
cd myproject
composer require kreait/firebase-php
<?php
# run.php

# Again, this example uses Google Application Credentials exposed via the
# `GOOGLE_APPLICATION_CREDENTIALS` environment variable. The SDK picks
# them up automatically.

declare(strict_types=1);

require 'vendor/autoload.php';

use Kreait\Firebase\Factory;

### Initialize FCM
putenv('GOOGLE_APPLICATION_CREDENTIALS=/path/to/my/credentials.json');
$fcm = (new Factory())->createMessaging();

### Setup the message (without target)

$deviceTokens = [/* ... */];
$message = [
    'notification' => [
        'title' => 'Notification Title',
        'body' => 'Notification Body',
        'image' => 'https://example.com/test.jpg',
    ],
    'webpush' => [
        'fcm_options' => [
            'link' => 'https://example.com'
        ],
    ],
];

### Send the message to the given tokens

$reports = $fcm->sendMulticast($message, $deviceTokens);

# https://firebase-php.readthedocs.io/en/stable/cloud-messaging.html#send-messages-to-multiple-devices-multicast
# goes more into detail what you can do with the reports

我希望这对你有帮助!

相关问题