使用cURL在v1 API中向多个设备发送FCM推送

huangapple go评论85阅读模式
英文:

Send Push FCM to multiple devices with cURL in v1 API

问题

我需要将 FCM 推送通知发送到多个设备。我不能使用 "topics",因为我需要将通知发送到特定的多个令牌。

在旧的方法中,我使用 "register_ids" 来实现这个目的,但是谷歌在2023年6月20日宣布,旧的方法将在2024年6月20日停止支持。在新的 v1 API 中,不再支持 "register_ids"。

我需要的是使用 cURL 和 PHP 发送推送通知到多个令牌的解决方案。

在这个网站上,有人提出了与我的问题类似的问题:

https://stackoverflow.com/questions/73717105/fcm-batch-messages-url

@Frank van Puffelen 说:

"在这个新的、版本化的 API 中,您可以通过向常规端点发送多部分请求来发送多条消息。这个过程在发送批量消息的部分中得到了充分的文档支持,而且大多数可用的 Admin SDK 也都支持这个过程。"

Frank von Puffelen 提供了一个链接:

https://firebase.google.com/docs/cloud-messaging/send-message#send-a-batch-of-messages

然而,现在这个网站上有一个注释:

"这一部分描述的批量发送方法已于2023年6月21日被弃用,将在2024年6月被移除。相反,请使用标准的HTTP v1 API发送方法,通过实现自己的批量发送逻辑,迭代遍历接收者列表并发送给每个接收者的令牌。对于 Admin SDK 方法,请确保更新到下一个主要版本。"

在网站的更上面,有一个标题为 "向多个设备发送消息" 的部分。然而,这一部分只提供了 node.js、Java、Python、Go、C# 和 REST 的解决方案。我需要一个适用于 PHP 和 cURL 的解决方案。

到目前为止,我尝试过的方法如下,但由于模式错误而无法正常工作:

$tokens = array(
    "token 1",
    "token 2"
);

foreach ($tokens as $token) {
    $data = json_encode(array(
        "message" => array(
            "token" => $token,
            "notification" => array(
                "title" => "New Message",
                "body" => "New Text",
                "image" => "https://example.com/test.jpg"
            ),
            "data" => array(
                "website_link" => "https://example.com/",
                "icon" => "https://example.com/test.jpg"
            )
        )
    ));

    $accessToken = file_get_contents("access_token.txt");

    curl_setopt_array($curl, array(
        CURLOPT_URL => 'https://fcm.googleapis.com/v1/projects/myapp/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 => $data,
        CURLOPT_HTTPHEADER => array(
            'Content-Type: application/json',
            'Authorization: Bearer ' . $accessToken
        ),
    ));
}

$response = curl_exec($curl);

我知道我可以为每个令牌循环使用 cURL 代码,但我认为这不是一个好的做法,因为它会多次触发 "https://fcm.googleapis.com/v1/projects/myapp/messages:send"。

我更希望一次性收集所有令牌并发送它们。是否有解决方案?

非常感谢。

英文:

I need to send FCM push notifications to multiple devices. I cannot use "topics" for that because I need to send it to specific and multiple tokens.

In the legacy method, I used "register_ids" for this purpose, but Google announced on June 20, 2023, that the legacy method will end on June 20, 2024. In the new v1 API, "register_ids" is no longer supported.

What I need is a solution to send push notifications to multiple tokens using cURL and PHP.

On this website, someone asked a similar question to mine:

https://stackoverflow.com/questions/73717105/fcm-batch-messages-url

@Frank van Puffelen said:

"In this new, versioned API, you can send multiple messages by sending a multi-part request to the regular endpoint. This process is fully documented in the section on sending a batch of messages and is also supported by most of the available Admin SDKs."

Frank von Puffelen provided a link:

https://firebase.google.com/docs/cloud-messaging/send-message#send-a-batch-of-messages

However, there is now a note on this website stating:

"The batch send methods described in this section were deprecated on June 21, 2023, and will be removed in June 2024. Instead, use the standard HTTP v1 API send method by implementing your own batch send logic, iterating through the list of recipients and sending to each recipient's token. For Admin SDK methods, make sure to update to the next major version."

Further up on that website, there is a section titled "Send messages to multiple devices." However, this section only provides solutions for node.js, Java, Python, Go, C#, and REST. I need a solution for PHP and cURL.

What I have tried so far is as follows, but it is not working because of error with the schema:

$tokens = array(
"token 1",
"token 2"
);

foreach ($tokens as $token) {
$data = json_encode(array(
"message" => array(
"token" => $token,
"notification" => array(
"title" => "New Message",
"body" => "New Text",
"image" => "https://example.com/test.jpg"
),
"data" => array(
"website_link" => "https://example.com/",
"icon" => "https://example.com/test.jpg"
)
)
));

$accessToken = file_get_contents("access_token.txt");

curl_setopt_array($curl, array(
CURLOPT_URL => 'https://fcm.googleapis.com/v1/projects/myapp/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 => $data,
CURLOPT_HTTPHEADER => array(
'Content-Type: application/json',
'Authorization: Bearer ' . $accessToken
),
));
}

$response = curl_exec($curl);

I know I can loop the cURL code for each token, but I believe this is not a good practice because it would trigger the "https://fcm.googleapis.com/v1/projects/myapp/messages:send" multiple times in a row.

I would prefer to collect all the tokens and send them at once. Is there a solution?

Thank you very much.

答案1

得分: 1

我已找到一个解决方案,希望能节省某人的时间。

编辑:很抱歉,但这个解决方案明年也将被弃用。请查看以下主题,其中提供了一个新的解决方案:

https://stackoverflow.com/questions/76563436/firebase-http-v1-api-and-no-batch-send-anymore

请查看此网站上的“向多个设备发送消息”部分:

https://firebase.google.com/docs/cloud-messaging/send-message#send-messages-to-multiple-devices

重点关注REST部分。

使用这个示例,我在相同的REST API架构中实现了一个foreach循环。在这种情况下,您不需要一个名为cURL的batch_request.txt文件。

代码中唯一需要的是您的设备令牌数组和Bearer访问令牌。要获取访问令牌,我在Peter Bruins的这个PHP函数中找到了:

https://stackoverflow.com/questions/74192530/generating-access-token-for-firebase-messaging

请确保更改代码的以下部分以匹配您的应用程序名称:

$request .= "POST /v1/projects/your-app/messages:send\r\n";

以下是PHP cURL FCM v1 API解决方案:

$deviceTokens = 'yourarrayoftokens';

foreach ($deviceTokens as $token) {
  $request .= "\r\n--subrequest_boundary\r\n";
  $request .= "Content-Type: application/http\r\n";
  $request .= "Content-Transfer-Encoding: binary\r\n\r\n";
  $request .= "POST /v1/projects/your-app/messages:send\r\n";
  $request .= "Content-Type: application/json\r\n";
  $request .= "accept: application/json\r\n\r\n";
  $request .= '{
    "message":{
       "token":"' . $token . '",
       "notification":{
         "title":"FCM Push Test",
         "body":"This is only a test",
         "image":"http://example.com/1.jpg"
       }
    }
}';
}

$request .= "\r\n\r\n--subrequest_boundary--";

$curl = curl_init();

$accessToken = file_get_contents("bearer_token.txt");

curl_setopt_array($curl, array(
  CURLOPT_URL => 'https://fcm.googleapis.com/batch',
  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 />';

我希望"https://fcm.googleapis.com/batch"不会在不久的将来被弃用。根据我的理解,唯一需要更改的是将"https://fcm.googleapis.com/send"替换为"/v1/projects/your-app/messages:send",而"https://fcm.googleapis.com/batch"仍然可以使用。如果我错了,请纠正我。Google建议使用这个解决方案,并在他们的官方文档中提供了它作为推荐方法。(请参见以下行末尾的URL)

curl --data-binary @batch_request.txt -H 'Content-Type: multipart/mixed; boundary="subrequest_boundary"' -H 'Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA' https://fcm.googleapis.com/batch

如果有人需要一个数据foreach而不是通知,可以使用以下foreach:

foreach ($deviceTokens as $token) {
  $request .= "\r\n--subrequest_boundary\r\n";
  $request .= "Content-Type: application/http\r\n";
  $request .= "Content-Transfer-Encoding: binary\r\n\r\n";
  $request .= "POST /v1/projects/my-app/messages:send\r\n";
  $request .= "Content-Type: application/json\r\n";
  $request .= "accept: application/json\r\n\r\n";
  $request .= '{
    "message":{
       "token":"' . $token . '",
       "data":{
         "message_title":"Test",
         "message_body":"Test",
         "website_link":"example.com", 
         "notification_type":"message",
         "image":"example.com/1.jpg"
       }
    }
}';
}
英文:

I have found a solution and I hope it will save someone's time.

Edit: Sorry to say, but this solution will also be deprecated next year. See this topic with a new solution:

https://stackoverflow.com/questions/76563436/firebase-http-v1-api-and-no-batch-send-anymore

Please check the section "Send messages to multiple devices" on this website:

https://firebase.google.com/docs/cloud-messaging/send-message#send-messages-to-multiple-devices

Focus on the REST part.

Using this example, I have implemented a foreach loop in the same REST API schema. In this case, you don't need a batch_request.txt file for cURL.

The only things you need for the code are your array of device tokens and the bearer access token. To obtain the access token, I found this PHP function from Peter Bruins:

https://stackoverflow.com/questions/74192530/generating-access-token-for-firebase-messaging

Make sure to change the following part of the code to match your app name:

$request .= &quot;POST /v1/projects/your-app/messages:send\r\n&quot;;

Here is the PHP cURL FCM v1 API solution:

$deviceTokens = &#39;yourarrayoftokens&#39;;

foreach ($deviceTokens as $token) {
  $request .= &quot;\r\n--subrequest_boundary\r\n&quot;;
  $request .= &quot;Content-Type: application/http\r\n&quot;;
  $request .= &quot;Content-Transfer-Encoding: binary\r\n\r\n&quot;;
  $request .= &quot;POST /v1/projects/your-app/messages:send\r\n&quot;;
  $request .= &quot;Content-Type: application/json\r\n&quot;;
  $request .= &quot;accept: application/json\r\n\r\n&quot;;
  $request .= &#39;{
    &quot;message&quot;:{
       &quot;token&quot;:&quot;&#39; . $token . &#39;&quot;,
       &quot;notification&quot;:{
         &quot;title&quot;:&quot;FCM Push Test&quot;,
         &quot;body&quot;:&quot;This is only a test&quot;,
         &quot;image&quot;:&quot;http://example.com/1.jpg&quot;
       }
    }
}&#39;;
}

$request .= &quot;\r\n\r\n--subrequest_boundary--&quot;;

$curl = curl_init();

$accessToken = file_get_contents(&quot;bearer_token.txt&quot;);

curl_setopt_array($curl, array(
  CURLOPT_URL =&gt; &#39;https://fcm.googleapis.com/batch&#39;,
  CURLOPT_RETURNTRANSFER =&gt; true,
  CURLOPT_ENCODING =&gt; &#39;&#39;,
  CURLOPT_MAXREDIRS =&gt; 10,
  CURLOPT_TIMEOUT =&gt; 0,
  CURLOPT_FOLLOWLOCATION =&gt; true,
  CURLOPT_HTTP_VERSION =&gt; CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST =&gt; &#39;POST&#39;,
  CURLOPT_POSTFIELDS =&gt; $request,
  CURLOPT_HTTPHEADER =&gt; array(
    &#39;Content-Type: multipart/mixed; boundary=&quot;subrequest_boundary&quot;&#39;,
    &#39;Authorization: Bearer &#39; . $accessToken 
  ),
));

$response = curl_exec($curl);
echo $response . &#39;&lt;br /&gt;&#39;;

I hope that "https://fcm.googleapis.com/batch" will not be deprecated in the near future. From my understanding, the only change required is replacing "https://fcm.googleapis.com/send" with "/v1/projects/your-app/messages:send", while "https://fcm.googleapis.com/batch" can still be used. Please correct me if I am wrong. Google recommends this solution and has provided it as a recommended approach in their official documentation. (see the url at the end of the following line)

curl --data-binary @batch_request.txt -H &#39;Content-Type: multipart/mixed; boundary=&quot;subrequest_boundary&quot;&#39; -H &#39;Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA&#39; https://fcm.googleapis.com/batch

If someone need a data foreach instead of notification, take this foreach:

foreach ($deviceTokens as $token) {
  $request .= &quot;\r\n--subrequest_boundary\r\n&quot;;
  $request .= &quot;Content-Type: application/http\r\n&quot;;
  $request .= &quot;Content-Transfer-Encoding: binary\r\n\r\n&quot;;
  $request .= &quot;POST /v1/projects/my-app/messages:send\r\n&quot;;
  $request .= &quot;Content-Type: application/json\r\n&quot;;
  $request .= &quot;accept: application/json\r\n\r\n&quot;;
  $request .= &#39;{
    &quot;message&quot;:{
       &quot;token&quot;:&quot;&#39; . $token . &#39;&quot;,
       &quot;data&quot;:{
         &quot;message_title&quot;:&quot;Test&quot;,
         &quot;message_body&quot;:&quot;Test&quot;,
         &quot;website_link&quot;:&quot;example.com&quot;, 
         &quot;notification_type&quot;:&quot;message&quot;,
         &quot;image&quot;:&quot;example.com/1.jpg&quot;
       }
    }
}&#39;;
}

huangapple
  • 本文由 发表于 2023年6月22日 15:20:11
  • 转载请务必保留本文链接:https://go.coder-hub.com/76529438.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定