Chrome不会显示推送通知

时间:2020-03-22 19:29:35

标签: javascript node.js reactjs service-worker web-push

设置

  1. 操作系统:OS X
  2. 节点版本:12
  3. 网络推送版本:3.4.3

请选择您遇到问题的任何浏览器:

  1. [x] Chrome版本80.0.3987.132(正式版本)(64位)
  2. [] Firefox开发人员版
  3. [x] iPhone 8+上的Safari
  4. [x]其他

问题

Service Worker可以注册,但推送通知不会在Chrome 80.0.3987.132(官方内部版本)(64位)中弹出,但可以在Firefox Developers Edition中使用。我可以在Chrome浏览器的控制台中看到推送通知数据,但浏览器通知未显示。在Chrome的“应用程序”标签中,我可以在“推送消息和通知”部分中提取通知。

预期

我希望在Chrome和其他浏览器(包括移动设备)中看到浏览器通知

客户

打开通知的按钮将调用attemptToRegisterSW功能。

const attemptToRegisterSW = async dispatch => {
  if (
    !('serviceWorker' in navigator) ||
    !('PushManager' in window) ||
    !('Notification' in window)
  ) {
    dispatch(setNotificationMessage(`Sorry, your browser doesn't support push notifications`));
    return;
  }

  try {
    const components = await Fingerprint2.getPromise({
      excludes: { webdriver: true, cpuClass: true, fonts: true },
    });

    const fingerPrint = Fingerprint2.x64hash128(
      components.map(component => component.value).join(''),
      31,
    );

    const register = await navigator.serviceWorker.register('/service-worker.js', { scope: '/' });

    await navigator.serviceWorker.ready;

    const permissionResult = await askPermission();

    if (permissionResult === 'granted') {
      const subscription = await register.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: urlBase64ToUint8Array(publicVapidKey),
      });

      const token = getItemFromLocalStorage(INNERYOU_JWT);

      if (fingerPrint) {
        const req = await fetch('/api/alerts/subscribe', {
          method: 'POST',
          headers: {
            'content-type': 'application/json',
            accept: 'application/json',
            authorization: `Bearer ${token}`,
          },
          body: JSON.stringify({ subscription, fingerPrint }),
        });

        if (req.status === 201) dispatch(setNotificationMessage(`Push notifications turned on`));
      }
    } else {
      dispatch(
        setNotificationMessage(
          `Push notifications are either blocked or denied, please adjust your browser settings`,
        ),
      );
    }
  } catch (error) {
    dispatch(
      setNotificationMessage(`Error while turning on push notifications, please try again.`),
    );
    console.error(`Error while registering serviceWorker ${error}`);
  }
};

助手功能

检查是否已授予权限

const getNotificationPermissionState = async () => {
  try {
    if (navigator.permissions) {
      const navigatorPermissions = await navigator.permissions.query({ name: 'notifications' });
      return navigatorPermissions.state;
    }

    return await Notification.permission;
  } catch (error) {
    console.error(`Error while getting notification status ${error}`);
    throw new Error("We weren't granted permission.");
  }
};

询问用户权限

export const askPermission = async () => {
  try {
    const notificationStatus = await getNotificationPermissionState();

    if (notificationStatus === 'granted') {
      return notificationStatus;
    }

    return await Notification.requestPermission();
  } catch (error) {
    console.error(`Error while requesting notification permission ${error}`);
    throw new Error("We weren't granted permission.");
  }
};

服务器

import webpush from 'web-push';

const publicVapidKey = process.env.PUBLICVAPIDKEY;
const privateVapidKey = process.env.PRIVATEVAPIDKEY;

webpush.setVapidDetails('mailto:noresponse@inneryou.io', publicVapidKey, privateVapidKey);

alertRouter.post('/subscribe', verifyUserAuthStatus, async (req, res, next) => {
  try {
    const userId = res?.locals?.user?.id;
    const { subscription, fingerPrint } = req.body;

    if (!fingerPrint || !subscription) {
      res.status(400);
      res.locals.error = 'Bad Request';
      throw new Error('Bad Request');
    }

    const isExistingDevice: DeviceModel = await Devices.findOne({
      fingerPrint,
      'subscription.keys.auth': subscription.keys.auth,
    });
    let newDevice: DeviceModel = null;

    if (!isExistingDevice) {
      newDevice = await Devices.create({ user: userId, fingerPrint, subscription });
    }

    if (newDevice) {
      await User.findByIdAndUpdate(userId, {
        $push: {
          devices: newDevice._id,
        },
      });
    }

    res.status(201).json({});

    const notification = {
      title: 'Push Notification',
      body: 'Subscribed to push notifications',
      icon: '',
    };

    const payload = buildCommonMessage(notification);
    const devices: DeviceModel[] = await Devices.find({ user: userId }).lean();

    for (const device of devices) {
      await webpush.sendNotification(device.subscription, payload).catch(err => {
        if (err.statusCode === 410) {
          // DELETE DEVICE IF SUBSCRIPTION IS INVALID
          console.error(`Deleting invalid subscription: ${err}`);
          return Devices.findByIdAndRemove(device._id);
        } else {
          console.error(`Subscription is no longer valid: ${err}`);
        }
      });
    }
  } catch (error) {
    console.error(`Error with push notification ${error}`);
  }
});

服务器助手

export const buildCommonMessage = ({ title, body, icon }: CommonMessage): any => {
  return JSON.stringify({
    title: title,
    body: body,
    icon: icon || NOTIFICATION_IMAGE_URL,
  });
};

服务人员

/* eslint-disable no-restricted-globals */

self.addEventListener('push', (e) => {
  console.log('[Service Worker] Push Received.');
  const data = e.data.json();
  const title = data.title || 'InnerYou Notification';
  self.registration.showNotification(title, {
    body: data.body,
    icon: data.icon,
  });
});

0 个答案:

没有答案