使用Javascript将数据/有效负载发送到Google Chrome推送通知

Adr*_*dao 22 javascript google-chrome push-notification

我正在处理Google Chrome推送通知,我正在尝试将有效负载发送给谷歌Chrome工作者但是,我不知道我是如何收到此有效负载的.

我有一个API来创建和保存我的数据库中的通知,我需要通过https://android.googleapis.com/gcm/sendworker.js 发送和接收值

这是我的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
        })
      );
    });
Run Code Online (Sandbox Code Playgroud)

这就是我打电话给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\"]}"
Run Code Online (Sandbox Code Playgroud)

我试着去event.data,但这是未定义的.

有没有人有任何想法或消化?

gau*_*nky 30

不幸的是这似乎是一个预期的行为:

当前在Chrome中实现Push API的一个缺点是您无法使用推送消息发送有效负载.不,没什么.这样做的原因是,在将来的实现中,在将服务器发送到推送消息传递端点之前,必须在服务器上对其进行加密.这样,无论推送提供商是什么,端点都无法轻松查看推送有效负载的内容.这还可以防止其他漏洞,例如HTTPS证书验证不当以及服务器和推送提供程序之间的中间人攻击.但是,此加密尚不支持,因此在此期间您需要执行获取请求以获取填充通知所需的信息.

如上所述,解决方法是在收到推送后联系您的后端,并在第三方服务器上获取存储的数据.

  • 确实.希望他们很快就会支持加密的有效载荷,因为这个功能在没有有效载荷的情 (9认同)
  • @AndyGaskell如果我很了解这个想法是你总是对最后一个事件感兴趣,否则你的服务器需要为你的设备保留一些带有所有排队警报的收件箱.无论哪种方式,您都需要在您身边实施此操作.到目前为止,推动只表示发生了"某事". (3认同)
  • 感谢您的时间.我以前读过它但是,我不想相信= l.这是个坏消息......我会在服务器上发出新请求,以获取有关我的通知的所有信息.再次感谢你 (2认同)

And*_*ell 17

@ gauchofunky的回答是正确的.在Chromium dev slack channel和@gauchofunky的人们的一些指导下,我能够拼凑出一些东西.以下是解决当前局限的方法; 希望我的答案很快就会过时!

首先弄清楚你将如何在你的后端保持通知.我正在使用Node/Express和MongoDB与Mongoose,我的架构如下所示:

var NotificationSchema = new Schema({
  _user: {type: mongoose.Schema.Types.ObjectId, ref: 'User'},
  subscriptionId: String,
  title: String,
  body: String,
  sent: { type: Boolean, default: false }
});
Run Code Online (Sandbox Code Playgroud)

如果您想要更改图标,请务必添加图标.我每次都使用相同的图标,因此我的服务人员硬编码.

找出正确的REST Web服务需要一些思考.GET似乎是一个简单的选择,但获得通知的调用会导致副作用,因此GET已经出局.我结束了一个去POST/api/notifications与身体{subscriptionId: <SUBSCRIPTION_ID>}.在方法中我们基本上执行一个dequeue:

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);
  });
});
Run Code Online (Sandbox Code Playgroud)

在服务工作者中,我们需要确保在我们制作之前获得订阅fetch.

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);
      });
    })
  );
});
Run Code Online (Sandbox Code Playgroud)

同样值得注意的是,订阅对象已从Chrome 43更改为Chrome 45.在Chrome 45中,该subscriptionId属性已被删除,只需注意一些内容 - 此代码是为了与Chrome 43一起使用而编写的.

我想对我的后端进行经过身份验证的调用,所以我需要弄清楚如何从我的Angular应用程序中获取JWT给我的服务工作者.我最终使用了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);
});
Run Code Online (Sandbox Code Playgroud)

在服务工作者中听取消息:

self.onmessage.addEventListener('message', function(event) {
  self.token = event.data.token;
});
Run Code Online (Sandbox Code Playgroud)

奇怪的是,这个听众可以在Chrome 43中使用,但不适用于Chrome 45. Chrome 45可以使用这样的处理程序:

self.addEventListener('message', function(event) {
  self.token = event.data.token;
});
Run Code Online (Sandbox Code Playgroud)

现在推送通知需要相当多的工作才能获得有用的东西 - 我真的很期待有效载荷!


Via*_*dov 14

实际上,有效负载应该在Chrome 50中实现(发布日期 - 2016年4月19日).在Chrome 50(以及桌面上当前版本的Firefox)中,您可以随推送一些任意数据,以便客户端可以避免发出额外请求.所有有效载荷数据必须加密.

以下是开发人员的加密详细信息:https://developers.google.com/web/updates/2016/03/web-push-encryption?hl = zh-CN


小智 3

要检索该数据,您需要将“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
Run Code Online (Sandbox Code Playgroud)

就我个人而言,我将创建一个“通用”通知,以防我的数据很奇怪,并且还将使用 try/catch。我建议也这样做。