准备工作
在本地开发时,你可以先申请一个 测试公众号,并且将JS接口安全域名设置为 127.0.0.1 申请地址
找到网页授权获取用户信息这一项,点击修改之后填入 127.0.0.1
特别说明
这里需要配置的是ip或者域名,切记不要添加 http:// 或者 https://
实现逻辑
第一步:用户同意授权,获取 code 。如果用户同意授权,页面将跳转至 redirect_uri/?code=CODE&state=STATE。
第二步:通过 code 换取网页授权 access_token。
第三步:刷新 access_token(如果需要)
第四步:拉取用户信息(需scope为 snsapi_userinfo)
以下是封装后的代码
import router from "../routerConfig";
import { axiosPost } from "../api";
/*微信登录相关 start*/
const APP_ID = 'xxx'
//方法:用来判断是否是微信内置的浏览器
export function isWechat() {
return String(navigator.userAgent.toLowerCase().match(/MicroMessenger/i)) === "micromessenger";
}
//方法:用来提取code
export function getUrlCode(name) {
return (
decodeURIComponent(
(new RegExp("[?|&]" + name + "=" + "([^&;]+?)(&|#|;|$)").exec(
location.href
) || [, ""])[1].replace(/\+/g, "%20")
) || null
);
}
//检查浏览器地址栏中微信接口返回的code
export function checkWeChatCode() {
// 如果没有code,则跳转到微信授权页面
let code = getUrlCode('code')
if (code) {
getOpenidAndUserinfo(code)
} else {
getWeChatCode()
}
}
//请求微信接口,用来获取code
export function getWeChatCode() {
const local = encodeURIComponent(window.location.href); //获取当前页面地址作为回调地址
let appid = APP_ID
//通过微信官方接口获取code之后,会重新刷新设置的回调地址【redirect_uri】
window.location.href =
"https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
appid +
"&redirect_uri=" +
local +
"&response_type=code&scope=snsapi_base&state=" +
encodeURIComponent(
JSON.stringify({
p: "/auth"
})) + "#wechat_redirect";
}
//把code传递给后台接口,静默登录
export function getOpenidAndUserinfo(code) {
axiosPost('/pWechatUser/loginByCode', {
code
}).then(async ({ retData }) => {
if (retData.retCode === 100) {
// 用户不存在,创建用户
showToast({ message: '当前微信未绑定用户,正在跳转到登录页面', wordBreak: 'break-all' })
setTimeout(() => {
router.push(`/login/${retData.retMessage}`)
}, 1000)
} else {
localStorage.setItem('token', retData)
router.replace({
path: '/home'
})
const { retData: userinfo } = await axiosPost('/pWechatUser/getUserInfo')
localStorage.setItem('userInfo', JSON.stringify(userinfo))
}
})
}
本地开发注意事项
在本地调试时,你需要将你的项目开启使用ip访问,例如 http://127.0.0.1:5173 而不是 http://localhost:5173
开启方法以vite为例:
export default defineConfig({
base: './',
server: {
// 开启ip访问
host: "0.0.0.0",
},
}
vue-router hash模式问题
vue-router默认hash模式下,页面的url都带有#,但微信授权的回调地址不能有#,所以要进行一些处理
// 在配置授权链接时,先传入回调地址的路由path
export function getWeChatCode() {
const local = encodeURIComponent(window.location.href); //获取当前页面地址作为回调地址
let appid = APP_ID
//通过微信官方接口获取code之后,会重新刷新设置的回调地址【redirect_uri】
window.location.href =
"https://open.weixin.qq.com/connect/oauth2/authorize?appid=" +
appid +
"&redirect_uri=" +
local +
"&response_type=code&scope=snsapi_base&state=" +
encodeURIComponent(
JSON.stringify({
p: "/auth"
})) + "#wechat_redirect";
}
然后在vue-router的路由守卫中添加如下代码
router.beforeEach((to, from) => {
if (replaceWechatRedirectUri()) return false;
});
function getQueryVariable(variable) {
const query = window.location.search.substring(1);
const vars = query.split('&');
for (let i = 0; i < vars.length; i++) {
const pair = vars[i].split('=');
if (pair[0] === variable) {
return pair[1];
}
}
return (false);
}
/**
* 处理微信授权回调redirect_uri
*/
function replaceWechatRedirectUri() {
const w = location.href.indexOf('?');
const j = location.href.indexOf('#');
if (w !== -1 && j > w && getQueryVariable('state')) {
const state = getQueryVariable('state').split('#')[0];
const redirect_path = JSON.parse(decodeURIComponent(state)).p;
const url =
location.origin +
'/[多级目录路径]/#' +
redirect_path +
`?code=${getQueryVariable('code')}&state=${state}`;
location.replace(url);
return true;
}
这样在授权后回到我们的应用时,就不会出现类似 https://xxx.com/auth?code=xxxxxx#/auth 这样的路径了