使用Javascript向Google Chrome推送通知发送数据/负载
我正在处理Google Chrome推送通知,我正在尝试将负载发送给Google Chrome worker,但我不知道如何接收此负载 我有一个API来创建和保存数据库中的通知,我需要通过使用Javascript向Google Chrome推送通知发送数据/负载,javascript,google-chrome,push-notification,Javascript,Google Chrome,Push Notification,我正在处理Google Chrome推送通知,我正在尝试将负载发送给Google Chrome worker,但我不知道如何接收此负载 我有一个API来创建和保存数据库中的通知,我需要通过https://android.googleapis.com/gcm/send并在worker.js上接收 self.addEventListener('push', function(event) { var title = 'Yay a message.'; var body
https://android.googleapis.com/gcm/send
并在worker.js上接收
self.addEventListener('push', function(event) {
var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = '/images/icon-192x192.png';
var tag = 'simple-push-demo-notification-tag';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
});
这是我的worker.js
self.addEventListener('push', function(event) {
var title = 'Yay a message.';
var body = 'We have received a push message.';
var icon = '/images/icon-192x192.png';
var tag = 'simple-push-demo-notification-tag';
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag
})
);
});
这就是我对GCM的称呼
curl --header "Authorization: key=AIzaSyDQjYDxeS9MM0LcJm3oR6B7MU7Ad2x2Vqc" --header "Content-Type: application/json" https://android.googleapis.com/gcm/send -d "{ \"data\":{\"foo\":\"bar\"}, \"registration_ids\":[\"APA91bGqJpCmyCnSHLjY6STaBQEumz3eFY9r-2CHTtbsUMzBttq0crU3nEXzzU9TxNpsYeFmjA27urSaszKtA0WWC3yez1hhneLjbwJqlRdc_Yj1EiqLHluVwHB6V4FNdXdKb_gc_-7rbkYkypI3MtHpEaJbWsj6M5Pgs4nKqQ2R-WNho82mnRU\"]}"
我试图获取event.data
,但这是未定义的
有人有什么想法或建议吗?不幸的是,这似乎是一个: 当前在Chrome中实现推送API的一个缺点是 不能用推送消息发送有效负载。没有,没有。这个 原因是在未来的实现中,有效负载将 在发送到推送消息之前在服务器上进行加密 终点。这样,端点(无论它是什么推送提供程序)将 无法轻松查看推送有效负载的内容。这也 防止其他漏洞,如HTTPS验证不良 服务器和服务器之间的证书和中间人攻击 推送提供程序。但是,此加密尚不受支持,因此在 同时,您需要执行一个获取请求来获取信息 需要填充通知
如上所述,解决方法是在收到推送后与后端联系,并在第三方服务器上获取存储的数据。@gauchofunky的答案是正确的。在电视频道和@gauchofunky的指导下,我能够拼凑出一些东西。以下是如何绕过当前的限制;希望我的答案很快就过时了 首先要弄清楚如何在后端持久保存通知。我在Mongoose中使用Node/Express和MongoDB,我的模式如下所示:
var NotificationSchema = new Schema({
_user: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
subscriptionId: String,
title: String,
body: String,
sent: { type: Boolean, default: false }
});
const webpush = require('web-push');
setImmediate(async () => {
const params = {
payload: {title: 'Hey', body: 'Hello World'}
};
//this is the subscription object you should get in the browser. This is a demo of how it should look like
const subscription = {"endpoint":"https://android.googleapis.com/gcm/send/deC24xZL8z4:APA91bE9ZWs2KvLdo71NGYvBHGX6ZO4FFIQCppMsZhiTXtM1S2SlAqoOPNxzLlPye4ieL2ulzzSvPue-dGFBszDcFbSkfb_VhleiJgXRA8UwgLn5Z20_77WroZ1LofWQ22g6bpIGmg2JwYAqjeca_gzrZi3XUpcWHfw","expirationTime":null,"keys":{"p256dh":"BG55fZ3zZq7Cd20vVouPXeVic9-3pa7RhcR5g3kRb13MyJyghTY86IO_IToVKdBmk_2kA9znmbqvd0-o8U1FfA3M","auth":"1gNTE1wddcuF3FUPryGTZOA"}};
if (subscription.keys) {
params.userPublicKey = subscription.keys.p256dh;
params.userAuth = subscription.keys.auth;
}
// this key you should take from firebase console for example
// settings -> cloud messaging -> Server key
webpush.setGCMAPIKey('AAAASwYmslc:APfA91bGy3tdKvuq90eOvz4AoUm6uPtbqZktZ9dAnElrlH4gglUiuvereTJJWxz8_dANEQciX9legijnJrxvlapI84bno4icD2D0cdVX3_XBOuW3aWrpoqsoxLDTdth86CjkDD4JhqRzxV7RrDXQZd_sZAOpC6f32nbA');
try {
const r = await webpush.sendNotification(subscription, JSON.stringify(params));
console.log(r);
}
catch (e) {
console.error(e);
}
});
如果要更改图标,请确保添加图标。我每次都使用相同的图标,所以我的图标在服务人员中硬编码
找出正确的RESTWeb服务需要一些思考。GET似乎是一个简单的选择,但是调用获取通知会产生副作用,因此GET被取消。最后我用{subscriptionId:}
的主体将帖子
发送到/api/notifications
。在该方法中,我们基本上执行出列:
var subscriptionId = req.body.subscriptionId;
Notification
.findOne({_user: req.user, subscriptionId: subscriptionId, sent: false})
.exec(function(err, notification) {
if(err) { return handleError(res, err); }
notification.sent = true;
notification.save(function(err) {
if(err) { return handleError(res, err); }
return res.status(201).json(notification);
});
});
在service worker中,我们需要确保在执行获取之前获得订阅
self.addEventListener('push', function(event) {
event.waitUntil(
self.registration.pushManager.getSubscription().then(function(subscription) {
fetch('/api/notifications/', {
method: 'post',
headers: {
'Authorization': 'Bearer ' + self.token,
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: JSON.stringify(subscription)
})
.then(function(response) { return response.json(); })
.then(function(data) {
self.registration.showNotification(data.title, {
body: data.body,
icon: 'favicon-196x196.png'
});
})
.catch(function(err) {
console.log('err');
console.log(err);
});
})
);
});
还值得注意的是,订阅对象从Chrome43更改为Chrome45。在Chrome45中,subscriptionId
属性被删除,这只是需要注意的一点——这段代码是为了与Chrome43配合使用而编写的
我想对我的后端进行身份验证调用,因此我需要弄清楚如何将JWT从我的Angular应用程序发送给我的服务人员。我最后使用了postMessage
。以下是我在注册服务人员后所做的操作:
navigator.serviceWorker.register('/service-worker.js', {scope:'./'}).then(function(reg) {
var messenger = reg.installing || navigator.serviceWorker.controller;
messenger.postMessage({token: $localStorage.token});
}).catch(function(err) {
console.log('err');
console.log(err);
});
在service worker中,侦听消息:
self.onmessage.addEventListener('message', function(event) {
self.token = event.data.token;
});
奇怪的是,这个监听器使用的是Chrome43,而不是Chrome45。Chrome 45与如下处理程序配合使用:
self.addEventListener('message', function(event) {
self.token = event.data.token;
});
现在推送通知需要相当多的工作才能得到有用的东西-我真的很期待有效载荷 实际上,有效载荷应该在Chrome 50中实现(发布日期:2016年4月19日)。在Chrome50(以及桌面上当前版本的Firefox)中,您可以在推送过程中发送一些任意数据,这样客户端就可以避免发出额外的请求。所有有效负载数据都必须加密
下面是开发人员提供的加密详细信息:我刚刚遇到这个问题。firefox和chrome(版本50+)的较新版本支持有效负载传输
开发文档详细介绍了如何实现此功能。需要注意的一件重要事情是,如果负载没有加密,google GCM或可能的client/chome(我不知道是哪一个)实际上会完全忽略负载
该网站有客户机/服务器两种实现方式,可以通过服务人员进行推送和检索。示例使用的推送库仅仅是一个
服务人员实施示例:
self.addEventListener('push', function(event) {
var payload = event.data ? event.data.text() : 'no payload';
event.waitUntil(
self.registration.showNotification('ServiceWorker Cookbook', {
body: payload,
})
);
});
var webPush = require('web-push');
webPush.setGCMAPIKey(process.env.GCM_API_KEY);
module.exports = function(app, route) {
app.post(route + 'register', function(req, res) {
res.sendStatus(201);
});
app.post(route + 'sendNotification', function(req, res) {
setTimeout(function() {
webPush.sendNotification(req.body.endpoint, {
TTL: req.body.ttl,
payload: req.body.payload,
userPublicKey: req.body.key,
userAuth: req.body.authSecret,
}).then(function() {
res.sendStatus(201);
});
}, req.body.delay * 1000);
});
};
服务器实施示例:
self.addEventListener('push', function(event) {
var payload = event.data ? event.data.text() : 'no payload';
event.waitUntil(
self.registration.showNotification('ServiceWorker Cookbook', {
body: payload,
})
);
});
var webPush = require('web-push');
webPush.setGCMAPIKey(process.env.GCM_API_KEY);
module.exports = function(app, route) {
app.post(route + 'register', function(req, res) {
res.sendStatus(201);
});
app.post(route + 'sendNotification', function(req, res) {
setTimeout(function() {
webPush.sendNotification(req.body.endpoint, {
TTL: req.body.ttl,
payload: req.body.payload,
userPublicKey: req.body.key,
userAuth: req.body.authSecret,
}).then(function() {
res.sendStatus(201);
});
}, req.body.delay * 1000);
});
};
客户端javascript打印所需字段的实现示例
navigator.serviceWorker.register('serviceWorker.js')
.then(function(registration) {
return registration.pushManager.getSubscription()
.then(function(subscription) {
if (subscription) {
return subscription;
}
return registration.pushManager.subscribe({
userVisibleOnly: true
});
});
}).then(function(subscription) {
var rawKey = subscription.getKey ? subscription.getKey('p256dh') : '';
key = rawKey ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawKey))) : '';
var rawAuthSecret = subscription.getKey ? subscription.getKey('auth') : '';
authSecret = rawAuthSecret ? btoa(String.fromCharCode.apply(null, new Uint8Array(rawAuthSecret))) : '';
endpoint = subscription.endpoint;
console.log("Endpoint: " + endpoint);
console.log("Key: " + key);
console.log("AuthSecret: " + authSecret);
});
要检索该数据,需要将“event.data.text()”解析为JSON对象。我猜自从你尝试让它工作以来,有些东西被更新了,但现在它工作了。真倒霉
然而,由于我是在自己寻找解决方案时登上这篇文章的,其他人可能会想要一个有效的答案。这是:
// Push message event handler
self.addEventListener('push', function(event) {
// If true, the event holds data
if(event.data){
// Need to parse to JSON format
// - Consider event.data.text() the "stringify()"
// version of the data
var payload = JSON.parse(event.data.text());
// For those of you who love logging
console.log(payload);
var title = payload.data.title;
var body = payload.data.body;
var icon = './assets/icons/icon.ico'
var tag = 'notification-tag';
// Wait until payload is fetched
event.waitUntil(
self.registration.showNotification(title, {
body: body,
icon: icon,
tag: tag,
data: {} // Keeping this here in case I need it later
})
);
} else {
console.log("Event does not have data...");
}
}); // End push listener
// Notification Click event
self.addEventListener('notificationclick', function(event) {
console.log("Notification Clicked");
}); // End click listener
就个人而言,我将创建一个“通用”通知,以防我的数据有问题,并将使用try/catch。我建议您也这样做。请按照以下步骤进行操作:
在浏览器中:
您需要获取订阅
对象并保存它,以便您的服务器能够访问它:
在服务器中:
安装
并发送如下web推送:
var NotificationSchema = new Schema({
_user: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
subscriptionId: String,
title: String,
body: String,
sent: { type: Boolean, default: false }
});
const webpush = require('web-push');
setImmediate(async () => {
const params = {
payload: {title: 'Hey', body: 'Hello World'}
};
//this is the subscription object you should get in the browser. This is a demo of how it should look like
const subscription = {"endpoint":"https://android.googleapis.com/gcm/send/deC24xZL8z4:APA91bE9ZWs2KvLdo71NGYvBHGX6ZO4FFIQCppMsZhiTXtM1S2SlAqoOPNxzLlPye4ieL2ulzzSvPue-dGFBszDcFbSkfb_VhleiJgXRA8UwgLn5Z20_77WroZ1LofWQ22g6bpIGmg2JwYAqjeca_gzrZi3XUpcWHfw","expirationTime":null,"keys":{"p256dh":"BG55fZ3zZq7Cd20vVouPXeVic9-3pa7RhcR5g3kRb13MyJyghTY86IO_IToVKdBmk_2kA9znmbqvd0-o8U1FfA3M","auth":"1gNTE1wddcuF3FUPryGTZOA"}};
if (subscription.keys) {
params.userPublicKey = subscription.keys.p256dh;
params.userAuth = subscription.keys.auth;
}
// this key you should take from firebase console for example
// settings -> cloud messaging -> Server key
webpush.setGCMAPIKey('AAAASwYmslc:APfA91bGy3tdKvuq90eOvz4AoUm6uPtbqZktZ9dAnElrlH4gglUiuvereTJJWxz8_dANEQciX9legijnJrxvlapI84bno4icD2D0cdVX3_XBOuW3aWrpoqsoxLDTdth86CjkDD4JhqRzxV7RrDXQZd_sZAOpC6f32nbA');
try {
const r = await webpush.sendNotification(subscription, JSON.stringify(params));
console.log(r);
}
catch (e) {
console.error(e);
}
});
谢谢你抽出时间。我以前读过,但我不想相信。这是个坏消息。。。我将在服务器上发出新请求,以获取有关我的通知的所有信息。再次感谢你。希望他们能很快支持加密的有效载荷,因为没有有效载荷,这项功能几乎毫无用处。@AndyGaskell如果我理解得很清楚的话,那就是你总是对最后一个事件感兴趣,否则你的服务器需要为你的设备保留一个包含所有排队警报的收件箱。无论哪种方式,您都需要在自己的方面实现这一点。到目前为止,推送只表示“有什么”发生了。@gauchofunky谢谢。在周末完成这项工作之后,您基本上需要一个包含您的用户ID的队列服务器端(如果appli