极光征文 | 浏览器推送你该知道的秘密

前言

手机推送功能是比较常见的需求,由于墙的原因浏览器推送宛如鸡肋,最近公司业务需要面向海外市场,所以计划给网页添加推送功能。

手机 app 推送国内有很多的推送厂商可以选择(ex:JPush),但是浏览器推送由于大环境影响基本没有类似产品,只能手撸(听说 JPush 正在着手浏览器推送,很是期待)。听说我司的产品(iOS、Android app)使用极光推送已经 3 年了,为什么是听说,因为我才入职两年,手动 [捂脸]。

本文将主要介绍两种网页推送,要求网页支持 HTTPS。

支持 Push Api 的浏览器

现在主流的现代浏览器都支持 Web Push API ,web push 允许浏览器打开的时候接收到推送(就算页面被关闭也能接受)。

Push APi 要求网页支持 HTTPS,因为 Push API 使用 Service Work 只能在 HTTPS 网站上使用,但是如果测试的话可以直接使用 localhost 也是允许的。

Push APi 推送的全流程如下图所示:

极光征文 | 浏览器推送你该知道的秘密_第1张图片
image.png

浏览器通过如下代码完成:


// https://example.com/webapp.js

navigator.serviceWorker.register('serviceworker.js').then(

  function(serviceWorkerRegistration) {

    serviceWorkerRegistration.pushManager.subscribe().then(

      function(pushSubscription) {

        console.log(pushSubscription.endpoint);

        console.log(pushSubscription.getKey('p256dh'));

        console.log(pushSubscription.getKey('auth'));

        // The push subscription details needed by the application

        // server are now available, and can be sent to it using,

        // for example, an XMLHttpRequest.

      }, function(error) {

        // During development it often helps to log errors to the

        // console. In a production environment it might make sense to

        // also report information about errors back to the

        // application server.

        console.log(error);

      }

    );

  });

我们需要注册一个 ServiceWork,成功注册后会得到一个 serviceWorkerRegistration,可以使用 serviceWorkerRegistration.pushManager.subscribe 这个方法来订阅推送成功订阅后返回 pushSubscription 用于标识当前当前的网页用户,需要传到自己的应用服务中用于推送。注意现在是能收到推送,但是不发触发通知,我们可以在 servicework.js 文件中添加 通知逻辑:


self.addEventListener('push', function(event) {

  console.log('[Service Worker] Push Received.');

  console.log(`[Service Worker] Push had this data: "${event.data.text()}"`);

  const title = 'Push Codelab';

  const options = {

    body: 'Yay it works.',

    icon: 'images/icon.png',

    badge: 'images/badge.png'

  };

  event.waitUntil(self.registration.showNotification(title, options));

});

服务端等到 pushSubscription 后可以通过里面的参数 auth 和 p256dh 给 endpoint 发送推送请求。

到此支持 Push Api 浏览推送就到此结束。

Safari 的 APNs 推送

Safari 的没有支持 Push Api 功能,但 OS X v10.9 之后可以使用 APNs 服务来支持推送功能,且功能更强大,允许 Safari 在关闭的情况下接受推送通知。

极光征文 | 浏览器推送你该知道的秘密_第2张图片
image.png

safari apns 要求网页支持 HTTPS,不然无法请求推送,本地测试的话可以使用自建证书来测试。

Safari 推送和手机应用推送都走的 APNS 通道,由于公司的手机 APP 已经支持了推送,后台使用 token 做验证,所以后台基本不需要修改推送逻辑,非常的简单。

注册 Website Push IDs

首先需要在 Certificates, Identifiers & Profiles

中注册 Website Push IDs

极光征文 | 浏览器推送你该知道的秘密_第3张图片
Register as a push provider with Apple

构建 Push Package

当 Safari 请求推送权限的时候,Safari 会向自己的服务器请求 Push Package,如果请求失败会返回错误,所以我们需要先创建这个 Push Package。

Push Package 最终要包含如下文件


BayAirlines.pushpackage/

    icon.iconset/

        icon_16x16.png

        [email protected]

        icon_32x32.png

        [email protected]

        icon_128x128.png

        [email protected]

    manifest.json

    signature

    website.json

icon.iconset/ 里面包含了推送所需的 icon。

website.json 主要包含网页信息。

Manifest.json 会记录所有的文件的 hash 值。大概长这样


{

    "website.json": {

        "hashType": "sha512",

        "hashValue": "4309a0cf6ee37909423fb4f5f762eb530d4a7cfe9e1d30b9c85b602afb9296a508f5df00c6f63439e4dcc4484aae4cd77d1f632678ece0ef1b62ca6c9cbdebb3"

    },

    "icon.iconset/icon_16x16.png": {

        "hashType": "sha512",

        "hashValue": "8bb462e25ca79cca241355f5ae97ffab352acf7d2a0390f6547f1d0a55ade59e01e725bea70778ad2822b1ec137a8c0547197727ae2e9fed620b0d3ddea6803b"

    },

    ...

}

幸运的是 Apple 提供了一个工具让我们很方便的生成 website.json 和 signature 这两个文件, 我们只需要准备好 icon.iconset/ 和 website.json 即可。createPushPackage.php 我们会得到 PushPackage 文件。

此时我们还需要给自己的应用服务添加一个 API,返回刚刚生成的 PushPackage 文件。


webServiceURL/version/pushPackages/websitePushID

请求权限

请求推送权限的流程可以整理成下图所示:

极光征文 | 浏览器推送你该知道的秘密_第4张图片
The user controls their notification permissions
  • 调用 window.safari.pushNotification.permission("< 你的 应用 id>") 可以获得当前的应用权限,如果当前权限为 default 则表示之前没有请求过。可以调用

window.safari.pushNotification.requestPermission(

          'The web service URL.', //

          'The Website Push ID.',    //

          {}, // Data that you choose to send to your server to help you identify the user.

          function () { } // 请求结果回调

      );

注意调用 requestPermission 时,safari 回去获取 push package 这个文件,如果之前的不步骤没有完成这里会失败。如果成功则会弹框提醒用户是否要运行当前网站接收推送通知。

用户同意后可以通过 window.safari.pushNotification.permission("< 你的 应用 id>") 方法获得 permission object,permission. deviceToken 需要传到自己服务器用于给 APNS 发送推送请求。到此 safari 推送已经完成。

Safari 推送和 iOS app 推送都是走的 APNS 服务,由于之前应用(react native 应用)已经集成了推送功能使用 jpush-react-native 这个插件,而且使用 token 的验证方式,所有服务端那边需要修改的东西比较少,只需要修改web 应用的 keyId 即可。

done!

PS:为了极光征文大赛才注册的,平常文章都是放 GitHub 的,希望下次活动可以支持 Github 上的文章。

「本文为极光征文参赛文章」

你可能感兴趣的:(极光征文 | 浏览器推送你该知道的秘密)