一、背景
hs-hybrid-app 中包含了很多 H5 落地页,落地页的主要职责是引流。涵盖两种场景:已下载 App 的用户,将会唤起 APP,并跳转到对应页面;未下载 App 的用户,将跳转至应用市场下载 APP。
落地页的分享依赖微信生态,为了达到用户裂变的效果,这里我们将了解在微信 H5 中,如何唤起我们的应用。
二、目标
- 了解微信开放标签
wx-open-launch-app
- 在 React 中使用,实现微信唤起的 APP 功能
- 常见错误及解决方案
三、行动
微信开放标签
微信开放标签是微信公众平台面向网页开发者提供的扩展标签集合。通过使用微信开放标签,网页开发者可安全便捷地使用微信或系统的能力,为微信用户提供更优质的网页体验。
文档:开放标签说明文档
在 React 中使用
-
注册微信能力
import wx from 'weixin-js-sdk'; async wxRegister(config) { wx.config({ debug: false, // 开启调试模式 appId: config.appId, // 必填,公众号的唯一标识 timestamp: config.timestamp, // 必填,生成签名的时间戳 nonceStr: config.noncestr, // 必填,生成签名的随机串 signature: config.signature, // 必填,签名,见附录1 jsApiList: [ 'onMenuShareTimeline', // 获取“分享给朋友”按钮点击状态及自定义分享内容接口 'onMenuShareAppMessage', // 获取“分享到朋友圈”按钮点击状态及自定义分享内容接口 ], // 必填,需要使用的JS接口列表 openTagList: ['wx-open-launch-weapp', 'wx-open-launch-app'], // 可选,需要使用的开放标签列表 }); // 处理验证失败 wx.error((res) => { console.log('微信注册失败', JSON.stringify(res)); }); // 处理验证成功 return new Promise((resolve) => { wx.ready(() => { console.log('微信注成功'); resolve({}); }); }); }
-
封装 LaunchApp 组件
import React, { CSSProperties, useEffect, useRef } from 'react'; import { View } from '@tarojs/components'; import { TARGET_APP_ID } from '@/consts/app'; interface LaunchAppProps { extinfo: string; // 兼容 Android 跳转,跳转页面的地址 style?: CSSProperties | string; children?: React.ReactNode; targetAppId?: string; // 唤起目标应用 AppId,注意,不同于初始化微信能力的 AppId downloadApp?: () => void; // 下载方法 } const LaunchAppWrapper: React.FC<LaunchAppProps> = ({ downloadApp, style, targetAppId, extinfo, children }) => { const downloadApp = _downloadApp; const appId = targetAppId || TARGET_APP_ID; const wxRef = useRef<DocumentType>(null); useEffect(() => { if (wxRef.current) { wxRef.current.addEventListener('launch', function () { console.log('success'); }); wxRef.current.addEventListener('error', function (e: any) { console.log('launch app fail', e.detail); downloadApp(); }); } return () => { wxRef.current?.removeEventListener('launch', () => {}); wxRef.current?.removeEventListener('error', () => {}); }; }, []); return ( <View className='launch-app'> <wx-open-launch-app ref={wxRef} appid={appId} style={style} extinfo={extinfo} className='launch-app-tag'> <script type='text/wxtag-template'> <View style={{ position: 'fixed', bottom: 0, right: 0, width: '100%', height: '100%', opacity: 0.3, }} /> </script> </wx-open-launch-app> </View> ); }; export default React.memo(LaunchAppWrapper);
🏝 特别讲一下 AppId:注册微信能力时,所提供的 AppId 应改是公众号的 AppId;而在 LaunchAppWrapper 组件中的 AppId 是打开应用的 Id,通常 iOS/Android 对应着不同 Id。
FAQ
❌ 微信注册失败 {errMsg: "config:fail,invalid url domain"}
✅ 错误信息指无效的 URL domain,因为每个 appId 绑定了对应的安全域名,所以首先检验 appId 和域名是否对应;其次,在 DEV 环境,只能通过 iOS 验证微信唤端的逻辑,Beta 环境中只能通过 Android 验证;最后,我们还遇到过 appId 过期,导致注册失败的情况
❌ 微信注册失败,config: invalid signature
`{
"realAuthUrl": [
"https://mobilebeta.hongsong.club/hs-hybrid-app/liteAppPages/productionDetail?standCode=s_ABLOO5HU2401&sequenceId=1660809381491000&fromUserId=un_620502069848010752&showFromUserInfo=true&fromUserInfo=%7B%22avatar%22%3A%22%2F%2Fimages-1300484082.cos.ap-chengdu.myqcloud.com%2FuserAvatar%2F3747203507361%2F1632824472096.jpeg%22%2C%22name%22%3A%22%E4%B9%A6%E6%B3%95%E8%B5%B7%E6%BA%90%E4%B9%8B%E5%9C%B0%22%7D&debug=true"
],
"errMsg": "config:invalid signature"
}
错误信息指签名无效,具体现象是:
- 微信通过识别二维码后打开的 H5 页面,点击元素不生效,但刷新或通过链接点击的可以
- iOS 无法点击,但 Android 可以
出现问题的原因是参与签名的 URL 地址无效。因为微信内打开的网页(包括微信开发者工具)会对 URL里的字符自动转义(效果类似于 encodeURI(url)),通常签名由后端代码实现,后端取到的 URL 是转义后的,所以拿这个 URL 来做签名就跟微信端实际的 URL 不匹配了导致 invalid signature。
✅ JS 中使用到的 url,为了保证传输的 url 格式一致,一定要使用 encodeURI 进行转义!
🏝 当微信注册成功,控制台可以看到,获取权限成功的日志
❌ The slot <template>
or <script type="text/wxtag-template">
of <wx-open-launch-app>
is missing
✅ 实际上我写了标签,但是标签内没有子元素,添加子元素后,再没有错误提示。但是添加一个蒙层后,在浏览器、微信开发者工具中样式不一样,在本地开发和打包部署后样式也不一样。需要注意的是:
由于插槽中模版的样式是和页面隔离的,因此需要注意在插槽中定义模版的样式。插槽模版及样式均需要通过<script type="text/wxtag-template"></script>
进行包裹。
四、总结
- 微信开发需要了解微信生态的玩法,看相关的开发文档,否则遇到问题,排查起来比较花时间,比如应该使用哪个 AppId。
- 线上调试可以使用 vconsole 这类工具,方便查看日志