Buka konsol

Lingkungan server dan FCM Anda

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 baik ke backend FCM.
  • Mampu menangani permintaan dan mengirimnya kembali menggunakan back-off 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 balasan). 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 memiliki dukungan untuk 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).
  • Protokol HTTP lama.
  • Protokol server XMPP. Perlu diperhatikan bahwa jika Anda ingin menggunakan pengiriman upstream dari aplikasi klien, Anda harus menggunakan XMPP.

Firebase Admin SDK untuk FCM

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

  • Mengirim pesan ke satu perangkat
  • 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. Jika Anda sudah memiliki project Firebase, mulailah dengan Menambahkan SDK. Setelah Firebase Admin SDK diinstal, Anda dapat langsung menulis logika untuk membuat permintaan kirim.

Protokol Server FCM

Saat ini, FCM menyediakan protokol server mentah berikut:

Server aplikasi Anda dapat menggunakan semua protokol ini secara terpisah atau berpasangan. 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 pesan downstream, dari cloud ke perangkat.
    • XMPP: Pesan upstream dan downstream (perangkat ke cloud, cloud ke perangkat).
  • Pengiriman pesan (sinkron atau asinkron)
    • HTTP: Sinkron. Server aplikasi mengirim pesan sebagai permintaan HTTP POST 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 baris penuh tertinggi melalui koneksi XMPP persisten. Server koneksi XMPP mengirim notifikasi konfirmasi atau kegagalan (dalam format pesan XMPP berenkode ACK dan NACK JSON khusus) secara asinkron.
  • JSON
    • HTTP: Pesan JSON dikirim sebagai HTTP POST.
    • XMPP: Pesan JSON dibungkus 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 Membuat Permintaan Pengiriman 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 harus selalu ada dan juga harus unik (per ID pengirim).
  • XMPP menggunakan kunci server untuk mengotorisasi koneksi tetap ke FCM. Lihat Mengotorisasi 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",
      "delivery_receipt_requested": true/false
  }
  </gcm>
</message>

Format respons

Respons FCM bisa memiliki tiga kemungkinan format. Yang pertama adalah pesan 'ack' biasa. Tetapi jika respons berisi error, pesan bisa tampil dalam 2 format berbeda, 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 dengan pesan status message_type 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":"SomeInvalidRegistrationId",
    "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>

Jumlah 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 ber-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 dikuras dan akan segera ditutup. "Pengurasan" 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 memulai pengiriman 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 CONNECTION_DRAINING adalah satu-satunya control_type yang didukung.

Menerima tanda terima pengiriman

Untuk aplikasi klien Android dan Chrome, Anda bisa memperoleh tanda terima pengiriman (dikirim dari FCM ke server aplikasi) ketika perangkat mengonfirmasi telah menerima pesan yang dikirim oleh FCM.

Untuk mengaktifkan fitur ini, pesan yang dikirim oleh server aplikasi Anda ke FCM harus menyertakan kolom delivery_receipt_requested. Jika kolom ini ditetapkan ke true, FCM akan mengirim tanda terima pengiriman ketika perangkat mengonfirmasi telah menerima pesan tertentu.

Berikut adalah stanza XMPP yang berisi pesan JSON dengan "delivery_receipt_requested" disetel ke true:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "to":"REGISTRATION_ID",
      "message_id":"m-1366082849205"
      "data":
      {
          "hello":"world",
      }
      "time_to_live":"600",
      "delivery_receipt_requested": true
  }
  </gcm>
</message>

Ini adalah contoh tanda terima pengiriman yang dikirim oleh FCM untuk memberi tahu server aplikasi Anda bahwa perangkat menerima pesan yang dikirim oleh FCM:

<message id="">
  <gcm xmlns="google:mobile:data">
  {
      "category":"com.example.yourapp", // to know which app sent it
      "data":
      {
         “message_status":"MESSAGE_SENT_TO_DEVICE",
         “original_message_id”:”m-1366082849205”
         “device_registration_id”: “REGISTRATION_ID”
      },
      "message_id":"dr2:m-1366082849205",
      "message_type":"receipt",
      "from":"fcm.googleapis.com"
  }
  </gcm>
</message>

Perhatikan hal-hal berikut ini:

  • "message_type" disetel ke "receipt".
  • "message_status" disetel ke "MESSAGE_SENT_TO_DEVICE", menunjukkan bahwa perangkat telah menerima pesan. Perhatikan bahwa dalam kasus ini, "message_status" bukan kolom tapi bagian dari payload data.
  • ID pesan tanda terima terdiri dari ID pesan asal, tetapi dengan awalan dr2:. Server aplikasi harus menggunakan koneksi yang sama untuk mengirimkan kembali ACK dengan ID ini, yang dalam contoh ini adalah dr2:m-1366082849205.
  • ID pesan asal, token pendaftaran perangkat, dan status ada di dalam kolom "data".
  • Jika koneksi antara FCM dan perangkat buruk, Firebase Cloud Messaging bisa mengirim beberapa duplikasi tanda terima pengiriman. Anda boleh mengabaikan duplikasi tersebut.

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:

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.