点击Web推送通知时打开自定义URL

26
我正在使用Webpush ruby gem实现向我的网站用户发送推送通知。
服务器代码:
  Webpush.payload_send({
      message: notification.message,
      url: notification.url,  # I can't figure out how to access this key
      id: notification.id,    # or this key from the service worker
      endpoint: endpoint,
      p256dh: p256dh_key,
      vapid: vapid_keys,
      ttl: 24 * 60 * 60,
      auth: auth_key,
    })

我已在客户端设置了一个服务工作者,用于显示通知并使其可点击。

self.addEventListener("push", function (event) {
  var title = (event.data && event.data.text()) || "New Message";

  event.waitUntil(
    self.registration.showNotification(title, {
      body: "New push notification",
      icon: "/images/logo@2x.png",
      tag:  "push-notification-tag",
      data: {
        url: event.data.url, // This is returning null
        id: event.data.id // And this is returning null
      }
    })
  )
});

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
    clients.openWindow(event.data.url + "?notification_id=" + event.data.id)
  );
})

除了我传递的自定义键(urlid)无法从服务工作者中访问外,一切都正常运行。

有人知道如何通过WebPush gem传递自定义数据吗?


1
我对此不是专家,但我会这样做:在服务器上使用message: JSON.stringify(notification),在客户端上使用JSON.parse。 - Jonas Wilms
@Jonasw - 我最终采用了你的解决方案。如果你把它写成答案,我会接受它。感谢你的帮助。 - BananaNeil
4个回答

26

根据 Webpush (with a payload) 文档,你应该使用 JSON.stringify() 方法将所有数据放入消息中,在服务工作者中使用 JSON.parse() 检索它。

服务器:

Webpush.payload_send({
  message:JSON.stringify({
    message: notification.message,
    url: notification.url,
    id: notification.id,
  }),
  endpoint: endpoint,
  p256dh: p256dh_key,
  vapid: vapid_keys,
  ttl: 24 * 60 * 60,
  auth: auth_key,
})

客户:

 event.waitUntil(
   self.registration.showNotification(title, {
   body: "New push notification",
   icon: "/images/logo@2x.png",
   tag:  "push-notification-tag",
   data: {
     url: JSON.parse(event.message).url
   }
})

21

自定义数据存储在事件对象event.notification中而不是直接存储在event中(在notificationclick事件中)。因此,如果您想在notificationclick函数中获取自定义数据变量,那么应该这样做 :)

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
    clients.openWindow(event.notification.data.url + "?notification_id=" + event.notification.data.id)
  );
})

2
问题在于从推送事件接收数据,而不是从点击事件接收数据。但你是正确的,那是另一个我最终需要修复的错误。 - BananaNeil
@BananaNeil,您能否请提及一下您是如何解决这个问题的:“问题在于从推送事件接收数据,而不是从单击事件接收数据。”因为我也无法从服务器端向客户端发送数据... - Muhammad Usama Mashkoor
@usama 请看一下被接受的答案,它包含了服务器/客户端代码。 - BananaNeil

3

对于Webpush Ruby Gem,经过一些修改,以下是我成功的方法:

Webpush.payload_send(
  endpoint: user.push_subscription.endpoint,
  message: {
    message: "A new service request is created",
    id: service_request.request_number,
    url: "https://google.com/"
  }.to_json,
  p256dh: user.push_subscription.key,
  auth: user.push_subscription.auth_key,
  ttl: 24 * 60 * 60,
  vapid: {
    subject: 'A Push Notification',
    public_key: ENV['VAPID_PUBLIC_KEY'],
    private_key: ENV['VAPID_PRIVATE_KEY']
  }
)

说明:

  • user.push_subscription.endpoint 是在 PushSubscription 模型中定义的方法,用于返回终端节点
  • user.push_subscription.key, user.push_subscription.auth_key 同样是在同一模型中定义的方法

/serviceworker.js.erb 中。

self.addEventListener("push", (event) => {
  let response = event.data && event.data.text();
  let title = JSON.parse(response).message;
  let body = JSON.parse(response).id;
  let icon = '/assets/logo-blue-120x120.jpg';

  event.waitUntil(
    self.registration.showNotification(title, { body, icon, data: { url: JSON.parse(response).url } })
  )
});

self.addEventListener('notificationclick', function(event) {
  event.notification.close();
  event.waitUntil(
    clients.openWindow(event.notification.data.url)
  );
});

0

将此代码添加到您的Angular项目中的node_modules/@angular/service-worker/ngsw-worker.js文件中

this.scope.addEventListener('notificationclick', (event) => {
            console.log('[Service Worker] Notification click Received. event:%s', event);
            event.notification.close();
            if (clients.openWindow && event.notification.data.url) {
                event.waitUntil(clients.openWindow(event.notification.data.url));
            }
        });

您可以在文件中找到此行,然后输入上述代码

this.scope.addEventListener('notificationclick', (event) => ..

你需要重新构建分发才能使这个工作。在后端,你需要使用这个格式:

{"notification":{"body":"This is a message.","title":"PUSH MESSAGE","vibrate":[300,100,400,100,400,100,400],"icon":"https://upload.wikimedia.org/wikipedia/en/thumb/3/34/AlthepalHappyface.svg/256px-AlthepalHappyface.svg.png","tag":"push demo","requireInteraction":true,"renotify":true,"data":{"url":"https://maps.google.com"}}}

在URL中,您可以输入您的URL,并在点击通知时打开给定的链接并将其聚焦于浏览器中。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接