要禁用微信分享功能,或者设置微信分享等其他功能,需要用到微信js-sdk。
微信JS-SDK介绍
微信JS-SDK是微信公众平台面向网页开发者提供的基于微信内的网页开发工具包。
也就是说,我们可以调用微信JS-SDK中的一些API,来调用微信中的一些功能,比如使用拍照、选图、语音、位置等手机系统的功能,同时也可以直接使用微信分享、扫一扫、卡券、支付等微信特有的能力。
微信JS-SDK的使用步骤
1. 先登录微信公众平台进入“公众号设置”的“功能设置”里填写“JS接口安全域名”
2. 引入JS-SDK的文件
// 安装js-sdk依赖包
npm install weixin-js-sdk --save
复制代码// 在文件中引入
import wx from 'weixin-js-sdk';
复制代码
3. 通过config接口注入权限验证配置
⚠️ 所有需要使用JS-SDK的页面必须先注入配置信息,否则将无法调用(同一个url仅需调用一次,对于变化url的SPA的web app可在每次url变化时进行调用,目前Android微信客户端不支持pushState的H5新特性,所以使用pushState来实现web app的页面会导致签名失败)。
wx.config({
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp: , // 必填,生成签名的时间戳
nonceStr: '', // 必填,生成签名的随机串
signature: '',// 必填,签名
jsApiList: [] // 必填,需要使用的JS接口列表
});
复制代码
可以看出,config方法需要传入以上几个参数。appId这个参数是开发微信公众号的必备物料,需要提前准备好。接下来,我们需要自己生成签名的时间戳timestamp,生成签名的随机串nonceStr,和生成签名signature。
4. 通过ready接口处理成功验证
wx.ready(function(){
// config信息验证后会执行ready方法,所有接口调用都必须在config接口获得结果之后,config是一个客户端的异步操作,所以如果需要在页面加载时就调用相关接口,则须把相关接口放在ready函数中调用来确保正确执行。对于用户触发时才调用的接口,则可以直接调用,不需要放在ready函数中。
});
复制代码
5. 通过error接口处理失败验证
wx.error(function(res){
// config信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名。
});
复制代码
在开始封装微信配置方法之前,我们需要先了解一下微信签名的算法。
JS-SDK使用权限签名算法
我们这边是服务端提供了一个接口去获取jsapi_ticket。
签名算法
签名生成规则:参与签名的字段包括noncestr(随机字符串), 有效的jsapi_ticket, timestamp(时间戳), url(当前网页的URL,不包含#及其后面部分) 。对所有待签名参数按照字段名的ASCII 码从小到大排序(字典序)后,使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串string1。所有参数名均为小写字符。对string1作sha1加密,字段名和字段值都采用原始值,不进行URL 转义。即signature=sha1(string1)。
下面,根据以上规则,我们开始封装微信配置方法。
封装微信配置方法
// wxconfig.js
// 引入微信js-sdk
import wx from 'weixin-js-sdk';
// 引入获取jsapi_ticket 的服务端接口
import { getWechatApiTicket } from '@/api/';
// 引入加密方法
import sha1 from 'js-sha1';
// 获取微信jsapi-ticket,我们这边是服务端提供接口获取的
function getTicket(){
return getWechatApiTicket().then((res) => res.data);
}
// 生成时间戳
function generateTimestamp(){
return Date.parse(new Date()) / 1000;
}
// 生成随机字符串
function generateNoncestr(){
const n = 17;
let nonceStr = '';
const str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
const len = str.length;
for (let i = 0; i < n; i += 1) {
const rand = Math.floor(Math.random() * len);
nonceStr += str.charAt(rand);
}
return nonceStr;
}
// 生成签名
function generateSignature(ticket, noncestr, timestamp){
const obj = {
jsapi_ticket: ticket,
noncestr,
timestamp,
url: window.location.href.split('#')[0],
};
let str = '';
Object.keys(obj).forEach((k) => {
str += `&${k}=${obj[k]}`;
});
return sha1(str.slice(1));
}
// 微信配置方法
async function initWechatConfig(){
const ticket = await getTicket();
const timestamp = generateTimestamp();
const nonceStr = generateNoncestr();
const signature = generateSignature(ticket, nonceStr, timestamp);
const config = {
debug: true, // 开启调试模式,调用的所有api的返回值会在客户端alert出来,若要查看传入的参数,可以在pc端打开,参数信息会通过log打出,仅在pc端时才会打印。
appId: '', // 必填,公众号的唯一标识
timestamp, // 必填,生成签名的时间戳
nonceStr, // 必填,生成签名的随机串
signature, // 必填,签名
jsApiList: ['hideAllNonBaseMenuItem'], // 必填,需要使用的JS接口列表
};
wx.config(config);
// 通过ready接口处理成功验证
wx.ready(() => {
// config信息验证成功后会执行ready方法,所有接口调用都必须在config接口获得结果之后
// config 是一个客户端的异步操作,所以如果需要在页面加载时调用相关接口,
// 则须把相关接口放在ready函数中调用来确保正确执行.对于用户触发是才调用的接口,则可以直接调用,不需要放在ready函数中
// 判断当前客户端版本是否支持指定JS接口
wx.checkJsApi({
jsApiList: [
'hideAllNonBaseMenuItem',
],
success: (res) => {
// 以键值对的形式返回,可用true,不可用false。如:{"checkResult":{"scanQRCode":true},"errMsg":"checkJsApi:ok"}
if (res.checkResult.hideAllNonBaseMenuItem === true) {
// 隐藏所有非基础按钮接口
wx.hideAllNonBaseMenuItem();
} else {
console.log('当前客户端不支持隐藏非接口功能');
}
},
fail: (err) => { // 检测getNetworkType该功能失败时处理
console.log(`fail:${err}`);
},
});
});
// 通过error接口处理失败验证
wx.error((err) => {
// config 信息验证失败会执行error函数,如签名过期导致验证失败,具体错误信息可以打开config的debug模式查看,也可以在返回的res参数中查看,对于SPA可以在这里更新签名
console.log(`配置验证失败:${err.errMsg}`);
});
}
export default initWechatConfig;
复制代码
调用微信配置方法
单页应用需要在url变化时调用wx.config,所以对于这种公共的一些js配置功能,我们可以在全局的钩子函数beforeEach中处理微信的初始化配置。
import initWechatConfig from '@/utils/wxconfig';
import { Toast } from 'vant';
...
router.beforeEach(async (to, from, next) => {
// isWeChat是一个判断是否在微信浏览器的方法
const isweChat = () => {
const ua = window.navigator.userAgent.toLowerCase();
// eslint-disable-next-line eqeqeq
if (ua.match(/MicroMessenger/i) == 'micromessenger') {
return true;
}
return false;
};
// 判断是否是微信浏览器
if (!isweChat()) {
Toast('请在微信中打开');
return;
}
// 调用微信配置方法
await initWechatConfig();
next();
});
复制代码