💡微信:内置网页登录分享、小程序处理token过期401自动登录方案

276 阅读3分钟

微信内网页

微信内开发网页的注意事项

1.登录

我们要在微信内开发网页,那肯定是需要用到微信登录获取到用户唯一标识符。这就要用到微信提供的网页授权,官方文档步骤写的比较清晰:网页授权官方文档 ,在这里说几点我在项目中使用的方法,因为网页授权是需要跳转到另一个网页,用户点授权后返回的url带回code参数,因此我们需要根据具体的业务需求来确定方法,是必须要登录才能进行操作还是在关键操作下再进行登录。

这里我是采用用户进入就必须登录的方案,首先根据用户本地是否存储过urserinfo,其次判断token是否过期也就是返回值是不是401,如果两者有一个不符合就调用登录方法:

const wxCode = async () => {
  const callbackURL = encodeURIComponent("https://XXXXXX");
  const redirectURI = `https://open.weixin.qq.com/connect/oauth2/authorize?appid=${wechatId}&redirect_uri=${callbackURL}&response_type=code&connect_redirect=1&scope=snsapi_userinfo&state=1#wechat_redirect`;
  window.location.href = redirectURI;
};

appid、redirect_uri这些文档上都有说明,当用户同意授权后,会跳转到callbackURL,并且后面携带code参数,这时我们只要在页面进入时判断url是否有code参数,如果有则执行登录操作

const hasCode = async () => {
  const currentURL = new URL(window.location.href);
  const params = new URLSearchParams(currentURL.search);
  if (params.has("code")) {
    code.value = params.get("code"); // 这里拿到code
    await login(code.value);
  }
};

这个函数放在onMounted周期中执行

2.分享

我们一般希望用户分享出去的内容是我们能控制的,用户点击链接进入我们预想的页面,这里链接地址必须在公众号设置里的JS接口安全域名中进行配置。

这里我使用了weixin-js-sdk库,JS—SDK可以看文档说明:官方文档

// 在组件加载时初始化微信JS-SDK
async function initWechatJS() {
  const wechatConfig = await getWechatConfig(); // 后端获取微信配置信息
  wx.config({
    debug: false, // 是否开启调试模式,调试模式下会输出调试信息
    appId: 'wx000000000000', // 微信公众号的唯一标识
    timestamp: wechatConfig.timestamp, // 生成签名的时间戳
    nonceStr: wechatConfig.nonceStr, // 生成签名的随机串
    signature: wechatConfig.signature, // 签名
    jsApiList: ['onMenuShareAppMessage', 'onMenuShareTimeline'] // 需要使用的JS接口列表
  })
  wx.ready(function () {
    const title = 'XXXXX'
    const link = 'https://XXXXXXXX'
    const imgUrl = ''
    wx.onMenuShareAppMessage({
      title,
      link,
      imgUrl,
      success: async function () {
          // 成功操作
      }
    })
    wx.onMenuShareTimeline({
      title,
      link,
      imgUrl,
      success: async function () {
        ...
      }
    })
  })
}
initWechatJS()
// 调用后端接口获取微信配置信息
async function getWechatConfig() {
  const currentURL = new URL(window.location.href);
  // 发送请求获取微信配置信息,将当前页面的URL作为参数传递给后端
  const response = await getWxAuth(currentURL);
  const data = response.data;
  return data;
}

wechatConfig里面的数据都是由后端返回,JS-SDK里面有详细说明

微信小程序

3.接口401自动登录

我们公司项目为了用户体验设计成自动登录,token又只有一个时效也很短,于是乎我们只能在前端上处理一下啦,在响应拦截里面对401做处理,设计一个队列,并在登录操作时候加锁,当处理完401登录操作之后,对队列中的请求进行再次发送。

这样相当于响应的还是用户之前的操作,让用户能无感登录。具体代码贴下面:

// 使用一个变量来表示是否正在进行登录操作
let isLoggingIn = false
// 用于等待登录完成的队列
const loginQueue = []

// 请求拦截
http.interceptors.request.use(async (config) => {
	if (config.url) {
		if (isLoggingIn && config.url !== '/login') {
			return new Promise((resolve) => {
				loginQueue.push(() => {
					resolve(config)
				})
			})
		}
		...
		return config
	} else {
		http.abort()
	}
})

// 响应拦截
http.interceptors.response.use(async (response) => {
	const code = response.data.code || 200;
	try {
		if (code === 401) {
			// 如果没有在进行登录操作,则执行登录操作
			if (!isLoggingIn) {
				isLoggingIn = true
				await login()
				isLoggingIn = false
				// 登录完成后执行等待队列中的请求
				while (loginQueue.length > 0) {
					const nextRequest = loginQueue.shift()
					nextRequest && await http.request(nextRequest())
				}
			} else {
				return new Promise((resolve) => {
					loginQueue.push(() => {
						resolve(http.request(response.config))
					})
				})
			}
			return http.request(response.config)
		} else {
			return response ? response.data : {}
		}
	} catch (error) {
		...
	}
}, (error) => {
	...
})

这样的处理方案其实不好,还是用双token为妙!