ไปที่คอนโซล

构建应用服务器发送请求

使用 Firebase Admin SDK 或 FCM 应用服务器协议,您可以构建消息请求并将其发送到以下各类目标:

  • 主题名称
  • 条件
  • 设备注册令牌
  • 设备组名称(仅限旧版协议或 Node.js 版 Firebase Admin SDK)

您可以发送包含通知负载(由预定义字段组成)的消息、包含数据负载(由您自己的用户指定字段组成)的消息,或者包含这两种负载的消息。如需了解详情,请参阅消息类型

本页面中的示例说明如何使用 Firebase Admin SDK(支持 NodeJavaPythonC#Go)和 v1 HTTP 协议发送通知消息。本文还包含有关如何通过旧版 HTTP 和 XMPP 协议发送消息的指导。

向特定设备发送消息

要向单个特定设备发送消息,请传递设备的注册令牌(如图所示)。请查看适用于您的平台的客户端设置信息,以详细了解注册令牌。

Node.js

// This registration token comes from the client FCM SDKs.
var registrationToken = 'YOUR_REGISTRATION_TOKEN';

var message = {
  data: {
    score: '850',
    time: '2:45'
  },
  token: registrationToken
};

// Send a message to the device corresponding to the provided
// registration token.
admin.messaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

Java

// This registration token comes from the client FCM SDKs.
String registrationToken = "YOUR_REGISTRATION_TOKEN";

// See documentation on defining a message payload.
Message message = Message.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .setToken(registrationToken)
    .build();

// Send a message to the device corresponding to the provided
// registration token.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

Python

# This registration token comes from the client FCM SDKs.
registration_token = 'YOUR_REGISTRATION_TOKEN'

# See documentation on defining a message payload.
message = messaging.Message(
    data={
        'score': '850',
        'time': '2:45',
    },
    token=registration_token,
)

# Send a message to the device corresponding to the provided
# registration token.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

Go

// Obtain a messaging.Client from the App.
ctx := context.Background()
client, err := app.Messaging(ctx)
if err != nil {
	log.Fatalf("error getting Messaging client: %v\n", err)
}

// This registration token comes from the client FCM SDKs.
registrationToken := "YOUR_REGISTRATION_TOKEN"

// See documentation on defining a message payload.
message := &messaging.Message{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Token: registrationToken,
}

// Send a message to the device corresponding to the provided
// registration token.
response, err := client.Send(ctx, message)
if err != nil {
	log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)

C#

// This registration token comes from the client FCM SDKs.
var registrationToken = "YOUR_REGISTRATION_TOKEN";

// See documentation on defining a message payload.
var message = new Message()
{
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
    Token = registrationToken,
};

// Send a message to the device corresponding to the provided
// registration token.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

REST

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

{
  "message":{
    "token" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
    "notification" : {
      "body" : "This is an FCM notification message!",
      "title" : "FCM Message",
      }
   }
}

cURL 命令:

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"message":{
  "notification": {
    "title": "FCM Message",
    "body": "This is an FCM Message",
  },
  "token": "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
  }
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send

运行成功后,每个发送方法都将返回一个消息 ID。Firebase Admin SDK 会返回 projects/{project_id}/messages/{message_id} 格式的消息 ID 字符串。HTTP 协议响应为单个 JSON 密钥:

    {
      "name": "projects/myproject-b5ae1/messages/0:1500415314455276%31bd1c9631bd1c96"
    }

向多台设备发送消息

借助 Node、Java 和 .NET 版 Admin FCM API,您可以将消息多播到一系列设备注册令牌。每次调用时,您最多可以指定 100 个设备注册令牌。

Node.js

// Create a list containing up to 100 registration tokens.
// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // …
  'YOUR_REGISTRATION_TOKEN_N',
];

const message = {
  data: {score: '850', time: '2:45'},
  tokens: registrationTokens,
}

admin.messaging().sendMulticast(message)
  .then((response) => {
    console.log(response.successCount + ' messages were sent successfully');

Java

// Create a list containing up to 100 registration tokens.
// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

MulticastMessage message = MulticastMessage.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .addAllTokens(registrationTokens)
    .build();
BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
// See the BatchResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " messages were sent successfully");

Go

// Create a list containing up to 100 registration tokens.
// This registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}
message := &messaging.MulticastMessage{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Tokens: registrationTokens,
}

br, err := client.SendMulticast(context.Background(), message)
if err != nil {
	log.Fatalln(err)
}

// See the BatchResponse reference documentation
// for the contents of response.
fmt.Printf("%d messages were sent successfully\n", br.SuccessCount)

C#

// Create a list containing up to 100 registration tokens.
// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};
var message = new MulticastMessage()
{
    Tokens = registrationTokens,
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
};

var response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(message);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");

此操作使用底层的 sendAll() API,如下面的示例所示。返回值是 BatchResponse,其响应列表对应于输入令牌的顺序。当您想要检查是哪些令牌导致了错误时,此操作非常有用。

Node.js

// These registration tokens come from the client FCM SDKs.
const registrationTokens = [
  'YOUR_REGISTRATION_TOKEN_1',
  // …
  'YOUR_REGISTRATION_TOKEN_N',
];

const message = {
  data: {score: '850', time: '2:45'},
  tokens: registrationTokens,
}

admin.messaging().sendMulticast(message)
  .then((response) => {
    if (response.failureCount > 0) {
      const failedTokens = [];
      response.responses.forEach((resp, idx) => {
        if (!resp.success) {
          failedTokens.push(registrationTokens[idx]);
        }
      });
      console.log('List of tokens that caused failures: ' + failedTokens);
    }
  });

Java

// These registration tokens come from the client FCM SDKs.
List<String> registrationTokens = Arrays.asList(
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n"
);

MulticastMessage message = MulticastMessage.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .addAllTokens(registrationTokens)
    .build();
BatchResponse response = FirebaseMessaging.getInstance().sendMulticast(message);
if (response.getFailureCount() > 0) {
  List<SendResponse> responses = response.getResponses();
  List<String> failedTokens = new ArrayList<>();
  for (int i = 0; i < responses.size(); i++) {
    if (!responses.get(i).isSuccessful()) {
      // The order of responses corresponds to the order of the registration tokens.
      failedTokens.add(registrationTokens.get(i));
    }
  }

  System.out.println("List of tokens that caused failures: " + failedTokens);
}

Go

// Create a list containing up to 100 registration tokens.
// This registration tokens come from the client FCM SDKs.
registrationTokens := []string{
	"YOUR_REGISTRATION_TOKEN_1",
	// ...
	"YOUR_REGISTRATION_TOKEN_n",
}
message := &messaging.MulticastMessage{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Tokens: registrationTokens,
}

br, err := client.SendMulticast(context.Background(), message)
if err != nil {
	log.Fatalln(err)
}

if br.FailureCount > 0 {
	var failedTokens []string
	for idx, resp := range br.Responses {
		if !resp.Success {
			// The order of responses corresponds to the order of the registration tokens.
			failedTokens = append(failedTokens, registrationTokens[idx])
		}
	}

	fmt.Printf("List of tokens that caused failures: %v\n", failedTokens)
}

C#

// These registration tokens come from the client FCM SDKs.
var registrationTokens = new List<string>()
{
    "YOUR_REGISTRATION_TOKEN_1",
    // ...
    "YOUR_REGISTRATION_TOKEN_n",
};
var message = new MulticastMessage()
{
    Tokens = registrationTokens,
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
};

var response = await FirebaseMessaging.DefaultInstance.SendMulticastAsync(message);
if (response.FailureCount > 0)
{
    var failedTokens = new List<string>();
    for (var i = 0; i < response.Responses.Count; i++)
    {
        if (!response.Responses[i].IsSuccess)
        {
            // The order of responses corresponds to the order of the registration tokens.
            failedTokens.Add(registrationTokens[i]);
        }
    }

    Console.WriteLine($"List of tokens that caused failures: {failedTokens}");
}

向主题发送消息

您创建一个主题后,可以通过两种方法向主题发送消息:一是在客户端为客户端应用实例订阅主题,二是通过服务器 API。在后端的发送逻辑中,按如下所示指定所需的主题名称:

Node.js

// The topic name can be optionally prefixed with "/topics/".
var topic = 'highScores';

var message = {
  data: {
    score: '850',
    time: '2:45'
  },
  topic: topic
};

// Send a message to devices subscribed to the provided topic.
admin.messaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

Java

// The topic name can be optionally prefixed with "/topics/".
String topic = "highScores";

// See documentation on defining a message payload.
Message message = Message.builder()
    .putData("score", "850")
    .putData("time", "2:45")
    .setTopic(topic)
    .build();

// Send a message to the devices subscribed to the provided topic.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

Python

# The topic name can be optionally prefixed with "/topics/".
topic = 'highScores'

# See documentation on defining a message payload.
message = messaging.Message(
    data={
        'score': '850',
        'time': '2:45',
    },
    topic=topic,
)

# Send a message to the devices subscribed to the provided topic.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

Go

// The topic name can be optionally prefixed with "/topics/".
topic := "highScores"

// See documentation on defining a message payload.
message := &messaging.Message{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Topic: topic,
}

// Send a message to the devices subscribed to the provided topic.
response, err := client.Send(ctx, message)
if err != nil {
	log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)

C#

// The topic name can be optionally prefixed with "/topics/".
var topic = "highScores";

// See documentation on defining a message payload.
var message = new Message()
{
    Data = new Dictionary<string, string>()
    {
        { "score", "850" },
        { "time", "2:45" },
    },
    Topic = topic,
};

// Send a message to the devices subscribed to the provided topic.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

REST

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
  "message":{
    "topic" : "foo-bar",
    "notification" : {
      "body" : "This is a Firebase Cloud Messaging Topic Message!",
      "title" : "FCM Message"
      }
   }
}

cURL 命令:

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
  "message": {
    "topic" : "foo-bar",
    "notification": {
      "body": "This is a Firebase Cloud Messaging Topic Message!",
      "title": "FCM Message"
    }
  }
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

如需向主题组合发送消息,请指定一个条件,即指定目标主题的布尔表达式。例如,以下条件会将消息发送至已订阅 TopicA 以及 TopicBTopicC 的设备:

"'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)"

FCM 首先对括号中的所有条件求值,然后从左至右对表达式求值。在上述表达式中,只订阅某个单一主题的用户将不会接收到消息。同样地,未订阅 TopicA 的用户也不会接收到消息。下列组合将会接收到消息:

  • TopicATopicB
  • TopicATopicC

您最多可以在条件表达式中包括五个主题。

向条件发送消息:

Node.js

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
var message = {
  notification: {
    title: '$GOOG up 1.43% on the day',
    body: '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.'
  },
  condition: condition
};

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
admin.messaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

Java

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
String condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
Message message = Message.builder()
    .setNotification(new Notification(
        "$GOOG up 1.43% on the day",
        "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day."))
    .setCondition(condition)
    .build();

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
String response = FirebaseMessaging.getInstance().send(message);
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);

Python

# Define a condition which will send to devices which are subscribed
# to either the Google stock or the tech industry topics.
condition = "'stock-GOOG' in topics || 'industry-tech' in topics"

# See documentation on defining a message payload.
message = messaging.Message(
    notification=messaging.Notification(
        title='$GOOG up 1.43% on the day',
        body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
    ),
    condition=condition,
)

# Send a message to devices subscribed to the combination of topics
# specified by the provided condition.
response = messaging.send(message)
# Response is a message ID string.
print('Successfully sent message:', response)

Go

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
condition := "'stock-GOOG' in topics || 'industry-tech' in topics"

// See documentation on defining a message payload.
message := &messaging.Message{
	Data: map[string]string{
		"score": "850",
		"time":  "2:45",
	},
	Condition: condition,
}

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
response, err := client.Send(ctx, message)
if err != nil {
	log.Fatalln(err)
}
// Response is a message ID string.
fmt.Println("Successfully sent message:", response)

C#

// Define a condition which will send to devices which are subscribed
// to either the Google stock or the tech industry topics.
var condition = "'stock-GOOG' in topics || 'industry-tech' in topics";

// See documentation on defining a message payload.
var message = new Message()
{
    Notification = new Notification()
    {
        Title = "$GOOG up 1.43% on the day",
        Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
    },
    Condition = condition,
};

// Send a message to devices subscribed to the combination of topics
// specified by the provided condition.
string response = await FirebaseMessaging.DefaultInstance.SendAsync(message);
// Response is a message ID string.
Console.WriteLine("Successfully sent message: " + response);

REST

POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

Content-Type: application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
{
   "message":{
    "condition": "'dogs' in topics || 'cats' in topics",
    "notification" : {
      "body" : "This is a Firebase Cloud Messaging Topic Message!",
      "title" : "FCM Message",
    }
  }
}

cURL 命令:

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
  "notification": {
    "title": "FCM Message",
    "body": "This is a Firebase Cloud Messaging Topic Message!",
  },
  "condition": "'dogs' in topics || 'cats' in topics"
}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send HTTP/1.1

批量发送消息

Node、Java 和 .NET 版 Admin SDK 支持批量发送消息。您可以将多达 100 条消息组合到一个批处理中,并在单个 API 调用中将它们全部发送出去。与为每条消息发送单独的 HTTP 请求相比,这种方法可以显着提高性能。

此功能可用于构建一组自定义消息(包括主题或特定设备注册令牌)并将其发送给不同的收件人。例如,当您需要同时向不同受众发送消息正文中具有略微不同细节的消息时,请使用此功能。

Node.js

// Create a list containing up to 100 messages.
const messages = [];
messages.push({
  notification: {title: 'Price drop', body: '5% off all electronics'},
  token: registrationToken,
});
messages.push({
  notification: {title: 'Price drop', body: '2% off all books'},
  topic: 'readers-club',
});

admin.messaging().sendAll(messages)
  .then((response) => {
    console.log(response.successCount + ' messages were sent successfully');
  });

Java

// Create a list containing up to 100 messages.
List<Message> messages = Arrays.asList(
    Message.builder()
        .setNotification(new Notification("Price drop", "5% off all electronics"))
        .setToken(registrationToken)
        .build(),
    // ...
    Message.builder()
        .setNotification(new Notification("Price drop", "2% off all books"))
        .setTopic("readers-club")
        .build()
);

BatchResponse response = FirebaseMessaging.getInstance().sendAll(messages);
// See the BatchResponse reference documentation
// for the contents of response.
System.out.println(response.getSuccessCount() + " messages were sent successfully");

Go

// Create a list containing up to 100 messages.
messages := []*messaging.Message{
	{
		Notification: &messaging.Notification{
			Title: "Price drop",
			Body:  "5% off all electronics",
		},
		Token: registrationToken,
	},
	{
		Notification: &messaging.Notification{
			Title: "Price drop",
			Body:  "2% off all books",
		},
		Topic: "readers-club",
	},
}

br, err := client.SendAll(context.Background(), messages)
if err != nil {
	log.Fatalln(err)
}

// See the BatchResponse reference documentation
// for the contents of response.
fmt.Printf("%d messages were sent successfully\n", br.SuccessCount)

C#

// Create a list containing up to 100 messages.
var messages = new List<Message>()
{
    new Message()
    {
        Notification = new Notification()
        {
            Title = "Price drop",
            Body = "5% off all electronics",
        },
        Token = registrationToken,
    },
    new Message()
    {
        Notification = new Notification()
        {
            Title = "Price drop",
            Body = "2% off all books",
        },
        Topic = "readers-club",
    },
};

var response = await FirebaseMessaging.DefaultInstance.SendAllAsync(messages);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");

您可以查询返回的 BatchResponse 以检查有多少消息已成功传递给 FCM。它还显示一系列可用于检查各个消息的状态的响应。这些响应的顺序对应于输入列表中的消息的顺序。

跨平台自定义消息

Firebase Admin SDK 和 FCM v1 HTTP 协议都允许您的消息请求对 message 对象中的所有可用字段进行设置。包括:

  • 由接收到消息的所有应用实例解读的一组通用字段。
  • 仅由在指定平台上运行的应用实例解读的、针对具体平台的字段集,例如 AndroidConfigWebpushConfig

针对具体平台的字段块可让您灵活地针对不同平台自定义消息,以确保它们在被收到后得到正确处理。FCM 后端会考虑所有指定参数并针对每个平台自定义消息。

何时使用通用字段

在以下情况下使用通用字段:

  • 定位到所有平台(iOS、Android 和网页)上的应用实例
  • 向主题发送消息

无论平台如何,所有应用实例都可以解读以下通用字段:

何时使用针对具体平台的字段

如果需要执行下列操作,请使用针对具体平台的字段:

  • 仅向特定平台发送字段
  • 发送针对具体平台的字段以及通用字段

每当您想仅向特定平台发送值时,请不要使用通用字段,而是使用针对具体平台的字段。例如,要仅向 iOS 和网页发送通知而不向 Android 发送通知,您必须针对 iOS 和网页各使用一组字段。

当您发送包含特定递送选项的消息时,请使用针对具体平台的字段进行设置。您可以视需要为每个平台指定不同的值。但是,即使您想为各种平台设置本质上相同的值,也必须使用针对具体平台的字段。这是因为每种平台对值的解读方式可能会略有不同 - 例如,存留时间在 Android 上设置为以秒为单位的到期时间,而在 iOS 上则设置为到期日期。

示例:包含针对具体平台的递送选项的通知消息

以下发送请求会向所有平台发送通用的通知标题和内容,但也会发送一些针对具体平台的覆盖内容。具体而言,该请求会:

  • 为 Android 设置较长的生存时间,并设置在 Android 设备上显示的特殊图标和颜色。
  • 设置 APNs 负载中仅限 iOS 的 badge 字段,以用于传送到 iOS 设备。

Node.js

var message = {
  notification: {
    title: '$GOOG up 1.43% on the day',
    body: '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
  },
  android: {
    ttl: 3600 * 1000,
    notification: {
      icon: 'stock_ticker_update',
      color: '#f45342',
    },
  },
  apns: {
    payload: {
      aps: {
        badge: 42,
      },
    },
  },
  topic: 'industry-tech'
};

Java

Message message = Message.builder()
    .setNotification(new Notification(
        "$GOOG up 1.43% on the day",
        "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day."))
    .setAndroidConfig(AndroidConfig.builder()
        .setTtl(3600 * 1000)
        .setNotification(AndroidNotification.builder()
            .setIcon("stock_ticker_update")
            .setColor("#f45342")
            .build())
        .build())
    .setApnsConfig(ApnsConfig.builder()
        .setAps(Aps.builder()
            .setBadge(42)
            .build())
        .build())
    .setTopic("industry-tech")
    .build();

Python

message = messaging.Message(
    notification=messaging.Notification(
        title='$GOOG up 1.43% on the day',
        body='$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.',
    ),
    android=messaging.AndroidConfig(
        ttl=datetime.timedelta(seconds=3600),
        priority='normal',
        notification=messaging.AndroidNotification(
            icon='stock_ticker_update',
            color='#f45342'
        ),
    ),
    apns=messaging.APNSConfig(
        payload=messaging.APNSPayload(
            aps=messaging.Aps(badge=42),
        ),
    ),
    topic='industry-tech',
)

Go

oneHour := time.Duration(1) * time.Hour
badge := 42
message := &messaging.Message{
	Notification: &messaging.Notification{
		Title: "$GOOG up 1.43% on the day",
		Body:  "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
	},
	Android: &messaging.AndroidConfig{
		TTL: &oneHour,
		Notification: &messaging.AndroidNotification{
			Icon:  "stock_ticker_update",
			Color: "#f45342",
		},
	},
	APNS: &messaging.APNSConfig{
		Payload: &messaging.APNSPayload{
			Aps: &messaging.Aps{
				Badge: &badge,
			},
		},
	},
	Topic: "industry-tech",
}

C#

var message = new Message
{
    Notification = new Notification()
    {
        Title = "$GOOG up 1.43% on the day",
        Body = "$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.",
    },
    Android = new AndroidConfig()
    {
        TimeToLive = TimeSpan.FromHours(1),
        Notification = new AndroidNotification()
        {
            Icon = "stock_ticker_update",
            Color = "#f45342",
        },
    },
    Apns = new ApnsConfig()
    {
        Aps = new Aps()
        {
            Badge = 42,
        },
    },
    Topic = "industry-tech",
};

REST

{
  "message":{
     "topic":"industry-tech",
     "notification":{
       "title": "$GOOG" up 1.43% on the day",
       "body":"GOOG gained 11.80 points to close at 835.67, up 1.43% on the day."
     },
     "android":{
       "ttl":"3600s",
       "notification"{
         "icon:stock_ticker_update"
         "color:#f45342"
       }
     },
     "apns": {
       "payload": {
         "aps": {
           "badge": "42"
         }
       }
     },
     "webpush":{
       "headers":{
         "TTL":"86400"
       }
     }
   }
 }

要全面、详细地了解消息正文中针对具体平台的块内提供的键,请参阅 HTTP v1 参考文档

Admin FCM SDK 错误参考

下表列出了 Firebase Admin FCM API 错误代码及其说明,包括建议的解决步骤。

错误代码 说明和解决步骤
messaging/invalid-argument 向 FCM 方法提供的参数无效。错误消息中应该会包含更多信息。
messaging/invalid-recipient 预期的消息接收者无效。错误消息中应该会包含更多信息。
messaging/invalid-payload 提供的消息负载对象无效。错误消息中应该会包含更多信息。
messaging/invalid-data-payload-key 数据消息载荷包含无效键。如需了解受限制的键,请参阅 DataMessagePayload 的参考文档。
messaging/payload-size-limit-exceeded 提供的消息载荷超出了 FCM 大小限制。对于大多数消息,此限制为 4096 字节。对于发送到主题的消息,此限制为 2048 字节。键和值都会计入负载总大小。
messaging/invalid-options 提供的消息选项对象无效。错误消息中应该会包含更多信息。
messaging/invalid-registration-token 提供的注册令牌无效。请确保它与客户端应用在注册 FCM 时获得的注册令牌相符。不要截断或添加其他字符。
messaging/registration-token-not-registered 提供的注册令牌未注册。以前有效的注册令牌可能会因多种原因而被取消注册,其中包括:
  • 客户端应用自身取消 FCM 注册。
  • 客户端应用被自动取消注册。如果用户卸载该应用,或者在 iOS 中,APNs 反馈服务报告称 APNs 令牌无效,就可能会发生这种情况。
  • 注册令牌已过期。例如,Google 可能决定更新注册令牌,或 iOS 设备的 APNs 令牌可能已过期。
  • 客户端应用已更新,但新版本未配置为接收消息。
对于所有这些情况,请移除此注册令牌,并停止用其发送消息。
messaging/invalid-package-name 消息被发送至软件包名称与提供的 restrictedPackageName 选项不匹配的注册令牌。
messaging/message-rate-exceeded 向特定目标发送消息的频率过高。请减少发送到此设备或主题的消息数,且不要立即重试向此目标发送消息。
messaging/device-message-rate-exceeded 向特定设备发送消息的频率过高。请减少发送到此设备的消息数,且不要立即重试向此设备发送消息。
messaging/topics-message-rate-exceeded 向特定主题的订阅者发送消息的频率过高。请减少发送到此主题的消息数,且不要立即重试向此主题发送消息。
messaging/too-many-topics 注册令牌订阅的主题数量已达到上限,无法订阅更多主题。
messaging/invalid-apns-credentials 因为所需的 APNs SSL 证书尚未上传或已过期,所以无法向 iOS 设备发送消息。请检查您的开发环境证书和生产环境证书是否有效。
messaging/mismatched-credential 用于对此 SDK 进行身份验证的凭据无权向所提供的注册令牌对应的设备发送消息。请确保相应凭据和注册令牌均属于同一个 Firebase 项目。如需查看有关如何验证 Firebase Admin SDK 的文档,请参阅将 Firebase 添加到您的应用
messaging/authentication-error SDK 无法向 FCM 服务器验证身份。请确保您使用具有适当权限来发送 FCM 消息的凭据对 Admin SDK 进行身份验证。如需查看有关如何验证 Firebase Admin SDK 的文档,请参阅将 Firebase 添加到您的应用
messaging/server-unavailable FCM 服务器无法及时处理请求。您应该重试同一个请求,但必须:
  • 如果 FCM 连接服务器发出的响应中包含 Retry-After 标头,则应在该标头指明的间隔后重试。
  • 在您的重试机制中实现指数退避。例如,如果等待一秒钟后进行第一次重试,则至少要等待两秒钟再进行下一次重试,然后等待四秒钟,依此类推。如果您要发送多条消息,请分别将每条消息延迟额外的随机时长,从而避免同时为所有消息发出新的请求。
导致出现问题的发送者有可能会被列入黑名单。
messaging/internal-error FCM 服务器在尝试处理请求时遇到错误。您可按照上一行 messaging/server-unavailable 中列出的要求重试同一请求。如果错误持续存在,请向我们的错误报告支持渠道报告该问题。
messaging/unknown-error 返回了未知的服务器错误。如需了解详情,请参阅错误消息中的原始服务器响应。如果您看到此错误,请向我们的错误报告支持渠道报告完整的错误消息。

使用旧版应用服务器协议发送消息

如果您更喜欢使用旧版协议,请按本部分所示方法构建消息请求。请注意,如果您通过 HTTP 发送消息到多个平台,v1 协议可以简化您的消息请求。

向特定设备发送消息

要向特定设备发送消息,请将 to 键设置为特定应用实例的注册令牌。请查看针对您的平台的客户端设置信息,了解有关注册令牌的更多信息。

HTTP POST 请求

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

{ "data": {
    "score": "5x1",
    "time": "15:10"
  },
  "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}

HTTP 响应

{ "multicast_id": 108,
  "success": 1,
  "failure": 0,
  "results": [
    { "message_id": "1:08" }
  ]
}

XMPP 消息

<message id="">
  <gcm xmlns="google:mobile:data">
    { "data": {
      "score": "5x1",
      "time": "15:10"
    },
    "to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
  }
  </gcm>
</message>

XMPP 响应

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "from":"REGID",
      "message_id":"m-1366082849205"
      "message_type":"ack"
  }
  </gcm>
</message>

XMPP 连接服务器提供了另外几种可供选择的响应格式。请参阅服务器响应格式

如需查看向客户端应用发送下行消息时可用的消息选项的完整列表,请参阅所选连接服务器协议(HTTPXMPP)的参考信息。

向主题发送消息

向 Firebase 云消息传递主题发送消息与向单台设备或一个用户组发送消息十分类似。应用服务器会将 to 键设为类似 /topics/yourTopic 这样的值。开发者可以选择符合以下正则表达式的任何主题名称:"/topics/[a-zA-Z0-9-_.~%]+"

要向多个主题的组合发送消息,应用服务器必须将 condition 键(而非 to 键)设为用于指定目标主题的布尔型条件。例如,要向已订阅 TopicATopicBTopicC 的设备发送消息,则设置如下条件:

'TopicA' in topics && ('TopicB' in topics || 'TopicC' in topics)

FCM 首先对括号中的所有条件求值,然后从左至右对表达式求值。在上述表达式中,只订阅某个单一主题的用户将不会接收到消息。同样地,未订阅 TopicA 的用户也不会接收到消息。下列组合将会接收到消息:

  • TopicA 和 TopicB
  • TopicA 和 TopicC

您最多可以在条件表达式中添加五个主题,支持使用括号。支持的运算符包括 &&||!。请注意 ! 的用法:

!('TopicA' in topics)

使用此表达式,任何未订阅 TopicA 的应用实例(包括未订阅任何主题的应用实例)都会收到消息。

如需详细了解应用服务器键,请参阅所选连接服务器协议(HTTPXMPP)的参考信息。本页面中的示例说明了如何使用 HTTP 和 XMPP 协议将消息发送至主题。

主题 HTTP POST 请求

发送至一个主题:

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

发送至已订阅“dogs”或“cats”主题的设备:

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

主题 HTTP 响应

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}

主题 XMPP 消息

发送至一个主题:

<message id="">
  <gcm xmlns="google:mobile:data">

  </gcm>
</message>

发送至已订阅“dogs”或“cats”主题的设备:

<message id="">
  <gcm xmlns="google:mobile:data">

  </gcm>
</message>

主题 XMPP 响应

//Success example:
{
  "message_id": "1023456"
}

//failure example:
{
  "error": "TopicsMessageRateExceeded"
}

FCM 服务器对主题发送请求返回成功或失败响应前,可能会有最长 30 秒的延迟。请务必在请求中相应地设置应用服务器的超时值。

如需查看消息选项的完整列表,请参阅所选连接服务器协议(HTTPXMPP)的参考信息。

向设备组发送消息

向设备组发送消息与向单台设备发送消息十分类似。您需要将 to 参数设为特定于设备组的通知键。如需详细了解负载支持,请参阅消息类型。本页的示例展示了如何通过 HTTP 和 XMPP 协议向设备组发送数据消息。

设备组 HTTP POST 请求

https://fcm.googleapis.com/fcm/send
Content-Type:application/json
Authorization:key=AIzaSyZ-1u...0GBYzPu7Udno5aA

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

设备组 HTTP 响应

以下是一个“成功”的示例:notification_key 有 2 个关联的注册令牌,且消息已成功发送至这两个令牌:

{
  "success": 2,
  "failure": 0
}

以下是一个“部分成功”的示例:notification_key 有 3 个关联的注册令牌。消息仅成功发送至其中一个注册令牌。响应消息列出了未收到消息的注册令牌:

{
  "success":1,
  "failure":2,
  "failed_registration_ids":[
     "regId1",
     "regId2"
  ]
}

当消息未能发送至与某个 notification_key 关联的一个或多个注册令牌时,应用服务器隔一段时间会重试一次。

如果服务器尝试向没有成员的设备组发送消息,则响应如下所示(0 个成功,0 个失败):

{
  "success": 0,
  "failure": 0
}

设备组 XMPP 消息

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "to": "aUniqueKey",
      "message_id": "m-1366082849205" ,
      "data": {
          "hello":"This is a Firebase Cloud Messaging Device Group Message!"
      }
  }
  </gcm>
</message>

设备组 XMPP 响应

当消息成功发送至设备组中的任何一台设备时,XMPP 连接服务器都会发送 ACK 响应。当发送至组中所有设备的所有消息都失败时,XMPP 连接服务器会发送 NACK 响应。

以下是一个“成功”的示例:notification_key 有 3 个关联的注册令牌,且消息已成功发送至这 3 个令牌:

{
  "from": "aUniqueKey",
  "message_type": "ack",
  "success": 3,
  "failure": 0,
  "message_id": "m-1366082849205"
}

以下是一个“部分成功”的示例:notification_key 有 3 个关联的注册令牌。 消息仅成功发送至其中一个注册令牌。响应消息列出了未收到消息的注册令牌:

{
  "from": "aUniqueKey",
  "message_type": "ack",
  "success":1,
  "failure":2,
  "failed_registration_ids":[
     "regId1",
     "regId2"
  ]
}

当 FCM 连接服务器未能将消息发送至组中的所有设备时,应用服务器将收到 NACK 响应。

如需查看消息选项的完整列表,请参阅所选连接服务器协议(HTTPXMPP)的参考信息。

Firebase Admin SDK 旧版发送方法

Firebase Admin Node.js SDK 支持基于旧版 FCM 服务器 API 发送 (FCM) 消息的方法。与 send() 方法相比,这些方法接受的参数有所不同。您应该尽可能使用 send() 方法,并且在向个别设备或设备组发送消息时仅使用本页面中介绍的方法。

向个别设备发送消息

您可以将一个注册令牌传递给 sendToDevice() 方法以向该设备发送消息:

Node.js

// This registration token comes from the client FCM SDKs.
var registrationToken = 'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...';

// See the "Defining the message payload" section below for details
// on how to define a message payload.
var payload = {
  data: {
    score: '850',
    time: '2:45'
  }
};

// Send a message to the device corresponding to the provided
// registration token.
admin.messaging().sendToDevice(registrationToken, payload)
  .then(function(response) {
    // See the MessagingDevicesResponse reference documentation for
    // the contents of response.
    console.log('Successfully sent message:', response);
  })
  .catch(function(error) {
    console.log('Error sending message:', error);
  });

sendToDevice() 方法还可以通过传递一组注册令牌(而不是仅仅单个注册令牌)发送一条“多播”消息(即向多台设备发送的消息)

Node.js

// These registration tokens come from the client FCM SDKs.
var registrationTokens = [
  'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...',
  // ...
  'ecupwIfBy1w:APA91bFtuMY7MktgxA3Au_Qx7cKqnf...'
];

// See the "Defining the message payload" section below for details
// on how to define a message payload.
var payload = {
  data: {
    score: '850',
    time: '2:45'
  }
};

// Send a message to the devices corresponding to the provided
// registration tokens.
admin.messaging().sendToDevice(registrationTokens, payload)
  .then(function(response) {
    // See the MessagingDevicesResponse reference documentation for
    // the contents of response.
    console.log('Successfully sent message:', response);
  })
  .catch(function(error) {
    console.log('Error sending message:', error);
  });

sendToDevice() 方法将返回一个使用包含 FCM 响应的 MessagingDevicesResponse 对象来解析的 promise。无论传递单个注册令牌还是一组注册令牌,返回类型的格式都是相同的。

有些情况(如身份验证错误或速率限制)会导致整个消息无法处理。在这些情况下,sendToDevice() 返回的 promise 会被拒绝并报错。如需错误代码的完整列表(包括说明和解决步骤),请参阅 Admin FCM API 错误

向设备组发送消息

利用设备组消息传递功能,您可以向单个设备组添加多台设备。这类似于主题消息传递,但设备组消息传递加入了身份验证,以确保组成员资格仅受您的服务器管理。例如,如果要向不同的手机型号发送不同的消息,您的服务器可以向相应的设备组添加注册信息或从其中删除注册信息,并将相应的消息发送到每个设备组。设备组消息传递与主题消息传递的不同之处在于:设备组消息传递是从服务器上管理设备组,而不是直接在应用中管理。

您可以通过应用服务器上的旧版 XMPPHTTP 协议使用设备组消息传递功能。 基于旧版协议的 Node.js Firebase Admin SDK 也提供设备组消息传递功能。一个通知键最多支持 20 个成员设备。

您可以通过应用服务器或 Android 客户端创建设备组并生成通知键。如需了解详情,请参阅管理设备组

借助 sendToDeviceGroup() 方法,您可以通过指定设备组的通知键来向该设备组发送消息:

Node.js

// See the "Managing device groups" link above on how to generate a
// notification key.
var notificationKey = 'some-notification-key';

// See the "Defining the message payload" section below for details
// on how to define a message payload.
var payload = {
  data: {
    score: '850',
    time: '2:45'
  }
};

// Send a message to the device group corresponding to the provided
// notification key.
admin.messaging().sendToDeviceGroup(notificationKey, payload)
  .then(function(response) {
    // See the MessagingDeviceGroupResponse reference documentation for
    // the contents of response.
    console.log('Successfully sent message:', response);
  })
  .catch(function(error) {
    console.log('Error sending message:', error);
  });

sendToDeviceGroup() 方法将返回一个使用包含 FCM 响应的 MessagingDeviceGroupResponse 对象来解析的 promise。

有些情况(如身份验证错误或速率限制)会导致整个消息无法处理。在这些情况下,sendToDeviceGroup() 返回的 promise 会被拒绝并报错。如需错误代码的完整列表(包括说明和解决步骤),请参阅 Admin FCM API 错误

定义消息负载

上述基于 FCM 旧版协议的方法允许将消息负载作为其第二个参数,并支持通知消息和数据消息。您可以创建一个含有 data 和/或 notification 键的对象,以指定其中一种或两种消息类型。下方示例介绍了如何定义不同类型的消息有效负载:

通知消息

var payload = {
  notification: {
    title: '$GOOG up 1.43% on the day',
    body: '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.'
  }
};

数据消息

var payload = {
  data: {
    score: '850',
    time: '2:45'
  }
};

组合消息

var payload = {
  notification: {
    title: '$GOOG up 1.43% on the day',
    body: '$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.'
  },
  data: {
    stock: 'GOOG',
    open: '829.62',
    close: '635.67'
  }
};

通知消息有效负载具有预定义的有效属性子集,且会因您定位的移动操作系统不同而略有不同。如需查看完整列表,请参阅 NotificationMessagePayload 的参考文档。

数据消息有效负载由自定义键值对组成,但有一些限制(包括所有值都必须为字符串)。如需查看完整的限制列表,请参阅 DataMessagePayload 的参考文档。

定义消息选项

上述基于 FCM 旧版协议的方法接受第三个参数(可选),用于指定消息的一些选项。例如,以下示例会向将于 24 小时后到期的设备发送高优先级消息:

Node.js

// This registration token comes from the client FCM SDKs.
var registrationToken = 'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...';

// See the "Defining the message payload" section above for details
// on how to define a message payload.
var payload = {
  notification: {
    title: 'Urgent action needed!',
    body: 'Urgent action is needed to prevent your account from being disabled!'
  }
};

// Set the message as high priority and have it expire after 24 hours.
var options = {
  priority: 'high',
  timeToLive: 60 * 60 * 24
};

// Send a message to the device corresponding to the provided
// registration token with the provided options.
admin.messaging().sendToDevice(registrationToken, payload, options)
  .then(function(response) {
    console.log('Successfully sent message:', response);
  })
  .catch(function(error) {
    console.log('Error sending message:', error);
  });

如需查看可用选项的完整列表,请参阅 MessagingOptions 的参考文档。