Lingkungan server Anda dan FCM

Sisi server Firebase Cloud Messaging terdiri dari dua komponen:

  • Backend FCM yang disediakan oleh Google.
  • Server aplikasi Anda atau lingkungan server tepercaya lainnya untuk menjalankan logika server, seperti Cloud Functions for Firebase atau lingkungan cloud lain yang dikelola oleh Google.

Server aplikasi Anda atau lingkungan server tepercaya mengirimkan permintaan pesan ke backend FCM, yang kemudian merutekan pesan ke aplikasi klien yang berjalan di perangkat pengguna.

Persyaratan untuk lingkungan server tepercaya

Lingkungan server aplikasi Anda harus memenuhi kriteria berikut:

  • Mampu mengirim permintaan pesan yang diformat dengan benar ke backend FCM.
  • Mampu menangani permintaan dan mengirimnya kembali menggunakan backoff eksponensial.
  • Mampu menyimpan kredensial otorisasi server dan token pendaftaran klien dengan aman.
  • Untuk protokol XMPP (jika digunakan), server harus mampu menghasilkan ID pesan sebagai identifikasi unik bagi setiap pesan yang dikirimkannya (backend HTTP FCM menghasilkan ID pesan dan menampilkannya dalam respons). ID pesan XMPP harus unik per ID pengirim.

Memilih opsi server

Anda harus memutuskan metode interaksi dengan server FCM: menggunakan Firebase Admin SDK atau protokol mentah. Karena dukungannya di seluruh bahasa pemrograman populer dan metode praktisnya untuk menangani autentikasi dan otorisasi, Firebase Admin SDK adalah metode yang direkomendasikan.

Opsi untuk berinteraksi dengan server FCM meliputi hal berikut:

  • Firebase Admin SDK, yang mendukung Node, Java, Python, C#, dan Go.
  • FCM HTTP v1 API, yang merupakan opsi protokol terbaru, dengan otorisasi yang lebih aman dan kemampuan pengiriman pesan lintas platform yang fleksibel (Firebase Admin SDK didasarkan pada protokol ini dan memberikan semua keuntungan yang dimilikinya). Karena fitur baru biasanya hanya ditambahkan ke API HTTP v1, sebaiknya gunakan API ini untuk kebanyakan kasus penggunaan.
  • Protokol HTTP lama. Project baru sangat direkomendasikan untuk menggunakan HTTP v1 API FCM, bukan protokol lama.
  • Protokol server XMPP lama. Project baru sangat direkomendasikan untuk menggunakan HTTP v1 API FCM, bukan protokol lama.

Firebase Admin SDK untuk FCM

Admin FCM API menangani autentikasi dengan backend dan memfasilitasi pengiriman pesan serta pengelolaan langganan topik. Dengan Firebase Admin SDK, Anda dapat:

  • Mengirim pesan ke setiap perangkat secara terpisah
  • Mengirim pesan ke topik dan pernyataan kondisi yang cocok dengan satu topik atau lebih
  • Membuat perangkat berlangganan ke topik dan berhenti berlangganan dari topik
  • Membuat payload pesan yang disesuaikan untuk berbagai platform target

Admin Node.js SDK menyediakan metode untuk mengirim pesan ke grup perangkat.

Untuk menyiapkan Firebase Admin SDK, baca bagian Menambahkan Firebase Admin SDK ke Server Anda. Jika Anda sudah memiliki project Firebase, mulailah dengan Menambahkan SDK tersebut. Selain itu, pastikan untuk mengaktifkan Cloud Messaging API di halaman setelan Cloud Messaging untuk project Anda. Kemudian, setelah Firebase Admin SDK diinstal, Anda dapat langsung menulis logika untuk mem-build permintaan kirim.

Protokol Server FCM

Saat ini, FCM menyediakan protokol server mentah berikut:

Server aplikasi Anda dapat menggunakan semua protokol ini secara terpisah atau bersama-sama. Sebagai protokol yang paling baru dan fleksibel untuk mengirim pesan ke beberapa platform, FCM HTTP v1 API direkomendasikan di mana pun dimungkinkan. Jika persyaratan Anda mencakup pengiriman pesan upstream dari perangkat ke server, Anda harus menerapkan protokol XMPP.

Pengiriman pesan XMPP berbeda dari pengiriman pesan HTTP dalam hal berikut:

  • Pesan Upstream/Downstream
    • HTTP: Hanya downstream, dari cloud ke perangkat.
    • XMPP: Upstream dan downstream (perangkat ke cloud, cloud ke perangkat).
  • Pengiriman pesan (sinkron atau asinkron)
    • HTTP: Sinkron. Server aplikasi mengirim pesan sebagai permintaan POST HTTP dan menunggu respons. Mekanisme ini bersifat sinkron dan memblokir pengirim agar tidak mengirim pesan lain hingga respons diterima.
    • XMPP: Asinkron. Server aplikasi mengirim/menerima pesan ke/dari semua perangkatnya dengan kecepatan penuh melalui koneksi XMPP persisten. Server koneksi XMPP mengirim notifikasi konfirmasi atau kegagalan (dalam format pesan XMPP khusus yang berisi ACK dan NACK berenkode JSON) secara asinkron.
  • JSON
    • HTTP: Pesan JSON dikirim sebagai HTTP POST.
    • XMPP: Pesan JSON dienkapsulasi dalam pesan XMPP.
  • Teks Biasa
    • HTTP: Pesan Teks Biasa dikirim sebagai HTTP POST.
    • XMPP: Tidak didukung.
  • Downstream multicast mengirim ke beberapa token pendaftaran.
    • HTTP: Didukung dalam format pesan JSON.
    • XMPP: Tidak didukung.

Mengimplementasikan protokol server HTTP

Untuk mengirim pesan, server aplikasi akan menerbitkan permintaan POST dengan header HTTP dan isi HTTP yang terdiri dari key-value pair JSON. Untuk detail tentang opsi header dan isi, lihat Mem-build Permintaan Kirim Server Aplikasi

Mengimplementasikan protokol server XMPP

Payload JSON untuk pesan FCM mirip dengan protokol HTTP, dengan pengecualian berikut:

  • Tidak ada dukungan untuk banyak penerima.
  • FCM menambahkan kolom message_id, yang merupakan kolom wajib. ID ini secara unik mengidentifikasi pesan dalam koneksi XMPP. ACK atau NACK dari FCM menggunakan message_id untuk mengidentifikasi pesan yang dikirimkan dari server aplikasi ke FCM. Oleh karena itu, message_id tidak hanya harus unik (per ID pengirim), tetapi juga harus selalu ada.
  • XMPP menggunakan kunci server untuk mengizinkan koneksi persisten ke FCM. Baca artikel Mengizinkan Permintaan Kirim untuk mengetahui informasi lebih lanjut.

Selain pesan FCM biasa, pesan kontrol juga dikirim, yang ditunjukkan oleh kolom message_type dalam objek JSON. Nilainya bisa 'ack' atau 'nack', atau 'control' (lihat format di bawah). Setiap pesan FCM dengan message_type yang tidak dikenal bisa diabaikan oleh server Anda.

Server aplikasi perlu mengirim pesan ACK untuk setiap pesan perangkat yang diterima dari FCM. Server tidak perlu mengirim pesan NACK. Jika Anda tidak mengirim ACK untuk pesan, FCM akan mengirimnya ulang pada saat koneksi XMPP baru dibuat lagi, kecuali jika masa berlaku pesan tersebut sudah habis terlebih dahulu.

FCM juga mengirim pesan ACK atau NACK untuk setiap pesan server ke perangkat. Jika Anda tidak menerima salah satunya, berarti koneksi TCP tertutup saat operasi berlangsung dan server perlu mengirim ulang pesan tersebut. Lihat bagian Kontrol Alur untuk mengetahui detailnya.

Buka Referensi Protokol untuk melihat daftar semua parameter pesan.

Format permintaan

Pesan dengan payload — pesan notifikasi

Berikut ini stanza XMPP untuk pesan notifikasi:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
     "to":"REGISTRATION_ID",  // "to" replaces "registration_ids"
     "notification": {
        "title": "Portugal vs. Denmark”,
        "body”: "5 to 1”
      },
      "time_to_live":"600"
  }
  </gcm>
</message>

Pesan dengan payload — pesan data

Berikut ini stanza XMPP yang berisi pesan JSON dari server aplikasi ke FCM:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "to":"REGISTRATION_ID",  // "to" replaces "registration_ids"
      "message_id":"m-1366082849205" // new required field
      "data":
      {
          "hello":"world",
      }
      "time_to_live":"600",
  }
  </gcm>
</message>

Format respons

Respons FCM bisa memiliki tiga kemungkinan format. Yang pertama adalah pesan 'ack' biasa. Namun, jika respons tersebut berisi error, pesan bisa ditampilkan dalam 2 format lain, yang dijelaskan di bawah ini.

Pesan ACK

Berikut ini stanza XMPP yang berisi pesan ACK/NACK dari FCM ke server aplikasi:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "from":"REGID",
      "message_id":"m-1366082849205"
      "message_type":"ack"
  }
  </gcm>
</message>

Pesan NACK

Error NACK merupakan pesan XMPP biasa yang pesan status message_type-nya adalah "nack". Pesan NACK berisi:

  • Kode error NACK.
  • Deskripsi error NACK.

Berikut ini adalah beberapa contoh.

Pendaftaran buruk:

<message>
  <gcm xmlns="google:mobile:data">
  {
    "message_type":"nack",
    "message_id":"msgId1",
    "from":"SomeInvalidRegistrationToken",
    "error":"BAD_REGISTRATION",
    "error_description":"Invalid token on 'to' field: SomeInvalidRegistrationId"
  }
  </gcm>
</message>

JSON tidak valid:

<message>
 <gcm xmlns="google:mobile:data">
 {
   "message_type":"nack",
   "message_id":"msgId1",
   "from":"bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
   "error":"INVALID_JSON",
   "error_description":"InvalidJson: JSON_TYPE_ERROR : Field \"time_to_live\" must be a JSON java.lang.Number: abc"
 }
 </gcm>
</message>

Tingkat Pengiriman Pesan Perangkat Terlampaui:

<message id="...">
  <gcm xmlns="google:mobile:data">
  {
    "message_type":"nack",
    "message_id":"msgId1",
    "from":"REGID",
    "error":"DEVICE_MESSAGE_RATE_EXCEEDED",
    "error_description":"Downstream message rate exceeded for this registration id"
  }
  </gcm>
</message>

Buka Referensi Server untuk melihat daftar lengkap kode error NACK. Pesan yang di-NACK tidak boleh dicoba lagi, kecuali jika ada ketentuan lain. Kode error NACK yang tidak terduga harus diperlakukan sama dengan INTERNAL_SERVER_ERROR.

Error stanza

Anda juga bisa mengalami error stanza dalam kasus tertentu. Error stanza berisi:

  • Kode error stanza.
  • Deskripsi error stanza (teks bebas).

Misalnya:

<message id="3" type="error" to="123456789@fcm.googleapis.com/ABC">
  <gcm xmlns="google:mobile:data">
     {"random": "text"}
  </gcm>
  <error code="400" type="modify">
    <bad-request xmlns="urn:ietf:params:xml:ns:xmpp-stanzas"/>
    <text xmlns="urn:ietf:params:xml:ns:xmpp-stanzas">
      InvalidJson: JSON_PARSING_ERROR : Missing Required Field: message_id\n
    </text>
  </error>
</message>

Pesan kontrol

FCM perlu menutup koneksi secara berkala untuk melakukan load balancing. Sebelum menutup koneksi, FCM mengirim pesan CONNECTION_DRAINING untuk menunjukkan bahwa koneksi sedang dikosongkan dan akan segera ditutup. "Pengosongan" adalah penutupan aliran pesan yang masuk ke koneksi, tapi mengizinkan apa pun yang sudah ada dalam pipeline untuk terus mengalir. Saat menerima pesan CONNECTION_DRAINING, Anda harus segera mulai mengirimkan pesan ke koneksi FCM lain, dengan membuka koneksi baru jika perlu. Walaupun demikian, Anda harus tetap membuka koneksi asal dan terus menerima pesan yang mungkin datang melalui koneksi tersebut (dan meng-ACK pesan tersebut). FCM akan memulai penutupan koneksi ketika telah siap.

Pesan CONNECTION_DRAINING terlihat seperti ini:

<message>
  <data:gcm xmlns:data="google:mobile:data">
  {
    "message_type":"control"
    "control_type":"CONNECTION_DRAINING"
  }
  </data:gcm>
</message>

Saat ini, satu-satunya control_type yang didukung adalah CONNECTION_DRAINING.

Kontrol alur

Setiap pesan yang dikirim ke FCM akan menerima respons ACK atau NACK. Pesan yang belum menerima salah satu respons ini dianggap tertunda. Jika pesan tertunda mencapai 100, server aplikasi akan berhenti mengirim pesan baru dan menunggu FCM untuk mengonfirmasi beberapa pesan tertunda, seperti ditunjukkan dalam gambar 1:

Diagram mendetail tentang alur kontrol antara FCM dan server aplikasi

Gambar 1. Alur pesan/ack.

Sebaliknya, agar server aplikasi tidak kelebihan muatan, FCM berhenti mengirim jika ada terlalu banyak pesan yang tidak terkonfirmasi. Oleh sebab itu, server aplikasi harus meng-"ACK" pesan upstream, yang diterima dari aplikasi klien melalui FCM, sesegera mungkin agar alur pesan masuk tetap konstan. Batas pesan tertunda yang disebutkan di atas tidak berlaku untuk ACK ini. Bahkan jika jumlah pesan tertunda mencapai 100, server aplikasi harus terus mengirim ACK untuk pesan yang diterima dari FCM, agar pengiriman pesan upstream baru tidak terblokir.

ACK hanya valid dalam konteks satu koneksi. Jika koneksi tertutup sebelum pesan bisa ditandai sebagai ACK, server aplikasi harus menunggu FCM mengirim ulang pesan upstream sebelum menandainya sebagai ACK lagi. Demikian juga, semua pesan tertunda yang belum menerima ACK/NACK dari FCM sebelum koneksi tertutup harus dikirim lagi.