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 不再批量发送? 的相关文章

  • openssl_pkey_get_details($res) 不返回公共指数

    我在用着这个例子 https stackoverflow com a 12575951 2016196使用 php 生成的密钥进行 javascript 加密openssl图书馆 但是 details openssl pkey get de
  • 搜索引擎如何找到相关内容? [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 Google 在解析网络时如何找到相关内容 例如 Google 使用 PHP 原生 DOM 库来解析内
  • 当数据验证失败时保留表单字段中的值

    我在弄清楚验证失败时如何保留用户数据时遇到问题 我对 PHP 有点陌生 所以我的逻辑可能会犯一些巨大的错误 目前 如果验证失败 所有字段都会被清除 并且 Post 数据也会消失 这是一些代码 假设用户输入无效电子邮件 我希望保留 名称 字段
  • 重定向而不改变url

    我总是不喜欢 htaccess 我正在尝试建立一个所有请求都通过index php 的网站 但我希望URL 类似于www sample com home 该网址实际上会加载 www sample com index php page hom
  • 优雅地处理没有数据的 amcharts

    我想知道我的 dataProvider 是否为空 amCharts绘制时默认为null 我怎样才能动态地处理它 var chart AmCharts makeChart chartdiv theme none type serial dat
  • 如何检查PHP变量是否包含非数字?

    我只是想知道检查 PHP 变量中是否有非数字的方法以及它是否也检测字符之间的空格 需要确保我的表单字段中没有添加任何奇怪的内容 提前致谢 如果您的意思是您只想要一个包含数字的值 那么您可以使用ctype digit http php net
  • PHP MySQL 使用选项/选择 HTML 表单标签进行多重搜索查询

    我正在尝试使用两个搜索字段设置基本的 MySQL LIKE 搜索 我不想拥有它 所以它有多个可选搜索字段 例如if isset POST city isset POST name 我不知道如何用 HTML 来做到这一点
  • FPDI/FPDF:水印和打印多页

    我修改了这个堆栈问题 当用户尝试下载文件时在 pdf 文件上应用水印 https stackoverflow com questions 3983432 applying watermarks on pdf files when users
  • 检查 PHP 中“@”字符后面的单词

    我现在正在制作一个新闻和评论系统 但是我已经在一个部分上停留了一段时间了 我希望用户能够在 Twitter 上引用其他玩家的风格 例如 用户名 该脚本看起来像这样 不是真正的 PHP 只是想象脚本 3 string I loved the
  • Firebase 托管部署失败

    Running firebase deploy在给我一个超时错误之前会运行几分钟Error ESOCKETTIMEDOUT 我之前已经成功部署了多次 除了项目的前端 用 React 编写 之外 没有更改任何内容 我有一个单独的文件夹 其中包
  • 如何使用 php 发送服务器错误响应?

    一旦用户点击删除按钮我的 jQuery 脚本要求服务器删除所选项目 现在我想要我的php发送成功或错误响应的脚本 是否有可能触发错误回调万一该项目无法删除 Thanks 我的 jQuery 代码 ajax type post url myA
  • posts_search 中的自定义查询

    如何使用此查询作为我的自定义搜索查询 add filter posts search my search is perfect 20 2 function my search is perfect search wp query sWord
  • 扩展蓝图类?

    我想覆盖timestamps 函数中发现Blueprint班级 我怎样才能做到这一点 e g public function up Schema create users function Blueprint table table gt
  • 使用 preg_replace 仅替换第一个匹配项

    我有一个结构类似于以下的字符串 aba aaa cba sbd dga gad aaa cbz 该字符串每次都可能有点不同 因为它来自外部源 我只想替换第一次出现的 aaa 但其他人则不然 是否可以 可选的第四个参数预替换 http php
  • 学说迁移后备

    我们正在使用原则迁移 当迁移包含多个操作并且其中一个操作失败时 通常会出现问题 例如 如果迁移添加了 5 个外键 其中第 5 个失败 而字段长度不同 则修复字段错误并重新生成迁移不会not修复整个问题 而现在出现一个与 4 个密钥已存在有关
  • preg_match_all 查询仅显示有问题的外部组

    我无法弄清楚如何只显示 preg 查询的外部组级别 我会给你一个例子 preg match all start end input matches 这个输入start1 start2 2end 1end产生这个输出start1 start2
  • 从 .phar 存档中提取文件

    对于 Phar 文件 我完全错过了一些东西 我正在安装一个需要 phpunit pdepend 和其他依赖项的项目 我将它们作为 phar 文件获取 但是 我无法使用命令行工具 php 命令 从中提取文件 我用谷歌搜索了这个问题 但没有发现
  • 如何在 PHP 中从 IP 地址/国家/地区名称查找时区 ID?

    谁能告诉我 PHP 中是否有任何方法可以从 IP 地址或国家 地区名称获取时区区域 例如 亚洲 加尔各答 描述 我正在尝试根据他 她的国家 地区设置用户时区 我从他的 IP 地址获取用户所在国家 地区 但我需要该国家 地区的时区区域 例如
  • 没有用于警告的设置器/字段 Firebase 数据库检索数据填充列表视图

    我只是想将 Firebase 数据库中的数据填充到我的列表视图中 日志显示正在检索数据 但适配器不会将值设置为列表中单个列表项中的文本 它只说 没有二传手 场地插入值 这让我觉得我的设置器没有正确制作 但 Android Studio 自动
  • 为什么 Composer 降级了我的包?

    php composer phar update这样做了 删除了 2 3 0 软件包并安装了整个 2 2 5 Zend Framework php composer phar update Loading composer reposito

随机推荐