使用已棄用的 HTTP 和 XMPP FCM 舊版 API 的應用程式應儘早遷移到 HTTP v1 API。除了持續的支援和新功能之外,HTTP v1 API 相對於舊版 API 還具有以下優勢:
透過存取令牌提高安全性HTTP v1 API 根據 OAuth2 安全模型使用短期存取權杖。如果存取令牌公開,它只能被惡意使用一個小時左右,然後就會過期。刷新令牌的傳輸頻率不像舊 API 中使用的安全金鑰那麼頻繁,因此它們被捕獲的可能性要小得多。
跨平台更有效率地自訂訊息對於訊息正文,HTTP v1 API 具有可存取所有目標實例的通用金鑰,以及可讓您跨平台自訂訊息的特定於平台的金鑰。這允許您建立“覆蓋”,在單一訊息中將略有不同的有效負載傳送到不同的客戶端平台。
新客戶端平台版本的可擴展性更強且面向未來HTTP v1 API 完全支援 Apple 平台、Android 和 Web 上提供的訊息傳遞選項。由於每個平台在 JSON 有效負載中都有自己定義的區塊,因此 FCM 可以根據需要將 API 擴展到新版本和新平台。
更新伺服器端點
HTTP v1 API 的端點 URL 與舊端點的差異如下:
- 它是有版本的,路徑中帶有
/v1
。 - 此路徑包含您的套用的 Firebase 專案的專案 ID,格式為
/projects/myproject-ID/
。此 ID 可在 Firebase 控制台的常規項目設定標籤中找到。 - 它明確指定
send
方法為:send
。
若要更新 HTTP v1 的伺服器端點,請將這些元素新增至傳送請求標頭中的端點。
之前的 HTTP 請求
POST https://fcm.googleapis.com/fcm/send
之前的 XMPP 請求
舊版 XMPP 訊息透過連線傳送到以下端點:
fcm-xmpp.googleapis.com:5235
後
POST https://fcm.googleapis.com/v1/projects/myproject-b5ae1/messages:send
更新發送請求的授權
HTTP v1 傳送請求需要 OAuth 2.0 存取令牌,而不是舊請求中使用的伺服器金鑰字串。如果您使用 Admin SDK 傳送訊息,該程式庫會為您處理令牌。如果您使用的是原始協議,請按照本節中所述獲取令牌,並將其新增至標頭中,格式為Authorization: Bearer <valid Oauth 2.0 token>
。
前
Authorization: key=AIzaSyZ-1u...0GBYzPu7Udno5aA
後
Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA
根據伺服器環境的詳細信息,使用以下策略的組合來授權對 Firebase 服務的伺服器請求:
- Google 應用程式預設憑證 (ADC)
- 服務帳戶 JSON 文件
- 從服務帳戶派生的短暫 OAuth 2.0 存取令牌
如果您的應用程式在 Compute Engine、Google Kubernetes Engine、App Engine 或 Cloud Functions(包括 Cloud Functions for Firebase)上執行,請使用應用程式預設憑證 (ADC)。 ADC 使用您現有的預設服務帳戶來取得憑證來授權請求,並且 ADC 透過環境變數GOOGLE_APPLICATION_CREDENTIALS啟用靈活的本機測試。為了實現授權流程的最完全自動化,請將 ADC 與 Admin SDK 伺服器庫一起使用。
如果您的應用程式在非 Google 伺服器環境上執行,則需要從 Firebase 專案下載服務帳戶 JSON 檔案。只要您有權存取包含私鑰檔案的檔案系統,就可以使用環境變數GOOGLE_APPLICATION_CREDENTIALS透過這些手動取得的憑證來授權請求。如果您缺乏此類文件存取權限,則必須在程式碼中引用服務帳戶文件 - 由於存在暴露憑證的風險,因此應格外小心。
使用 ADC 提供憑證
Google 應用程式預設憑證 (ADC) 會依照下列順序檢查您的憑證:
ADC 檢查環境變數GOOGLE_APPLICATION_CREDENTIALS是否已設定。如果設定了該變量,ADC 將使用該變數指向的服務帳戶檔案。
如果未設定環境變量,ADC 將使用 Compute Engine、Google Kubernetes Engine、App Engine 和 Cloud Functions 為在這些服務上執行的應用程式提供的預設服務帳戶。
如果 ADC 無法使用上述任一憑證,系統將會引發錯誤。
以下 Admin SDK 程式碼範例說明了此策略。此範例未明確指定應用程式憑證。但是,只要設定了環境變量,或只要應用程式在 Compute Engine、Google Kubernetes Engine、App Engine 或 Cloud Functions 上執行,ADC 就能夠隱含地找到憑證。
Node.js
admin.initializeApp({
credential: admin.credential.applicationDefault(),
});
爪哇
FirebaseOptions options = FirebaseOptions.builder()
.setCredentials(GoogleCredentials.getApplicationDefault())
.setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
.build();
FirebaseApp.initializeApp(options);
Python
default_app = firebase_admin.initialize_app()
去
app, err := firebase.NewApp(context.Background(), nil)
if err != nil {
log.Fatalf("error initializing app: %v\n", err)
}
C#
FirebaseApp.Create(new AppOptions()
{
Credential = GoogleCredential.GetApplicationDefault(),
});
手動提供憑證
Firebase 專案支援 Google服務帳戶,您可以使用它從應用程式伺服器或受信任的環境中呼叫 Firebase 伺服器 API。如果您在本機開發程式碼或在本機部署應用程序,則可以使用透過此服務帳戶取得的憑證來授權伺服器請求。
若要對服務帳戶進行驗證並授權其存取 Firebase 服務,您必須產生 JSON 格式的私鑰檔案。
要為您的服務帳戶產生私鑰檔案:
在 Firebase 控制台中,開啟設定 >服務帳戶。
按一下「產生新私鑰」 ,然後按一下「產生金鑰」進行確認。
安全地儲存包含金鑰的 JSON 檔案。
透過服務帳戶授權時,您有兩種選擇向應用程式提供憑證。您可以設定GOOGLE_APPLICATION_CREDENTIALS環境變量,也可以在程式碼中明確傳遞服務帳戶金鑰的路徑。第一個選項更安全,強烈建議。
設定環境變數:
將環境變數GOOGLE_APPLICATION_CREDENTIALS設定為包含服務帳戶金鑰的 JSON 檔案的檔案路徑。此變數僅適用於目前的 shell 會話,因此如果您開啟新會話,請再次設定該變數。
Linux 或 macOS
export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"
視窗
使用 PowerShell:
$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"
完成上述步驟後,應用程式預設憑證 (ADC) 能夠隱含地確定您的憑證,從而允許您在非 Google 環境中測試或執行時使用服務帳戶憑證。
使用憑證建立存取令牌
將您的 Firebase 憑證與您的首選語言的Google Auth 庫一起使用,以檢索短期 OAuth 2.0 存取權令牌:
節點.js
function getAccessToken() {
return new Promise(function(resolve, reject) {
const key = require('../placeholders/service-account.json');
const jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
SCOPES,
null
);
jwtClient.authorize(function(err, tokens) {
if (err) {
reject(err);
return;
}
resolve(tokens.access_token);
});
});
}
在此範例中,Google API 用戶端程式庫使用 JSON Web 令牌或 JWT 對請求進行身份驗證。有關更多信息,請參閱JSON Web 令牌。
Python
def _get_access_token():
"""Retrieve a valid access token that can be used to authorize requests.
:return: Access token.
"""
credentials = service_account.Credentials.from_service_account_file(
'service-account.json', scopes=SCOPES)
request = google.auth.transport.requests.Request()
credentials.refresh(request)
return credentials.token
爪哇
private static String getAccessToken() throws IOException {
GoogleCredentials googleCredentials = GoogleCredentials
.fromStream(new FileInputStream("service-account.json"))
.createScoped(Arrays.asList(SCOPES));
googleCredentials.refresh();
return googleCredentials.getAccessToken().getTokenValue();
}
存取令牌過期後,會自動呼叫令牌刷新方法以檢索更新的存取令牌。
若要授權存取 FCM,請請求範圍https://www.googleapis.com/auth/firebase.messaging
。
若要將存取權杖新增至 HTTP 請求標頭:
將令牌新增為Authorization
標頭的值,格式為Authorization: Bearer <access_token>
:
節點.js
headers: {
'Authorization': 'Bearer ' + accessToken
}
Python
headers = {
'Authorization': 'Bearer ' + _get_access_token(),
'Content-Type': 'application/json; UTF-8',
}
爪哇
URL url = new URL(BASE_URL + FCM_SEND_ENDPOINT);
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
httpURLConnection.setRequestProperty("Authorization", "Bearer " + getServiceAccountAccessToken());
httpURLConnection.setRequestProperty("Content-Type", "application/json; UTF-8");
return httpURLConnection;
更新發送請求的負載
FCM HTTP v1 在 JSON 訊息負載的結構中引入了重大變更。主要是,這些變更確保在不同客戶端平台上接收訊息時能夠正確處理訊息;此外,這些變更為您提供了額外的靈活性,可以自訂或「覆蓋」每個平台的訊息欄位。
除了檢查本節中的範例之外,請參閱跨平台自訂訊息並查看API 參考以熟悉 HTTP v1。
範例:簡單的通知訊息
以下是一個非常簡單的通知有效負載(僅包含title
、 body
和data
欄位)的比較,展示了舊版有效負載和 HTTP v1 有效負載的根本差異。
前
{
"to": "/topics/news",
"notification": {
"title": "Breaking News",
"body": "New news story available."
},
"data": {
"story_id": "story_12345"
}
}
後
{
"message": {
"topic": "news",
"notification": {
"title": "Breaking News",
"body": "New news story available."
},
"data": {
"story_id": "story_12345"
}
}
}
範例:針對多個平台
為了實現多平台定位,舊版 API 在後端執行了覆蓋。相較之下,HTTP v1 提供了特定於平台的密鑰塊,使平台之間的任何差異對開發人員來說都是明確可見的。這允許您始終透過單一請求定位多個平台,如下例所示。
前
// Android
{
"to": "/topics/news",
"notification": {
"title": "Breaking News",
"body": "New news story available.",
"click_action": "TOP_STORY_ACTIVITY"
},
"data": {
"story_id": "story_12345"
}
}
// Apple
{
"to": "/topics/news",
"notification": {
"title": "Breaking News",
"body": "New news story available.",
"click_action": "HANDLE_BREAKING_NEWS"
},
"data": {
"story_id": "story_12345"
}
}
後
{
"message": {
"topic": "news",
"notification": {
"title": "Breaking News",
"body": "New news story available."
},
"data": {
"story_id": "story_12345"
},
"android": {
"notification": {
"click_action": "TOP_STORY_ACTIVITY"
}
},
"apns": {
"payload": {
"aps": {
"category" : "NEW_MESSAGE_CATEGORY"
}
}
}
}
}
範例:使用平台覆蓋進行自訂
除了簡化訊息的跨平台定位之外,HTTP v1 API 還提供了根據平台自訂訊息的靈活性。
前
// Android
{
"to": "/topics/news",
"notification": {
"title": "Breaking News",
"body": "Check out the Top Story.",
"click_action": "TOP_STORY_ACTIVITY"
},
"data": {
"story_id": "story_12345"
}
}
// Apple
{
"to": "/topics/news",
"notification": {
"title": "Breaking News",
"body": "New news story available.",
"click_action": "HANDLE_BREAKING_NEWS"
},
"data": {
"story_id": "story_12345"
}
}
後
{
"message": {
"topic": "news",
"notification": {
"title": "Breaking News",
"body": "New news story available."
},
"data": {
"story_id": "story_12345"
},
"android": {
"notification": {
"click_action": "TOP_STORY_ACTIVITY",
"body": "Check out the Top Story"
}
},
"apns": {
"payload": {
"aps": {
"category" : "NEW_MESSAGE_CATEGORY"
}
}
}
}
}
範例:針對特定設備
若要使用 HTTP v1 API 定位特定設備,請在token
鍵(而非to
鍵)中提供裝置的目前註冊令牌。
前
{ "notification": {
"body": "This is an FCM notification message!",
"time": "FCM Message"
},
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1..."
}
後
{
"message":{
"token":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification":{
"body":"This is an FCM notification message!",
"title":"FCM Message"
}
}
}
有關 FCM HTTP v1 API 的更多範例和信息,請參閱以下內容:
有關如何建立應用程式伺服器並使用 HTTP v1 API 發送請求的指南。除非特別說明,所有「REST」片段均使用 v1 API。