Bermigrasi dari FCM API lama ke HTTP v1

Aplikasi yang menggunakan API lama FCM yang tidak digunakan lagi untuk HTTP dan XMPP harus bermigrasi ke HTTP v1 API secepat mungkin. Mengirim pesan (termasuk pesan upstream) dengan API tersebut sudah tidak digunakan lagi pada 20 Juni 2023, dan penonaktifan akan dimulai pada 22 Juli 2024.

Pelajari lebih lanjut tentang fitur yang terpengaruh.

Selain dukungan berkelanjutan dan fitur baru, HTTP v1 API memiliki keunggulan ini dibandingkan API lama:

  • Keamanan yang lebih baik melalui token akses HTTP v1 API menggunakan token akses berumur pendek sesuai dengan model keamanan OAuth2. Jika suatu token akses terungkap ke publik, token tersebut hanya dapat disalahgunakan selama sekitar satu jam sebelum masa berlakunya berakhir. Token refresh tidak akan dikirim sesering kunci keamanan yang digunakan di API lama, sehingga memperkecil kemungkinan diambil.

  • Penyesuaian pesan yang lebih efisien lintas platform Untuk isi pesan, HTTP v1 API memiliki kunci umum yang diterapkan ke semua instance target, ditambah kunci khusus platform yang dapat digunakan untuk menyesuaikan pesan lintas platform. Dengan begitu, Anda dapat membuat "penggantian" yang mengirimkan payload yang sedikit berbeda ke berbagai platform klien dalam satu pesan.

  • Dapat terus diperluas dan tidak akan ketinggalan zaman untuk versi platform klien yang baru HTTP v1 API sepenuhnya mendukung opsi pesan yang tersedia di platform Apple, Android, dan Web. Karena setiap platform memiliki bloknya sendiri dalam payload JSON, FCM dapat memperluas API ke versi dan platform baru sesuai kebutuhan.

Memperbarui endpoint server

URL endpoint untuk HTTP v1 API berbeda dengan endpoint lama dalam beberapa hal berikut:

  • Memiliki versi, dengan /v1 tercantum di jalurnya.
  • Jalurnya berisi project ID pada project Firebase untuk aplikasi Anda, dalam format /projects/myproject-ID/. ID ini tersedia di tab General project settings di Firebase console.
  • Secara eksplisit menetapkan metode send sebagai :send.

Guna memperbarui endpoint server untuk HTTP v1, tambahkan elemen berikut ke endpoint di header permintaan kirim Anda.

Permintaan HTTP sebelumnya

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

Permintaan XMPP sebelumnya

Pesan XMPP lama dikirim melalui koneksi ke endpoint berikut:

fcm-xmpp.googleapis.com:5235

Setelah

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

Memperbarui otorisasi permintaan kirim

Sebagai pengganti string kunci server yang digunakan dalam permintaan lama, permintaan kirim HTTP v1 memerlukan token akses OAuth 2.0. Jika Anda menggunakan Admin SDK untuk mengirim pesan, library akan menangani tokennya. Jika menggunakan protokol mentah, Anda akan mendapatkan token seperti yang dijelaskan di bagian ini lalu tambahkan ke header sebagai Authorization: Bearer <valid Oauth 2.0 token>.

Sebelum

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

Setelah

Authorization: Bearer ya29.ElqKBGN2Ri_Uz...HnS_uNreA

Tergantung detail lingkungan server Anda, gunakan kombinasi strategi berikut ini untuk mengizinkan permintaan server ke layanan Firebase:

  • Kredensial Default Aplikasi (ADC) Google
  • File JSON akun layanan
  • Token akses OAuth 2.0 berumur pendek yang berasal dari akun layanan

Jika aplikasi Anda berjalan di Compute Engine, Google Kubernetes Engine, App Engine, atau Cloud Functions (termasuk Cloud Functions for Firebase), gunakan Kredensial Default Aplikasi (ADC). ADC menggunakan akun layanan default yang sudah ada untuk mendapatkan kredensial guna mengizinkan permintaan, dan ADC memungkinkan pengujian lokal fleksibel melalui variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS. Untuk otomatisasi alur otorisasi sepenuhnya, gunakan ADC bersama dengan library server Admin SDK.

Jika aplikasi Anda berjalan pada lingkungan server non-Google, Anda harus mendownload file JSON akun layanan dari project Firebase. Selama memiliki akses ke sistem file yang berisi file kunci pribadi, Anda dapat menggunakan variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS untuk mengizinkan permintaan dengan kredensial yang diperoleh secara manual ini. Jika tidak memiliki akses ke file tersebut, Anda harus merujuk file akun layanan dalam kode Anda. Lakukan ini dengan sangat hati-hati karena dapat berisiko mengekspos kredensial Anda.

Memberikan kredensial dengan ADC

Kredensial Default Aplikasi (ADC) Google memeriksa kredensial Anda dengan urutan sebagai berikut:

  1. ADC memeriksa apakah variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS ditetapkan. Jika variabel ditetapkan, ADC akan menggunakan file akun layanan yang ditunjuk variabel.

  2. Jika variabel lingkungan tidak ditetapkan, ADC akan menggunakan akun layanan default yang disediakan Compute Engine, Google Kubernetes Engine, App Engine, dan Cloud Functions untuk aplikasi yang berjalan pada layanan tersebut.

  3. Jika ADC tidak dapat menggunakan salah satu dari kredensial di atas, sistem akan melemparkan error.

Contoh kode Admin SDK berikut menggambarkan strategi ini. Contoh ini tidak secara eksplisit menentukan kredensial aplikasi. Namun, ADC secara implisit dapat menemukan kredensial asalkan variabel lingkungan ditetapkan, atau asalkan aplikasi berjalan di Compute Engine, Google Kubernetes Engine, App Engine, atau 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(),
});

Memberikan kredensial secara manual

Project Firebase mendukung akun layanan Google, yang dapat Anda gunakan untuk memanggil API server Firebase dari server aplikasi atau lingkungan tepercaya. Jika Anda mengembangkan kode secara lokal atau men-deploy aplikasi secara lokal, gunakan kredensial yang diperoleh melalui akun layanan ini untuk mengizinkan permintaan server.

Untuk mengautentikasi akun layanan dan memberinya akses ke layanan Firebase, Anda harus membuat file kunci pribadi dalam format JSON.

Untuk membuat file kunci pribadi untuk akun layanan Anda:

  1. Di Firebase console, buka Settings > Service Accounts.

  2. Klik Generate New Private Key, lalu konfirmasikan dengan mengklik Generate Key.

  3. Simpan dengan aman file JSON yang memuat kunci tersebut.

Saat Anda memberi otorisasi melalui akun layanan, ada dua opsi untuk menyediakan kredensial ke aplikasi. Anda dapat menetapkan variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS, atau secara eksplisit meneruskan jalur ke kunci akun layanan dalam kode. Opsi pertama lebih aman dan sangat direkomendasikan.

Untuk menetapkan variabel lingkungan:

Tetapkan variabel lingkungan GOOGLE_APPLICATION_CREDENTIALS ke jalur file JSON yang berisi kunci akun layanan Anda. Variabel ini hanya berlaku untuk sesi shell Anda saat ini. Jadi, jika Anda membuka sesi baru, tetapkan variabel kembali.

Linux atau macOS

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

Windows

Dengan PowerShell:

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

Setelah Anda menyelesaikan langkah-langkah di atas, Kredensial Default Aplikasi (ADC) secara implisit dapat menentukan kredensial Anda, sehingga Anda dapat menggunakan kredensial akun layanan saat menguji atau beroperasi di lingkungan non-Google.

Menggunakan kredensial untuk membuat token akses

Gunakan kredensial Firebase Anda beserta Library Google Auth untuk bahasa pilihan Anda saat mengambil token akses OAuth 2.0 yang berumur pendek:

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

Dalam contoh ini, library klien Google API mengautentikasi permintaan dengan token web JSON, atau yang disebut JWT. Untuk informasi lebih lanjut, baca token web 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();
}

Setelah masa berlaku token akses berakhir, metode refresh token akan otomatis dipanggil untuk mengambil token yang telah diperbarui.

Untuk mengizinkan akses ke FCM, minta cakupan https://www.googleapis.com/auth/firebase.messaging.

Untuk menambahkan token akses ke header permintaan HTTP:

Tambahkan token sebagai nilai header Authorization dalam format 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;

Memperbarui payload permintaan kirim

FCM HTTP v1 menghadirkan perubahan signifikan dalam struktur payload pesan JSON. Perubahan ini terutama memastikan bahwa pesan akan ditangani dengan benar saat diterima di berbagai platform klien. Selain itu, dengan perubahan ini, Anda dapat lebih leluasa menyesuaikan atau "mengganti" kolom pesan menurut platform.

Selain memeriksa contoh di bagian ini, baca Menyesuaikan pesan lintas platform dan pelajari referensi API untuk memahami HTTP v1.

Contoh: pesan notifikasi sederhana

Berikut adalah perbandingan payload notifikasi yang sangat sederhana serta hanya berisi kolom title, body, dan data, yang menunjukkan perbedaan mendasar antara payload lama dan payload HTTP v1.

Sebelum

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

Setelah

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

Contoh: data JSON bertingkat

Tidak seperti API pesan lama, HTTP v1 API tidak mendukung nilai JSON bertingkat di kolom data. Diperlukan konversi dari JSON ke string.

Sebelum

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

Setelah

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

Contoh: menarget beberapa platform

Untuk mengaktifkan penargetan multi-platform, API lama melakukan penggantian di backend. Sebaliknya, HTTP v1 memberikan blok kunci khusus platform yang membuat perbedaan antar-platform menjadi eksplisit dan terlihat oleh developer. Dengan demikian, Anda dapat menarget beberapa platform hanya dengan satu permintaan, seperti yang ditunjukkan dalam contoh berikut.

Sebelum

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

Setelah

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

Contoh: menyesuaikan pesan dengan penggantian platform

Selain menyederhanakan penargetan pesan lintas platform, HTTP v1 API memberikan fleksibilitas untuk menyesuaikan pesan per platform.

Sebelum

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

Setelah

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

Contoh: menargetkan perangkat tertentu

Untuk menargetkan perangkat tertentu dengan HTTP v1 API, berikan token pendaftaran perangkat saat ini dalam kunci token, bukan kunci to.

Sebelum

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

Setelah

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

Untuk mengetahui contoh dan informasi lainnya tentang FCM HTTP v1 API, baca bagian berikut: