首次做一个公众号网页项目,难免会有一些磕磕碰碰,但项目进展还算顺利,在此记录一下。
我用的框架是Vue。其实开发公众号里面的页面和其他移动端页面(h5)并没有多大不同,和平常是一样的开发方式。不同的地方主要是用户授权、鉴权和一些微信提供的接口 如分享给朋友、到朋友圈设置等。
微信授权有两种,1)一种是静默授权,用户基本无感,能获取到code再获取openId,从而识别用户,2)打开微信授权页面,用户手动同意,还可以获取到用户基本信息。关于微信公众号网页授权的详细,可查看文档
由于项目只需要识别用户,所以静默授权就可以满足项目需求。
https://open.weixin.qq.com/connect/oauth2/authorize?appid=你的公众号appid&redirect_uri=授权成功后的重定向地址&response_type=code&scope=snsapi_base&state=123#wechat_redirect
静默授权就是请求一个授权链接,请求之后会回到你在授权链接里填的重定向地址,该地址上就携带了code.
redirect_uri/?code=CODE
我们的业务逻辑大概是这样的:
1.我们用来鉴权的access_token是存在cookies中的,这个方法我们会调用多次可以封装起来,从而复用。
//设置cookies
setCookie(cname, cvalue, exdays, path = '/') {
const date = new Date();
date.setTime(date.getTime() + exdays * 24 * 60 * 60 * 1000);
const expires = `expires=${date.toGMTString()}`;
document.cookie = `${cname}=${cvalue}; ${expires}; path=${path}`;
}
//获取cookies
getCookie(cname) {
const name = `${cname}=`;
const cookies = document.cookie.split(';');
for (let i = 0; i < cookies.length; i += 1) {
const cookie = cookies[i].trim();
if (cookie.indexOf(name) === 0) {
return cookie.substring(name.length, cookie.length);
}
}
return '';
}
2.进入页面先判断有没有token,有token且token有效,就去获取用户相关数据,并进行其他操作。token是否有效字段我是通过localStorage存储和改变的,这里面有个小细节需要注意下,token是否有效的字段值我期望是布尔类型,但localStorage都会转为字符串,所以如果判断的时候不JSON.parse解析下,判断的时候就会出问题,因为字符串中除了空字符串其他转化为布尔类型都是true。当然在vue中你也可以使用vuex存放在store中,再通过一些插件把store中数据缓存在本地。
3.没有token或token失效 且没有code就去请求授权接口。这里也有个问题出现了,项目中我们用axios来发送ajax请求比较多,但是一开始我用aixos.get去请求,一直有问题,一时也找不出原因,最后放弃,通过window.loacation.href 去访问授权链接。
4.获取到code后,使用code去调后端接口获取token,写入cookies, 进行其他业务操作。获取url上参数的方法有可能多次调用,我们也可以简单封装下。
getQueryString(name) {
const reg = new RegExp(`(^|&)${name}=([^&]*)(&|$)`);
const r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]);
return null;
}
//先判断有没有token
//vue中可以在created生命周期钩子中
const token = utils.getCookie('X-Access-Token') || '';
const code = utils.getQueryString('code');
const tokenValid = localStorage.getItem('tokenValid') || 'true';
if (token && tokenValid === 'true') {
进行业务操作操作
} else if ((!token || tokenValid === 'false') && !code) {
//token不存在或无效且没有code就去调微信授权获取code
const url = encodeURIComponent(window.location.href);
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${url}&response_type=code&scope=snsapi_base#wechat_redirect`
} else if (code) {
//code存在 用code去调后台登陆接口 获取并更新token
this._login(code).then(进行业务操作)
}
5.token失效的时候后端会统一报一个错误状态码,在axios响应错误拦截处,判断失效状态码,把token是否有效字段更新为失效并调微信授权接口重新授权。
const fetch = Axios.create({
withCredentials: false,
baseURL,
timeout: 20000,
});
// 添加响应拦截器
fetch.interceptors.response.use(function (response) {
//token有效
localStorage.setItem('tokenValid', true)
return response;
}, function (error) {
// 对响应错误做点什么
const { status, data } = error.response;
switch (status) {
case 403:
router.push('/register');
window.toast(data.error.message);
break;
case 401:
case 412:
//token字段设为无效
localStorage.setItem('tokenValid', false)
const url = encodeURIComponent(window.location.href);
// 重新授权
window.location.href = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${appId}&redirect_uri=${url}&response_type=code&scope=snsapi_base#wechat_redirect`
break;
default:
window.toast(data.error.message)
return Promise.reject(data);
}
});
授权相关基本上就上面那些了。如果我们公众号项目中还需要用到微信提供的js-sdk的话,需要进行一些额外操作。
1.首先你的项目域名必须要先在微信公众平台进行绑定,否则无法使用js-sdk;
2.引入js文件。vue项目的话,在public目录下面index.html文件中通过script标签引入就可以了。
//http https都可以
<script charset="utf-8" src="https://res.wx.qq.com/open/js/jweixin-1.4.0.js"></script>
3.在使用的地方进行相应配置。config里面的签名参数,由后端去获取返回。获取签名参数的url必须为当前页面的url,分享链接可以是其他页面的URL。
wx.config({
debug: true, // 开启调试模式
appId: 'xxx', // 必填,公众号的唯一标识
timestamp: that.signInfo.timestamp, // 必填,生成签名的时间戳
nonceStr: that.signInfo.noncestr, // 必填,生成签名的随机串
signature: that.signInfo.sign,// 必填,签名
jsApiList: ['updateAppMessageShareData', 'updateTimelineShareData'] // 必填,需要使用的JS接口列表
});
wx.ready(function(){
wx.updateAppMessageShareData({
title: '邀请好友,赢万元红包', // 分享标题
desc: '新用户提交资料注册成功即可获得万元购物红包', // 分享描述
link: that.shareUrl, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: `${that.imgDomain}FlJfZ0rFuXGAeoYprsy735GZTzaB`, // 分享图标
success: function () {
window.toast('分享成功', 'txt')
that.showImg = false;
}
})
wx.updateTimelineShareData({
title: '邀请好友,赢万元红包', // 分享标题
link: that.shareUrl, // 分享链接,该链接域名或路径必须与当前页面对应的公众号JS安全域名一致
imgUrl: `${that.imgDomain}FlJfZ0rFuXGAeoYprsy735GZTzaB`, // 分享图标
success: function () {
window.toast('分享成功', 'txt')
that.showImg = false;
}
})
})
我们项目中分享功能当用户通过分享链接进来,邀请人是能获得相应奖励的。那如何获知用户是通过谁邀请进来的呢?其实很简单,用户在邀请的时候,把该用户标识拼接在分享链接上。其他人通过分享链接进入,获取链接上的用户标识就知道是谁邀请的了。
分享这里也踩了个坑,按照文档使用新的api,updateAppMessageShareData,updateTimelineShareData, IOS分享自定义设置是可以的,但是安卓不起作用,折腾了一会儿,最后换成旧的api, onMenuShareTimeline, onMenuShareAppMessage就可以了。