מעבר מממשקי API מדור קודם של FCM ל-HTTP v1

אפליקציות שמשתמשות בממשקי ה-API הקודמים של FCM ל-HTTP ול-XMPP צריכות לעבור ל-HTTP v1 API בהקדם האפשרי. ב-20 ביוני 2023 הוצאנו משימוש את האפשרות לשלוח הודעות (כולל הודעות מ-upstream) באמצעות ממשקי ה-API האלה, והשבתה שלהם תתחיל ב-22 ביולי 2024.

מידע נוסף על התכונות הספציפיות שמושפעות

בנוסף לתמיכה שוטפת ולתכונות חדשות, ל-HTTP v1 API יש את היתרונות הבאים על פני ממשקי ה-API מהדור הקודם:

  • אבטחה משופרת באמצעות אסימוני גישה ב-API של HTTP v1 נעשה שימוש באסימוני גישה לטווח קצר בהתאם למודל האבטחה של OAuth2. אם אסימון הגישה יהפוך לציבורי, אפשר יהיה להשתמש בו לרעה רק למשך שעה בערך לפני שתוקף האסימון יפוג. אסימוני הרענון לא מועברים בתדירות גבוהה כמו מפתחות האבטחה שמשמשים ב-API הקודם, ולכן הסיכוי שהם ייחשפו נמוך בהרבה.

  • התאמה אישית יעילה יותר של הודעות בפלטפורמות שונות לגוף ההודעה, ל-HTTP v1 API יש מפתחות משותפים שנשלחים לכל המכונות המטורגטות, וגם מפתחות ספציפיים לפלטפורמה שמאפשרים להתאים אישית את ההודעה בפלטפורמות שונות. כך אפשר ליצור 'עקיפות' ששולחות עומסי נתונים שונים במקצת לפלטפורמות לקוח שונות בהודעה אחת.

  • אפשרות להרחבה רבה יותר ותאימות לעתיד לגרסאות חדשות של פלטפורמות לקוח ממשק ה-API של HTTP v1 תומך באופן מלא באפשרויות שליחת ההודעות שזמינות בפלטפורמות של Apple, ב-Android ובאינטרנט. מכיוון שלכל פלטפורמה יש בלוק מוגדר משלה בעומס העבודה ב-JSON, אפשר להרחיב את ה-API לגרסאות חדשות ולפלטפורמות חדשות לפי הצורך.FCM

עדכון נקודת הקצה של השרת

כתובת ה-URL של נקודת הקצה של ה-API ל-HTTP v1 שונה מנקודת הקצה הקודמת בדרכים הבאות:

  • הוא מחולק לגרסאות, עם /v1 בנתיב.
  • הנתיב מכיל את מזהה הפרויקט של פרויקט Firebase של האפליקציה, בפורמט /projects/myproject-ID/. המזהה הזה זמין בכרטיסייה General project settings במסוף 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 כדי לשלוח הודעות, הספרייה מטפלת באסימון בשבילכם. אם אתם משתמשים בפרוטוקול גולמי של EEF, צריך לקבל את האסימון כפי שמתואר בקטע הזה ולהוסיף אותו לכותרת בתור Authorization: Bearer <valid Oauth 2.0 token>.

לפני

Authorization: key=AIzaSyZ-1u...0GBYzPu7Udno5aA

אחרי

Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

בהתאם לפרטים של סביבת השרת, אפשר להשתמש בשילוב של אסטרטגיות האלה כדי לאשר בקשות מהשרת לשירותי Firebase:

  • Google Application Default Credentials‏ (ADC)
  • קובץ JSON של חשבון שירות
  • אסימון גישה לטווח קצר מסוג OAuth 2.0 שמבוסס על חשבון שירות

אם האפליקציה שלכם פועלת ב-Compute Engine,‏ Google Kubernetes Engine,‏ App Engine או ב-Cloud Functions (כולל Cloud Functions for Firebase), השתמשו ב-Application Default Credentials ‏ (ADC). מערכת ADC משתמשת בחשבון השירות המוגדר כברירת מחדל כדי לקבל פרטי כניסה להרשאת בקשות, והיא מאפשרת בדיקה מקומית גמישה באמצעות משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS. כדי לבצע אוטומציה מלאה של תהליך ההרשאה, צריך להשתמש ב-ADC יחד עם ספריות השרת של Admin SDK.

אם האפליקציה פועלת בסביבת שרת שאינה של Google, תצטרכו להוריד קובץ JSON של חשבון שירות מהפרויקט ב-Firebase. כל עוד יש לכם גישה למערכת קבצים שמכילה את קובץ המפתח הפרטי, תוכלו להשתמש במשתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS כדי לאשר בקשות באמצעות פרטי הכניסה האלה שהתקבלו באופן ידני. אם אין לכם גישה לקובץ כזה, עליכם להפנות לקובץ של חשבון השירות בקוד – וצריך לעשות זאת בזהירות רבה בגלל הסיכון לחשוף את פרטי הכניסה שלכם.

איך מספקים פרטי כניסה באמצעות ADC

השירות Application Default Credentials ‏ (ADC) של Google מחפש את פרטי הכניסה שלכם בסדר הבא:

  1. מערכת ADC בודקת אם משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS מוגדר. אם המשתנה מוגדר, חיפוש פרטי הכניסה ב-ADC מתבצע באמצעות קובץ חשבון השירות שהמשתנה מצביע אליו.

  2. אם משתנה הסביבה לא מוגדר, חיפוש פרטי הכניסה ב-ADC מתבצע באמצעות חשבון השירות שמוגדר כברירת מחדל ב-Compute Engine, ב-Google Kubernetes Engine, ב-App Engine וב-Cloud Functions לאפליקציות שפועלות בשירותים האלה.

  3. אם המערכת של ADC לא מצליחה להשתמש באף אחד מפרטי הכניסה האלה, המערכת תציג הודעת שגיאה.

דוגמת הקוד הבאה של Admin SDK ממחישה את האסטרטגיה הזו. בדוגמה לא צוינו באופן מפורש פרטי הכניסה של האפליקציה. עם זאת, ADC יכול למצוא את פרטי הכניסה באופן משתמע כל עוד משתנה הסביבה מוגדר, או כל עוד האפליקציה פועלת ב-Compute Engine, ב-Google Kubernetes Engine, ב-App Engine או ב-Cloud Functions.

Node.js

admin.initializeApp({
  credential: admin.credential.applicationDefault(),
});

Java

FirebaseOptions options = FirebaseOptions.builder()
    .setCredentials(GoogleCredentials.getApplicationDefault())
    .setDatabaseUrl("https://<DATABASE_NAME>.firebaseio.com/")
    .build();

FirebaseApp.initializeApp(options);

Python

default_app = firebase_admin.initialize_app()

Go

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, שבאמצעותם אפשר לבצע קריאה ל-API של שרת Firebase משרת האפליקציה או מסביבה מהימנה. אם אתם מפתחים קוד באופן מקומי או פורסים את האפליקציה בארגון, תוכלו להשתמש בפרטי הכניסה שהתקבלו דרך חשבון השירות הזה כדי לאשר בקשות מהשרת.

כדי לאמת חשבון שירות ולהעניק לו הרשאת גישה לשירותי Firebase, צריך ליצור קובץ מפתח פרטי בפורמט JSON.

כדי ליצור קובץ מפתח פרטי לחשבון השירות:

  1. במסוף Firebase, פותחים את Settings (הגדרות) > Service Accounts (חשבונות שירות).

  2. לוחצים על Generate New Private Key (יצירת מפתח פרטי חדש) ואז על Generate Key (יצירת מפתח) כדי לאשר.

  3. מאחסנים באופן מאובטח את קובץ ה-JSON שמכיל את המפתח.

כשאתם נותנים הרשאה דרך חשבון שירות, יש לכם שתי אפשרויות למסור את פרטי הכניסה לאפליקציה. אתם יכולים להגדיר את משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS או להעביר את הנתיב למפתח של חשבון השירות בקוד באופן מפורש. האפשרות הראשונה מאובטחת יותר ומומלצת מאוד.

כדי להגדיר את משתנה הסביבה:

מגדירים את משתנה הסביבה GOOGLE_APPLICATION_CREDENTIALS לנתיב של קובץ ה-JSON שמכיל את המַפְתח של חשבון השירות. המשתנה הזה חל רק על סשן המעטפת הנוכחי, כך שאם פותחים סשן חדש צריך להגדיר את המשתנה שוב.

Linux או macOS

export GOOGLE_APPLICATION_CREDENTIALS="/home/user/Downloads/service-account-file.json"

Windows

באמצעות PowerShell:

$env:GOOGLE_APPLICATION_CREDENTIALS="C:\Users\username\Downloads\service-account-file.json"

אחרי שתשלימו את השלבים שלמעלה, השירות Application Default Credentials (ADC) יוכל לקבוע באופן משתמע את פרטי הכניסה שלכם, כך שתוכלו להשתמש בפרטי הכניסה של חשבון השירות בזמן בדיקה או הפעלה בסביבות שאינן של Google.

שימוש בפרטי כניסה כדי ליצור אסימוני גישה

משתמשים בפרטי הכניסה ל-Firebase יחד עם ספריית האימות של Google בשפה המועדפת עליכם כדי לאחזר אסימון גישה לטווח קצר מסוג OAuth 2.0:

node.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‏ (JWT). למידע נוסף, ראו אסימוני אינטרנט מסוג JSON.

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

Java

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>:

node.js

headers: {
  'Authorization': 'Bearer ' + accessToken
}

Python

headers = {
  'Authorization': 'Bearer ' + _get_access_token(),
  'Content-Type': 'application/json; UTF-8',
}

Java

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.

דוגמה: הודעת התראה פשוטה

בהשוואה הבאה מוצגת הודעה פשוטה מאוד עם עומס נתונים (payload) שמכיל רק את השדות 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"
    }
  }
}

דוגמה: נתוני JSON בתצוגת עץ

בניגוד ל-Messaging API הקודם, ה-API של HTTP v1 לא תומך בערכי JSON בתצוגת עץ בשדה data. צריך לבצע המרה מ-JSON למחרוזת.

לפני

{
  ...
  "data": {
    "keysandvalues": {"key1": "value1", "key2": 123}
  }
}

אחרי

{
  "message": {
   ...
    "data": {
      "keysandvalues": "{\"key1\": \"value1\", \"key2\": 123}"
    }
  }
}

דוגמה: טירגוט לכמה פלטפורמות

כדי לאפשר טירגוט לכמה פלטפורמות, ה-API הקודם ביצע שינויים קודמים (overriding) בקצה העורפי. לעומת זאת, ב-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"
        }
      }
    }
  }
}

דוגמה: התאמה אישית באמצעות שינויים שמוגדרים ברמת הפלטפורמה

בנוסף לפשטות של טירגוט הודעות בפלטפורמות שונות, ממשק ה-API של HTTP v1 מספק גמישות בהתאמה אישית של הודעות לכל פלטפורמה.

לפני

// 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"
        }
      }
    }
  }
}

דוגמה: טירגוט למכשירים ספציפיים

כדי לטרגט מכשירים ספציפיים באמצעות ה-API של HTTP v1, צריך לספק את הטוקן הנוכחי של הרישום של המכשיר במפתח token במקום במפתח to.

לפני

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

אחרי

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

דוגמאות ומידע נוסף על ה-API של FCM HTTP v1 זמינים במאמרים הבאים: