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

Aplikacje korzystające z wycofanych 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 wysyłanych z aplikacji do serwera) 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, których dotyczy ta zmiana.

Oprócz bieżącej pomocy i nowych funkcji interfejs API HTTP w wersji 1 ma te zalety w porównaniu ze starszymi interfejsami API:

  • Większe bezpieczeństwo dzięki tokenom dostępu Interfejs HTTP API w wersji 1 używa krótkotrwałych tokenów dostępu zgodnie z modelem zabezpieczeń OAuth2. Jeśli token dostępu stanie się publiczny, może być używany w złośliwy sposób tylko przez około godzinę, zanim wygaśnie. Tokeny odświeżania nie są przesyłane tak często jak klucze zabezpieczeń używane w starszej wersji interfejsu API, więc są znacznie mniej podatne na przechwycenie.

  • Bardziej efektywne dostosowywanie wiadomości na różnych platformach W przypadku treści wiadomości interfejs HTTP v1 API ma wspólne klucze, które są wysyłane do wszystkich docelowych instancji, a także klucze specyficzne dla platformy, które umożliwiają dostosowywanie wiadomości na różnych platformach. Umożliwia to tworzenie „zastąpień”, które wysyłają nieco inne ładunki do różnych platform klienckich w jednej wiadomości.

  • Bardziej rozbudowany i przygotowany na przyszłe wersje platform klienckich Interfejs HTTP v1 API w pełni obsługuje opcje przesyłania wiadomości dostępne na platformach Apple, Android i w internecie. Każda platforma ma w ładunku JSON własny zdefiniowany blok, więc FCM może w razie potrzeby rozszerzać interfejs API o nowe wersje i platformy.

Aktualizowanie punktu końcowego serwera

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

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

Aby zaktualizować punkt końcowy serwera dla HTTP v1, dodaj te elementy do punktu końcowego w nagłówku żądań wysyłania.

Żądania HTTP przed

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

Żądania XMPP przed

Starsze wiadomości XMPP są wysyłane przez połączenie z tym punktem końcowym:

fcm-xmpp.googleapis.com:5235

Po

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

Aktualizowanie autoryzacji żądań wysyłania

Zamiast ciągu klucza serwera używanego w starszych żądaniach żądania wysyłania HTTP v1 wymagają tokena dostępu OAuth 2.0. Jeśli do wysyłania wiadomości używasz pakietu Admin SDK, biblioteka obsługuje token za Ciebie. Jeśli używasz protokołu surowego, uzyskaj token zgodnie z opisem 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 dane logowania aplikacji Google (ADC)
  • plik JSON konta usługi,
  • krótkotrwały token dostępu OAuth 2.0 pochodzący z konta usługi;

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

Jeśli Twoja aplikacja działa w środowisku serwera innego niż Google, musisz pobrać z projektu Firebase plik JSON konta usługi. 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 ręcznie uzyskanych danych logowania. Jeśli nie masz dostępu do takiego pliku, musisz odwołać się do pliku konta usługi w kodzie. Należy to zrobić z najwyższą ostrożnością ze względu na ryzyko ujawnienia danych logowania.

Podawanie danych logowania za pomocą ADC

Domyślne uwierzytelnianie aplikacji Google (ADC) sprawdza Twoje dane logowania w tej kolejności:

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

  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 domyślne dane logowania aplikacji nie mogą użyć żadnych z powyższych danych logowania, system zgłosi błąd.

Poniższy przykładowy kod pakietu Admin SDK ilustruje tę strategię. W przykładzie nie podano wyraźnie danych logowania aplikacji. Jednak ADC może niejawnie znaleźć dane logowania, o ile ustawiona jest zmienna środowiskowa lub aplikacja działa w Compute Engine, Google Kubernetes Engine, App Engine lub 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(),
});

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 tworzysz kod 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 przyznać mu uprawnienia 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 Firebase konsoli 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 jawnie przekazać ścieżkę do klucza konta usługi w kodzie. Pierwsza opcja jest bezpieczniejsza i zdecydowanie zalecana.

Aby ustawić zmienną środowiskową:

Ustaw zmienną środowiskową GOOGLE_APPLICATION_CREDENTIALS na ścieżkę pliku JSON zawierającego klucz konta usługi. Ta zmienna jest stosowana tylko w bieżącej sesji powłoki, więc jeśli otworzysz nową sesję, ustaw ją ponownie.

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"

Po wykonaniu powyższych kroków domyślne dane logowania aplikacji (ADC) będą mogły niejawnie określać Twoje dane logowania, co umożliwi Ci używanie danych logowania konta usługi podczas testowania lub uruchamiania w środowiskach innych niż Google.

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

Użyj danych logowania Firebase razem z Google Auth Library w preferowanym języku, aby pobrać krótkotrwały token dostępu 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);
    });
  });
}

W tym przykładzie biblioteka klienta interfejsu Google API 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();
}

Po wygaśnięciu tokena dostępu automatycznie wywoływana jest metoda odświeżania tokena, aby pobrać zaktualizowany token dostępu.

Aby autoryzować dostęp do FCM, poproś o zakreshttps://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 żądań wysyłania

FCM HTTP v1 wprowadza znaczącą zmianę w strukturze ładunku wiadomości JSON. Te zmiany mają przede wszystkim zapewnić prawidłowe przetwarzanie wiadomości po ich otrzymaniu na różnych platformach klientów. Dodatkowo dają Ci większą elastyczność w dostosowywaniu lub „zastępowaniu” pól wiadomości na poszczególnych platformach.

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

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 starszymi ładunkami a ładunkami HTTP v1.

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 Messaging API interfejs HTTP v1 API nie obsługuje zagnieżdżonych wartości JSON w polu data. Wymagana jest konwersja z 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 włączyć kierowanie na wiele platform, starszy interfejs API zastępował ustawienia w backendzie. Z kolei HTTP v1 udostępnia bloki kluczy specyficzne dla platformy, które sprawiają, że 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

Interfejs HTTP v1 API nie tylko upraszcza kierowanie wiadomości na różne platformy, ale też zapewnia 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 konkretne urządzenia za pomocą interfejsu HTTP v1 API, podaj bieżący token rejestracji urządzenia w kluczu token zamiast w kluczu to.

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 FCM HTTP v1 API znajdziesz w tych artykułach: