H5微信公众号静默网页授权,本地调试及上线
1、前言
企业服务平台有一个h5端的需求,需要用到微信静默授权来实现用户无感登录。
2、工具
既然在本地调试,那自然少不了微信开发者工具了,对,没错,就是那个微信开发者工具。这玩意是微信公众号官方推出来的一款专门给用户制作微信小程序小游戏和公众号的软件。
概念: 用户在
微信客户端中访问第三方网页,公众号可以通过微信网页授权机制,来获取用户基本信息,进而实现业务逻辑。
题外话: 每个用户在不同的公众号openid不同。如果需要在多个公众号统一用户的账号的话,就需要UnionID,在这里配。同一用户,对同一个微信开放平台下的不同应用,unionid是相同的。
3、流程
🔴 微信开发者工具
前期我们需要在本地进行调试,也就是在微信开发者工具里面调试。下载完成之后,打开软件出现二维码:
微信扫码进去。
手机端出现是否确定登录微信开发者工具,点击确认登录进去。
进来,点击公众号网页项目进去,
🔴 网页授权解剖
我们来看一下文档网页授权这块,文档当中提及两种授权,
一种是不弹出授权页面,直接跳转,就能获取用户openid(scope为snsapi_base),
另外一种是弹出授权页面,可通过openid拿到昵称、性别、所在地。并且呢,即使在未关注的情况下,只要用户授权,也能获取这个用户相关信息。
1、scope=snsapi_base(静默,无感知):
以snsapi_base为scope发起的网页授权,是用来获取进入页面的用户的openid的,并且是静默授权并自动跳转到回调页面。 [用户感知的就是直接进入回调页(往往是业务页面)]
2、snsapi_userinfo(弹框,需要用户手动同意):
以snsapi_userinfo为scope发起的网页授权,是用来获取用户的基本信息的。 [需要用户手动同意,无需关注,用户同意授权给我们去拿他们的相关基本信息]
至于第3种就是需要用户关注了公众号之后,才能得到用户的openid去得到用户的一些基本信息的,这里只讲前面两种。
无论是上面1还是2,都需要条件为已认证服务号,需要引导用户打开地址。
注意:
如果在地址栏中输入https://open.weixin.qq.com/connect/oauth2/authorize?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect这个地址,直接提示改链接无法访问的话,解决(1、看参数正确与否,2、看认证没认证,也就是scope参数授权作用域权限有没有)。
🔴 链接格式
1、静默授权snsapi_base:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=这个公众号的appid&redirect_uri=后端跳转拿code接口地址&response_type=code&scope=snsapi_base&state=123#wechat_redirect
2、弹窗用户同意授权 snsapi_userinfo:
https://open.weixin.qq.com/connect/oauth2/authorize?appid=这个公众号的appid&redirect_uri=后端跳转拿code接口地址&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect
| 参数 | 说明 |
|---|---|
| appid | 公众号的appid |
| redirect_uri | 授权后重定向的回调链接地址,使用urlEncode处理 |
| response_type | 返回类型,就填code就可以了 |
| scope | 两个,上面👆讲过,一个静默snsapi_base,一个需同意snsapi_userinfo |
| state | 重定向会带上state参数,可填a-zA-Z0-9 |
| #wechat_redirect | 必带 |
到最后会跳转到
redirect_uri/?code=CODE&state=STATE我们做这些授权的目的就是为了得到code,code这个玩意就是得到access_token的敲门砖,code每次授权都不一样,每次的code只能使用一次,5分钟过期
4、沙盒测试(本地调试)
🔴 配置公众号平台测试账号
在【设置与开发】-【开发者工具】-【公众平台测试账号】,点进去。
这里呢,微信官方为我们提供了一个测试号,我们本地调试的话,先这个测试号来调网页授权功能。后期部署到线上,再换成我们自己这个公众号的appid和配置线上后端的域名,这是后面本地调试没问题了,再放到线上到这一步。
测试号的appid和appsecret,到后面有用:
你就看到这里就行了,其他的不用管,看到网页服务-网页账号那里,去授权网页授权获取用户基本信息。
点击修改,进去网页授权域名填写,就是你希望跳转的地址的域名,这里本地调试可以填ip:port (ip:端口)这样。本地开发不用域名,当然如果你host映射重定向到一个域名(这种就是简单东西复杂化)也不是不行,就是没必要。
做完这些配置,就到代码部分了。
🔴 代码
前端新建一个用户需要授权的loading页面:
代码如下:
js
复制代码<script setup lang="ts" name="LoadingPage">
import { wxLogin as wxLoginApi } from "~/api/login";
import { AES_ECB_DECRYPT } from "~/utils/crypto";
const WX_AUTHORIZE_URL = "https://open.weixin.qq.com/connect/oauth2/authorize";
const APP_ID = import.meta.env.VITE_WX_APPID;
const REDIRECT_URI = encodeURIComponent(import.meta.env.VITE_WX_REDIRECT_URL);
const SCOPE = "snsapi_base";
const STATE = "123";
const HOME_PAGE_PATH = import.meta.env.VITE_HOME_PAGE_PATH;
const router = useRouter();
const token = useAuthorization();
const loading = ref(true);
const redirectToWxAuth = (state?: string) => {
window.location.href = `${WX_AUTHORIZE_URL}?appid=${APP_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=${SCOPE}&state=${state}#wechat_redirect`;
};
const isEnvWeixin = () => {
const ua = navigator.userAgent.toLowerCase();
const isWXWork = ua.match(/wxwork/i)?.[0] === "wxwork";
const isWeixin =
!isWXWork && ua.match(/MicroMessenger/i)?.[0] === "micromessenger";
return isWeixin;
};
// const jump2Auth = () => {
// if (import.meta.env.MODE === "development") {
// // 给当前地址添加添加一个query : ?code = test
// history.pushState({}, "", `?code=test`);
// // 刷新页面
// window.location.reload();
// } else {
// window.location.href = `${WX_AUTHORIZE_URL}?appid=${APP_ID}&redirect_uri=${REDIRECT_URI}&response_type=code&scope=${SCOPE}&state=${STATE}#wechat_redirect`;
// }
// };
const wxLogin = async (wxCode: string) => {
const { code, data } = await wxLoginApi({
code: wxCode
});
if (code === "200") {
const result = JSON.parse(AES_ECB_DECRYPT(data));
if (result.token) {
token.value = result.token;
router.replace(HOME_PAGE_PATH);
}
} else {
// 生成四位数的随机数
const randomNum = `${Math.floor(Math.random() * 9000) + 1000}`;
redirectToWxAuth(randomNum);
// router.replace({
// path: "/login",
// query: {
// code: wxCode
// }
// });
// showNotify({ type: "danger", message: msg });
}
};
const getQueryCode = () => {
const params = new URLSearchParams(window.location.search);
const code = params.get("code");
return code;
};
const getQueryState = () => {
const params = new URLSearchParams(window.location.search);
const state = params.get("state");
return state;
};
const redirectToLoginWithCode = (code: string) => {
router.replace({
path: "/login",
query: {
code
}
});
};
const redirectToLogin = () => {
router.replace({
path: "/login"
});
};
onBeforeMount(() => {
if (isEnvWeixin()) {
const code = getQueryCode();
const state = getQueryState();
console.log(
"%c [ code ]-94",
"font-size:13px; background:pink; color:#bf2c9f;",
code
);
console.log(
"%c [ state ]-95",
"font-size:13px; background:pink; color:#bf2c9f;",
state
);
if (code && state === STATE) {
wxLogin(code);
return;
}
if (code && state !== STATE) {
redirectToLoginWithCode(code);
return;
}
redirectToWxAuth(STATE);
return;
}
redirectToLogin();
});
</script>
<template>
<div class="w-full h-full flex justify-center items-center">
<van-loading v-if="loading" color="#1989fa" />
</div>
</template>
<style scoped></style>
获取token的过程:
获取code后,请求以下链接获取access_token:
请求这个接口
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
传参是 appid、secret、code、grant_type写authorization_code。
最后得到的json数据就是下面👇这个:
具体页面代码是这样的:
🔴 效果
5、上线
此文讲的是本地调试怎么调,上线之后呢,我们就换,appid要换,把测试appid换成线上公众号appid(后台拿),网页授权域名要加(在【设置与开发】-【公众号设置】-【功能设置】-【网页授权域名】那里改成我们线上的域名,一个月只能改5次,可加两个域名)。
6、总结
没有太多花里胡哨的东西,就是通过code拿token,code怎么来,code通过跳转得来,这就完事了。