Web推送通知:如何使用Web Push PHP库?

qyuhtwio  于 2023-03-11  发布在  PHP
关注(0)|答案(3)|浏览(151)

我想添加Web通知到我的网站。我在谷歌上搜索,并找到了一些教程。如这些教程中所述,我管理显示订阅框的访问者,我也可以存储他们的数据。

主要.js

'use strict';

const applicationServerPublicKey = 'BBw_opB12mBhg66Dc94m7pOlTTHb5oqFAafbhN-BNeazWk8woAcSeHdgbmQaroCYssUkqFfoHqEJyCKw';

const pushButton = document.querySelector('.js-push-btn');

let isSubscribed = false;
let swRegistration = null;

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


if ('serviceWorker' in navigator && 'PushManager' in window) {
  console.log('Service Worker and Push is supported');

  navigator.serviceWorker.register('sw.js')
  .then(function(swReg) {
    console.log('Service Worker is registered', swReg);

    swRegistration = swReg;
  })
  .catch(function(error) {
    console.error('Service Worker Error', error);
  });
} else {
  console.warn('Push messaging is not supported');
  pushButton.textContent = 'Push Not Supported';
}

function initialiseUI() {
  // Set the initial subscription value
  swRegistration.pushManager.getSubscription()
  .then(function(subscription) {
    isSubscribed = !(subscription === null);

    if (isSubscribed) {
      console.log('User IS subscribed.');
    } else {
      console.log('User is NOT subscribed.');
    }

    updateBtn();
  });
}

function updateBtn() {
  if (isSubscribed) {
    pushButton.textContent = 'Disable Push Messaging';
  } else {
    pushButton.textContent = 'Enable Push Messaging';
  }

  pushButton.disabled = false;
}

软件.js

'use strict';

self.addEventListener('push', function(event) {
  console.log('[Service Worker] Push Received.');
  console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);

  const title = 'Motoroids Lab';
  const options = { 
    body: 'Motoroids',
    icon: 'images/icon.png',
    badge: 'images/badge.png'
  };

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

self.addEventListener('notificationclick', function(event) {
  console.log('[Service Worker] Notification click Received.');

  event.notification.close();

  event.waitUntil(
    clients.openWindow('https://developers.google.com/web/')
  );
});

但是现在我卡住了。不管我怎么努力,还是很难理解如何从我的服务器发送推送消息:(
我在服务器上启用了SSL。我使用composer require minishlink/web-push命令在服务器上安装了PHP Web Push库及其依赖项。
但是接下来呢?我也看不懂他们的文档。https://github.com/web-push-libs/web-push-php
我需要一些帮助,请帮助我了解它是如何工作的。
谢谢

3qpi33ja

3qpi33ja1#

请看https://web-push-book.gauntface.com/,了解Web Push的一般性介绍,其中How Push WorksSubscribing a User这一章您应该特别感兴趣。总结如下:

  • 在客户端,您需要通过调用pushManager.subscribe来创建订阅。
  • 您应该将此订阅发送到您的服务器。例如,发出 AJAX 请求以将订阅(端点、keys.p256dh、keys.auth)发送到服务器。此处提供更多信息。
  • 在服务器上,你可以使用PHP Web Push库发送一个推送消息。首先,你需要用你的密钥对配置这个库。然后,你需要使用订阅(endpoint,keys.p256dh,keys.auth)来发送一个推送消息。
juzqafwq

juzqafwq2#

  • 安装库“合成器需要minishlink/web-push”
  • 您应该生成VAPID密钥。
  • 然后替换php脚本中的“虚拟公钥”和“虚拟私钥”。
  • 'BFrp-电视频道...'
  • '9 BvI 1aN 1CR 4 w 4冰MS'
  • 然后替换js脚本中的“VAPID PUBLIC KEY”。替换:'BFrp-电视频道...'
  • 然后上传文件(“service-worker.js ',”index.html“,”send.php')到网站
  • 在浏览器中打开“index.html”并允许推送通知。之后,您将在控制台中看到“endpoint”、“p256 dh”和“auth”。
  • 将这些参数('endpoint','p256 dh','auth')设置为php脚本('send.php')。
  • “请访问以下网址:
  • 'SPB_网络路由...'
  • “业务流程图-WMuJdP 7 buopSb_HrNX...”
  • 在浏览器中打开“send.php”,推送就会被发送。

这段代码在Chrome和Mozilla中可以正常工作。

generate.php-生成VAPID密钥:

<?php

error_reporting(E_ALL);
ini_set("display_errors", 1);
header('Content-Type: text/html; charset=utf-8');

require __DIR__ . '/vendor/autoload.php';

use Minishlink\WebPush\VAPID;

print_r(VAPID::createVapidKeys());

服务工人.js

'use strict';

/**
 * Received push
 */
self.addEventListener('push', function (event) {
    let pushMessageJSON = event.data.json();
    self.registration.showNotification(pushMessageJSON.title, {
        body: pushMessageJSON.body,
        icon: pushMessageJSON.icon,
        vibrate: pushMessageJSON.data.vibrate,
        data: {
            additionalData: pushMessageJSON.data.additionalData,
            url: pushMessageJSON.data.url,
        },
    });

    console.info("**** Recv'd a push message::", event);
});

/**
 * Click by push
 */
self.addEventListener('notificationclick', function(event) {
    let url = event.notification.data.url;
    event.notification.close(); // Android needs explicit close.
    if (!url) return;
    event.waitUntil(
        clients.matchAll({type: 'window'}).then( windowClients => {
            // Check if there is already a window/tab open with the target URL
            for (var i = 0; i < windowClients.length; i++) {
                var client = windowClients[i];
                // If so, just focus it.
                if (client.url === url && 'focus' in client) {
                    return client.focus();
                }
            }
            // If not, then open the target URL in a new window/tab.
            if (clients.openWindow) {
                return clients.openWindow(url);
            }
        })
    );
});

self.addEventListener('message', function (event) {
    // A message has been sent to this service worker.
    console.log("sw Handling message event:", event);
});

self.addEventListener('pushsubscriptionchange', function (event) {
    // The Push subscription ID has changed. The App should send this
    // information back to the App Server.
    console.log("sw Push Subscription Change", event);
    event.waitUntil(
        self.clients.matchAll()
            .then(clientList => {
                let sent = false;
                console.debug("Service worker found clients",
                    JSON.stringify(clients));
                clientList.forEach(client => {
                    console.debug("Service worker sending to client...", client);
                    sent = true;
                    client.postMessage({'type': 'update'});
                });
                if (sent == false) {
                    throw new Error("No valid client to send to.");
                }
            })
            .catch(err => {
                console.error("Service worker couldn't send message: ", err);
            })
    );

});

self.addEventListener('registration', function (event) {
    // The service worker has been registered.
    console.log("sw Registration: ", event);
});

self.addEventListener('install', function (event) {
    // The serivce worker has been loaded and installed.
    // The browser aggressively caches the service worker code.
    console.log("sw Install: ", JSON.stringify(event));
    // This replaces currently active service workers with this one
    // making this service worker a singleton.
    event.waitUntil(self.skipWaiting());
    console.log("sw Installed: ", JSON.stringify(event));

});

self.addEventListener('activate', function (event) {
    // The service worker is now Active and functioning.
    console.log("sw Activate : ", JSON.stringify(event));
    // Again, ensure that this is the only active service worker for this
    // page.
    event.waitUntil(self.clients.claim());
    console.log("sw Activated: ", JSON.stringify(event));
    navigator.serviceWorker
});

index.html请求推送通知

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <meta name="viewport" content="width=device-width,initial-scale=1.0,maximum-scale=1"/>
</head>
<body>

<script>
    if (!Notification) {
        console.log('*Browser does not support Web Notification');
    }

    if ('serviceWorker' in navigator) {
        navigator.serviceWorker
            .register('service-worker.js?v=1', {scope: './'})
            .then(function (registration) {
                console.log("Service Worker Registered");
            })
            .catch(function (err) {
                console.log("Service Worker Failed to Register", err);
            })
    }

    navigator.serviceWorker.ready.then((reg) => {
        const subscribeOptions = {
            userVisibleOnly: true,
            applicationServerKey: 'BFrp-TvkuqCeNsytRt...'
        };
        reg.pushManager.subscribe(subscribeOptions).then((subscription) => {
            //send endpoint, p256dh and auth to backend
            console.log('endpoint is: ' + subscription.endpoint);
            console.log('p256dh is: ' + subscription.toJSON().keys.p256dh);
            console.log('auth is: ' + subscription.toJSON().keys.auth);

            document.write('<p>endpoint is: ' + subscription.endpoint + '</p>');
            document.write('<p>p256dh is: ' + subscription.toJSON().keys.p256dh + '</p>');
            document.write('<p>auth is: ' + subscription.toJSON().keys.auth + '</p>');
        });
    });
</script>
</body>
</html>

send.php发送推送通知

<?php

error_reporting(E_ALL);
ini_set("display_errors", 1);
header('Content-Type: text/html; charset=utf-8');

require __DIR__ . '/vendor/autoload.php';

use Minishlink\WebPush\WebPush;
use Minishlink\WebPush\Subscription;

$push = [
    'subscription' => Subscription::create([
        'endpoint' => 'https://fcm.googleapis.com/fcm/send/djRg_IDPtSs:APA91bFwYCC73F4X3cXELK...',
        'keys' => [
            'auth' => 'SPB_NNfRw...',
            'p256dh' => 'BP-WMuJdP7buopSb_HrNX...'
        ]
    ]),
    'payload' => json_encode([
        'title' => "Hello",
        'body' => "How are you?",
        'icon' => "https://cdn-icons-png.flaticon.com/512/3884/3884851.png",
        'data' => [
            'vibrate' => [100, 200],
            'additionalData' => [],
            'url' => "https://google.com",
        ],
    ]),
];

$auth = [
    'VAPID' => [
        'subject' => 'support@gmail.com', // can be a mailto: or your website address
        'publicKey' => 'BFrp-TvkuqCeNsytRt...', // (recommended) uncompressed public key P-256 encoded in Base64-URL
        'privateKey' => '9BvI1aN1CR4w4iceMS...', // (recommended) in fact the secret multiplier of the private key encoded in Base64-URL
    ],
];

$webPush = new WebPush($auth);

try {
    $webPush->queueNotification(
        $push['subscription'],
        $push['payload']
    );
    $report = $webPush->flush()->current();
    $is_success = $report->isSuccess();
    $response = $report->getResponseContent();
} catch (\Throwable $th) {
    $is_success = false;
    $response = $th->getMessage();
}

if ($is_success) {
    echo "Push was sent";
} else {
    echo "Push was not sent. Error message: " . $response;
}
zsbz8rwp

zsbz8rwp3#

您必须将此代码添加到您的项目https://developers.google.com/web/fundamentals/getting-started/codelabs/push-notifications/有时您必须将代码添加到您已经创建的部分

相关问题