Firebase HTTP v1 API 不再批量发送?

2023-12-25

我收到了一封来自 Google 的电子邮件,通知我以下服务即将停用:

“在对 FCM 的单个 HTTP 请求中包含多个发送请求,称为批量发送。”

推荐的方法是:

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

在本页面:

https://firebase.google.com/support/faq#fcm-23-deprecation https://firebase.google.com/support/faq#fcm-23-deprecation

其中提到:

https://fcm.googleapis.com/batch https://fcm.googleapis.com/batch

"2024 年 6 月 21 日之后,对端点的请求将开始失败。"

建议采取的行动是:

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

现在,我对此事有一个疑问。

目前,我使用 PHP 和 cURL 通过 fcm.googleapis.com/batch 发送 FCM 消息。由于明年这将不再起作用,所以我已经停止使用这种方法,现在我将消息发送过程放在 foreach (while) 循环中。这意味着,例如,如果我发送 400 条 FCM 消息,我将连续/行触发或联系以下 URL 400 次:

https://fcm.googleapis.com/v1/projects/my-app/messages:发送 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);
}

如果您想继续原始 cURL 请求,您可以查看异步curl_multi_*函数 - 说实话,我已经有一段时间没有直接使用 cURL 了,所以我只参考PHP docs https://www.php.net/manual/en/function.curl-multi-init.php它还提供了一个可以用作模板的用法示例。

但是,我建议采取的方法是使用google/auth https://github.com/googleapis/google-auth-library-phpPHP 库,Guzzle HTTP 客户端 https://docs.guzzlephp.org/en/stable/验证并向 FCM API 发送请求,以及狂饮的承诺 https://github.com/guzzle/promises异步执行请求。

为了让事情变得“更糟”,您不仅必须使用 HTTP V1 端点,还必须使用HTTP V1 FCM 消息格式 https://firebase.google.com/docs/reference/fcm/rest/v1/projects.messages#Message以及。下面的代码显示了原始帖子中的消息将如何更改。

因此,以下是我如何在单个脚本的帮助下从头开始执行此操作Composer https://getcomposer.org:

# 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 管理 PHP SDK https://github.com/kreait/firebase-php,切换到这种确切的方法 在最新的 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

我希望这有帮助!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Firebase HTTP v1 API 不再批量发送? 的相关文章

随机推荐