Membuat Langganan Pengguna

Langkah pertama adalah mendapatkan izin dari pengguna untuk mengirimkan pesan push kepada mereka, lalu kita bisa mendapatkan PushSubscription.

JavaScript API untuk melakukan hal ini cukup mudah, jadi mari kita telusuri alur logika.

Deteksi fitur

Pertama-tama kita perlu memeriksa apakah {i>browser <i} saat ini mendukung {i>push messaging<i}. Kita dapat memeriksa apakah push didukung dengan dua pemeriksaan sederhana.

  1. Periksa serviceWorker di navigator.
  2. Periksa PushManager di window.
if (!('serviceWorker' in navigator)) {
  // Service Worker isn't supported on this browser, disable or hide UI.
  return;
}

if (!('PushManager' in window)) {
  // Push isn't supported on this browser, disable or hide UI.
  return;
}

Meskipun dukungan browser berkembang dengan cepat untuk pekerja layanan dan pesan push, sebaiknya Anda memiliki deteksi fitur untuk keduanya dan meningkatkan kualitas secara progresif.

Mendaftarkan pekerja layanan

Dengan deteksi fitur, kita tahu bahwa pekerja layanan dan Push didukung. Langkah berikutnya adalah "mendaftarkan" pekerja layanan kita.

Ketika mendaftarkan pekerja layanan, kita memberi tahu browser lokasi file pekerja layanan. File tersebut masih berupa JavaScript, tetapi browser akan "memberikan akses" ke API pekerja layanan, termasuk push. Lebih tepatnya, browser menjalankan file di lingkungan pekerja layanan.

Untuk mendaftarkan pekerja layanan, panggil navigator.serviceWorker.register(), dengan meneruskan jalur ke file kita. Seperti ini:

function registerServiceWorker() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      console.log('Service worker successfully registered.');
      return registration;
    })
    .catch(function (err) {
      console.error('Unable to register service worker.', err);
    });
}

Fungsi ini memberi tahu browser bahwa kita memiliki file service worker dan lokasinya. Dalam hal ini, file pekerja layanan berada di /service-worker.js. Di balik layar, browser akan melakukan langkah berikut setelah memanggil register():

  1. Download file pekerja layanan.

  2. Jalankan JavaScript.

  3. Jika semuanya berjalan dengan benar dan tidak ada error, promise yang ditampilkan oleh register() akan diselesaikan. Jika ada kesalahan dalam bentuk apa pun, promise akan ditolak.

Jika register() menolak, periksa kembali JavaScript Anda untuk menemukan kesalahan ketik / error di Chrome DevTools.

Setelah di-resolve, register() akan menampilkan ServiceWorkerRegistration. Kita akan menggunakan pendaftaran ini untuk mengakses PushManager API.

Kompatibilitas browser API PushManager

Dukungan Browser

  • 42
  • 17
  • 44
  • 16

Sumber

Meminta izin

Kita telah mendaftarkan pekerja layanan dan siap membuat pengguna berlangganan, langkah berikutnya adalah mendapatkan izin dari pengguna untuk mengirimkan pesan push.

API untuk mendapatkan izin relatif sederhana. Kelemahannya adalah API tersebut baru-baru ini diubah dari menerima callback menjadi menampilkan Promise. Masalah ini adalah kita tidak dapat mengetahui versi API mana yang diimplementasikan oleh browser saat ini, sehingga Anda harus mengimplementasikan keduanya dan menangani keduanya.

function askPermission() {
  return new Promise(function (resolve, reject) {
    const permissionResult = Notification.requestPermission(function (result) {
      resolve(result);
    });

    if (permissionResult) {
      permissionResult.then(resolve, reject);
    }
  }).then(function (permissionResult) {
    if (permissionResult !== 'granted') {
      throw new Error("We weren't granted permission.");
    }
  });
}

Dalam kode di atas, cuplikan kode yang penting adalah panggilan ke Notification.requestPermission(). Metode ini akan menampilkan perintah kepada pengguna:

Permintaan izin di Chrome desktop dan seluler.

Setelah pengguna berinteraksi dengan dialog izin dengan menekan Izinkan, Blokir, atau cukup menutupnya, kita akan diberi hasilnya sebagai string: 'granted', 'default', atau 'denied'.

Dalam kode contoh di atas, promise yang ditampilkan oleh askPermission() akan di-resolve jika izin diberikan. Jika tidak, kita akan menampilkan error yang membuat promise ditolak.

Satu kasus ekstrem yang perlu Anda tangani adalah jika pengguna mengklik tombol 'Blokir'. Jika hal ini terjadi, aplikasi web Anda tidak akan dapat meminta izin lagi kepada pengguna. Mereka harus "membuka blokir" aplikasi secara manual dengan mengubah status izinnya, yang tersembunyi di panel setelan. Pikirkan baik-baik cara dan waktu Anda meminta izin kepada pengguna, karena jika mereka mengklik blokir, bukan cara mudah untuk membatalkan keputusan tersebut.

Kabar baiknya, sebagian besar pengguna dengan senang hati memberikan izin selama mereka mengetahui alasan permintaan izin tersebut.

Kita akan melihat bagaimana beberapa situs populer meminta izin nanti.

Membuat pengguna berlangganan dengan PushManager

Setelah pekerja layanan terdaftar dan mendapatkan izin, kita bisa membuat pengguna berlangganan dengan memanggil registration.pushManager.subscribe().

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

Saat memanggil metode subscribe(), kita meneruskan objek options, yang terdiri dari parameter wajib dan opsional.

Mari kita lihat semua opsi yang bisa kita teruskan.

Opsi userVisibleOnly

Ketika push pertama kali ditambahkan ke browser, ada ketidakpastian tentang apakah developer harus dapat mengirim pesan push dan tidak menampilkan notifikasi. Hal ini biasanya disebut sebagai push senyap, karena pengguna tidak mengetahui bahwa sesuatu telah terjadi di latar belakang.

Masalahnya adalah developer dapat melakukan hal-hal buruk seperti melacak lokasi pengguna secara terus-menerus tanpa diketahui pengguna.

Untuk menghindari skenario ini dan memberikan waktu kepada penulis spesifikasi untuk mempertimbangkan cara terbaik dalam mendukung fitur ini, opsi userVisibleOnly ditambahkan dan meneruskan nilai true adalah perjanjian simbolis dengan browser bahwa aplikasi web akan menampilkan notifikasi setiap kali push diterima (yaitu tidak ada push diam).

Saat ini, Anda harus memasukkan nilai true. Jika Anda tidak menyertakan kunci userVisibleOnly atau meneruskan false, Anda akan mendapatkan error berikut:

Chrome saat ini hanya mendukung Push API untuk langganan yang akan menghasilkan pesan yang terlihat oleh pengguna. Anda dapat menunjukkannya dengan memanggil pushManager.subscribe({userVisibleOnly: true}). Lihat https://goo.gl/yqv4Q4 untuk mengetahui detail selengkapnya.

Sepertinya push senyap menyeluruh tidak akan pernah diterapkan di Chrome. Sebaliknya, penulis spesifikasi mempelajari gagasan API anggaran yang akan memungkinkan aplikasi web menerima sejumlah pesan push senyap tertentu berdasarkan penggunaan aplikasi web.

Opsi applicationServerKey

Kami menyebutkan secara singkat "kunci server aplikasi" di bagian sebelumnya. "Kunci server aplikasi" digunakan oleh layanan push untuk mengidentifikasi aplikasi yang membuat pengguna berlangganan dan memastikan bahwa aplikasi yang sama mengirimkan pesan kepada pengguna tersebut.

Kunci server aplikasi adalah pasangan kunci publik dan pribadi yang unik untuk aplikasi Anda. Kunci pribadi harus dirahasiakan untuk aplikasi Anda, dan kunci publik dapat dibagikan dengan bebas.

Opsi applicationServerKey yang diteruskan ke panggilan subscribe() adalah kunci publik aplikasi. Browser meneruskannya ke layanan push saat pengguna berlangganan, yang berarti layanan push dapat mengaitkan kunci publik aplikasi Anda ke PushSubscription pengguna.

Diagram di bawah menggambarkan langkah-langkah ini.

  1. Aplikasi web Anda dimuat di browser, lalu memanggil subscribe(), yang meneruskan kunci server aplikasi publik Anda.
  2. Selanjutnya, browser membuat permintaan jaringan ke layanan push yang akan membuat endpoint, mengaitkan endpoint ini dengan kunci publik aplikasi, dan menampilkan endpoint ke browser.
  3. Browser akan menambahkan endpoint ini ke PushSubscription, yang ditampilkan melalui promise subscribe().

Ilustrasi kunci server aplikasi publik digunakan dalam metode
berlangganan.

Jika nantinya Anda ingin mengirim pesan push, Anda harus membuat header Authorization yang akan berisi informasi yang ditandatangani dengan kunci pribadi server aplikasi Anda. Saat menerima permintaan untuk mengirim pesan push, layanan push dapat memvalidasi header Otorisasi yang ditandatangani ini dengan mencari kunci publik yang ditautkan ke endpoint yang menerima permintaan tersebut. Jika tanda tangan tersebut valid, layanan push tahu bahwa tanda tangan itu harus berasal dari server aplikasi dengan kunci pribadi yang cocok. Pada dasarnya, ini adalah langkah keamanan yang mencegah orang lain mengirim pesan ke pengguna aplikasi.

Cara kunci server aplikasi pribadi digunakan saat mengirim
pesan

Secara teknis, applicationServerKey bersifat opsional. Namun, penerapan paling mudah di Chrome memerlukannya, dan browser lain mungkin memerlukannya di masa mendatang. Ini opsional di Firefox.

Spesifikasi yang menentukan apa kunci server aplikasi yang seharusnya adalah spesifikasi VAPID. Setiap kali Anda membaca sesuatu yang mengacu pada "kunci server aplikasi" atau "kunci VAPID", ingatlah bahwa keduanya sama.

Cara membuat kunci server aplikasi

Anda dapat membuat kumpulan kunci server aplikasi publik dan pribadi dengan membuka web-push-codelab.glitch.me atau Anda dapat menggunakan command line web-push untuk membuat kunci dengan melakukan hal berikut:

    $ npm install -g web-push
    $ web-push generate-vapid-keys

Anda hanya perlu membuat kunci ini satu kali untuk aplikasi Anda, tetapi pastikan Anda menjaga kerahasiaan kunci pribadi. (Ya, saya baru saja mengatakan itu.)

Izin dan subscribe()

Ada satu efek samping memanggil subscribe(). Jika aplikasi web Anda tidak memiliki izin untuk menampilkan notifikasi pada saat memanggil subscribe(), browser akan meminta izin untuk Anda. Hal ini berguna jika UI Anda berfungsi dengan alur ini, tetapi jika Anda menginginkan lebih banyak kontrol (dan saya rasa sebagian besar developer akan memerlukannya), tetap gunakan Notification.requestPermission() API yang kita gunakan sebelumnya.

Apa itu PushSubscription?

Kita memanggil subscribe(), meneruskan beberapa opsi, dan sebagai gantinya kita mendapatkan promise yang di-resolve menjadi PushSubscription sehingga menghasilkan beberapa kode seperti ini:

function subscribeUserToPush() {
  return navigator.serviceWorker
    .register('/service-worker.js')
    .then(function (registration) {
      const subscribeOptions = {
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(
          'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U',
        ),
      };

      return registration.pushManager.subscribe(subscribeOptions);
    })
    .then(function (pushSubscription) {
      console.log(
        'Received PushSubscription: ',
        JSON.stringify(pushSubscription),
      );
      return pushSubscription;
    });
}

Objek PushSubscription berisi semua informasi yang diperlukan untuk mengirim pesan push kepada pengguna tersebut. Jika Anda mencetak konten menggunakan JSON.stringify(), Anda akan melihat hal berikut:

    {
      "endpoint": "https://some.pushservice.com/something-unique",
      "keys": {
        "p256dh":
    "BIPUL12DLfytvTajnryr2PRdAgXS3HGKiLqndGcJGabyhHheJYlNGCeXl1dn18gSJ1WAkAPIxr4gK0_dQds4yiI=",
        "auth":"FPssNDTKnInHVndSTdbKFw=="
      }
    }

endpoint adalah URL layanan push. Untuk memicu pesan push, buat permintaan POST ke URL ini.

Objek keys berisi nilai yang digunakan untuk mengenkripsi data pesan yang dikirim dengan pesan push (yang akan kita bahas nanti di bagian ini).

Mengirim langganan ke Server Anda

Setelah Anda memiliki langganan push, Anda dapat mengirimkannya ke server Anda. Anda dapat menentukan cara untuk melakukannya, tetapi sebaiknya gunakan JSON.stringify() untuk mendapatkan semua data yang diperlukan dari objek langganan. Atau, Anda dapat mengumpulkan hasil yang sama secara manual seperti ini:

const subscriptionObject = {
  endpoint: pushSubscription.endpoint,
  keys: {
    p256dh: pushSubscription.getKeys('p256dh'),
    auth: pushSubscription.getKeys('auth'),
  },
};

// The above is the same output as:

const subscriptionObjectToo = JSON.stringify(pushSubscription);

Pengiriman langganan dilakukan di halaman web seperti berikut:

function sendSubscriptionToBackEnd(subscription) {
  return fetch('/api/save-subscription/', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
    },
    body: JSON.stringify(subscription),
  })
    .then(function (response) {
      if (!response.ok) {
        throw new Error('Bad status code from server.');
      }

      return response.json();
    })
    .then(function (responseData) {
      if (!(responseData.data && responseData.data.success)) {
        throw new Error('Bad response from server.');
      }
    });
}

Server node menerima permintaan ini dan menyimpan data ke database untuk digunakan nanti.

app.post('/api/save-subscription/', function (req, res) {
  if (!isValidSaveRequest(req, res)) {
    return;
  }

  return saveSubscriptionToDatabase(req.body)
    .then(function (subscriptionId) {
      res.setHeader('Content-Type', 'application/json');
      res.send(JSON.stringify({data: {success: true}}));
    })
    .catch(function (err) {
      res.status(500);
      res.setHeader('Content-Type', 'application/json');
      res.send(
        JSON.stringify({
          error: {
            id: 'unable-to-save-subscription',
            message:
              'The subscription was received but we were unable to save it to our database.',
          },
        }),
      );
    });
});

Dengan detail PushSubscription di server, kita dapat mengirim pesan kepada pengguna kapan pun kita mau.

FAQ

Beberapa pertanyaan umum yang diajukan orang saat ini:

Dapatkah saya mengubah layanan push yang digunakan browser?

Tidak. Layanan push dipilih oleh browser dan seperti yang kita lihat pada panggilan subscribe(), browser akan membuat permintaan jaringan ke layanan push untuk mengambil detail yang membentuk PushSubscription.

Setiap browser menggunakan Push Service yang berbeda, bukankah mereka memiliki API yang berbeda?

Semua layanan push akan mengharapkan API yang sama.

API umum ini disebut Web Push Protocol dan menjelaskan permintaan jaringan yang perlu dibuat oleh aplikasi Anda untuk memicu pesan push.

Jika saya berlangganan pengguna melalui desktop, apakah mereka juga berlangganan di ponsel?

Sayangnya tidak. Pengguna harus mendaftar push pada setiap browser tempat mereka ingin menerima pesan. Perlu diketahui juga bahwa hal ini akan mengharuskan pengguna memberikan izin di setiap perangkat.

Langkah berikutnya

Lab kode