前两天有个需求,进入页面授权登录【公众号A】,判断该微信用户是否关注该公众号,如果已关注则再授权【公众号B】,如果未关注则提示用户关注【公众号A】。是不是听起来还挺简单的,当时给的领导的工作量是0.5/人天,万万没想到最后搞了很久,妥妥的踩了个深坑(苦笑)。
😂
以下代码是最开始的错误处理方式:
// 获取地址栏url参数code
var code = getQueryString(window.location.href, 'code');
// 授权登录
function authorize () {
$loading.show()
return new Promise((resolve) => {
if (code == null || code == ''){
// 【公众号A】授权登录
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + configUrl[evn].huishangAppId + "&redirect_uri=" + encodeURIComponent(window.location.href) + "&response_type=code&scope=snsapi_base&state=2&connect_redirect=1#wechat_redirect"
}
$.ajax({
url: configUrl[evn].h5Url + '/api/wx/userInfo',
type: 'POST',
contentType: 'application/json',
dataType: "json",
data: code,
success: function (res) {
if (res.code == 200) {
if (res.subscribe === true) { // 已关注【公众号A】
// 【公众号B】授权登录
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + configUrl[evn].appid + "&redirect_uri=" + encodeURIComponent(window.location.href) + "&response_type=code&scope=snsapi_base&state=2&connect_redirect=1#wechat_redirect";
$.ajax({
url: configUrl[evn].rootUrl + '/weChat/authorize',
type: 'POST',
contentType: 'application/json',
dataType: "json",
data: JSON.stringify({
"code": code
}),
success: function (res) {
console.info("授权返回:" + res.toString())
if (res.resultCode !== "00000") {
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + configUrl[evn].appid + "&redirect_uri=" + encodeURIComponent(window.location.href) + "&response_type=code&scope=snsapi_base&state=2&connect_redirect=1#wechat_redirect"
}
if (code === "0019Je1h0ZSlLw1dtpZg0E7h1h09Je1y") {
resolve({
openId: "oaiFL6MDdsT7GThvKLo22NGhSNt4",
huishangOpenId: window.sessionStorage.getItem("huishang_openId"),
subscribe: window.sessionStorage.getItem("huishang_subscribe")
});
openId = "oaiFL6MDdsT7GThvKLo22NGhSNt4";
setCache('openId', "oaiFL6MDdsT7GThvKLo22NGhSNt4");
} else {
resolve({
openId: res.data,
huishangOpenId: window.sessionStorage.getItem("huishang_openId"),
subscribe: window.sessionStorage.getItem("huishang_subscribe")
});
openId = res.data;
setCache('openId', res.data)
}
}
});
} else { // 未关注【公众号A】
$toast("未关注公众号A,请关注公众号再领券哦!");
}
} else {
$toast("获取公众号授权信息错误");
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + configUrl[evn].huishangAppId + "&redirect_uri=" + encodeURIComponent(window.location.href) + "&response_type=code&scope=snsapi_base&state=2&connect_redirect=1#wechat_redirect"
}
}
});
$loading.hide()
});
}
//截取url参数
function getQueryString (url, par) {
var arr1 = url.split('?');
if (arr1.length >= 2) {
var arr2 = arr1[1].split('&')
var obj = {}
arr2.forEach(v => {
var arr3 = v.split('=')
if (arr3.length >= 2) {
obj[arr3[0]] = arr3[1]
} else {
obj[arr3[0]] = ''
}
})
return obj[par] || ''
} else {
return ''
}
}
以上代码存在一下几点问题:
授权【公众号A】时使用的window.location.href方式授权登录,后面的ajax代码块会被执行,导致取不到code,code为null。(window.location.href 控制页面跳转的时候,会等当前宏任务走完再跳转。也就是说,控制跳转代码后面的同步代码会执行,Promise 创建的微任务也会执行。(但 setTimeout 创建的任务就不会执行))
授权【公众号A】成功之后,再授权【公众号B】时回调地址有问题:&redirect_uri=" + encodeURIComponent(window.location.href),这里的window.location.href地址会带有【公众号A】回调的code,导致地址栏会出现多个重复参数。
在授权【公众号B】时,会重新刷新页面,代码又重新被执行,导致页面不停被刷新。
以下代码解决的方法:
// 获取地址栏url参数code的值
var code = getQueryString(window.location.href, 'code');
// 获取地址栏url参数id的值
var id = getQueryString(window.location.href, 'id');
// 获取地址栏url参数state的值
var state = getQueryString(window.location.href, 'state')
var redirect_uri = `https://baidu.com/index.html?id=${id}`
// 授权登录
function authorize() {
$loading.show()
return new Promise((resolve) => {
if (code == null || code == ''){
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + configUrl[evn].huishangAppId + "&redirect_uri=" + encodeURIComponent(window.location.href) + "&response_type=code&scope=snsapi_base&state=1&connect_redirect=1#wechat_redirect"
}
if (code && state != 2 ){
$.ajax({
url: configUrl[evn].h5Url + '/api/wx/userInfo',
type: 'POST',
contentType: 'application/json',
dataType: "json",
data: code,
success: function (res) {
if (res.code == 200) {
window.sessionStorage.setItem('huishang_openId', res.openid)
window.sessionStorage.setItem('huishang_subscribe', res.subscribe)
if (res.subscribe == true) {
window.location.replace("https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + configUrl[evn].appid + "&redirect_uri=" + encodeURIComponent(redirect_uri) + "&response_type=code&scope=snsapi_base&state=2&connect_redirect=1#wechat_redirect")
} else {
$toast("未关注公众号A,请关注公众号再领券哦!");
resolve({
openId: "",
huishangOpenId: res.openid,
subscribe: res.subscribe
});
}
} else {
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + configUrl[evn].huishangAppId + "&redirect_uri=" + encodeURIComponent(redirect_uri) + "&response_type=code&scope=snsapi_base&state=1&connect_redirect=1#wechat_redirect"
}
}
});
} else if (code != null && code != "" && state == 2) {
$.ajax({
url: configUrl[evn].rootUrl + '/weChat/authorize',
type: 'POST',
contentType: 'application/json',
dataType: "json",
data: JSON.stringify({
"code": code
}),
success: function (res) {
console.info("授权返回:" + res.toString())
if (res.resultCode !== "00000") {
window.location.href = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + configUrl[evn].appid + "&redirect_uri=" + encodeURIComponent(redirect_uri) + "&response_type=code&scope=snsapi_base&state=2&connect_redirect=1#wechat_redirect"
}
if (code === "0019Je1h0ZSlLw1dtpZg0E7h1h09Je1y1") {
resolve({
openId: "oaiFL6MDdsT7GThvKLo22NGhSNt41",
huishangOpenId: window.sessionStorage.getItem("huishang_openId"),
subscribe: window.sessionStorage.getItem("huishang_subscribe")
});
openId = "oaiFL6MDdsT7GThvKLo22NGhSNt14";
setCache('openId', "oaiFL6MDdsT7GThvKLo22NGhSNt14");
} else {
resolve({
openId: res.data,
huishangOpenId: window.sessionStorage.getItem("huishang_openId"),
subscribe: window.sessionStorage.getItem("huishang_subscribe")
});
openId = res.data;
setCache('openId', res.data)
}
}
});
}
$loading.hide()
});
}
//截取url参数
function getQueryString (url, par) {
var arr1 = url.split('?');
if (arr1.length >= 2) {
var arr2 = arr1[1].split('&')
var obj = {}
arr2.forEach(v => {
var arr3 = v.split('=')
if (arr3.length >= 2) {
obj[arr3[0]] = arr3[1]
} else {
obj[arr3[0]] = ''
}
})
return obj[par] || ''
} else {
return ''
}
}