评论

小程序开发之 web-view 的进阶玩法

主要从 web-view 与 JSSDK 的实现来展开,顺带过一下 web-view 的基础,最后在文末发放一些实用的小糖豆。

背景

半年前写过一个项目,在京东手机的小程序里内嵌老罗的锤子发布会的活动页。前几天老罗又发布了他的加湿器,而这份关于锤子项目的迟到的总结,经过这几天在全网搜索的相关问题来看,依然有必要写一下。

本文主要从 web-view 与 JSSDK 的实现来展开,顺带过一下 web-view 的基础,最后在文末发放一些实用的小糖豆。

ok,废话不多说,开始吧。

web-view 中可用的 JSSDK 接口

1. web-view 的本质 与 JSSDK

我们已知,web-view 是闭环的小程序对外开启的一扇窗户,是小程序承载网页链接的容器。web-view 就像小程序里内置的浏览器内核,可以运行网页,其实 web-view 本质即是微信的 WKWebview 的实现。

区别:小程序框架系统包括两部分,视图层和逻辑层,两者对应的技术实现分别是 webview 和 JSCore;web-view本质上就是一个浏览器,承载网页,包括视图和逻辑实现。

微信Webview 不仅应用于小程序的 web-view,也应用于公众号等所有微信里可以打开网页的位置。

微信Webview 不仅集成了普通 webkit 引擎的基础功能,还注入了微信JSBridge(JS-SDK)相关的脚本,提供给开发者更多高效的能力,如:拍照、语音、位置基于手机系统的能力;扫一扫、微信分享、卡券、支付等微信个性化能力。

而基于微信Webview 的 web-view 组件,除开放承载页面的功能外,也被赋予了一些 JS-SDK 的使用能力,尽管有一定的限制,但整理来看也使 web-view 的能力变得强大了。

2. web-view 中可用的 JSSDK 接口

本文从两个维度介绍 JSSDK 的接口。只简单列举几个,更多可支持的接口还请查看web-view的文档。

1) 可用的通用JSSDK接口

接口模块 接口说明 接口名称
判断客户端是否支持js checkJSApi
图像接口 拍照或上传 chooseImage
图像接口 预览图片 previewImage
图像接口 上传/下载图片 uploadImage/downloadImage
图像接口 获取本地图片 getLocalImgData
音频接口 开始/停止录音 startRecord/stopRecord
音频接口 播放/暂停/停止语音 playVoice/pauseVoice/stopVoice
地理位置 使用内置地图/获取地理位置 getLocation/openLocation
蓝牙接口 开启/关闭/监听 start/stopSearchBeacons/onSearchBeacons
扫码 微信扫一扫 scanQRCode
卡券 列表/添加/打开 chooseCard/addCard/openCard
长按 小程序圆形码
智能接口 识别音频 translateVoice

2)与小程序相关的接口

除通用的JSSDK接口外,web-view 还支持和小程序跳转相关的接口,比如:navigateTo、redirectTo、switchTab、navigateBack,类似这种。具体写法都是加上 wx.miniProgram. 这样。

此外,关于小程序和web-view 的通信需要请求:wx.miniProgram.postMessage 方法,小程序侧进行侦听即可,具体方法可参看公众号的另一篇文章。

3)这些接口的可用性

能够运行这些接口的最前提的条件就是,需要在小程序的环境里进行。那如何判断是否在小程序的环境里?

有两种方法:

  • wx.miniProgram.getEnv
wx.miniProgram.getEnv(function(res) { console.log(res.miniprogram) // true })
  • window.__wxjs_environment
console.log(window.__wxjs_environment === 'miniprogram')

web-view 如何使用 JSSDK 接口?

了解 web-view 可用的API 后,我们知道,在嵌入的H5 页面里,可以从相机里选择图片,或使用扫一扫的功能,那具体我们该如何实现呢?

微信公众平台给出了详尽的 JS-SDK 的实现方法,我们这里将几个当年踩过的要点给出。

1)绑定域名。

首先需要登录相关联的公众号,嗯!你没有看错,确实是公众号,(有很多人吐槽此事,但这确实是目前的事实。)登录后进入“公众号设置”-“功能设置”,填写“JS接口安全域名”。

这一行为,建立了网页域名和 appId 之间的绑定关系,即,该appId 下可以打开这几个域名白名单里的网页。

同web-view 的业务域名配置一样,也需要将生成的校验文件拷贝到域名指向的 web 服务器的目录下。

2)签名的实现。

签名是进入下一步的必要条件,这部分交由后端实现,了解它会提升你们的联调能力。

第一步,获取微信网页授权,拿到access_token值。

接口:
https请求方式:

GET
https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET
参数 是否必须 说明
grant_type 获取access_token填写client_credential
appid 第三方用户唯一凭证
secret 第三方用户唯一凭证密钥,即appsecret

公众号和小程序均可以使用 AppIDAppSecret 调用本接口来获取access_token。

AppID和AppSecret可在“微信公众平台-开发-基本配置”页中获得(需要已经成为开发者,且帐号没有异常状态)。

需要设置IP白名单:登录“微信公众平台-开发-基本配置”提前将服务器IP地址添加到IP白名单中,点击查看设置方法,否则将无法调用成功。小程序无需配置IP白名单。

入口:

具体设置:

第二步,获得jsapi_ticket。

用第一步拿到的access_token 采用http GET方式请求获得jsapi_ticket(有效期7200秒,开发者必须在自己的服务全局缓存jsapi_ticket):

https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi
{
"errcode":0,
"errmsg":"ok",
"ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA",
"expires_in":7200
}

第三步,生成签名。

初始字段:noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分)。

noncestr=Wm3WZYTPz0wzccnW
jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg
timestamp=1414587457
url=http://mp.weixin.qq.com?params=value

中间过程:对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串。

jsapi_ticket=sM4AOVdWfPE4DxkXGEs8VMCPGGVi4C3VM0P37wVUCFvkVAy_90u5h9nbSlYy3-Sl-HhTdfl2fzFy1AOcHKP7qg&noncestr=Wm3WZYTPz0wzccnW&timestamp=1414587457&url=http://mp.weixin.qq.com?params=value

生成签名:对生成的字符串作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。

0f9de62fce790f9a083d5c99e95740ceb90c27ed
3)当前页面注入权限验证配置。

所有需要使用 JSSDK 的页面必须首先注入配置信息,否则无法调用 JSSDK 的 API。在2)中我们有生成的签名和生成签名依赖的时间戳和随机串,这些都是我们进行配置的必要入参。具体如下:

wx.config({
    debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: '', // 必填,公众号的唯一标识
    timestamp: , // 必填,生成签名的时间戳
    nonceStr: '', // 必填,生成签名的随机串
    signature: '',// 必填,签名
    jsApiList: [] // 必填,需要使用的JS接口列表
});

其中 apilist 是本页面里支持使用的 JSSDK 的 API,如果不声明,是不可以被调用使用的。

在下一步4)中会有一个实例。

4)万事俱备之后

config 接口是异步请求的,所以增加 ready 的接口来判定config 是否已经具备;同时,也提供了error 接口来实现 config 失败后的处理。

哈哈,以上基本就是 JSSDK 在小程序 web-view 里的打通实现,因为中间牵扯前后端的实现,看起来篇幅长且凌乱,不知道你还能不能看到这里呢?

如果你是前端童鞋,先跟你报个喜,绑定域名和实现签名这些都不是你需要做的事情,把这些丢给你的后端童鞋,让他们来实现吧。但我还是提个醒,这些我们有必要知道,因为你在打通 web-view 和 JSSDK 时,可能无从下手。

5)一个例子帮你搞定

以下我们用一个例子,把前端方案的实现串起来,给大家一个直观的展示。

引入微信 JSSDK 库:

请求后端生成签名的接口,获取相关config依赖的字段:

在ready后,使用 wx.chooseImage() 选择本地相册的图片。

ok,到此为止,我们基本把 JSSDK 在 web-view 里的应用实现介绍完了。

总的来说,这是一个看起来比较简单,但实现起来可能有很多不可知问题的事情,我们当年苦于不了解需要在公众号下申请各种资源,不知道使用哪个 JSSDK 走了许多弯路,后来还踩过设置IP白名单的问题。这些都还是比较好解决的,本文也基本把这些很详尽的做了描述。在签名的实现中,还会有很多问题,还好我们当时也根据文档附录中的指点一一解除。

长征路漫漫,还好有分享~

糖豆:web-view 在实际场景中的应用问题

在这些和 web-view 相伴相生的日子里,也逐渐总结了一些问题,大致分为了几类,列举如下:

1. 开放能力的问题:
  • 是否开放支付,是否支持直播,是否支持h5里添加分享按钮? 答案否!
  • 插件禁用 webview 组件
  • 个人账号可以测试,无法上线
  • 小程序无法读取 web-view 的 cookie。
  • 小程序不可以触发模板消息

类似以上问题,都可以归结为小程序的 web-view 对 JSSDK 的开放能力,须严格按微信的JSSDK提供的能力检查是否可行。

  • 能否嵌套了其他的第三方网站的页面?答案:一切h5里引入的链接都需要加业务域名。
  • 喜报:支持打开相关联公众号的文章!!

web-view 对外部网页的开放能力都是基于业务域名的白名单设置!

感谢开放关联公众号的打开权限,运营小伙伴可以玩起来。

2. 白屏问题?

紧接上文,强化一下业务域名配置问题。很多业务域名配置失败的直接症状就是白屏,然后给一句话,引用非业务域名。问题直接明了!那如何解决?

1)优先查看业务配置是否ok,是否是https等。2)不能解决问题继续查看其他证书,如TSL版本。具体可查阅小程序HTTPS证书的约定。

3. 跳转问题。

首页是web-view 时没有回退按钮?层级过深时,回退过多?

这个是经常被问到的问题,首页web-view 没有回退,官方没有给出很明确的说法;而非首页的 web-view 一旦路由跳转建立起来,web-view 里的路由就默认加入了路由栈中。有什么好办法解决?

这个已跟小程序没关系了,唤醒你在浏览器里的处理吧。

4. 缓存、网页不刷新问题?

这个也可以归结为浏览器里如何处理缓存的问题,类似浏览器网页中的缓存,可以通过时间戳。另外看看是不是你的CDN 缓存了内容?

5. 分享问题?

分享接口拿到的 webViewUrl 只是第一个 url,如果你的页面已经进入到它的子页面中,再次分享时,这时候你分享得到的 url 没有变化。这时候 你需要在子页面中使用 postMessage,捕获到当前页面的路径,传递给小程序。当用户触发分享时,只要读取消息队列最近的一条数据即可。

记得拼接参数时需要encodeURIComponent。

6 web-view 改宽高?

不可以。默认铺满整屏。web-view 和 其他UI组件的关系是互斥的,并且小程序会优先选择展示 web-view。如果你想放多个web-view,很抱歉,它默认只展示第一个web-view 的内容,还会在控制台给个大大的报错。

7 web-view 提示“未绑定网页开发者”?

没有开发该网页的权限!需要在公众号的开发者工具里绑定开发者微信号。

8 web-view 的校验文件是什么格式?

官方回答:是一个含有普通字符串的txt文件,只是一个随机的字符串,与appid无关。放心使用~

好啦~以上是对 web-view 常见问题的总结,总结不敢保证全对,另外一定是会过时的,所以,这只是你遇到问题的一个思考方向,具体方案还要请参看小程序官方文档。

如果你有更好的方案,欢迎回复我们,超级无敌感谢!

最后,感谢你能够读到这里,也愿你不枉此行。

扩展阅读

[1] 微信JS-SDK说明文档
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421141115
[2] 微信小程序开放能力-web-view
https://developers.weixin.qq.com/miniprogram/dev/component/web-view.html

文章原载于公众号:全栈探索。

最后一次编辑于  2019-02-21  
点赞 5
收藏
评论

5 个评论

  • 哈喽哈喽
    哈喽哈喽
    2019-02-22

    建议官方也审核一下评论留言🙂

    2019-02-22
    赞同 3
    回复
  • 小猪佩奇会上树
    小猪佩奇会上树
    2022-05-09

    有人 就实现了 小程序 打开 公众号文章,公众号文章正常显示,并且可以正常评论回复,还有蒙版层,就很牛逼

    2022-05-09
    赞同
    回复
  • 赵光裕
    赵光裕
    2019-02-27

    关于审核有个问提,我知道IOS商店中如果只有一个webview会不过审,因为内容太少,微信这边审核也会出现这样的问题吗

    2019-02-27
    赞同
    回复 1
    • 2019-02-28

      目前没有遇到,您可以试一试。

      2019-02-28
      回复
  • A0银泰华为张柏18532659345
    A0银泰华为张柏18532659345
    2019-02-23

    2019-02-23
    赞同
    回复
  • 刘汝佳
    刘汝佳
    2019-02-22

    2019-02-22
    赞同
    回复
登录 后发表内容