从服务器发送通知时未触发推送事件

Posted

技术标签:

【中文标题】从服务器发送通知时未触发推送事件【英文标题】:Push event not firing on send notification from server 【发布时间】:2018-02-17 04:07:28 【问题描述】:

我想从我的服务器推送通知。因为我正在使用 Java 的 Web 推送 API,我可以将通知发送到端点 url,但在接收方我的服务工作者没有执行推送事件,因为我正在使用 VAPID所以根据我的理解不需要使用 gcm Id,这里是我的 service worker 文件。

'use strict';

const applicationServerPublicKey = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-
SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';

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;

self.addEventListener('install', function(event)
 event.waitUntil(self.skipWaiting());
 console.log("activate");
);

self.addEventListener('activate', function(event)
event.waitUntil(self.clients.claim());
 console.log("install");
);

self.addEventListener('push', function(event) 
  console.log('Received push');
  let notificationTitle = 'Hello';
  const notificationOptions = 
    body: 'Thanks for sending this push msg.',
    icon: '/JMS/resources/images/icon.png',
    badge: '/JMS/resources/images/badge.png',
    tag: 'simple-push-demo-notification',
    data: 
      url: 'https://developers.google.com/web/fundamentals/getting-
      started/push-notifications/',
    ,
  ;

  if (event.data) 
    const dataText = event.data.text();
    notificationTitle = 'Received Payload';
    notificationOptions.body = `Push data: '$dataText'`;
  

    event.waitUntil(
    Promise.all([
      self.registration.showNotification(
        notificationTitle, notificationOptions),
    ])
  );
);

self.addEventListener('notificationclick', function(event) 
    event.notification.close();
    event.waitUntil(
            clients.openWindow('https://www.auctiontiger.net')
          );
  let clickResponsePromise = Promise.resolve();
  if (event.notification.data && event.notification.data.url) 
    clickResponsePromise = clients.openWindow(event.notification.data.url);
  

  event.waitUntil(
    Promise.all([
      clickResponsePromise
    ])
  );
);

这是我的 main.js 文件,我可以从中调用我的本地服务器。

'use strict';

const applicationServerPublicKey = 'BEl62iUYgUivxIkv69yViEuiBIa-Ib9-
SkvMeAtA3LFgDzkrxZJjSgSnfckjBJuBkr3qBUYIHBQFLXYp5Nksh8U';
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;


function updateBtn() 
if (Notification.permission === 'denied') 
pushButton.textContent = 'Push Messaging Blocked.';
pushButton.disabled = true;
updateSubscriptionOnServer(null);
return;


    if (isSubscribed) 
     pushButton.textContent = 'Disable Push Messaging';
      else 
     pushButton.textContent = 'Enable Push Messaging';
     

     pushButton.disabled = false;
    

  function updateSubscriptionOnServer(subscription) 
  // TODO: Send subscription to application server

const subscriptionJson = document.querySelector('.js-subscription-json');
const subscriptionDetails =
document.querySelector('.js-subscription-details');

if (subscription) 
subscriptionJson.textContent = JSON.stringify(subscription);
subscriptionDetails.classList.remove('is-invisible');
  else 
 subscriptionDetails.classList.add('is-invisible');
 
 

function subscribeUser() 
const applicationServerKey = urlB64ToUint8Array(applicationServerPublicKey);
swRegistration.pushManager.subscribe(
userVisibleOnly: true,
applicationServerKey:applicationServerKey 

  )
 .then(function(subscription) 
  updateSubscriptionOnServer(subscription);
  isSubscribed = true;
  updateBtn();
  initialiseUI();
  return sendSubscriptionToServer(subscription);
  )
   .catch(function(err) 
   console.log('Failed to subscribe the user: ', err);

   );
   
function sendSubscriptionToServer(subscription) 
var key = subscription.getKey ? subscription.getKey('p256dh') : '';
var auth = subscription.getKey ? subscription.getKey('auth') : '';

return fetch('/JMS/profile/subscription', 
    method: 'POST',
    headers: 
        'Content-Type': 'application/json'
    ,
    body: JSON.stringify(
        endpoint: subscription.endpoint,
        // Take byte[] and turn it into a base64 encoded string suitable for
        // POSTing to a server over HTTP
        key:key ? btoa(String.fromCharCode.apply(null, new Uint8Array(key))) 
        : '',
        auth:auth ? btoa(String.fromCharCode.apply(null, new 
        Uint8Array(auth))) : ''
    )
    );

     

   function unsubscribeUser() 
   swRegistration.pushManager.getSubscription()
  .then(function(subscription) 
   if (subscription) 
    return subscription.unsubscribe();
   
   )
  .catch(function(error) 
  console.log('Error unsubscribing', error);
   )
  .then(function() 
  updateSubscriptionOnServer(null);

  console.log('User is unsubscribed.');
  isSubscribed = false;

  updateBtn();
  );
  

   function initialiseUI() 
   pushButton.addEventListener('click', function() 
   pushButton.disabled = true;
   if (isSubscribed) 
    unsubscribeUser();
    else 
  subscribeUser();
    
    );

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

    updateSubscriptionOnServer(subscription);

      if (isSubscribed) 

        console.log('User IS subscribed.');
       else 
     console.log('User is NOT subscribed.');
      

       updateBtn();
      );
      

    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.scope);
    swReg.update();
    swRegistration = swReg;
    initialiseUI();
    )
    .catch(function(error) 
    console.error('Service Worker Error', error);
    );
     else 
    console.warn('Push messaging is not supported');
    pushButton.textContent = 'Push Not Supported';
    

这是我用于我的应用程序的 webpush API 的 URL, [https://github.com/web-push-libs/webpush-java][1] 最后是我的服务器端代码,

@RequestMapping(value = "profile/subscription", method = RequestMethod.POST, 
headers = "Content-Type=application/json")
@ResponseBody
public String post(@RequestBody String body,byte[] 
    payload,HttpServletResponse response)
            throws GeneralSecurityException, IOException, JoseException, 
    ExecutionException, InterruptedException, ParseException, JSONException 
    
    String data="";
    org.json.JSONObject ob = new org.json.JSONObject(body);
    final int TTL = 255;
    payload= "hello".getBytes(); 
    com.demo.controller.PushService pushService = new  
    com.demo.controller.PushService();
    nl.martijndwars.webpush.Notification notification =new 
    nl.martijndwars.webpush.Notification(ob.getString("endpoint")
   ,new Subscription().getUserPublicKey((ob.getString("key"))),
    Base64.decode(ob.getString("auth")), 
    payload,TTL);
    pushService.send(notification);
    org.json.JSONObject ob2 = new org.json.JSONObject(body);
    ob2.put("data", notification.getPayload());
    JSONArray arr= new JSONArray();
    arr.add(ob2);
    data=arr.toJSONString();
    response.setHeader("Service-Worker-Allowed", "/"); 
    return data;
   

实际上我是从客户端浏览器和端点上的服务器端发送通知中获取的,我能够发送通知,但我的 服务人员无法触发推送事件,所以我的浏览器没有收到通知。

  
  auth:"hcQQq+1FeDuSu7V0zd5DXA==" 
  endpoint:"https://fcm.googleapis.com/fcm/send/
  cXgp0l3svNo:APA91bG8dDfZhrc0iaSyzvuV1BvnxXz9T-
  SmLCKOymKrEdwvrh0_SjzjnU3ORRKvW5QD-
  Zp196T5nAGPayR7EKu_Bkb0pQrSex7Q3DZSu54Lo83AEiUE6p-2Xn-nrquCymKVFt6Z4nY8"
  key:"BJv2qC3WSCsRszMi57vOBpFjnIpdJ/
  uXQQFj4d0XZD9lRuZKuBgJNVFra0SFEvRlQQ88eG8RWWs7sSvO9Pbdkwk="
  

请帮助我摆脱这种情况,任何帮助将不胜感激。在此先感谢您。

【问题讨论】:

当您说“我可以发送通知”时,您的意思是您从推送服务中获得了成功的响应代码(即 2xx)吗?如果没有,则必须检查 HTTP 响应代码 是的,我收到成功响应代码 200。 全部在 VAPID 上,我们不需要在 fcm 和 gcm 中创建任何项目,是否可以看到我发送的消息? 【参考方案1】:

问题可能是由于某些防火墙阻止您接收推送通知。我就是这种情况。

【讨论】:

以上是关于从服务器发送通知时未触发推送事件的主要内容,如果未能解决你的问题,请参考以下文章

AlarmManager 在请求时未触发

从 webrick 发送推送事件

service-worker 可以停止 GCM api 发送的推送通知吗?

从一个信号触发的 Firebase 云功能发送 voip 推送通知

向我的 iPhone PHP 发送事件推送通知

消息传递服务器如何识别目标客户端并发送推送通知