Przejście ze starszych interfejsów API FCM na HTTP v1

Aplikacje korzystające ze starszych interfejsów API FCM dla protokołów HTTP i XMPP powinny jak najszybciej przejść na interfejs HTTP w wersji 1. Wysyłanie wiadomości (w tym wiadomości nadrzędnych) za pomocą tych interfejsów API zostało wycofane 20 czerwca 2023 r., a wyłączanie rozpocznie się 22 lipca 2024 r.

Dowiedz się więcej o funkcjach, na które ma wpływ ta zmiana.

Oprócz zapewniania stałego wsparcia i nowych funkcji interfejs HTTP w wersji 1 ma te zalety w porównaniu ze starszymi interfejsami:

  • Większe bezpieczeństwo dzięki tokenom dostępu Interfejs HTTP w wersji 1 używa tokenów dostępu o krótkim czasie ważności zgodnie z modelem zabezpieczeń OAuth2. Jeśli token dostępu stanie się publiczny, może być użyty do celów szkodliwych tylko przez około godzinę przed wygaśnięciem. Tokeny odświeżania nie są przesyłane tak często jak klucze bezpieczeństwa używane w starszym interfejsie API, więc prawdopodobieństwo ich przechwycenia jest mniejsze.

  • Bardziej wydajne dostosowywanie wiadomości na różnych platformach W przypadku treści wiadomości interfejs API HTTP w wersji 1 zawiera wspólne klucze, które są wysyłane do wszystkich docelowych instancji, oraz klucze specyficzne dla platformy, które umożliwiają dostosowywanie wiadomości na różnych platformach. Pozwala to tworzyć „nadpisania”, które wysyłają nieco inne ładunki do różnych platform klientów w jednej wiadomości.

  • Większa możliwość rozbudowy i przyszłości na potrzeby nowych wersji platform klienckich Interfejs HTTP v1 API w pełni obsługuje opcje przesyłania wiadomości dostępne na platformach Apple oraz w przeglądarkach i na urządzeniach z Androidem. Każda platforma ma własny blok zdefiniowany w pliku danych JSON, więc FCM może w razie potrzeby rozszerzać interfejs API o nowe wersje i nowe platformy.

Aktualizowanie punktu końcowego serwera

Adres URL punktu końcowego interfejsu HTTP w wersji 1 różni się od starszego punktu końcowego w tych aspektach:

  • Ma ona różne wersje, a w ścieżce znajduje się /v1.
  • Ścieżka zawiera identyfikator projektu Firebase Twojej aplikacji w formacie /projects/myproject-ID/. Ten identyfikator jest dostępny na karcie Ogólne ustawienia projektu w konsoli Firebase.
  • Wyraźnie określa metodę send jako :send.

Aby zaktualizować punkt końcowy serwera w przypadku HTTP w wersji 1, dodaj te elementy do punktu końcowego w nagłówku wysyłanych żądań.

Żądania HTTP przed

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

Żądania XMPP przed

Starsze wiadomości XMPP są wysyłane przez połączenie do tego punktu końcowego:

fcm-xmpp.googleapis.com:5235

Po

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

Aktualizacja autoryzacji żądań wysyłania

Zamiast ciągu klucza serwera używanego w starszych żądaniach żądania wysyłania HTTP w wersji 1 wymagają tokena dostępu OAuth 2.0. Jeśli do wysyłania wiadomości używasz pakietu Admin SDK, biblioteka będzie za Ciebie zarządzać tokenem. Jeśli używasz nieprzetworzonego protokołu, uzyskaj token w sposób opisany w tej sekcji i dodaj go do nagłówka jako Authorization: Bearer <valid Oauth 2.0 token>.

Przed

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

Po

Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

W zależności od szczegółów środowiska serwera użyj kombinacji tych strategii, aby autoryzować żądania serwera do usług Firebase:

  • Domyślne uwierzytelnianie aplikacji Google (ADC)
  • plik JSON konta usługi;
  • Ograniczony czasowo token dostępu OAuth 2.0 utworzony na podstawie konta usługi

Jeśli Twoja aplikacja działa w środowisku Compute Engine, Google Kubernetes Engine, App Engine lub Cloud Functions (w tym Cloud Functions for Firebase), użyj domyślnego uwierzytelniania aplikacji (ADC). ADC używa istniejącego domyślnego konta usługi do uzyskiwania danych logowania na potrzeby autoryzacji żądań. Pozwala też na elastyczne testowanie lokalne za pomocą zmiennej środowiskowej GOOGLE_APPLICATION_CREDENTIALS. Aby w pełni zautomatyzować proces autoryzacji, użyj ADC razem z bibliotekami serwera Admin SDK.

Jeśli Twoja aplikacja działa w środowisku serwera innym niż Google, musisz pobrać plik JSON konta usługi ze swojego projektu Firebase. Jeśli masz dostęp do systemu plików zawierającego plik klucza prywatnego, możesz użyć zmiennej środowiskowej GOOGLE_APPLICATION_CREDENTIALS, aby autoryzować żądania za pomocą tych danych logowania uzyskanych ręcznie. Jeśli nie masz dostępu do takich plików, musisz w kodze odwoływać się do pliku konta usługi. Należy to robić z bardzo dużą ostrożnością, ponieważ istnieje ryzyko ujawnienia danych logowania.

Podawanie danych logowania za pomocą ADC

Domyślne uwierzytelnianie aplikacji Google sprawdza Twoje poświadczenia w takim porządku:

  1. ADC sprawdza, czy ustawiona jest zmienna środowiskowa GOOGLE_APPLICATION_CREDENTIALS. Jeśli zmienna jest ustawiona, ADC używa pliku konta usługi, do którego ona wskazuje.

  2. Jeśli zmienna środowiskowa nie jest ustawiona, ADC używa domyślnego konta usługi, które Compute Engine, Google Kubernetes Engine, App Engine i Cloud Functions udostępniają aplikacjom działającym w tych usługach.

  3. Jeśli ADC nie może użyć żadnego z tych danych logowania, system wyświetla błąd.

Przykładowy kod pakietu SDK administratora ilustruje tę strategię. Przykład nie zawiera wyraźnego określenia danych logowania aplikacji. Jednak ADC może znaleźć te dane logowania w sposób domyślny, o ile zmienna środowiskowa jest ustawiona lub aplikacja działa w kontekście Compute Engine, Google Kubernetes Engine, App Engine lub funkcji Cloud.

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

Ręczne podawanie danych logowania

Projekty Firebase obsługują konta usługi Google, których możesz używać do wywoływania interfejsów API serwera Firebase z serwera aplikacji lub zaufanego środowiska. Jeśli kod tworzysz lokalnie lub wdrażasz aplikację lokalnie, możesz użyć danych logowania uzyskanych za pomocą tego konta usługi, aby autoryzować żądania serwera.

Aby uwierzytelnić konto usługi i autoryzować je do dostępu do usług Firebase, musisz wygenerować plik klucza prywatnego w formacie JSON.

Aby wygenerować plik klucza prywatnego dla konta usługi:

  1. W konsoli Firebase otwórz Ustawienia > Konta usługi.

  2. Kliknij Wygeneruj nowy klucz prywatny, a następnie potwierdź, klikając Wygeneruj klucz.

  3. Bezpiecznie przechowuj plik JSON zawierający klucz.

Podczas autoryzacji za pomocą konta usługi masz 2 możliwości przekazania danych logowania do aplikacji. Możesz ustawić zmienną środowiskową GOOGLE_APPLICATION_CREDENTIALS lub w kodzie wyraźnie podać ścieżkę do klucza konta usługi. Pierwsza opcja jest bezpieczniejsza i zdecydowanie zalecana.

Aby ustawić zmienną środowiskową:

Ustaw zmienną środowiskową GOOGLE_APPLICATION_CREDENTIALS na ścieżkę do pliku JSON zawierającego klucz konta usługi. Ta zmienna dotyczy tylko bieżącej sesji powłoki, więc jeśli otworzysz nową sesję, musisz ponownie ustawić zmienną.

Linux lub macOS

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

Windows

W PowerShell:

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

Gdy wykonasz powyższe czynności, domyślne dane uwierzytelniające aplikacji (ADC) będą mogły niejawnie określić Twoje dane logowania. Dzięki temu możesz używać danych logowania do konta usługi podczas testowania lub uruchamiania aplikacji w środowiskach innych niż Google.

Używanie danych logowania do generowania tokenów dostępu

Aby pobrać krótkotrwały token dostępu OAuth 2.0, użyj danych logowania Firebase wraz z biblioteką Google Auth Library w preferowanym języku:

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

W tym przykładzie biblioteka klienta interfejsu API Google uwierzytelnia żądanie za pomocą tokena sieciowego JSON (JWT). Więcej informacji znajdziesz w artykule Tokeny sieciowe 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();
}

Gdy token dostępu wygaśnie, metoda odświeżania tokena zostanie wywołana automatycznie, aby pobrać zaktualizowany token dostępu.

Aby autoryzować dostęp do FCM, poproś o zakres https://www.googleapis.com/auth/firebase.messaging.

Aby dodać token dostępu do nagłówka żądania HTTP:

Dodaj token jako wartość nagłówka Authorization w formacie 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;

Aktualizowanie ładunku przesyłanych żądań

W wersji 1 protokołu FCM HTTP wprowadzono istotną zmianę w strukturze danych ładunku wiadomości JSON. Te zmiany mają na celu przede wszystkim zapewnienie prawidłowego obsługiwania wiadomości otrzymywanych na różnych platformach klientów. Dodatkowo dają Ci większą elastyczność w dostosowywaniu pól wiadomości lub ich „zastępowaniu” na poszczególnych platformach.

Oprócz zapoznania się z przykładami w tej sekcji przeczytaj artykuł Dostosowywanie wiadomości na różnych platformach i przeczytaj dokumentację interfejsu API, aby poznać interfejs HTTP v1.

Przykład: prosty komunikat powiadomienia

Oto porównanie bardzo prostego ładunku powiadomienia zawierającego tylko pola title, bodydata, które pokazuje podstawowe różnice między starszym ładunkiem a ładunkiem HTTP w wersji 1.

Przed

{
  "to": "/topics/news",
  "notification": {
    "title": "Breaking News",
    "body": "New news story available."
  },
  "data": {
    "story_id": "story_12345"
  }
}

Po

{
  "message": {
    "topic": "news",
    "notification": {
      "title": "Breaking News",
      "body": "New news story available."
    },
    "data": {
      "story_id": "story_12345"
    }
  }
}

Przykład: zagnieżdżone dane JSON

W przeciwieństwie do starszego interfejsu API przesyłania wiadomości interfejs HTTP w wersji 1 nie obsługuje zagnieżdżonych wartości JSON w polu data. Wymagane jest przekształcenie z formatu JSON na ciąg znaków.

Przed

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

Po

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

Przykład: kierowanie na wiele platform

Aby można było włączyć kierowanie na wiele platform, starsza wersja interfejsu API wprowadziła zastąpienia w backendzie. W przeciwieństwie do tego HTTP w wersji 1 udostępnia bloki kluczy dla poszczególnych platform, dzięki czemu wszelkie różnice między platformami są wyraźne i widoczne dla dewelopera. Dzięki temu możesz kierować reklamy na wiele platform za pomocą jednego żądania, jak pokazano w tym przykładzie.

Przed

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

Po

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

Przykład: dostosowywanie za pomocą zastąpień platformy

Oprócz uproszczenia kierowania wiadomości na różne platformy interfejs HTTP w wersji 1 zapewnia też elastyczność w dostosowywaniu wiadomości do poszczególnych platform.

Przed

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

Po

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

Przykład: kierowanie na określone urządzenia

Aby kierować reklamy na określone urządzenia za pomocą interfejsu HTTP w wersji 1, zamiast klucza to podaj w kluczu token bieżący token rejestracji urządzenia.

Przed

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

Po

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

Więcej przykładów i informacji o interfejsie API FCM HTTP w wersji 1 znajdziesz w tych artykułach: