微信开发工具——进行网页授权
微信公众平台设置
1.在首页创建好自己的订阅号
网站:https://mp.weixin.qq.com/
点击立即注册,在选择订阅号(个人创建使用)
之后按流程填写后,点击设置与开发-------->基本配置,这里可以通过点击成为开发人员(我显示的是已经点击后的页面)
之后会出现开发者工具,点击后出现该页面,选择公众平台测试账号
- 在该页面当中,填写域名(ps:作者的80端口被占用,使用的是90端口,如果用80默认可以不写)
- 同时修改页面授权的域名,两者保持一致
3. 修改本机中C:\Windows\System32\drivers\etc\hosts文件,以管理员身份打开修改,加入本机地址以及刚刚设置的域名
- 要扫描测试号二维码,加入自己的微信账号,否则后面无法进行测试授权
前端部分
1.前端页面中的设置
我设置的是90端口,注意写自己域名时写的端口
2.设计前端页面,授权可以通过超链接进行设置
<template><van-row><van-col span="24"><div class="header"><--头像--><van-image round width="5rem" height="5rem" :src="headimgurl" /><--点击授权的超链接,默认显示的是pinia中的微信登录--><aclass="login"href="https://open.weixin.qq.com/connect/oauth2/authorize?appid=wx11222333334444d&redirect_uri=http%3A%2F%2Fshimmer.com%3A90%2Fmy&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect">{{ pinia.nickname }}</a></div></van-col></van-row>
</template>
注意:其中的appid要写成自己测试号中的,其中的redirect_uri为授权后返回的页面,其url格式需要进行加密。
页面展示(使用微信开发者工具展示)
前后端联系:在点击微信登录,同意授权后,回调页面会跳转至 redirect_uri/?code=CODE&state=STATE之后通过调用对应后端传送的接口同时将code传到后台,后台通过code发送对应请求获取access_token,再发送对应请求可以获得网页授权的用户信息,后端将用户信息返回给前端。
结果:前端我将回调页面还写的是本页面,授权之后,会将我微信对应的头像和名称显示 在当前页面。
实现
- 在onMounted中,先对code进行判断,如果为空说明是第一次进入该页面,尚未进行授权,则不进行调用接口;如果存在,则说明已经授权了,进行调用。
由于code是进行授权后,回调的url中携带的参数,所以用路由来接收参数并进行判断
import { ref, onMounted } from "vue";
import { usePinia } from "@/store/pinia";
import { weixinApi } from "@/api";
import { useRoute } from "vue-router";
const pinia = usePinia();
const route = useRoute();
const headimgurl = ref(pinia.headimgurl);
onMounted(() => {const code = route.query.code;if (code != undefined) {weixinCallApi(code);}
});
const weixinCallApi = (code: any) => {weixinApi.getAccessToken.call({ code: code }).then((res: any) => {console.log(res);pinia.nickname = res.data.nickname;pinia.headimgurl = res.data.headimgurl;});
};
- 进行调用接口后,将返回的响应数据进行赋值给pinia,用于显示或后期使用。
结果展示
注意: 在练习的过程中,进行授权后不要携带同一个code进行多次刷新,否则后端请求返回的access_token会为空,报错40163(好像是)
原因:code作为换取access_token的票据,每次用户授权带上的code将不一样,code只能使用一次,5分钟未被使用自动过期。
后端部分
第一步:通过前端给的code换取网页授权access_token
通过发送请求https://api.weixin.qq.com/sns/oauth2/access_tokenappid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code,加粗的三个值都需要根据自己的进行传递
请求发送返回对应的json内容
{
“access_token”:“ACCESS_TOKEN”,
“expires_in”:7200,
“refresh_token”:“REFRESH_TOKEN”,
“openid”:“OPENID”,
“scope”:“SCOPE”,
“is_snapshotuser”: 1,
“unionid”: “UNIONID”
}
利用hutool工具,将返回的json转换为自己创建的modle对象
AccessTokenInfo
@Data
public class AccessTokenInfo {String access_token;int expires_in;String refresh_token;String openid;String scope;String unionid;int is_snapshotuser;
}
第二步:拉取用户信息(需scope为 snsapi_userinfo)
获取的access_token是网页授权接口调用凭证,以及openid 是用户的唯一标识,在这一步调用获取用户信息时需要这两个参数。
发送请求:
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
返回的就是用户信息的json
{
“openid”: “OPENID”,
“nickname”: NICKNAME,
“sex”: 1,
“province”:“PROVINCE”,
“city”:“CITY”,
“country”:“COUNTRY”,
“headimgurl”:“https://thirdwx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46”,
“privilege”:[ “PRIVILEGE1” “PRIVILEGE2” ],
“unionid”: “o6_bmasdasdsad6_2sgVt7hMZOPfL”
}
同理,利用hutool工具,将返回的json转换为自己创建的modle对象,最终把用户信息对象返回给前端
WeiXinUserInfo
@Data
public class WeiXinUserInfo {String openid;String nickname;int sex;String province;String city;String country;String headimgurl;String privilege;String unionid;
}
Controller完整代码
@RestController
@RequestMapping("/api/weixin")
public class H5WeiXinController {@Value("${wx.appid}")private String appId;@Value("${wx.secret}")private String secret;/*** 获取access_token* @param code 前端通过授权后会跳转的页面中携带的参数* @return*/@GetMapping("/getAccessToken")public WeiXinUserInfo getAccessToken(String code) {String url = StrFormatter.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid={}&secret={}&code={}&grant_type=authorization_code", appId, secret, code);//请求返回的内容,一个json对象String body = HttpUtil.get(url);//将接收的json对象转换为对象AccessTokenInfo accessTokenInfo = JSONUtil.toBean(body, AccessTokenInfo.class);//获取用户信息url = StrFormatter.format("https://api.weixin.qq.com/sns/userinfo?access_token={}&openid={}&lang=zh_CN",accessTokenInfo.getAccess_token(),accessTokenInfo.getOpenid());//请求返回的内容,一个json对象body = HttpUtil.get(url);WeiXinUserInfo weiXinUserInfo = JSONUtil.toBean(body, WeiXinUserInfo.class);//返回用户信息给前端return weiXinUserInfo;}
}