小程序开发之 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
公众号和小程序均可以使用 AppID 和 AppSecret 调用本接口来获取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×tamp=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
文章原载于公众号:全栈探索。