如何通过微信唤起 App

258 阅读3分钟

一、背景

hs-hybrid-app 中包含了很多 H5 落地页,落地页的主要职责是引流。涵盖两种场景:已下载 App 的用户,将会唤起 APP,并跳转到对应页面;未下载 App 的用户,将跳转至应用市场下载 APP。

落地页的分享依赖微信生态,为了达到用户裂变的效果,这里我们将了解在微信 H5 中,如何唤起我们的应用。

二、目标

  • 了解微信开放标签 wx-open-launch-app
  • 在 React 中使用,实现微信唤起的 APP 功能
  • 常见错误及解决方案

三、行动

微信开放标签

微信开放标签是微信公众平台面向网页开发者提供的扩展标签集合。通过使用微信开放标签,网页开发者可安全便捷地使用微信或系统的能力,为微信用户提供更优质的网页体验。

文档:开放标签说明文档

在 React 中使用

  1. 注册微信能力

    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({});
          });
        });
      }
    
  2. 封装 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 进行转义!

🏝  当微信注册成功,控制台可以看到,获取权限成功的日志

截屏2022-08-31 下午7.20.12.png

❌ The slot <template> or <script type="text/wxtag-template"> of <wx-open-launch-app> is missing

✅ 实际上我写了标签,但是标签内没有子元素,添加子元素后,再没有错误提示。但是添加一个蒙层后,在浏览器、微信开发者工具中样式不一样,在本地开发和打包部署后样式也不一样。需要注意的是: 由于插槽中模版的样式是和页面隔离的,因此需要注意在插槽中定义模版的样式。插槽模版及样式均需要通过<script type="text/wxtag-template"></script> 进行包裹。

四、总结

  • 微信开发需要了解微信生态的玩法,看相关的开发文档,否则遇到问题,排查起来比较花时间,比如应该使用哪个 AppId。
  • 线上调试可以使用 vconsole 这类工具,方便查看日志