Migrar de APIs FCM legadas para HTTP v1

Os aplicativos que usam as APIs legadas do FCM obsoletas para HTTP e XMPP devem migrar para a API HTTP v1 o mais rápido possível. O envio de mensagens (incluindo mensagens upstream) com essas APIs foi descontinuado em 20 de junho de 2023 e será removido em junho de 2024 .

Além do suporte contínuo e dos novos recursos, a API HTTP v1 tem estas vantagens sobre as APIs legadas:

  • Melhor segurança por meio de tokens de acesso A API HTTP v1 usa tokens de acesso de curta duração de acordo com o modelo de segurança OAuth2. Caso um token de acesso se torne público, ele só poderá ser usado maliciosamente por cerca de uma hora antes de expirar. Os tokens de atualização não são transmitidos com tanta frequência quanto as chaves de segurança usadas na API legada, portanto, é muito menos provável que sejam capturados.

  • Personalização mais eficiente de mensagens entre plataformas Para o corpo da mensagem, a API HTTP v1 possui chaves comuns que vão para todas as instâncias de destino, além de chaves específicas da plataforma que permitem personalizar a mensagem entre plataformas. Isso permite criar "substituições" que enviam cargas ligeiramente diferentes para diferentes plataformas de clientes em uma única mensagem.

  • Mais extensível e preparado para o futuro para novas versões de plataforma de cliente A API HTTP v1 oferece suporte total às opções de mensagens disponíveis nas plataformas Apple, Android e Web. Como cada plataforma tem seu próprio bloco definido na carga JSON, o FCM pode estender a API para novas versões e novas plataformas conforme necessário.

Atualizar o endpoint do servidor

O URL do endpoint para a API HTTP v1 difere do endpoint legado destas maneiras:

  • É versionado, com /v1 no caminho.
  • O caminho contém o ID do projeto do Firebase para seu aplicativo, no formato /projects/myproject-ID/ . Esse ID está disponível na guia Configurações gerais do projeto do console do Firebase.
  • Ele especifica explicitamente o método send como :send .

Para atualizar o endpoint do servidor para HTTP v1, adicione esses elementos ao endpoint no cabeçalho de suas solicitações de envio.

Solicitações HTTP antes

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

Solicitações XMPP antes

As mensagens XMPP legadas são enviadas por meio de uma conexão com o seguinte endpoint:

fcm-xmpp.googleapis.com:5235

Depois

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

Atualizar autorização de solicitações de envio

No lugar da string de chave do servidor usada em solicitações legadas, as solicitações de envio HTTP v1 exigem um token de acesso OAuth 2.0. Se você estiver usando o Admin SDK para enviar mensagens, a biblioteca manipulará o token para você. Se você estiver usando o protocolo bruto, obtenha o token conforme descrito nesta seção e adicione-o ao cabeçalho como Authorization: Bearer <valid Oauth 2.0 token> .

Antes

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

Depois

Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

Dependendo dos detalhes do seu ambiente de servidor, use uma combinação destas estratégias para autorizar solicitações de servidor para serviços do Firebase:

  • Credenciais padrão do aplicativo Google (ADC)
  • Um arquivo JSON da conta de serviço
  • Um token de acesso OAuth 2.0 de curta duração derivado de uma conta de serviço

Se seu aplicativo estiver em execução no Compute Engine, Google Kubernetes Engine, App Engine ou Cloud Functions (incluindo Cloud Functions para Firebase), use Application Default Credentials (ADC). O ADC usa sua conta de serviço padrão existente para obter credenciais para autorizar solicitações, e o ADC permite testes locais flexíveis por meio da variável de ambiente GOOGLE_APPLICATION_CREDENTIALS . Para obter a automação mais completa do fluxo de autorização, use o ADC junto com as bibliotecas do servidor Admin SDK.

Se o seu aplicativo estiver sendo executado em um ambiente de servidor que não seja do Google , você precisará fazer o download de um arquivo JSON da conta de serviço do seu projeto do Firebase. Contanto que você tenha acesso a um sistema de arquivos contendo o arquivo de chave privada, você poderá usar a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS para autorizar solicitações com essas credenciais obtidas manualmente. Se você não tiver acesso a esse arquivo, deverá fazer referência ao arquivo da conta de serviço em seu código, o que deve ser feito com extremo cuidado devido ao risco de expor suas credenciais.

Forneça credenciais usando ADC

O Google Application Default Credentials (ADC) verifica suas credenciais na seguinte ordem:

  1. O ADC verifica se a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS está definida. Se a variável estiver definida, o ADC usará o arquivo de conta de serviço para o qual a variável aponta.

  2. Se a variável de ambiente não estiver definida, o ADC usará a conta de serviço padrão fornecida pelo Compute Engine, Google Kubernetes Engine, App Engine e Cloud Functions para aplicativos executados nesses serviços.

  3. Se o ADC não puder usar nenhuma das credenciais acima, o sistema gerará um erro.

O exemplo de código do Admin SDK a seguir ilustra essa estratégia. O exemplo não especifica explicitamente as credenciais do aplicativo. No entanto, o ADC é capaz de encontrar implicitamente as credenciais desde que a variável de ambiente esteja definida ou enquanto o aplicativo estiver em execução no Compute Engine, Google Kubernetes Engine, App Engine ou 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);

Pitão

default_app = firebase_admin.initialize_app()

Ir

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

Forneça credenciais manualmente

Os projetos do Firebase oferecem suporte a contas de serviço do Google, que você pode usar para chamar APIs do servidor Firebase a partir do seu servidor de aplicativos ou ambiente confiável. Se estiver desenvolvendo código localmente ou implantando seu aplicativo localmente, você poderá usar credenciais obtidas por meio dessa conta de serviço para autorizar solicitações do servidor.

Para autenticar uma conta de serviço e autorizá-la a acessar os serviços do Firebase, você deve gerar um arquivo de chave privada no formato JSON.

Para gerar um arquivo de chave privada para sua conta de serviço:

  1. No console do Firebase, abra Configurações > Contas de serviço .

  2. Clique em Gerar nova chave privada e confirme clicando em Gerar chave .

  3. Armazene com segurança o arquivo JSON que contém a chave.

Ao autorizar por meio de uma conta de serviço, você tem duas opções para fornecer as credenciais ao seu aplicativo. Você pode definir a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS ou pode passar explicitamente o caminho para a chave da conta de serviço no código. A primeira opção é mais segura e é altamente recomendada.

Para definir a variável de ambiente:

Defina a variável de ambiente GOOGLE_APPLICATION_CREDENTIALS como o caminho do arquivo JSON que contém a chave da sua conta de serviço. Esta variável se aplica apenas à sua sessão atual do shell, portanto, se você abrir uma nova sessão, defina a variável novamente.

Linux ou macOS

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

janelas

Com PowerShell:

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

Depois de concluir as etapas acima, o Application Default Credentials (ADC) poderá determinar implicitamente suas credenciais, permitindo que você use credenciais de conta de serviço ao testar ou executar em ambientes que não sejam do Google.

Use credenciais para criar tokens de acesso

Use suas credenciais do Firebase junto com a Biblioteca Google Auth para seu idioma preferido para recuperar um token de acesso OAuth 2.0 de curta duração:

nó.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);
    });
  });
}

Neste exemplo, a biblioteca cliente da API do Google autentica a solicitação com um token da web JSON ou JWT. Para obter mais informações, consulte Tokens web JSON .

Pitão

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

Depois que seu token de acesso expirar, o método de atualização de token será chamado automaticamente para recuperar um token de acesso atualizado.

Para autorizar o acesso ao FCM, solicite o escopo https://www.googleapis.com/auth/firebase.messaging .

Para adicionar o token de acesso a um cabeçalho de solicitação HTTP:

Adicione o token como o valor do cabeçalho Authorization no formato Authorization: Bearer <access_token> :

nó.js

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

Pitão

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;

Atualizar a carga útil das solicitações de envio

O FCM HTTP v1 introduz uma mudança significativa na estruturação da carga útil da mensagem JSON. Principalmente, essas alterações garantem que as mensagens sejam tratadas corretamente quando recebidas em diferentes plataformas de clientes; além disso, as alterações oferecem flexibilidade extra para personalizar ou “substituir” campos de mensagens por plataforma.

Além de inspecionar os exemplos nesta seção, consulte Personalizando uma mensagem entre plataformas e revise a referência da API para se familiarizar com o HTTP v1.

Exemplo: mensagem de notificação simples

Aqui está uma comparação de uma carga útil de notificação muito simples - contendo apenas os campos title , body e data - demonstrando as diferenças fundamentais nas cargas legadas e HTTP v1.

Antes

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

Depois

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

Exemplo: segmentação em múltiplas plataformas

Para ativar a segmentação em múltiplas plataformas, a API legada executou substituições no back-end. Por outro lado, o HTTP v1 fornece blocos de chaves específicos da plataforma que tornam quaisquer diferenças entre plataformas explícitas e visíveis para o desenvolvedor. Isso permite que você atinja diversas plataformas sempre com uma única solicitação, conforme demonstrado no exemplo a seguir.

Antes

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

Depois

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

Exemplo: customização com substituições de plataforma

Além de simplificar o direcionamento de mensagens entre plataformas, a API HTTP v1 oferece flexibilidade para personalizar mensagens por plataforma.

Antes

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

Depois

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

Exemplo: segmentação para dispositivos específicos

Para direcionar dispositivos específicos com a API HTTP v1, forneça o token de registro atual do dispositivo na chave token em vez da chave to .

Antes

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

Depois

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

Para obter mais exemplos e informações sobre a API FCM HTTP v1, consulte o seguinte: