如何在不使用 Firebase 控制台的情况下发送 Firebase 云消息通知?

257

我正在使用新的Google通知服务Firebase Cloud Messaging

借助于这个代码https://github.com/firebase/quickstart-android/tree/master/messaging,我可以从我的Firebase用户控制台向我的Android设备发送通知。

是否有任何API或方法可以在不使用Firebase控制台的情况下发送通知?我的意思是,例如,一个PHP API或类似的东西,以直接从自己的服务器创建通知。


1
你将服务器托管在哪里以发送通知? - Rodrigo Ruiz
@David Corral,请检查我的答案是否正确。 https://dev59.com/DJffa4cB1Zd3GeqP6VaR#38992689 - Sandeep Devhare
已编写了一个Spring应用程序,用于发送FCM通知,如果您想查看它的工作原理-> https://github.com/aniket91/WebDynamo/blob/master/src/com/osfg/controllers/FCMSender.java - Aniket Thakur
你可以使用Retrofit来实现设备到设备的消息传递。https://dev59.com/0VoU5IYBdhLWcg3wc2xW#41913555 - eurosecom
阅读此博客文章以获取更多详细信息:http://developine.com/how-to-send-firebase-push-notifications-from-app-server-tutorial/ - Developine
显示剩余2条评论
17个回答

281

Firebase Cloud Messaging 具有服务器端 API,您可以调用它来发送消息。请参阅 https://firebase.google.com/docs/cloud-messaging/server

发送消息可以像使用 curl 调用 HTTP 终端点一样简单。请参阅https://firebase.google.com/docs/cloud-messaging/server#implementing-http-connection-server-protocol

curl -X POST --header "Authorization: key=<API_ACCESS_KEY>" \
    --Header "Content-Type: application/json" \
    https://fcm.googleapis.com/fcm/send \
    -d "{\"to\":\"<YOUR_DEVICE_ID_TOKEN>\",\"notification\":{\"title\":\"Hello\",\"body\":\"Yellow\"}}"

您可以在任何环境中使用此REST API,但是针对许多平台,这里列出了专门的所谓Admin SDK。此处


4
我该如何在iOS上获取设备ID?我们是通过didRegisterForRemoteNotificationsWithDeviceToken deviceToken: NSData获取的设备令牌还是通过*FIRInstanceID.instanceID().token()*获取的长令牌? - FelipeOliveira
4
我按照Firebase文档和Codelabs指南的步骤,在渐进式Web应用程序中添加推送通知,并使用Postman发送HTTP请求,但我一直收到401错误。我从Firebase控制台直接复制我的服务器密钥。有什么建议吗? - jasan
38
如何向所有用户发送消息而不是特定的用户或主题? - vinbhai4u
3
在我早期使用 CURL 代码片段时,遇到了这个错误消息:“优先级”字段必须是 JSON 数字:10。在我将末尾的引号从数字10中删除后,它就正常工作了。 - albert c braun
3
为发送给所有用户, 需要订阅主题到'all'话题,然后发送到'/topics/all'。 - roghayeh hosseini
显示剩余15条评论

68

这可以使用CURL实现

function sendGCM($message, $id) {


    $url = 'https://fcm.googleapis.com/fcm/send';

    $fields = array (
            'registration_ids' => array (
                    $id
            ),
            'data' => array (
                    "message" => $message
            )
    );
    $fields = json_encode ( $fields );

    $headers = array (
            'Authorization: key=' . "YOUR_KEY_HERE",
            'Content-Type: application/json'
    );

    $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_POSTFIELDS, $fields );

    $result = curl_exec ( $ch );
    echo $result;
    curl_close ( $ch );
}

?>

$message是您发送到设备的消息

$id是设备注册令牌

YOUR_KEY_HERE是您的服务器API密钥(或遗留服务器API密钥)


Firebase控制台没有将推送消息数据保存到https://fcm.googleapis.com/fcm/send中。 - Mahmudul Haque Khan
1
如何向浏览器发送推送通知并获取设备注册ID? - Amit Joshi
这个程序运行得很完美,但是由于文本过长,我得到了{"multicast_id":3694931298664346108,"success":0,"failure":1,"canonical_ids":0,"results":[{"error":"MessageTooBig"}]}的错误信息。有什么方法可以解决这个问题? - Alisha Lamichhane
@AlishaLamichhane 你的消息是否超过4096个字节?如果没有,你可以对其进行Base64编码(文本可能出现问题)。如果它超过了4096个字节……那就是FCM的限制。 - Rik
to replaces registration_ids - Yohanim
如果您希望在应用程序被杀死的模式下处理Firebase消息,您应该添加以下内容: ''notification' => array( "body" => '通知正文', 'title' => $message ),' - manna

62

使用服务API。

URL:https://fcm.googleapis.com/fcm/send

方法类型:POST

头部信息:

Content-Type: application/json
Authorization: key=your api key

正文/有效载荷:

{
   "notification": {
      "title": "Your Title",
      "text": "Your Text",
      "click_action": "OPEN_ACTIVITY_1"
   },
   "data": {
      "<some_key>": "<some_value>"
   },
   "to": "<device_token>"
}

有了这个功能,您可以在您的应用程序中添加下面的代码来调用:

<intent-filter>
    <action android:name="OPEN_ACTIVITY_1" />
    <category android:name="android.intent.category.DEFAULT" />
</intent-filter>

还可以查看Firebase在应用程序后台时不调用onMessageReceived的解答


Ankit,我可以发送到特定的设备ID。但是,我无法发送到所有设备。我需要将 "to" : "to_id(firebase refreshedToken)" 放在哪里,而不是设备ID? "all" 根本不起作用。我正在使用C# WebRequest 发送通知。@AshikurRahman 您的建议也受欢迎。我已经苦苦搜索了3-4天。 - Ravimallya
5
没事了,我找到解决方案了。将"/topics/all"用于通知将发送到所有设备,如果你只想针对iOS设备,则替换all为ios,如果是安卓设备,则替换为android。这些应该是默认的主题设置,我猜的。 - Ravimallya
http://developine.com/how-to-send-firebase-push-notifications-from-app-server-tutorial/ - Developine
@AnandRaj 在Firebase FCM中,您可以获取令牌并将其保存在您的存储(数据库)上。 - Ankit Adlakha
我们如何发送频道ID?有什么建议吗?非常感谢。 - Kamlesh
显示剩余3条评论

50

使用curl的示例

向特定设备发送消息

要向特定设备发送消息,请将<registration token>设置为特定应用程序实例的注册令牌

curl -H "Content-type: application/json" -H "Authorization:key=<Your Api key>"  -X POST -d '{ "data": { "score": "5x1","time": "15:10"},"to" : "<registration token>"}' https://fcm.googleapis.com/fcm/send

发送消息到主题

这里的主题是:/topics/foo-bar

curl -H "Content-type: application/json" -H "Authorization:key=<Your Api key>"  -X POST -d '{ "to": "/topics/foo-bar","data": { "message": "This is a Firebase Cloud Messaging Topic Message!"}}' https://fcm.googleapis.com/fcm/send

发送消息到设备组

向设备组发送消息与向单个设备发送消息非常相似。将“to”参数设置为设备组的唯一通知键即可。

curl -H "Content-type: application/json" -H "Authorization:key=<Your Api key>"  -X POST -d '{"to": "<aUniqueKey>","data": {"hello": "This is a Firebase Cloud Messaging Device Group Message!"}}' https://fcm.googleapis.com/fcm/send

使用服务API的示例

API URL:https://fcm.googleapis.com/fcm/send

头部信息:

Content-type: application/json
Authorization:key=<Your Api key>

请求方式: POST

请求体

向特定设备发送消息

{
  "data": {
    "score": "5x1",
    "time": "15:10"
  },
  "to": "<registration token>"
}

发送到主题的消息

{
  "to": "/topics/foo-bar",
  "data": {
    "message": "This is a Firebase Cloud Messaging Topic Message!"
  }
}

设备组消息

{
  "to": "<aUniqueKey>",
  "data": {
    "hello": "This is a Firebase Cloud Messaging Device Group Message!"
  }
}

你在哪里找到了端点URL https://fcm.googleapis.com/fcm/send?Firebase文档中没有提到过。 - Utsav Gupta
1
你可以在这个链接中找到 https://firebase.google.com/docs/cloud-messaging/server - J.R
@J.R. 我创建了一个聊天应用程序,当用户向接收者发送消息时,接收者应该收到一条通知消息。在这种情况下,我该如何使用您的答案?那么我应该为“to”字段提供什么值? - Arj 1411
请参考我的回答中的“向特定设备发送消息”,Anad Raj。 - J.R

25

正如Frank所提到的,您可以使用Firebase云消息传递(FCM)HTTP API从自己的后端触发推送通知。但是,您将无法:

  1. 向Firebase用户标识符(UID)发送通知
  2. 将通知发送到用户段(定位属性和事件,就像在用户控制台上一样)。

意思是:您必须自己存储FCM/GCM注册ID(推送令牌),或者使用FCM主题订阅用户。还要记住,FCM不是Firebase通知的API,它是一个较低级别的API,没有调度或开放率分析。Firebase通知是建立在FCM之上的。


12

介绍

我整理了上面大部分的答案,并根据FCM HTTP连接文档更新变量,以制定一个适用于2021年的与FCM配合的解决方案。特别感谢Hamzah Malik提供的非常有见地的答案。

先决条件

首先,请确保您已将项目与Firebase连接,并在应用程序中设置了所有依赖项。如果没有,请先转到FCM配置文档

如果已完成这些操作,您还需要从API复制项目的服务器响应密钥。前往您的Firebase控制台,单击正在使用的项目,然后导航到;

Project Settings(Setting wheel on upper left corner) -> Cloud Messaging Tab -> Copy the Server key

配置您的PHP后端

我将Hamzah的答案与Ankit Adlakha的API调用结构和FCM文档编译在一起,得到下面的PHP函数:

function sendGCM() {
  // FCM API Url
  $url = 'https://fcm.googleapis.com/fcm/send';

  // Put your Server Response Key here
  $apiKey = "YOUR SERVER RESPONSE KEY HERE";

  // Compile headers in one variable
  $headers = array (
    'Authorization:key=' . $apiKey,
    'Content-Type:application/json'
  );

  // Add notification content to a variable for easy reference
  $notifData = [
    'title' => "Test Title",
    'body' => "Test notification body",
    'click_action' => "android.intent.action.MAIN"
  ];

  // Create the api body
  $apiBody = [
    'notification' => $notifData,
    'data' => $notifData,
    "time_to_live" => "600" // Optional
    'to' => '/topics/mytargettopic' // Replace 'mytargettopic' with your intended notification audience
  ];

  // Initialize curl with the prepared headers and body
  $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_POSTFIELDS, json_encode($apiBody));

  // Execute call and save result
  $result = curl_exec ( $ch );

  // Close curl after call
  curl_close ( $ch );

  return $result;
}

自定义通知推送

使用'to' => 'registration token'来通过令牌提交通知。

预期结果

我在我的网站后端设置了该功能,并在Postman上进行了测试。如果配置成功,您应该期望获得类似下面这样的响应;

{"message":"{"message_id":3061657653031348530}"}

7
这个解决方案来自于该链接,对我帮助很大,你可以去看看。
curl.php文件包含那些指令就能够运行。
<?php 
// Server key from Firebase Console define( 'API_ACCESS_KEY', 'AAAA----FE6F' );
$data = array("to" => "cNf2---6Vs9", "notification" => array( "title" => "Shareurcodes.com", "body" => "A Code Sharing Blog!","icon" => "icon.png", "click_action" => "http://shareurcodes.com"));
$data_string = json_encode($data);
echo "The Json Data : ".$data_string;
$headers = array ( 'Authorization: key=' . API_ACCESS_KEY, 'Content-Type: application/json' );
$ch = curl_init(); curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send' );
curl_setopt( $ch,CURLOPT_POST, true );
curl_setopt( $ch,CURLOPT_HTTPHEADER, $headers );
curl_setopt( $ch,CURLOPT_RETURNTRANSFER, true );
curl_setopt( $ch,CURLOPT_POSTFIELDS, $data_string);
$result = curl_exec($ch);
curl_close ($ch);
echo "<p>&nbsp;</p>";
echo "The Result : ".$result;

请记住,您需要使用另一个浏览器执行curl.php文件,而不是使用用于获取用户令牌的浏览器。只有在您浏览其他网站时才能看到通知。


6

首先您需要从Android获取一个令牌,然后您可以调用这个PHP代码,甚至可以发送数据以进行应用程序中的进一步操作。

 <?php

// Call .php?Action=M&t=title&m=message&r=token
$action=$_GET["Action"];


switch ($action) {
    Case "M":
         $r=$_GET["r"];
        $t=$_GET["t"];
        $m=$_GET["m"];

        $j=json_decode(notify($r, $t, $m));

        $succ=0;
        $fail=0;

        $succ=$j->{'success'};
        $fail=$j->{'failure'};

        print "Success: " . $succ . "<br>";
        print "Fail   : " . $fail . "<br>";

        break;


default:
        print json_encode ("Error: Function not defined ->" . $action);
}

function notify ($r, $t, $m)
    {
    // API access key from Google API's Console
        if (!defined('API_ACCESS_KEY')) define( 'API_ACCESS_KEY', 'Insert here' );
        $tokenarray = array($r);
        // prep the bundle
        $msg = array
        (
            'title'     => $t,
            'message'     => $m,
           'MyKey1'       => 'MyData1',
            'MyKey2'       => 'MyData2', 

        );
        $fields = array
        (
            'registration_ids'     => $tokenarray,
            'data'            => $msg
        );

        $headers = array
        (
            'Authorization: key=' . API_ACCESS_KEY,
            'Content-Type: application/json'
        );

        $ch = curl_init();
        curl_setopt( $ch,CURLOPT_URL, 'fcm.googleapis.com/fcm/send' );
        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 );
        return $result;
    }


?>

5

以下是在我的项目中使用CURL的工作代码。

<?PHP
//Avoid keys confusions!
//firebase Cloud Messaging have 3 different keys: 
//API_KEY, SERVER_KEY and PUSH_KEY ... here we need SERVER_KEY

// SERVER access key from Google firebase Console    
define( 'SERVER_ACCESS_KEY', 'YOUR-SERVER-ACCESS-KEY-GOES-HERE' );


 $registrationIds = array( $_GET['id'] );

  // prep the bundle
 $msg = array
 (
   'message'    => 'here is a message. message',
    'title'     => 'This is a title. title',
    'subtitle'  => 'This is a subtitle. subtitle',
    'tickerText'    => 'Ticker text here...Ticker text here...Ticker text here',
    'vibrate'   => 1,
    'sound'     => 1,
    'largeIcon' => 'large_icon',
    'smallIcon' => 'small_icon'
 );

 $fields = array
 (
    // use this to method if want to send to topics
    // 'to' => 'topics/all'
    'registration_ids'  => $registrationIds,
     'notification'         => $msg
 );

 $headers = array
 (
    'Authorization: key=' . SERVER_ACCESS_KEY,
    'Content-Type: application/json'
 );

 $ch = curl_init();
 curl_setopt( $ch,CURLOPT_URL, 'https://fcm.googleapis.com/fcm/send' );
 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 );

 echo $result;

API_ACCESS_KEY 行缺少 define。此外,Google Cloud Messaging 的旧 URL 已被弃用,请使用 https://fcm.googleapis.com/fcm/send。 - sreekanth balu
1
另外,必须将API_ACCESS_KEY改为SERVER_ACCESS_KEY,因为Firebase消息传递有3个密钥:1.API_KEY 2.PUSH_KEY 3.SERVER_KEY...这可能会产生混淆...我对您的答案进行了编辑。测试并可用,截至2022年12月22日。 - MTK

4

2020年的作品

$response = Http::withHeaders([
            'Content-Type' => 'application/json',
            'Authorization'=> 'key='. $token,
        ])->post($url, [
            'notification' => [
                'body' => $request->summary,
                'title' => $request->title,
                'image' => 'http://'.request()->getHttpHost().$path,
                
            ],
            'priority'=> 'high',
            'data' => [
                'click_action'=> 'FLUTTER_NOTIFICATION_CLICK',
                
                'status'=> 'done',
                
            ],
            'to' => '/topics/all'
        ]);

1
2021年也适用。谢谢。我之前使用的是“text”,而不是“body”。 - Tufail Ahmad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接