Kullanıcının Abone Olması

Matt Gaunt

İlk adım, kullanıcıdan ona push mesajı göndermek için izin almaktır. Kullanıcı PushSubscription ile başlayalım.

Bunu yapan JavaScript API'nin bunu yapması makul ölçüde basit olduğu için, hikaye anlatacağım.

Özellik algılama

Öncelikle mevcut tarayıcının push mesajlarını gerçekten destekleyip desteklemediğini kontrol etmemiz gerekir. Kontrol edebildiğimiz push, iki basit kontrolle desteklenir.

  1. navigator üzerinde serviceWorker olup olmadığını kontrol edin.
  2. window'da PushManager'ı kontrol edin.
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;
}

Hem Service Worker hem de hizmet çalışanı için tarayıcı desteği hem bu hem de manuel olarak bildirim gönderen kademeli olarak geliştirir.

Hizmet çalışanı kaydedin

Algılama özelliği sayesinde hem Service Worker'ların hem Push'un desteklendiğini biliyoruz. Sonraki adım “kaydetmek” hizmet çalışanıdır.

Bir hizmet çalışanını kaydettiğimizde, tarayıcıya Service Worker dosyamızın nerede olduğunu bildirmiş oluruz. Dosya hâlâ yalnızca JavaScript'tir, ancak tarayıcı "dosyaya erişim izni verir" hizmet çalışanı için Push dahil API'ler. Daha kesin belirtmek gerekirse tarayıcı, dosyayı bir hizmet çalışanında çalıştırır. bahsedeceğim.

Bir hizmet çalışanını kaydetmek için navigator.serviceWorker.register() öğesini çağırın ve şu yolu iletin: inceleyeceğiz. Şunun gibi:

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

Bu işlev, tarayıcıya bir service Worker dosyamızın olduğunu ve bu dosyanın bulunduğu yeri bildirir. İçinde bu durumda, hizmet çalışanı dosyası /service-worker.js konumundadır. Kamera arkası register() arandıktan sonra şu adımları uygulayacak:

  1. Service Worker dosyasını indirin.

  2. JavaScript'i çalıştırın.

  3. Her şey düzgün çalışıyorsa ve hata yoksa register() tarafından verilen taahhüt çözer. Herhangi bir hata varsa taahhüt reddedilir.

register() reddederse Chrome Geliştirici Araçları'nda JavaScript'inizde yazım hatası / hata olup olmadığını tekrar kontrol edin.

register() çözümlediğinde bir ServiceWorkerRegistration döndürür. Bunu kullanacağız: PushManager API'sine erişmek için kayıt işlemini yapmanız gerekir.

PushManager API tarayıcı uyumluluğu

Tarayıcı Desteği

  • Chrome: 42..
  • Kenar: 17..
  • Firefox: 44..
  • Safari: 16..

Kaynak

İzin isteniyor

Service Worker'ımızı kaydettik ve kullanıcının abone olmasını sağlamaya hazırız. Sonraki adım, push mesajı göndermek için kullanıcıdan izin alması gerekir.

İzin alma API'si nispeten basittir. Dezavantajı ise API'nin kısa süre önce geri çağırması yerine Vaat döndürmesi yapıldı. İlgili içeriği oluşturmak için kullanılan şu anki sorun, API'nin hangi sürümünün mevcut sürüm tarafından bu yüzden her ikisini de uygulamanız ve ikisini de ele almanız gerekir.

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

Yukarıdaki kodda, önemli kod snippet'i Notification.requestPermission() Bu yöntemde kullanıcıya bir istem gösterilir:

Masaüstü ve mobil Chrome'da izin istemi.

Kullanıcı İzin Ver veya Engelle düğmesine basarak veya yalnızca kapatarak izin istemiyle etkileşimde bulunduğunda Bu sonuç bir dize olarak verilir: 'granted', 'default' veya 'denied'.

Yukarıdaki örnek kodda, askPermission() tarafından döndürülen taahhüt aksi takdirde, taahhüdün reddedilmesine neden olacak bir hata yaparız.

Yapmanız gereken tek şey, kullanıcının "Engelle" düğmesini tıklamasıdır. düğmesini tıklayın. Bu durumda, web uygulamanız kullanıcıdan tekrar izin isteyemeyecek. Kullanıcı, manuel olarak "engellemeyi kaldır" uygulamanızın gizli kalmış izin durumunu değiştirerek Ayarlar panelinde. Kullanıcıdan nasıl ve ne zaman izin isteyeceğinizi iyi düşünün. Çünkü "engelleme"yi tıklarlarsa bu kararı geri almanın kolay bir yolu olmaz.

Neyse ki çoğu kullanıcı bir web sitesini ziyaret ettiği sürece İznin neden istendiğini biliyor.

Bazı popüler sitelerin nasıl izin istediklerine daha sonra bakacağız.

PushManager ile bir kullanıcının abone olmasını sağlayın

Hizmet çalışanımızı kaydettirdikten ve izin aldıktan sonra bir kullanıcıyı abone olmak için registration.pushManager.subscribe() aranıyor.

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

subscribe() yöntemini çağırırken, ikisinden de oluşan bir options nesnesini iletiriz. Zorunlu ve isteğe bağlı parametrelerdir.

Sunabileceğimiz tüm seçeneklere göz atalım.

userGörünürlük seçenekleri

Push tarayıcılara ilk kez eklendiğinde, geliştiricilerin de push mesajı gönderebiliyor ancak bildirim gösteremiyor. Bu yöntem genellikle sessiz olarak adlandırılır kullanıcının arka planda bir şey olduğunu bilmemesi nedeniyle push bildirimi göndermektir.

Endişe, geliştiricilerin bir kullanıcının konumunu izlemek gibi kötü şeyler yapabilmeleriydi. devamlı olarak işlemesini sağlar.

Böyle bir senaryodan kaçınmak ve spesifikasyon yazarlarına bu konuyu en iyi şekilde nasıl destekleyebileceklerini düşünmeleri için zaman tanımak özelliğinde, userVisibleOnly seçeneği eklendi ve true değerini iletmek sembolik bir web uygulamasının bir bildirim göstereceğini belirten bir anlaşmaya vardığınızı lütfen unutmayın. (sessiz push olmamak kaydıyla).

Şu anda true değerini iletmeniz zorunludur. Örneğin userVisibleOnly anahtarı veya false girişinde şu hatayı alırsınız:

Chrome şu anda kullanıcılar tarafından görülebilen mesajlardır. Bu durumu, Bunun yerine pushManager.subscribe({userVisibleOnly: true}). Görüntüleyin Daha fazla bilgi için https://goo.gl/yqv4Q4 adresine gidin.

Şu anda Chrome'da hiçbir zaman sınırsız sessiz itme uygulanmayacak gibi görünüyor. Bunun yerine Spesifikasyon yazarları, web uygulamalarına belirli bir bir web uygulaması kullanımına dayalı sessiz push mesajlarının sayısı.

applicationServerKey seçeneği

"Uygulama sunucusu anahtarları"ndan kısaca bahsettik ele alacağız. "Uygulama sunucu anahtarları" bir push hizmeti tarafından kullanıcının abone olmasını sağlayan uygulamayı tanımlamak için kullanılır. aynı uygulamanın bu kullanıcıya mesaj gönderdiğinden emin olmalısınız.

Uygulama sunucusu anahtarları, uygulamanıza özgü genel ve özel anahtar çiftidir. Özel anahtar, uygulamanızda gizli tutulmalıdır ve ortak anahtar paylaşılabilir özgürce.

subscribe() çağrısına iletilen applicationServerKey seçeneği uygulamanın herkese açık tuşuna basın. Tarayıcı, kullanıcıya abone olurken bunu bir push hizmetine iletir. Yani push hizmeti, uygulamanızın ortak anahtarını kullanıcının PushSubscription koduna bağlayabilir.

Aşağıdaki şemada bu adımlar gösterilmiştir.

  1. Web uygulamanız bir tarayıcıda yüklendiğinde subscribe() adlı kişiyi herkese açık uygulama sunucusu anahtarıdır.
  2. Ardından tarayıcı, uç nokta oluşturacak şekilde bir push hizmetine ağ isteğinde bulunur. bu uç noktayı uygulamanın ortak anahtarıyla ilişkilendirir ve uç noktayı emin olun.
  3. Tarayıcı bu uç noktayı, PushSubscription subscribe() söz.

Abone olma bölümünde kullanılan ortak uygulama sunucusu anahtarı resmi
yöntemidir.

Daha sonra push mesajı göndermek istediğinizde, öncelikle Yetkilendirme üstbilgisi oluşturmanız gerekir. Bu e-posta adresi, uygulama sunucunuzun özel anahtarı ile imzalanan bilgileri içerir. push hizmeti push mesajı gönderme isteği aldığında, bu imzalı Yetkilendirme başlığını doğrulayabilir. isteği alan uç noktaya bağlı ortak anahtarı arayın. İmza , push hizmetinin mevcut sunucu tarafından eşleşen özel anahtar. Temel olarak, başkalarının e-posta göndermesini engelleyen bir güvenlik önlemi ve bir uygulamanın kullanıcılarına gönderilir.

Özel uygulama sunucusu anahtarı gönderilirken nasıl kullanılır?
mesaj

Teknik olarak, applicationServerKey isteğe bağlıdır. Ancak en kolay yöntem Chrome'daki uygulama için bunu gerektirir, diğer tarayıcılarda ise sahip olacaksınız. Firefox'ta isteğe bağlıdır.

Uygulama sunucusu anahtarının ne olması gerektiğini tanımlayan spesifikasyon VAPID spesifikasyonu. "Uygulama sunucusu anahtarları" ifadesini içeren bir metin okuduğunuzda veya "VAPID anahtarları" ile aynı şey olduklarını unutmayın.

Uygulama sunucusu anahtarları oluşturma

Uygulama sunucusu anahtarları için genel ve gizli bir grup oluşturmak için web-push-codelab.glitch.me veya web push komut satırı anahtar oluşturmak için aşağıdakileri yapın:

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

Bu anahtarları uygulamanız için yalnızca bir kez oluşturmanız yeterlidir. Anahtarları sakladığınızdan emin olun. olarak ayarlanır. (Evet, az önce söyledim.)

İzinler ve abone ol()

subscribe() çağrısının bir yan etkisi vardır. Web uygulamanız subscribe() çağrısı sırasında bildirim gösteriliyorsa tarayıcı, bazı izinler verebilirsiniz. Bu, kullanıcı arayüzünüz bu akışta çalışıyorsa faydalıdır. Ancak isterseniz Notification.requestPermission() API'ye bağlı kalın tasarlamak için bunu kullanıyor.

Push Aboneliği nedir?

subscribe() adını verip bazı seçenekleri değerlendiriyoruz ve karşılığında PushSubscription ile elde edilen aşağıdaki gibi bir kod vardır:

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

PushSubscription nesnesi, push işlemi göndermek için gereken tüm bilgileri içerir kullanıcıya gönderebilir. İçeriği JSON.stringify() kullanarak yazdırırsanız takip etmek için:

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

endpoint, push hizmetleri URL'sidir. Push mesajını tetiklemek için POST isteği oluşturun .

keys nesnesi, push mesajıyla gönderilen mesaj verilerini şifrelemek için kullanılan değerleri içerir. (bunu bu bölümde daha sonra ele alacağız).

Süre sonunu önlemek için düzenli olarak yeniden abonelik

Push bildirimlerine abone olduğunuzda genellikle PushSubscription.expirationTime olarak null alırsınız. Teoride bu, aboneliğin hiçbir zaman sona ermeyeceği anlamına gelir (DOMHighResTimeStamp aldığınızdan farklı olarak, aboneliğin süresinin tam olarak ne zaman dolacağını gösterir). Bununla birlikte, pratikte, tarayıcıların aboneliklerin süresinin dolmasına izin vermesi yaygın bir durumdur. Örneğin, daha uzun süre boyunca push bildirimi alınmamışsa veya tarayıcı, kullanıcının push bildirimi iznine sahip bir uygulama kullanmadığını tespit ederse. Bunu önlemek için, aşağıdaki snippet'te gösterildiği gibi, alınan her bildirimden sonra kullanıcının yeniden abone olması gerekir. Bu yöntem, tarayıcının aboneliğin otomatik olarak sona ermemesi için yeterince sık bildirim göndermenizi gerektirir ve aboneliğin süresinin dolmaması için meşru bildirim ihtiyaçlarının kullanıcıya istemsiz olarak spam yapmaya karşı avantaj ve dezavantajlarını çok dikkatli bir şekilde değerlendirmeniz gerekir. Sonuç olarak, kullanıcıyı uzun zamandır unutulmuş bildirim aboneliklerinden korumak için tarayıcıyla mücadele etmeye çalışmamalısınız.

/* In the Service Worker. */

self.addEventListener('push', function(event) {
  console.log('Received a push message', event);

  // Display notification or handle data
  // Example: show a notification
  const title = 'New Notification';
  const body = 'You have new updates!';
  const icon = '/images/icon.png';
  const tag = 'simple-push-demo-notification-tag';

  event.waitUntil(
    self.registration.showNotification(title, {
      body: body,
      icon: icon,
      tag: tag
    })
  );

  // Attempt to resubscribe after receiving a notification
  event.waitUntil(resubscribeToPush());
});

function resubscribeToPush() {
  return self.registration.pushManager.getSubscription()
    .then(function(subscription) {
      if (subscription) {
        return subscription.unsubscribe();
      }
    })
    .then(function() {
      return self.registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
      });
    })
    .then(function(subscription) {
      console.log('Resubscribed to push notifications:', subscription);
      // Optionally, send new subscription details to your server
    })
    .catch(function(error) {
      console.error('Failed to resubscribe:', error);
    });
}

Sunucunuza abonelik gönderin

Push aboneliğiniz olduğunda bunu sunucunuza göndermek isteyebilirsiniz. Nasıl iletişim kuracağınıza Ancak küçük bir ipucu, JSON.stringify() kullanarak gerekli tüm verileri subscription nesnesini tanımlayın. Alternatif olarak, aynı şu şekilde olabilir:

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

Abonelik, web sayfasında aşağıdaki şekilde gönderilir:

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

Düğüm sunucusu bu isteği alır ve daha sonra kullanılmak üzere verileri bir veritabanına kaydeder.

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

Sunucumuzdaki PushSubscription ayrıntılarını kullanıcımıza gönderebiliriz. mesajımızı sizinle paylaşabiliriz.

Süre sonunu önlemek için düzenli olarak yeniden abonelik

Push bildirimlerine abone olduğunuzda genellikle PushSubscription.expirationTime olarak null alırsınız. Teoride bu, aboneliğin hiçbir zaman sona ermeyeceği anlamına gelir (DOMHighResTimeStamp aldığınızdan farklı olarak, aboneliğin süresinin tam olarak ne zaman dolacağını gösterir). Bununla birlikte pratikte, tarayıcıların aboneliklerin süresinin dolmasına izin vermesi yaygın bir durumdur. Örneğin, uzun süre boyunca push bildirimi alınmamışsa veya tarayıcı, kullanıcının push bildirimi iznine sahip uygulamayı kullanmadığını tespit ederse. Bunu önlemek için, aşağıdaki snippet'te gösterildiği gibi, alınan her bildirimden sonra kullanıcının yeniden abone olması gerekir. Bu durumda, tarayıcının aboneliğin otomatik olarak dolmaması için yeterince sık bildirim göndermeniz gerekir. Bu nedenle, abonelik süresinin dolmaması için meşru bildirim ihtiyaçlarının kullanıcıya spam yapma karşısında avantaj ve dezavantajlarını çok dikkatli bir şekilde değerlendirmeniz gerekir. Sonuç olarak, kullanıcıyı uzun zamandır unutulmuş bildirim aboneliklerinden korumak için tarayıcıyla mücadele etmeye çalışmamalısınız.

/* In the Service Worker. */

self.addEventListener('push', function(event) {
  console.log('Received a push message', event);

  // Display notification or handle data
  // Example: show a notification
  const title = 'New Notification';
  const body = 'You have new updates!';
  const icon = '/images/icon.png';
  const tag = 'simple-push-demo-notification-tag';

  event.waitUntil(
    self.registration.showNotification(title, {
      body: body,
      icon: icon,
      tag: tag
    })
  );

  // Attempt to resubscribe after receiving a notification
  event.waitUntil(resubscribeToPush());
});

function resubscribeToPush() {
  return self.registration.pushManager.getSubscription()
    .then(function(subscription) {
      if (subscription) {
        return subscription.unsubscribe();
      }
    })
    .then(function() {
      return self.registration.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array('YOUR_PUBLIC_VAPID_KEY_HERE')
      });
    })
    .then(function(subscription) {
      console.log('Resubscribed to push notifications:', subscription);
      // Optionally, send new subscription details to your server
    })
    .catch(function(error) {
      console.error('Failed to resubscribe:', error);
    });
}

SSS

Bu noktada kullanıcıların sıkça sorduğu birkaç soru:

Bir tarayıcının kullandığı push hizmetini değiştirebilir miyim?

Hayır. Push hizmetini tarayıcı tarafından seçilir ve subscribe() çağrısı, tarayıcı, push hizmetine ağ isteklerinde bulunur seçeneğini tıklayarak PushSubscription öğesini oluşturan ayrıntıları alabilirsiniz.

Her tarayıcı farklı bir Push Hizmeti kullanır, farklı API'leri yok mu?

Tüm push hizmetlerinde aynı API beklenir.

Bu yaygın API'nin adı Web Push Protokolü ve ağ isteğini açıklar. uygulamanızın push mesajı tetiklemesi için yapması gereken işlemlerdir.

Bir kullanıcıyı masaüstünden abone olduğumda telefonundan da abone olur muyum?

Ne yazık ki mümkün değil. Bir kullanıcı, istediği her tarayıcıda push için kaydolmalıdır mesaj almayı açık hale getirir. Bunun yanı sıra, dönüşüm hunisinin orta kısmına yönelik bir her cihazda kullanıcı izni verir.

Yakında gidilecek yerler

Kod laboratuvarları