建構應用程式伺服器傳送要求

您可以使用 Firebase Admin SDK 或 FCM 應用程式伺服器通訊協定建立訊息要求,並將這些要求傳送至以下類型的目標:

  • 主題名稱
  • 條件
  • 裝置註冊權杖
  • 裝置群組名稱 (僅限通訊協定)

您可以透過由預先定義欄位、使用者定義欄位的資料酬載,或是同時包含這兩種酬載的訊息,傳送具有通知酬載的訊息。詳情請參閱 訊息類型

本頁面的範例說明如何使用 Firebase Admin SDK (支援 NodeJavaPythonC#Go) 和 v1 HTTP 通訊協定傳送通知訊息。另外,您也能在當中透過已淘汰的舊版 HTTP 和 XMPP 通訊協定傳送訊息。

將訊息傳送至特定裝置

如要傳送至單一特定裝置,請傳遞裝置的註冊權杖 (如圖所示)。請參閱平台的用戶端設定資訊,進一步瞭解註冊權杖。

Node.js

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

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

// Send a message to the device corresponding to the provided
// registration token.
getMessaging().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

成功時,每個 send 方法都會傳回訊息 ID。Firebase Admin SDK 會以 projects/{project_id}/messages/{message_id} 格式傳回 ID 字串。HTTP 通訊協定回應是單一 JSON 金鑰:

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

傳送訊息至多部裝置

Admin FCM API 可讓您將訊息多點傳播至裝置註冊權杖清單。每次叫用最多可以指定 500 個裝置註冊權杖。

Node.js

// Create a list containing up to 500 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,
};

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

Java

// Create a list containing up to 500 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");

Python

# Create a list containing up to 500 registration tokens.
# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_N',
]

message = messaging.MulticastMessage(
    data={'score': '850', 'time': '2:45'},
    tokens=registration_tokens,
)
response = messaging.send_multicast(message)
# See the BatchResponse reference documentation
# for the contents of response.
print('{0} messages were sent successfully'.format(response.success_count))

Go

// Create a list containing up to 500 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 500 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.SendEachForMulticastAsync(message);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");

傳回值是對應輸入權杖順序的權杖清單。如要檢查哪些權杖導致錯誤,這項功能就能派上用場。

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,
};

getMessaging().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);
}

Python

# These registration tokens come from the client FCM SDKs.
registration_tokens = [
    'YOUR_REGISTRATION_TOKEN_1',
    # ...
    'YOUR_REGISTRATION_TOKEN_N',
]

message = messaging.MulticastMessage(
    data={'score': '850', 'time': '2:45'},
    tokens=registration_tokens,
)
response = messaging.send_multicast(message)
if response.failure_count > 0:
    responses = response.responses
    failed_tokens = []
    for idx, resp in enumerate(responses):
        if not resp.success:
            # The order of responses corresponds to the order of the registration tokens.
            failed_tokens.append(registration_tokens[idx])
    print('List of tokens that caused failures: {0}'.format(failed_tokens))

Go

// Create a list containing up to 500 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.SendEachForMulticastAsync(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 將用戶端應用程式執行個體訂閱主題,藉此將訊息傳送至主題。如果這是您第一次建構 FCM 要求,請參閱伺服器環境和 FCM 指南,瞭解重要的背景和設定資訊。

在後端的傳送邏輯中,指定所需的主題名稱,如下所示:

Node.js

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

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

// Send a message to devices subscribed to the provided topic.
getMessaging().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.
const condition = '\'stock-GOOG\' in topics || \'industry-tech\' in topics';

// See documentation on defining a message payload.
const message = {
  notification: {
    title: '$FooCorp up 1.43% on the day',
    body: '$FooCorp 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.
getMessaging().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(Notification.builder()
        .setTitle("$GOOG up 1.43% on the day")
        .setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
        .build())
    .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

傳送訊息至裝置群組

如要傳送訊息至裝置群組,請使用 HTTP v1 API。如果您目前使用已淘汰的舊版傳送 API (適用於 HTTP 或 XMPP) 傳送至裝置群組,或根據舊版通訊協定使用任何舊版 Node.js 適用的 Firebase Admin SDK,強烈建議您盡早遷移至 HTTP v1 API。舊版傳送 API 將於 2024 年 6 月停用及移除。

使用相同方法授權傳送要求,將訊息傳送至裝置群組與傳送訊息給個別裝置非常類似。將 token 欄位設為群組通知鍵:

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":"APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ",
      "data":{
        "hello": "This is a Firebase Cloud Messaging device group message!"
      }
   }
}

cURL 指令

curl -X POST -H "Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA" -H "Content-Type: application/json" -d '{
"message":{
   "data":{
     "hello": "This is a Firebase Cloud Messaging device group message!"
   },
   "token":"APA91bGHXQBB...9QgnYOEURwm0I3lmyqzk2TXQ"
}}' https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send

一次傳送一批訊息

Admin SDK 支援批次傳送訊息。您最多可以將 500 則訊息合併成一個批次,再透過單一 API 呼叫傳送所有訊息。相較於為每則訊息分別傳送 HTTP 要求,效能可大幅提升。

這項功能可以用來建構自訂訊息組合,並將訊息傳送給不同的收件者,包括主題或特定裝置註冊權杖。舉例來說,如果您需要同時傳送訊息給不同目標對象,且訊息內文中的詳細資料稍有不同,就可以使用這項功能。

Node.js

// Create a list containing up to 500 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',
});

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

Java

// Create a list containing up to 500 messages.
List<Message> messages = Arrays.asList(
    Message.builder()
        .setNotification(Notification.builder()
            .setTitle("Price drop")
            .setBody("5% off all electronics")
            .build())
        .setToken(registrationToken)
        .build(),
    // ...
    Message.builder()
        .setNotification(Notification.builder()
            .setTitle("Price drop")
            .setBody("2% off all books")
            .build())
        .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");

Python

# Create a list containing up to 500 messages.
messages = [
    messaging.Message(
        notification=messaging.Notification('Price drop', '5% off all electronics'),
        token=registration_token,
    ),
    # ...
    messaging.Message(
        notification=messaging.Notification('Price drop', '2% off all books'),
        topic='readers-club',
    ),
]

response = messaging.send_all(messages)
# See the BatchResponse reference documentation
# for the contents of response.
print('{0} messages were sent successfully'.format(response.success_count))

Go

// Create a list containing up to 500 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 500 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.SendEachAsync(messages);
// See the BatchResponse reference documentation
// for the contents of response.
Console.WriteLine($"{response.SuccessCount} messages were sent successfully");

傳送啟用直接啟動功能的訊息 (僅限 Android)

您可以使用 HTTP v1 或舊版 HTTP API,以直接啟動模式傳送訊息到裝置。在直接啟動模式下傳送至裝置之前,請確認您已完成讓用戶端裝置以直接啟動模式接收 FCM 訊息的步驟。

使用 FCM v1 HTTP API 傳送

訊息要求必須在要求主體的 AndroidConfig 選項中加入 "direct_boot_ok" : true 鍵。例如:

https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send
Content-Type:application/json
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

{
  "message":{
    "token" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
    "data": {
      "score": "5x1",
      "time": "15:10"
    },
    "android": {
      "direct_boot_ok": true,
    },
}

使用 FCM 舊版 HTTP API 傳送

訊息要求必須在要求主體的頂層包含 "direct_boot_ok" : true 鍵。例如:

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..."
  "direct_boot_ok" : true
}

如果裝置目前處於直接啟動模式,而且未處於直接啟動模式,便能處理以此金鑰在要求主體中傳送的訊息。

自訂所有平台的訊息

Firebase Admin SDK 和 FCM v1 HTTP 通訊協定均可讓訊息要求設定 message 物件中的所有欄位。這包括:

  • 接收一組通用欄位,讓接收訊息的「所有」應用程式執行個體都能解讀。
  • 平台專屬的欄位組合 (例如 AndroidConfigWebpushConfig),只能解讀在指定平台上執行的應用程式執行個體。

平台專屬區塊可讓您靈活自訂不同平台的訊息,確保收到訊息時能正確處理。FCM 後端會將所有指定的參數納入考量,並為每個平台自訂訊息。

使用一般欄位的時機

如果您符合下列情況,請使用一般欄位:

  • 指定「所有」平台的應用程式執行個體:Apple、Android 和網頁
  • 傳送訊息至主題

無論平台為何,所有應用程式執行個體都能解讀下列常見欄位:

平台專用欄位的使用時機

如要執行以下操作,請使用平台專屬欄位:

  • 僅將欄位傳送至特定平台
  • 除了一般欄位,也傳送平台專屬欄位

如果您只想將值傳送到特定平台,「請勿」使用一般欄位;請使用平台專屬欄位。舉例來說,如果只想傳送通知到 Apple 平台和網路,而不傳送至 Android,則必須使用兩組不同的欄位,分別用於 Apple 和網站。

傳送含有特定傳送選項的訊息時,請使用平台專用欄位來設定。如有需要,您可以為每個平台指定不同的值。不過,即使您想跨平台設定本質上相同的值,也必須使用平台專屬欄位。這是因為每個平台解讀這個值可能略有不同,例如,在 Android 上將使用時間設為以秒為單位的到期時間,而在 Apple 上則設定為到期時間 date

示例:含有顏色和圖示選項的通知訊息

這個傳送範例會將通用通知標題和內容傳送至所有平台,但也會傳送部分平台專屬的覆寫值至 Android 裝置。

如果是 Android,要求會設定 Android 裝置要顯示的特殊圖示和顏色。如 AndroidNotification 參考資料中所述,系統會以 #rrggbb 格式指定顏色,且圖片必須是 Android 應用程式本機的可繪製圖示資源。

以下概略說明使用者裝置對視覺效果的影響:

兩部裝置的簡易繪圖,其中一部顯示自訂圖示和顏色

Node.js

const topicName = 'industry-tech';

const message = {
  notification: {
    title: '`$FooCorp` up 1.43% on the day',
    body: 'FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day.'
  },
  android: {
    notification: {
      icon: 'stock_ticker_update',
      color: '#7e55c3'
    }
  },
  topic: topicName,
};

getMessaging().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

Message message = Message.builder()
    .setNotification(Notification.builder()
        .setTitle("$GOOG up 1.43% on the day")
        .setBody("$GOOG gained 11.80 points to close at 835.67, up 1.43% on the day.")
        .build())
    .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

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":"industry-tech",
     "notification":{
       "title":"`$FooCorp` up 1.43% on the day",
       "body":"FooCorp gained 11.80 points to close at 835.67, up 1.43% on the day."
     },
     "android":{
       "notification":{
         "icon":"stock_ticker_update",
         "color":"#7e55c3"
       }
     }
   }
 }

請參閱 HTTP v1 參考說明文件,瞭解訊息主體中平台專屬區塊可用的金鑰完整資訊。

範例:包含自訂圖片的通知訊息

以下傳送要求範例會將通用通知標題傳送至所有平台,但也會傳送圖片。以下是使用者裝置的視覺效果:

顯示通知中的圖片簡易繪圖

Node.js

const topicName = 'industry-tech';

const message = {
  notification: {
    title: 'Sparky says hello!'
  },
  android: {
    notification: {
      imageUrl: 'https://foo.bar.pizza-monster.png'
    }
  },
  apns: {
    payload: {
      aps: {
        'mutable-content': 1
      }
    },
    fcm_options: {
      image: 'https://foo.bar.pizza-monster.png'
    }
  },
  webpush: {
    headers: {
      image: 'https://foo.bar.pizza-monster.png'
    }
  },
  topic: topicName,
};

getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

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":"industry-tech",
     "notification":{
       "title":"Sparky says hello!",
     },
     "android":{
       "notification":{
         "image":"https://foo.bar/pizza-monster.png"
       }
     },
     "apns":{
       "payload":{
         "aps":{
           "mutable-content":1
         }
       },
       "fcm_options": {
           "image":"https://foo.bar/pizza-monster.png"
       }
     },
     "webpush":{
       "headers":{
         "image":"https://foo.bar/pizza-monster.png"
       }
     }
   }
 }

請參閱 HTTP v1 參考說明文件,瞭解訊息主體中平台專屬區塊可用的金鑰完整資訊。

範例:與相關點擊動作相關的通知訊息

以下傳送要求範例會將通用通知標題傳送至所有平台,但也會傳送應用程式要執行的動作,以回應使用者與通知互動的情況。以下概略說明使用者裝置對視覺效果的影響:

使用者輕觸以開啟網頁的簡易繪圖

Node.js

const topicName = 'industry-tech';

const message = {
  notification: {
    title: 'Breaking News....'
  },
  android: {
    notification: {
      clickAction: 'news_intent'
    }
  },
  apns: {
    payload: {
      aps: {
        'category': 'INVITE_CATEGORY'
      }
    }
  },
  webpush: {
    fcmOptions: {
      link: 'breakingnews.html'
    }
  },
  topic: topicName,
};

getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

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":"industry-tech",
     "notification":{
       "title":"Breaking News...",
     },
     "android":{
       "notification":{
         "click_action":"news_intent"
       }
     },
     "apns":{
       "payload":{
         "aps":{
           "category" : "INVITE_CATEGORY"
         }
       },
     },
     "webpush":{
       "fcm_options":{
         "link":"breakingnews.html"
       }
     }
   }
 }

請參閱 HTTP v1 參考說明文件,瞭解訊息主體中平台專屬區塊可用的金鑰完整資訊。

示例:含有本地化選項的通知訊息

以下傳送要求範例會傳送本地化選項,讓用戶端顯示本地化訊息。以下概略說明使用者裝置對視覺效果的影響:

簡單的繪圖:兩部裝置顯示英文和西班牙文文字

Node.js

var topicName = 'industry-tech';

var message = {
  android: {
    ttl: 3600000,
    notification: {
      bodyLocKey: 'STOCK_NOTIFICATION_BODY',
      bodyLocArgs: ['FooCorp', '11.80', '835.67', '1.43']
    }
  },
  apns: {
    payload: {
      aps: {
        alert: {
          locKey: 'STOCK_NOTIFICATION_BODY',
          locArgs: ['FooCorp', '11.80', '835.67', '1.43']
        }
      }
    }
  },
  topic: topicName,
};

getMessaging().send(message)
  .then((response) => {
    // Response is a message ID string.
    console.log('Successfully sent message:', response);
  })
  .catch((error) => {
    console.log('Error sending message:', error);
  });

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":"Tech",
             "android":{
               "ttl":"3600s",
               "notification":{
                 "body_loc_key": "STOCK_NOTIFICATION_BODY",
                 "body_loc_args":  ["FooCorp", "11.80", "835.67", "1.43"],
               },
             },
             "apns":{
               "payload":{
                 "aps":{
                   "alert" : {
                     "loc-key": "STOCK_NOTIFICATION_BODY",
                     "loc-args":  ["FooCorp", "11.80", "835.67", "1.43"],
                    },
                 },
               },
             },
  },
}'

請參閱 HTTP v1 參考說明文件,瞭解訊息主體中平台專屬區塊可用的金鑰完整資訊。

HTTP v1 API 的 REST 錯誤代碼

HTTP v1 API 的 HTTP 錯誤回應包含錯誤代碼、錯誤訊息和錯誤狀態。這些註解也可能包含 details 陣列,且該陣列會提供更多錯誤詳細資料。

以下列舉兩個錯誤回應範例:

示例 1:資料訊息內含無效值的 HTTP v1 API 要求所發出的錯誤回應

{
  "error": {
    "code": 400,
    "message": "Invalid value at 'message.data[0].value' (TYPE_STRING), 12",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.rpc.BadRequest",
        "fieldViolations": [
          {
            "field": "message.data[0].value",
            "description": "Invalid value at 'message.data[0].value' (TYPE_STRING), 12"
          }
        ]
      }
    ]
  }
}

示例 2:包含註冊權杖無效 HTTP v1 API 要求的錯誤回應

{
  "error": {
    "code": 400,
    "message": "The registration token is not a valid FCM registration token",
    "status": "INVALID_ARGUMENT",
    "details": [
      {
        "@type": "type.googleapis.com/google.firebase.fcm.v1.FcmError",
        "errorCode": "INVALID_ARGUMENT"
      }
    ]
   }
}

請注意,這兩則訊息的代碼和狀態都相同,但 details 陣列含有不同類型的值。第一個範例的類型 type.googleapis.com/google.rpc.BadRequest 表示要求值發生錯誤。類型為 type.googleapis.com/google.firebase.fcm.v1.FcmError 的第二個範例含有 FCM 特定錯誤。針對許多錯誤,details 陣列包含您偵錯並找出解決方式所需的資訊。

下表列出 FCM v1 REST API 錯誤代碼及相關說明。

錯誤碼 說明與解決步驟
UNSPECIFIED_ERROR無法取得這個錯誤的詳細資訊。
INVALID_ARGUMENT (HTTP 錯誤代碼 = 400) 要求參數無效。系統會傳回 google.rpc.BadRequest 類型的延伸模組,指定無效欄位。 可能的原因包括註冊無效、套件名稱無效、訊息過大、資料金鑰無效、存留時間無效,或其他參數無效。
註冊無效:請檢查您傳送至伺服器的註冊權杖格式。必須與用戶端應用程式註冊 FCM 後收到的註冊權杖相符。請勿截斷符記或新增其他字元。
套件名稱無效:請確認訊息寄送地址是註冊權杖,而且該註冊權杖的套件名稱與要求中傳送的值相符。
郵件太大:檢查訊息內含的酬載資料總大小並未超過 FCM 限制:大多數訊息為 4096 個位元組;如果訊息傳送至主題則為 2048 位元組。包括鍵和值。
資料金鑰無效:請確認酬載資料不含 FCM 內部使用的鍵 (例如 from、gcm 或任何 google 前置字串的值)。請注意,FCM 也會使用某些字詞 (例如 merge_key),但有效酬載中允許,在此情況下,FCM 值會覆寫酬載值。
存留時間無效:請確認 ttl 中使用的值是整數,代表介於 0 至 2,419,200 (4 週) 之間的時間長度秒數。
參數無效:請確認提供的參數名稱和類型正確無誤。
UNREGISTERED (HTTP 錯誤代碼 = 404) 已從 FCM 取消註冊應用程式執行個體。這通常表示您使用的權杖已經失效,必須使用新的權杖。 缺少註冊權杖或未註冊權杖都可能導致這項錯誤。
缺少註冊資訊:如果訊息的目標為 token 值,請檢查要求是否包含註冊權杖。
未註冊:現有的註冊權杖可能會在許多情況下失效,包括:
- 如果用戶端應用程式向 FCM 取消註冊,
- 如果用戶端應用程式為自動取消註冊,當使用者解除安裝應用程式時,就可能發生這種情況。舉例來說,在 iOS 上,如果 APNs 意見回饋服務將 APN 權杖回報為無效,
- 如果註冊權杖已過期 (例如 Google 可能會決定更新註冊權杖,或者 iOS 裝置的 APN 權杖已失效)。
- 如果用戶端應用程式已更新,但新版本未設為接收訊息。
針對上述所有情況,請從應用程式伺服器中移除這個註冊權杖,並停止使用該權杖傳送訊息。
SENDER_ID_MISMATCH (HTTP 錯誤代碼 = 403) 已驗證的寄件者 ID 與註冊權杖的傳送者 ID 不同。 註冊權杖與特定的寄件者群組相關聯。用戶端應用程式註冊 FCM 時,必須指定允許哪些寄件者傳送訊息。傳送郵件至用戶端應用程式時,請務必使用其中一個傳送者 ID。如果改用其他傳送者,現有的註冊權杖將無法運作。
QUOTA_EXCEEDED (HTTP 錯誤代碼 = 429) 訊息目標的傳送上限已超過上限。系統會傳回 google.rpc.QuotaFailure 類型的擴充功能,指定已經超出的配額。 這可能是因為訊息比率超過配額、超出裝置訊息傳送率配額,或超過主題訊息比率配額。
郵件傳送頻率超過上限:訊息傳送率過高。您必須降低整體傳送訊息的速率。使用指數輪詢策略,並將初始延遲時間設為至少 1 分鐘,藉此重試遭到拒絕的訊息。
裝置訊息比率超過上限:傳送至特定裝置的訊息比率過高。請參閱僅限單一裝置的訊息頻率請減少傳送至這部裝置的訊息數量,並使用指數輪詢策略重試傳送。
超過主題訊息比率:向訂閱者傳送特定主題的訊息比率過高。請減少為這個主題傳送的訊息數量,並採用指數輪詢策略,將初始延遲時間設為至少 1 分鐘,然後重試傳送。
UNAVAILABLE (HTTP 錯誤代碼 = 503) 伺服器超載。 伺服器無法及時處理這項要求。重試相同的要求,但您必須採取以下動作:
- 如果 FCM 連線伺服器的回應中含有 Retrie-After 標頭。
- 在重試機制中實作指數輪詢。(例如,如果您等待一秒就送出一次重試,請至少等待兩秒鐘,再等待 2 秒鐘,再等待 4 秒,依此類推)。如果您要傳送多則訊息,請考慮套用時基誤差。詳情請參閱處理重試。造成問題風險遭拒絕的寄件者。
INTERNAL (HTTP 錯誤代碼 = 500) 發生未知的內部錯誤。 伺服器在嘗試處理要求時發生錯誤。您可以按照「處理重試」一文的建議,重試相同的要求。如果錯誤持續發生,請與 Firebase 支援團隊聯絡。
THIRD_PARTY_AUTH_ERROR (HTTP 錯誤代碼 = 401) APN 憑證或網路推送驗證金鑰無效或遺失。 無法傳送指定 iOS 裝置或網路推送註冊的訊息。檢查開發和實際工作環境憑證是否有效。

管理員錯誤代碼

下表列出 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 位元組。傳送至主題的訊息大小上限為 2,048 個位元組。總酬載大小包含鍵和值。
messaging/invalid-options 提供的訊息選項物件無效。錯誤訊息應包含額外資訊。
messaging/invalid-registration-token 提供的註冊權杖無效。請確保用戶端應用程式透過 FCM 註冊時收到的註冊權杖相符。請勿截斷或加入其他字元。
messaging/registration-token-not-registered 提供的註冊權杖未註冊。先前有效的註冊權杖可能會因為多種原因而遭到取消註冊,包括:
  • 用戶端應用程式本身已從 FCM 取消註冊。
  • 用戶端應用程式已自動取消註冊。如果使用者解除安裝應用程式,或是在 Apple 平台上將 APN 權杖回報為無效,就可能會發生這種情況。
  • 註冊權杖已過期,舉例來說,Google 可能會決定更新註冊權杖,或者 Apple 裝置的 APN 權杖可能已過期。
  • 用戶端應用程式已更新,但新版本未設為接收訊息。
針對上述所有情況,請移除這個註冊權杖,並停止使用該權杖傳送訊息。
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 未上傳必要的 APN SSL 憑證或訊息已過期,因此無法傳送指定 Apple 裝置的訊息。請檢查開發憑證和正式版憑證是否有效。
messaging/mismatched-credential 用來驗證這個 SDK 的憑證無權傳送訊息到與指定註冊權杖對應的裝置。請確定憑證和註冊權杖都屬於同一個 Firebase 專案。如要瞭解如何驗證 Firebase Admin SDK,請參閱「將 Firebase 新增至應用程式」一文。
messaging/authentication-error SDK 無法驗證 FCM 伺服器。請務必使用具備適當權限來傳送 FCM 訊息的憑證來驗證 Firebase Admin SDK。如要瞭解如何驗證 Firebase Admin SDK,請參閱「將 Firebase 新增至應用程式」一文。
messaging/server-unavailable FCM 伺服器無法及時處理這項要求。您應重試相同的要求,但必須:
  • 如果 Retry-After 標頭包含在 FCM 連線伺服器的回應中,請使用標頭。
  • 在重試機制中實作指數輪詢策略。例如,假設您在第一次重試之前等待一秒,請至少在接下來 2 秒鐘後再等待 4 秒,依此類推。如果您要傳送多則訊息,請以額外的隨機數量逐一延遲每個訊息,以免同時對所有訊息發出新的要求。
系統會將造成問題風險的寄件者列入黑名單。
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 連線伺服器提供其他回應回應的選項。請參閱伺服器回應格式

如需傳送下游訊息給用戶端應用程式時可用的完整訊息選項清單,請參閱所選連線伺服器通訊協定: HTTP XMPP 的參考資訊。

傳送訊息至主題

傳送訊息至 Firebase 雲端通訊主題,與傳送訊息給個別裝置或使用者群組非常相似。應用程式伺服器使用 /topics/yourTopic 之類的值設定 to 鍵。開發人員可以選擇任何符合規則運算式的主題名稱:"/topics/[a-zA-Z0-9-_.~%]+"

如要傳送至多個主題的組合,應用程式伺服器必須將 condition 鍵 (而非 to 鍵) 設為指定目標主題的布林值條件。舉例來說,如要將訊息傳送至訂閱 TopicA 以及 TopicBTopicC 的裝置,請執行以下操作:

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

FCM 會先評估括號中的所有條件,再從左到右評估運算式。在上述運算式中,訂閱任何單一主題的使用者不會收到訊息。同樣地,未訂閱 TopicA 的使用者也不會收到訊息。下列組合會收到:

  • 主題 A 和 主題 B
  • 主題 A 和 主題 C

條件運算式中最多可加入五個主題,系統支援使用括號。支援的運算子:&&||

主題 HTTP POST 要求

傳送到單一主題:

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


傳送到訂閱「狗」或「貓」主題的裝置:

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>

傳送到訂閱「狗」或「貓」主題的裝置:

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


  </gcm>
</message>

主題 XMPP 回應

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

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

請注意,FCM 伺服器最多會延遲 30 秒,才會對主題傳送要求傳回成功或失敗的回應。請務必在相應要求中設定應用程式伺服器的逾時值。

傳送訊息至裝置群組

使用已淘汰的舊版 API 傳送訊息給裝置群組,與傳送訊息至個別裝置的方式非常相似。將 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 個相關聯的註冊權杖。訊息已成功傳送至 1 個註冊權杖。回應訊息會列出無法接收訊息的註冊權杖 (registration_ids):

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

如果訊息無法傳送至一或多個與 notification_key 相關聯的註冊權杖,應用程式伺服器應在重試之間進行輪詢重試。

如果伺服器嘗試將訊息傳送至沒有成員的裝置群組,回應會如下所示,不會列出成功且 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 個相關聯的註冊權杖,且訊息已成功傳送給所有:

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

以下是「部分成功」的範例,notification_key 有 3 個相關聯的註冊權杖。訊息已成功傳送至 1 個註冊權杖。回應訊息會列出無法接收訊息的註冊權杖:

{
  "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.
const registrationToken = 'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...';

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

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

sendToDevice() 方法也可以傳送多點傳送訊息 (也就是傳送訊息給多部裝置),方法是傳遞註冊權杖陣列,而非只傳送單一註冊權杖:

Node.js

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

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

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

sendToDevice() 方法會傳回承諾,該承諾使用包含 FCM 回應的 MessagingDevicesResponse 物件解析。傳遞單一註冊權杖或註冊權杖陣列時,傳回類型的格式相同。

某些情況下 (例如驗證錯誤或頻率限制) 會導致系統無法處理整個訊息。在這種情況下,sendToDevice() 傳回的承諾會遭到拒絕,並顯示錯誤。如需錯誤代碼的完整清單,包括說明和解決步驟,請參閱「Admin FCM API 錯誤」。

傳送至裝置群組

sendToDeviceGroup() 方法可讓您指定該裝置群組的通知鍵,向裝置群組傳送訊息:

Node.js

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

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

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

sendToDeviceGroup() 方法會傳回承諾,該承諾使用包含 FCM 回應的 MessagingDevicesResponse 物件解析。

某些情況下 (例如驗證錯誤或頻率限制) 會導致系統無法處理整個訊息。在這種情況下,sendToDeviceGroup() 傳回的承諾會遭到拒絕,並顯示錯誤。如需錯誤代碼的完整清單,包括說明和解決步驟,請參閱「Admin FCM API 錯誤」。

定義訊息酬載

上述以 FCM 舊版通訊協定為基礎的方法會接受訊息酬載做為其第二個引數,並支援通知與資料訊息。您可以使用 data 和 / 或 notification 鍵建立物件,藉此指定一或兩種訊息類型。例如,以下說明如何定義不同類型的訊息酬載:

通知訊息

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

資料訊息

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

合併訊息

const payload = {
  notification: {
    title: '$FooCorp up 1.43% on the day',
    body: '$FooCorp 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.
const registrationToken = 'bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...';

// See the "Defining the message payload" section above for details
// on how to define a message payload.
const 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.
const options = {
  priority: 'high',
  timeToLive: 60 * 60 * 24
};

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

如需可用選項的完整清單,請參閱 MessagingOptions 的參考文件。