繁体   English   中英

使用 NodeJs Express 在 JavaScript 上推送通知

[英]Push notifications on JavaScript with NodeJs Express

我想从 NodeJs 向特定用户发送通知。 如果可能的话,这个想法是独立于 firebase 和任何类型的第三方服务器。 我找到了很多关于如何构建服务工作者的信息和很多关于显示通知的信息,但是我找不到任何对我有用的关于将推送消息发送给要显示的工作人员的信息。

这是 service-worker.js

if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('/layout/service-worker.js')
    .then(function (registration) {
        registration.pushManager.subscribe({
            userVisibleOnly: true
        }).then(function (subscription) {
            isPushEnabled = true;
            console.log("subscription.endpoint: ", subscription.endpoint);
            //Here I will have to store the endpoint on my DB
        });
    }).catch(function (err) {
        console.log(err);
    });
}

//I think that this could be the listener, but I don't know how to trigger it from the server
this.onpush = function (event) {
    console.log(event.data);
}

我有显示通知的代码(当我可以发送通知时)

var notificationTitle = 'Title';
var notificationOptions = {
    "body": "Some text",
    //"icon": "images/icon.png",
    "vibrate": [200, 100, 200, 100, 200, 100, 400]
}
showNotification(notificationTitle, notificationOptions);

这个想法是在“onpush”事件中实现这个代码,我会知道我会收到什么格式。

所以我需要一种方法来将推送发送到这些方法,但现在不知道如何去做。 我读了一些关于带有 VAPID 键的节点 web-push 模块的内容,但我仍然没有找到发送者喷气机。 我有一个 manifest.json,我不知道它是否真的做任何事情(我读到这是 Chrome 导航器所必需的,但不知道,我正在 Chrome、Firefox 和 Edge 中测试所有内容)。

此外,我在 localhost 中使用 http 对其进行测试。 我真的不知道如果没有 SSL 证书或自动签名证书,这是否可行。

每一次帮助都将不胜感激。

我找到了解决方案。 我不知道是否是最佳的,但它对我有用:

起初需要许多配置步骤:

//Installl web push module
npm install web-push --save

//Generate VAPID keys by console
cd ./node_modules/.bin/web-push generate-vapid-keys

//Store VAPID keys on environment
publicVapidKey: 'generated key',
privateVapidKey: 'generated key'
process.env.PUBLIC_VAPID_KEY = config.publicVapidKey;
process.env.PRIVATE_VAPID_KEY = config.privateVapidKey;

这是从客户端接收订阅并将其存储在数据库中的nodejs controller 代码:

//Subscriptions
app.post('/subscribe', (req, res) => {
    const subscription = req.body.subscription;
    const userId = req.body.userId;
    console.dir(subscription);
    //TODO: Store subscription keys and userId in DB
    webpush.setVapidDetails(
        process.env.DOMAIN, 
        process.env.PUBLIC_VAPID_KEY, 
        process.env.PRIVATE_VAPID_KEY
    );
    res.sendStatus(200);
    const payload = JSON.stringify({
        title: model.lang.pushTitle,
        body: model.lang.pushBody
    });
    webpush.sendNotification(subscription, payload);
});

这是我发现将消息从服务器推送到客户端或客户端的方法:

//Send push message
//TODO: Recover subscription keys from DB
var subscription = { 
    endpoint: 'recover from DB',
    expirationTime: null,
    keys: { 
        p256dh: 'recover from DB',
        auth: 'recover from DB' 
    } 
};
const payload = JSON.stringify({
    title: 'Notification Title',
    body: 'Notification message'
});
webpush.setVapidDetails(
    process.env.DOMAIN, 
    process.env.PUBLIC_VAPID_KEY, 
    process.env.PRIVATE_VAPID_KEY
);
webpush.sendNotification(subscription, payload)
.catch(function(err) {
    console.log(err);
});

这里有客户端视图脚本中的方法可以使用必要的数据进行订阅:

//Start subscription
const publicVapidKey = 'public key of server';
if (window.Notification) {
    if (Notification.permission != 'granted') {
        Notification.requestPermission(() => {
            if (Notification.permission === 'granted') {
                getSubscriptionObject().then(subscribe)
            }
        }).catch(function(err) {
            console.log(err);
        });
    }
}

//Generate subscription object
function getSubscriptionObject() {
    return navigator.serviceWorker.register('/layout/service-worker-push.js')
    .then((worker) => {
        return worker.pushManager.subscribe({
            userVisibleOnly: true,
            applicationServerKey: urlBase64ToUint8Array(publicVapidKey)
        }).catch(function(err) {
            console.log(err);
        });
    }).catch(function(err) {
        console.log(err);
    });
}

//Send subscription to server
function subscribe(subscription) {
    return fetch(window.location.origin + '/subscribe', {
        method: 'POST',
        body: JSON.stringify({
            subscription: subscription,
            userId: mv.user_id != undefined ? mv.user_id : ''
        }),
        headers: {
            'content-type': 'application/json'
        }
    }).catch(function(err) {
        console.log(err);
    });
}

//Decoder base64 to uint8
function urlBase64ToUint8Array(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;
}

这是在客户端中施展魔法的woker(必须在视图中导入)

//Event that shows a notification when is received by push
self.addEventListener('push', event => {
    const data = event.data.json();
    self.registration.showNotification(data.title, {
      body: data.body,
      icon: "/layout/src/android-chrome-192x192.png"
    });
});

//Event on notification click (have problems almost in Chrome)
self.addEventListener('notificationclick', () => {
    console.log('Notificación pulsada!');
});

而且,考虑到工人的重要性

<script type="text/javascript" src="/layout/service-worker-push.js"></script>

注意:我只在 localhost 上测试过,所以我不知道是否需要 SSL 证书。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM