使用微信wx-open-launch-app标签实现微信网页打开App记录

本文涉及的产品
简介: 使用微信wx-open-launch-app标签实现微信网页打开App记录

前提须知



笔者公司的项目在微信端的功能定位为基础功能交易及服务,通知用户交易提醒、交易流水等,而 APP 为主要的交易功能。之前是在多个页面有引流按钮跳转至 App,功能点比较粗暴,直接 location.href = 应用宝链接。现在产品有需求,说要用微信提供的标签来唤起 App


需求点:



所有跳转至 App 下载页面的部分,改成


image.png

需求点


Demo 先行



遇事不决,官网文档[1]。查看后与微信 JS-SDK 功能点很像,这里我不废话,直接跳过。按照官网 demo,把示例写进业务代码中


import React, { useEffect, useRef } from 'react';
import { toDownloadApp, isWechat, getWeixinVersion } from 'utils';
const Download = () => {
    const wxRef = useRef(null)
    useEffect(() => {
        if (wxRef.current) {
            // @ts-ignore
            wxRef.current?.addEventListener('launch', function (e: any) {
                console.log('success');
            });
            // @ts-ignore
            wxRef.current.addEventListener('error', function (e) {
                console.log('fail', e.detail);
                toDownloadApp()
            });
        }
    }, [])
    const onHandleClick = () => {
      toDownloadApp()
    }
    return (
        <div className="Download" onClick={onHandleClick}>
            {/*  @ts-ignore */}
            <wx-open-launch-app
                ref={wxRef}
                appid="XXXX"
            >
                <script type='text/wxtag-template'>
                    <button>App内查看</button>
                </script>
                {/*  @ts-ignore */}
            </wx-open-launch-app>
        </div>
    )
}
export default React.memo(Download);


测试成功,demo 能跑通


组件试点



现在搞业务,以这个组件(Download)为试点展开,我要点击页面顶部的卡片(多个地方使用,抽离成 Download 组件),让其唤起 App,但是要判断其版本,如果版本过低,让其跳转至应用宝


import React, { useState, useEffect, useRef } from 'react';
import LogoImg from '@/assets/images/logo.png';
import { toDownloadApp, isWechat, getWeixinVersion } from 'utils';
const Download = () => {
    const wxRef = useRef(null)
    const [enableLaunchWeapp, setEnableLaunchWeapp] = useState(false);
    useEffect(() => {
        const wxVersion = isWechat() && getWeixinVersion() || ''
        if (wxVersion) {
            let v = wxVersion.split('.')
            if (Number(v[0]) >= 7) {
                if (Number(v[1]) >= 0) {
                    if (Number(v[2]) >= 12) {
                        setEnableLaunchWeapp(true)
                    }
                }
            }
        }
        if (wxRef.current) {
            // @ts-ignore
            wxRef.current?.addEventListener('launch', function (e: any) {
                console.log('success');
            });
            // @ts-ignore
            wxRef.current.addEventListener('error', function (e) {
                console.log('fail', e.detail);
                toDownloadApp()
            });
        }
    }, [])
    const onHandleClick = () => {
        if (!enableLaunchWeapp) {
            toDownloadApp()
        }
    }
    return (
        <div className="Download" onClick={onHandleClick}>
            <div className="Download__logo">
                <img src={LogoImg} alt="logo" />
            </div>
            <div className="Download__content">
                <div className="Download__content-title">雅美App</div>
                <div className="Download__content-desc">长泽雅美服务专区</div>
            </div>
            {/* <div>1</div> */}
            <div className="Download__btn">立即打开</div>
            {/*  @ts-ignore */}
            <wx-open-launch-app
                ref={wxRef}
                appid="XXXXX"
                style={{ position: 'fixed', top: 0, left: 0, width: '100%', height: '60px', opacity: 0.3, background: 'blue' }}
            >
                <script type='text/wxtag-template'>
                    <div style={{ position: 'fixed', top: 0, left: 0, width: '90%', height: '100%', opacity: 0.3, background: 'red' }} />
                </script>
                {/*  @ts-ignore */}
            </wx-open-launch-app>
        </div>
    )
}
export default React.memo(Download);


思路逻辑参考:wx-open-launch-weapp 样式问题[2],我也给它配上颜色,方便后续观察


测试同步,能点击卡片跳转,好,下一步,在所有需要点击跳转页面的地方加入类似这样的代码


<wx-open-launch-app
    ref={wxRef}
    appid="XXXX"
    style={{ position: 'fixed', top: 0, left: 0, width: '100%', height: '60px', opacity: 0.3, background: 'blue' }}
    >
    <script type='text/wxtag-template'>
        <div style={{ position: 'fixed', top: 0, left: 0, width: '90%', height: '100%', opacity: 0.3, background: 'red' }} />
    </script>
    {/*  @ts-ignore */}
</wx-open-launch-app>


封装组件 WxOpenLaunchApp



如果是这样,就可以将其封装成一个组件了,起个名吧: WxOpenLaunchApp


将唤起 App 的内容包装成一个组件,暴雷 children 和 style 两个 props,代码如下:


import React, { useEffect, useRef, forwardRef } from 'react';
import { toDownloadApp } from 'utils';
export interface WxOpenLaunchAppProps {
    children: React.ReactNode;
    style?: React.CSSProperties;
}
const WxOpenLaunchApp: React.FC<WxOpenLaunchAppProps> = props => {
    const { style, children } = props;
    const wxRef = useRef(null)
    useEffect(() => {
        if (wxRef.current) {
            // @ts-ignore
            wxRef.current?.addEventListener('launch', function (e: any) {
                console.log('success');
            });
            // @ts-ignore
            wxRef.current.addEventListener('error', function (e) {
                console.log('fail', e.detail);
                toDownloadApp()
            });
        }
    }, [])
    return (
        <div className="wx-open-launch-app">
            {/*  @ts-ignore */}
            <wx-open-launch-app
                ref={wxRef}
                appid="XXXX"
                style={style}
            >
                <script type='text/wxtag-template'>
                    {children}
                </script>
                {/*  @ts-ignore */}
            </wx-open-launch-app>
        </div>
    )
}
export default React.memo(WxOpenLaunchApp);


那么 Download 组件也就可以干净很多


...
const Download = () => {
    ...
    return (
     ...
         <div className="Download__btn">立即打开</div>
            {/*  @ts-ignore */}
            <WxOpenLaunchApp style={{ position: 'fixed', top: 0, left: 0, width: '100%', height: '60px', opacity: 0.3, background: 'blue' }}>
                <div style={{ position: 'fixed', top: 0, left: 0, width: '100%', height: '100%', opacity: 0.3, background: 'red' }} />
            </WxOpenLaunchApp>
  ...
    )
}
...


业务组件 OpenAppPopup



回到需求点,每个点击的地方都要弹出弹出框,点击 打开 App ,再唤起 App,这样的话,弹出框 + WxOpenLaunchApp 就可以结合成一个组件,放出来供页面调用,名字就叫 OpenAppPopup ,代码如下:


import React, { FC } from 'react';
import { Popup, WxOpenLaunchApp, Toast } from 'components'; // 此乃公司自研组件库
export interface OpenAppPopupProps {
    show: boolean;
    onCancel: () => void;
    onSubmit: () => void;
}
const OpenAppPopup: FC<OpenAppPopupProps> = (props) => {
    const { show, onCancel, onSubmit } = props;
    return (
        <Popup.Group show={show}>
            <Popup.Confirm
                title="抱歉,此功能需在雅美App中使用"
                btnSubmitText={
                    <div style={{ position: 'relative' }}>
                        打开App
                        <WxOpenLaunchApp style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', opacity: 0.3, background: 'blue' }}>
                            <div style={{ position: 'absolute', top: 0, left: 0, width: '100%', height: '100%', opacity: 0.6, background: 'red' }} />
                        </WxOpenLaunchApp>
                    </div>
                }
                onCancel={onCancel}
                onSubmit={onSubmit}
            />
        </Popup.Group>
    )
}
export default React.memo(OpenAppPopup);


接着在所有有跳转 App 的页面上用上这块逻辑即可


封装 HOOK



每个页面点击类似 下载App 按钮时,会弹出 OpenAppPopup,点击 打开App,需要判断你的微信版本,是否达到 7.0.12,如果每个页面都要加上这段


const wxVersion = (isWechat() && getWeixinVersion()) || ''
if (wxVersion) {
  let v = wxVersion.split('.')
  if (Number(v[0]) >= 7) {
    if (Number(v[1]) >= 0) {
      if (Number(v[2]) >= 12) {
        setEnableLaunchWeapp(true)
      }
    }
  }
}


真的太恶心了,果断抽离成 hook。代码如下:


import { useState, useEffect } from 'react';
import { isWechat, getWeixinVersion } from 'utils';
const useEnableLaunchWeapp = () => {
    const [enableLaunchWeapp, setEnableLaunchWeapp] = useState(false);
    useEffect(() => {
        const wxVersion = isWechat() && getWeixinVersion() || ''
        if (wxVersion) {
            let v = wxVersion.split('.')
            if (Number(v[0]) >= 7) {
                if (Number(v[1]) >= 0) {
                    if (Number(v[2]) >= 12) {
                        setEnableLaunchWeapp(true)
                    }
                }
            }
        }
    }, [])
    return enableLaunchWeapp
}
export default useEnableLaunchWeapp;


逻辑也很简单,在刚加载时判断它是否可以点击,可以点击,就设置 enableLaunchWeapp 为 true。使用方法也很简单


import React, { useState, useEffect } from 'react';
import { Dispatch, History } from 'umi';
import {  OpenAppPopup } from 'components';
+import { useEnableLaunchWeapp } from 'hooks';
import { toDownloadApp } from 'utils';
interface KVProps {
    history: History;
}
const KV: React.FC<KVProps> = (props) => {
    const { history } = props;
    const [isShow, setIsShow] = useState(false);
    +const enableLaunchWeapp = useEnableLaunchWeapp();
    const onHandleClickToBuy = () => {
        setIsShow(true);
    };
    const onHandleClickToSubmit = () => {
        +if (!enableLaunchWeapp) {
        +    toDownloadApp()
        +}
    }
    return (
        <div className="KV" style={{ background: kvBgColor }}>
            <div className="KV__content">
                <img src={img} alt="" />
            </div>
            <OpenAppPopup
                show={isShow}
                onCancel={() => {
                    setIsShow(false);
                }}
                onSubmit={onHandleClickToSubmit}
            />
        </div>
    );
};
export default React.memo(KV);


与 App 交互



需求点里说:要在所在页面跳转至 App 相对页面,文档上写的很明显,可以传参数 extinfo="your-extinfo",随便写了个让客户端同事先测试先


未唤醒 App


我手机是 IOS 的,是可以唤起的,但是安卓同事调试的时候说,后台运行时,可以唤起 App,但是没有切换动作;如果杀掉进程,就无法唤起。而这问题,大概率是 SDK 配置的问题,同事看了半天没解决,扔给他 Android 接入指南[3]  。我又看不懂 Android,只能看他了


如果测试成功,能跳过去,那么就把本页链接当作 extinfo 传过去,他那边接收到 extinfo 后,做个映射表,跳转至自身的页面即可,所以 WxOpenLaunchApp 需要改造,多一个 extinfo 参数。。。


后记


因为我们用的是 flutter,同事说,因为引入的第三方库不支持,所以跳不过去,所以这个功能要后置,等他搞定了我再做更新


错误处理



除了在 WxOpenLaunchApp 组件中加入监听 error,错误就让它跳转至 App 外,还要做当微信或者系统版本不支持微信标签时,需要监听并进行回退兼容,代码如下:


document.addEventListener('WeixinOpenTagsError', function (e: any) {
  console.error(e.detail.errMsg) // 无法使用开放标签的错误原因,需回退兼容。仅无法使用开发标签,JS-SDK其他功能不受影响
  toDownloadApp()
})


总结



又复用就抽离成组件


必须要上生产环境,所以最好是有个预生产环境


参考资料



  • 微信开发社区[4]


  • 使用微信 wx-open-launch-app 标签实现微信网页打开 App 记录[5]


  • 微信开放标签 wx-open-launch-app 样式设置技巧[6]


  • wx-open-launch-weapp 样式问题[7]


[1] 官网文档: https://developers.weixin.qq.com/doc/offiaccount/OA_Web_Apps/Wechat_Open_Tag.html#22


[2] wx-open-launch-weapp 样式问题: https://www.jianshu.com/p/262658b8d19c


[3] Android 接入指南: https://developers.weixin.qq.com/doc/oplatform/Mobile_App/Access_Guide/Android.html


[4] 微信开发社区: https://developers.weixin.qq.com/community/homepage


[5] 使用微信 wx-open-launch-app 标签实现微信网页打开 App 记录: https://juejin.cn/post/7000652887390945294#heading-0


[6] 微信开放标签 wx-open-launch-app 样式设置技巧: https://developers.weixin.qq.com/community/develop/article/doc/0006e4bdccc9d83f8fba292a45b813


[7] wx-open-launch-weapp 样式问题: https://www.jianshu.com/p/262658b8d19c


相关实践学习
基于函数计算一键部署掌上游戏机
本场景介绍如何使用阿里云计算服务命令快速搭建一个掌上游戏机。
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
相关文章
|
2月前
|
存储 小程序 API
【微信小程序】-- uni-app 项目-- 购物车 -- 首页 - 轮播图效果(五十二)
【微信小程序】-- uni-app 项目-- 购物车 -- 首页 - 轮播图效果(五十二)
【微信小程序】-- uni-app 项目-- 购物车 -- 首页 - 轮播图效果(五十二)
|
2月前
|
小程序 开发工具 git
【微信小程序】-- uni-app 项目--- 购物车 -- 配置 tabBar 效果(五十一)
【微信小程序】-- uni-app 项目--- 购物车 -- 配置 tabBar 效果(五十一)
|
2月前
|
存储 小程序 前端开发
基于APP的微信点餐小程序的设计与实现
基于APP的微信点餐小程序的设计与实现
37 3
|
14天前
|
搜索推荐 前端开发 JavaScript
【专栏】从网页轻松转换为应用越来越便捷
【4月更文挑战第27天】本文介绍了将网页转换为移动应用的在线生成App过程,包括原理(封装网页内容,添加移动特性)、优势(便捷高效,节省成本,快速上线)以及具体步骤(选择工具,准备内容,配置选项,生成测试,发布推广)。同时,注意版权、兼容性和用户体验问题。通过案例分析和实践经验分享,帮助读者深入了解如何通过在线工具实现App梦想,强调了网页优化、用户界面设计和个性化定制的重要性。
|
2月前
|
开发框架 移动开发 小程序
【微信小程序】-- 配置uni-app的开发环境(四十八)
【微信小程序】-- 配置uni-app的开发环境(四十八)
|
2月前
|
数据采集 测试技术 API
python爬虫之app爬取-微信朋友圈
搭建appium环境,appium基本使用,API操作等等
95 0
|
1天前
|
Web App开发 数据采集 移动开发
开发uniapp过程中对app、微信小程序与h5的webview调试
开发uniapp过程中对app、微信小程序与h5的webview调试
|
21天前
|
安全 Java Linux
如何实现无公网IP及服务器实现公网环境企业微信网页应用开发调试
如何实现无公网IP及服务器实现公网环境企业微信网页应用开发调试
|
29天前
|
小程序 开发者
【微信小程序】微信开发者工具 app.json: [“subpackages“][0][“root“] 字段需为目录 已解决
【微信小程序】微信开发者工具 app.json: [“subpackages“][0][“root“] 字段需为目录 已解决
13 0
|
2月前
|
小程序 安全 JavaScript
【微信小程序】-- uni-app 项目创建 & 目录结构讲解(四十九)
【微信小程序】-- uni-app 项目创建 & 目录结构讲解(四十九)