zukucode
主にWEB関連の情報を技術メモとして発信しています。

WEBアプリでプッシュ通知を実装する

WEBアプリでプッシュ通知を実装する方法を紹介します。

googleが紹介している以下のページを参考にしました。

ウェブアプリへのプッシュ通知の追加  |  Web  |  Google Developers

処理の流れ

以下の流れで実装していきます。

  1. サイトに対してプッシュ通知の許可をユーザに促す
  2. 許可した際に取得できる情報(プッシュ通知に必要な情報)を取得し、サーバーのDBなどに保存
  3. 保存した情報を使ってユーザのブラウザにプッシュ通知を送る

1はクライアント処理、2はクライアント処理とサーバー処理、3はサーバー処理になります。

3のサーバー処理で使用するWEBプッシュライブラリは https://github.com/web-push-libs/web-push-php を使用しています。

プッシュ通知の許可

以下のようなダイアログを表示して、ユーザにプッシュ通知を許可してもらいます。

プッシュ通知許可

プッシュ通知の許可をユーザに促すにはService Workerの登録が必要です。

Service WorkerとはブラウザがWebページとは別にバックグラウンドで実行するためのスクリプトです。

今回のようなプッシュ通知や、オフラインの制御などで使用されます。

そのため、IE11など、Service Workerに対応していないブラウザはプッシュ通知は送れないことになります。

対応ブラウザは以下で確認できます。

https://caniuse.com/#feat=serviceworkers

Service Workerの登録

まずはService Workerのファイルをルートディレクトリに作成します。ファイル名は何でもかまいませんが、ここではservice-worker.jsとします。

ファイルの中身はひとまずは空で問題ありません。

  • ルートディレクトリ
    • index.html
    • service-worker.js

以下のようにページロード時にService Workerを登録します。

登録したService Workerの情報をwindowオブジェクトにswという名前で追加しておきます。

window.addEventListener('load', async () => {
  if ('serviceWorker' in navigator) {
    window.sw = await navigator.serviceWorker.register('/service-worker.js', { scope: '/' });
  }
});

アクセス後、Chromeの場合は以下のように開発者ツールからService Workerが登録されていることを確認できます。

SericeWorkerの登録確認

アプリケーション サーバーキーの入手

以下のサイトからPublic KeyPrivate Keyを入手します。

https://web-push-codelab.glitch.me/

アカウント登録などは必要なく、ページにアクセスするとPublic KeyPrivate Keyが表示されていますので、その組み合わせをコピーしてメモしておきます。

これはプッシュ通知を行う際に必要になります。

Private Keyは公開しないようにしてください。

通知許可を促す

まずは以下のファンクションを定義します。

PublicKeyはこのファンクションを使用してUInt8Arrayの形式に変換する必要があります。

function urlB64ToUint8Array (base64String) {
  const padding = '='.repeat((4 - base64String.length % 4) % 4);
  const base64 = (base64String + padding)
    .replace(/\-/g, '+')
    .replace(/_/g, '/');

  const rawData = window.atob(base64);
  const outputArray = new Uint8Array(rawData.length);

  for (let i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i);
  }
  return outputArray;
}

先のステップで登録したService Workerのオブジェクトを使用して、pushManager.subscribeメソッドを実行します。

ページロード時や、何かしらのボタンを押したときのイベントで実行することになると思います。

パラメータは以下を設定します。

userVisibleOnly
true固定
applicationServerKey
UInt8Arrayに変換したPublickKey
const appServerKey = PublicKey; // 取得したPublickKey
const applicationServerKey = urlB64ToUint8Array(appServerKey);

const subscription = await window.sw.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey
});

この処理を実行すると、プッシュ通知の許可を求めるダイアログが表示されます。

プッシュ通知許可

すでにプッシュ通知を許可されている場合はダイアログは表示されません。

また、ここでは省略していますが、ブロックボタンを押されたり、すでにブロックされているような場合は、Primiserejectされるため、実際はcatchの処理を実装する必要があります。

ブラウザのURLバーのアイコンをクリックすると以下のように通知許可の状態を表示・変更できます。

プッシュ通知許可の設定

許可情報を登録

通知が許可されると、変数subscriptionにプッシュ通知に必要な情報が設定されます。

以下の3つの情報をサーバーのDBなどに保存します。

  • endpoint
  • p256dh
  • auth

このうち、p256dhauthは、今回使用する https://github.com/web-push-libs/web-push-php で使用できる形式に合わせて変換します。

p256dhuserPublicKeyauthuserAuthTokenとして登録します。

(サーバー処理で使用するWEBプッシュライブラリによって、必要な情報や形式は変わってくると思います。)

const key = subscription.getKey('p256dh');
const token = subscription.getKey('auth');
const request = {
  endpoint: subscription.endpoint,
  userPublicKey: btoa(String.fromCharCode.apply(null, new Uint8Array(key))),
  userAuthToken: btoa(String.fromCharCode.apply(null, new Uint8Array(token)))
};

プッシュ通知を送信

今回使用するWEBプッシュライブラリ https://github.com/web-push-libs/web-push-php をインストールします。

$ composer require minishlink/web-push

以下の処理を実行すると、プッシュ通知が対象のブラウザに送信されます。

use Minishlink\WebPush\WebPush;

$auth = array(
    'VAPID' => array(
        'subject' => url, // 自身のWEBサイトのURL('http://localhost'など)
        'publicKey' => publicKey, // 取得したPublicKey
        'privateKey' => privateKey, // 取得したPrivateKey
    ),
);

$webPush = new WebPush($auth);

$webPush->sendNotification(
    endpoint, // 登録したendpoint
    'プッシュ通知のテストです。', // プッシュ通知に表示する文言
    userPublicKey, // 登録したuserPublicKey
    userAuthToken // 登録したuserAuthToken
);

$webPush->flush();

プッシュ通知を表示する

受け取ったプッシュ通知を表示するにはService Workerの中身を実装する必要があります。

以下のように実装しておけば、プッシュ通知が表示されるようになります。

service-worker.js
// プッシュ通知を受け取ったときのイベント
self.addEventListener('push', function (event) {
  const title = 'プッシュ通知のテスト';
  const options = {
    body: event.data.text(), // サーバーからのメッセージ
    tag: title, // タイトル
    icon: 'icon.png', // アイコン
    badge: 'icon.png' // アイコン
  };

  event.waitUntil(self.registration.showNotification(title, options));
});

// プッシュ通知をクリックしたときのイベント
self.addEventListener('notificationclick', function (event) {
  event.notification.close();

  event.waitUntil(
    // プッシュ通知をクリックしたときにブラウザを起動して表示するURL
    clients.openWindow('https://localhost/pushtest.html')
  );
});

まとめ

以上でプッシュ通知の実装ができました。

プッシュ通知の登録を削除する方法はJavaScript WEBアプリのプッシュ通知の許可を取り消す方法で紹介しています。


関連記事