公众号里推了一个活动 H5,用户看完想下单,结果下单流程在小程序里。以前只能在页面上放一张小程序码,配一行「长按识别进入小程序」,用户长按、识别、确认,三步走完还得再找一遍商品。转化率什么样可想而知。
微信后来开放了一组开放标签,其中 wx-open-launch-weapp 就是专门解决这件事的,H5 上放一个按钮,点一下直接拉起指定小程序的指定页面。这篇把接入过程完整记一遍,从资格确认、JS-SDK 配置,到在 Vue 项目里的具体写法,再到版本判断和降级。
在本篇文章中,我们将从浅入深,和大家一起学习以下知识:
- 开放标签的主体资格和系统版本门槛,哪些账号根本接不了
- 微信 JS-SDK 的两种引入方式,以及
openTagList这个容易漏的字段 - 在 Vue 项目里让自定义标签不报错的配置
- 怎么判断微信版本,以及原文那段版本判断代码为什么是错的
- 开放标签内部的样式限制和
username、path两个参数的填法 launch和error两个回调事件怎么用- 微信后台的配置路径这几年的变化,和相关的注意事项
# 一、先确认你有没有资格接
这一步别跳过,很多人代码写完了才发现账号根本用不了这个能力。
主体要求上,开放标签仅开放给已认证的服务号。订阅号不行,未认证的服务号也不行。如果你手上是个订阅号,到这里就可以停了,得先去做认证或者换主体。
系统要求上,微信版本要求为 7.0.12 及以上,系统版本要求为 iOS 10.3 及以上、Android 5.0 及以上。低于这个版本的客户端上,开放标签是渲染不出来的,页面上就是一片空白。
所以降级方案不是可选项,是必选项。
除了这两条硬门槛,还有两个前置动作要做:页面必须部署在公众号后台配置过的 JS 接口安全域名下,并且必须是 HTTPS。这两条不满足的话,wx.config 那一步就直接过不去。
# 二、接入微信JS-SDK
有两种引入方式,看你的项目是什么形态。
包使用方式,适合有构建流程的工程化项目:
"weixin-js-sdk": "^1.6.0"
直接在页面上使用,适合传统的多页项目。在需要调用 JS 接口的页面引入如下 JS 文件:http://res.wx.qq.com/open/js/jweixin-1.6.0.js,这个地址是支持 https 的。实际接入时请直接写 https,因为你的页面本来就必须是 HTTPS,混着引 HTTP 资源会被浏览器拦掉。
引入之后调 wx.config 注入配置:
wx.config({
appId: '',
debug: true,
timestamp: '',
nonceStr: '',
signature: '',
jsApiList: [],
openTagList: ['wx-open-launch-app','wx-open-launch-weapp'] // 获取开放标签权限
});
这段配置里最容易漏的就是 openTagList。很多人照着普通 JS-SDK 的文档抄,只填了 jsApiList,然后发现按钮死活不出来。开放标签的权限和普通 JS 接口的权限是分开申请的,用到哪个标签就把哪个标签名写进 openTagList。
需要注意的点归纳成三条:
wx.config内要列出使用到的openTagList- 要符合开放平台列出的要求,见
https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_H5_Launch_APP.html - 如果你还要跳 App,App 端需要按文档接入微信 SDK,见
https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/iOS.html
signature 那几个字段是后端算好返回给你的,不要在前端拼。签名的原始串里包含当前页面的 URL,这块的坑我在另一篇里写得比较细,可以对照着看:H5之微信公众号分享。
在微信开发者工具内打开你的网页测试,如果显示这样的返回,说明你已经接入 JS-SDK 成功了:
{errMsg: "config:ok"}
调试期间 debug: true 一定要开着,配置错了它会直接 alert 出具体原因,比自己猜快得多。上线前记得关掉。
# 三、在Vue中使用例子
下面这套是在 Vue 2 项目里的完整落地过程,分四步。
# 第1步 在main.js中设置
wx-open-launch-weapp 不是标准 HTML 元素,也不是 Vue 组件,Vue 在编译模板时碰到它会警告「未知的自定义元素」。所以要先告诉 Vue 忽略这几个标签:
// 忽略微信自定义标签
Vue.config.ignoredElements = ['wx-open-launch-weapp','wx-open-launch-app']
这行代码不写不会导致功能不可用,但控制台会一直刷警告。而且在某些构建配置下警告会被当成错误处理,直接把编译卡住。
# 第2步 获取微信版本
先判断是不是在微信环境里,再取版本号:
// 判断微信环境内
isWechat() {
let ua = window.navigator.userAgent.toLowerCase()
// console.log(ua)
if (ua.match(/MicroMessenger/i)) {
return true
} else {
return false
}
},
// 获取微信版本
// return eg. 7.0.16.1600
getWeixinVersion() {
return navigator.userAgent.match(/MicroMessenger\/([\d\.]+)/i)[1]
},
getWeixinVersion 里直接对 match 的结果取下标是有风险的,非微信环境下 match 返回 null,这句会直接抛错。原文用 isWechat() && getWeixinVersion() 的短路写法把它挡住了,逻辑上没问题,但如果这个函数被别处单独调用就会炸。稳妥的做法是在函数内部自己判空。
然后在 created 里做版本比较:
created(){
// 微信版本号大于 7.0.12 开放标签才可进行
const wxVersion = this.isWechat() && this.getWeixinVersion() || ''
if(wxVersion){
let v = wxVersion.split('.')
if(v[0]>=7){
if(v[1]>=0){
if(v[2]>=12){
this.enableLaunchWeapp = true
}
}
}
}
},
这段是原文的写法,我当时也是这么写的。但这里有个坑要注意,这个三层嵌套的判断是错的。
你想想看,微信版本走到 8.0.5 的时候会发生什么?v[0] 是 8,大于 7,进第一层;v[1] 是 0,进第二层;v[2] 是 5,小于 12,判断失败。结果一个明显比 7.0.12 新的版本被当成了低版本,开放标签被降级掉了。
版本号比较不能逐段独立判断,要按位比较并且高位分出胜负就立即返回。改成这样:
// 把版本号按段比较,高位一旦分出大小就返回,避免 8.0.5 被误判
function gteVersion(current, target) {
const a = String(current).split('.').map(Number)
const b = String(target).split('.').map(Number)
const len = Math.max(a.length, b.length)
for (let i = 0; i < len; i++) {
const x = a[i] || 0
const y = b[i] || 0
if (x > y) return true
if (x < y) return false
}
return true
}
调用起来就一行:
created(){
const wxVersion = this.isWechat() ? this.getWeixinVersion() : ''
this.enableLaunchWeapp = !!wxVersion && gteVersion(wxVersion, '7.0.12')
},
微信版本号有时候是四段的,比如注释里那个 7.0.16.1600,上面这个函数对段数不一致的情况也能正确处理,多出来的位按 0 补。
# 第3步 在页面上展示
如果微信版本低于 7.0.12,开放标签是无法使用的,需要降级处理。所以模板里用 enableLaunchWeapp 分了两个分支:
<div v-if="enableLaunchWeapp">
<wx-open-launch-weapp
id="launch-btn"
username="gh_edc489d117fa3d"
path="/pages/home/index.html"
>
<script type="text/wxtag-template"></script>
</wx-open-launch-weapp>
</div>
<h1 v-else>{{ goodsInfo.goodsName }}</h1>
上面 username 那个值是示例,换成你自己小程序的原始 ID。
这段模板里有四个点必须说清楚,每一个我都卡过:
- 在 Vue 中需要用
text/wxtag-template类型的脚本标签把内容包裹起来,否则按钮不能展示。这个标签不是真的脚本,微信会把它的内容当成模板取出来渲染到开放标签内部 username为小程序原始 ID,以gh_开头,需要在小程序后台的设置里获取。注意不是 AppID,这两个很容易搞混path是打开小程序的指定页面,需要加上.html,比如/pages/home/index.htmlstyle中的样式写法需要注意,goods-name这种带连字符的类名好像不支持,需要写成goodsname,而且只支持 px 格式
最后这条我排查了挺久。开放标签内部是一块独立的渲染区域,外面的 CSS 进不去,里面的样式只能写在这个模板里的 style 块中,而且支持的属性和写法都是受限的。rem、vw 这些相对单位不要用,直接写 px。带连字符的类名不生效这条是我实测的结论,不排除后来微信放开了限制,具体请以官方文档为准。
还有一个视觉上的坑。开放标签渲染出来的是一个透明的可点击区域,覆盖在你的模板内容上。你在外面给 wx-open-launch-weapp 设的宽高如果和内部模板对不上,就会出现「按钮看着在这里,点了没反应」或者「按钮外面一圈也能点」的情况。稳妥的做法是给外层容器和内部模板设一样的尺寸。
# 第4步 监听开放标签回调事件
开放标签会派发两个自定义事件,launch 表示跳转指令已经发出,error 表示跳转失败: