1. 在index.html中引用微信接口JS文件

<script type="text/javascript" src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>

2. 请求后端拿回公众号ID,签名等

这里仅涉及前端请求配置,关于jsapi_ticket获取和签名算法都交给后端处理,前端只需要将当前域名发给后端,来获取签名。
这里有两个需要注意的点:

  1. 一般post请求参数url不需要encodeURIComponent传给后端,因为参数是存放在请求体里的;而如果是get请求,需要encodeURIComponent再传给后端,否则后端没处理的话会读取错误,导致生成的签名失效。
  2. 注意传给后台的url参数是完整域名地址,包括?后的参数。因此需要location.href.split('#')[0])截取#前面的路径,#后面一般都是前端的路由配置。
  3. 还有的是,微信打开H5页面,一般都会强行加上query参数,例如

你的访问的网址

微信展示实际的网址

https://my-web.com

https://my-web.com/?from=singlemessage&isappinstalled=0

https://my-web.com/#/list

https://my-web.com/?from=singlemessage&isappinstalled=0#/list

https://my-web.com/#/user?id=2

https://my-web.com/?from=singlemessage&isappinstalled=0#/user?id=2

可以看到微信会主动加上from=singlemessage&isappinstalled=0参数,isappinstalled=0这参数IOS设备才会添加。而且可以看到有点别扭的感觉,这两个参数直接在hash前面插入了。因为hash后面是前端路由,微信不会主动拼成https://my-web.com/#/user?id=2&from=singlemessage&isappinstalled=0
不管怎样,当你的页面地址是https://my-web.com/?from=singlemessage&isappinstalled=0#/user?id=2,则传url参数https://my-web.com/?from=singlemessage&isappinstalled=0给后台,不然会导致签名失效,也即location.href.split('#')[0]。好了,写了有点啰嗦。

3. 微信接口配置

let result = await getWechatJsApiSign({ url: encodeURIComponent(location.href.split('#')[0]) }); // 请求接口
let data = result.data.data;

wx.config({
    debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
    appId: data.appId, // 必填,公众号的唯一标识
    timestamp: data.timestamp, // 必填,生成签名的时间戳
    nonceStr: data.nonceStr, // 必填,生成签名的随机串
    signature: data.signature,// 必填,签名,见附录1
    jsApiList: [ 'updateAppMessageShareData' ] // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
});

wx.ready(function() {   //需在用户可能点击分享按钮前就先调用
	wx.updateAppMessageShareData({
	   title: 'title', // 分享标题
	   desc: 'desc', // 分享描述
	   link: location.href,
	   imgUrl: "https://my-web.com/images/logo.jpg",
	   success: function () {
	       
	   }
	})
)

配置微信接口以及分享链接,到此就已经实现了。给张图展示一下。

h5 variable 方法 调用android h5调用接口_微信


但是你会发现,不管你分享任意一个页面,从分享链接打开都是跳转到主页面,这就尴尬了。这还是之前hash后面的前端路由问题,微信并不会去主动识别跳转hash后面的路由,也就导致每次从分享链接进入的路由都是"/"。

4. 解决分享链接一直是主页面的问题

我们需要把hash后面的路由通过一个参数存起来,然后自定义分享链接携带这个参数。暂且命名这个参数为shareUrl,当其他用户点击分享链接,判断到路径里有shareUrl这个参数,则重新拼接路径,再location.href跳转

let hashBefore = location.href.split("#")[0],
	path = location.href.split("#")[1];
	
// 自定义链接
let linkUrl = hashBefore.includes('?') ? `${hashBefore}&shareUrl=${path}` : `${hashBefore}?shareUrl=${path}`;

// 例如准备分享的页面为:`https://my-web.com/?from=singlemessage&isappinstalled=0#/item?id=2`;
// 则自定义链接为`https://my-web.com/?from=singlemessage&isappinstalled=0&shareUrl=/item?id=2`


wx.ready(function() { 
	wx.updateAppMessageShareData({
	    title: 'title',
	    desc: 'desc',
	    link: linkUrl,
	    imgUrl: 'https://my-web.com/img/logo.jpg',
	    success: function () {
	        
	    }
	})
)

然后在App.vue(基于vue项目)中

created() {
	if(location.href.includes("shareUrl")) {
		// 注意location.href并不是立刻执行,会继续往下执行代码,再跳转
	     location.href = location.origin+"/#" + util.getParamFromUrl().shareUrl;
     	// 将https://my-web.com/?from=singlemessage&isappinstalled=0&shareUrl=/item?id=2
     	// 拼接成https://my-web.com/#/item?id=2
	     return;
	 }
	 ...
}

完整代码

weixin-api.js 封装微信接口配置工具函数

import { getWechatJsApiSign } from '@/api/api';
import util from '@/utils/index.js';

const weixinApiConfigure = async (params) => {
    if (!util.IsWeixin || location.href.includes("shareUrl")) { // 包含shareUrl,说明分享链接进入的页面,不需要执行下面代码,等下还要跳转
        return;
    }
    
    let paramsData = JSON.parse(JSON.stringify(params || "{}"));
    const { title, desc, path="/", imgUrl, apiList=[ 'updateAppMessageShareData' ], disabledWeixinConfig=false } = paramsData;

    if (disabledWeixinConfig) {
        return;
    }
    
    let hasApi = {};
    for (let item of apiList) {
        hasApi[item] = true;
    }
    
    // 有配置信息就从本地保存拿,没有就从后台拿
    let data = sessionStorage.getItem("WechatJsApiSign");
    if (!data) {
        let res = await getWechatJsApiSign({ url: encodeURIComponent(location.href.split('#')[0]) });
        data = res.data.data;
        sessionStorage.setItem("WechatJsApiSign", JSON.stringify(data));
    } else {
        data = JSON.parse(data);
    }

    let wx = window.wx;

    wx.config({
        debug: false, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
        appId: data.appId, // 必填,公众号的唯一标识
        timestamp: data.timestamp, // 必填,生成签名的时间戳
        nonceStr: data.nonceStr, // 必填,生成签名的随机串
        signature: data.signature,// 必填,签名,见附录1
        jsApiList: apiList // 必填,需要使用的JS接口列表,所有JS接口列表见附录2
    });
    if (hasApi.updateAppMessageShareData) {
        /* 微信分享链接#后面的路径都失效的问题,也即分享链接只能跳转到主页
         * 例子:https://my-web.com/?from=singlemessage&isappinstalled=0#/items/detail/1181000
         *  ?from=singlemessage&isappinstalled=0 这是微信加上去的参数,而且分享链接中不能去掉
         * 前端定义个分享url的参数shareUrl,存放#后面的路径
         */

        let hashBefore = location.href.split("#")[0];

        let linkUrl = hashBefore.includes('?') ? `${hashBefore}&shareUrl=${path}` : `${hashBefore}?shareUrl=${path}`;

        wx.ready(function() {   //需在用户可能点击分享按钮前就先调用

            wx.updateAppMessageShareData({
                title: title || '默认', // 分享标题
                desc: desc || '默认', // 分享描述
                link: linkUrl, 
                imgUrl: imgUrl || 'https://my-web.com/images/logo.jpg', // 分享图标
                success: function () {
                    
                }
            })
        });
    }

    if (hasApi.hideAllNonBaseMenuItem) {
        wx.hideAllNonBaseMenuItem();
    }

    wx.error(function(res) {
        sessionStorage.setItem("WechatJsApiSign", "");
    });
}

export default weixinApiConfigure;

在vue路由守卫中,为每个路由页面配置微信接口

import weixinApiConfigure from '@/utils/weixin-api.js';

const routes = [
    {
        path: '/order',
        name: 'cart',
        meta: {
            weixinConfig: { apiList: ["hideAllNonBaseMenuItem"] }
        },
        components: {
            default: () => import('@/views/order/cart')
        }
    },
    ...
]

const RouterModel = new Router({ routes });

RouterModel.afterEach((to, from) => {
    weixinApiConfigure({
        ...to.meta.weixinConfig,
        path: to.path
    });
})