spring boot + vue 微信网页授权,获取用户信息
最近都在和微信的网页授权做斗争,由于第一次接触,所以道路比较曲折,不过,现在已经好啦,详细记录一下
需求: 公众号的网页授权并获取用户信息(包括unionid),unionid的获取前提是,同一开发平台的应用
开发前准备: 请先阅读微信公众平台技术文档
1.阅读网页授权开发文档
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842
2.获取微信凭证appid和appsecret
https://mp.weixin.qq.com/debug/cgi-bin/sandbox?t=sandbox/login
3.下载微信web开发者工具
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1455784140
4.修改本地hosts,最底下添加 127.0.0.1 www.t.cn,用来指向本地,设置回调地址时可用
路径: C:\Windows\System32\drivers\etc
5.vue的端口需要是80端口
6.在测试账号中找到并修改,我们hosts中修改的地址
开发思路
1.前端调用/user/oauth接口,后端传回微信授权地址
2.前端跳转授权地址,并获取回调地址后带的code
3.使用code,请求/user/publicInfo接口,获取用户信息
开始开发
1./user/oauth接口
/**
* 拼接公众号用户授权地址,并回传给前端
* params callbackUrl 前端回调地址
* @return
*/
@GetMapping(value = "/user/oauth")
public ResponseWrapper auth(@RequestParam Map<String, Object> params){
String callbackUrl = params.get("callbackUrl").toString();
Map<String, String> param = new HashMap<>();
param.put("appid", H5Configuration.getH5Configuration().getAppId());
param.put("redirect_uri", callbackUrl);
param.put("response_type", "code");
param.put("scope", "snsapi_userinfo");
String url = "";
try {
url = H5Configuration.getH5Configuration().getAuthUrl()+"?"+"appid="+H5Configuration.getH5Configuration().getAppId()+"&redirect_uri="+callbackUrl+"&response_type=code&scope=snsapi_userinfo#wechat_redirect";
} catch (Exception e) {
e.printStackTrace();
}
Map<String,String> result = new HashMap<>();
result.put("url",url);
return ResponseWrapper.ok(result);
}
2.前端获取授权地址
mounted(){
//调用获取凭证方法
this.getTicket();
},
methods:{
getTicket(){
let self = this;
this.$vux.loading.show({
text: '加载中...'
})
// 获取回调url中的参数code
let objData = this.GetRequest();
if(objData && objData.code){
let params = {
code:objData.code
}
//根据code向后端获取当前授权用户信息
self.$axios.userPublicInfo(params).then(res=>{
if(res.code == 200){
let {ticket} = res.data;
//存储用户信息
setSessionStore("userDataInfo",res.data);
if(ticket){
setSessionStore("userTicket",ticket);
//前往首页
self.goRoute("Home");
}
}
})
return
}else{
//此处写公众号配置的回调地址
let jumpToUrl = window.location.protocol+"//"+window.location.host;
let params = {
//回调url编码
callbackUrl:encodeURIComponent(jumpToUrl)
}
self.$axios.userOauth(params).then(res=>{
//跳转微信授权页面
window.location.href = res.data.url
})
}
},
goRoute(name){
this.$router.push({name:name})
},
GetRequest(){ //获取回调url及参数
var url = location.search; //获取url中"?"符后的字串
var theRequest = new Object();
if (url.indexOf("?") != -1) {
var str = url.substr(1);
var strs = str.split("&");
for(var i = 0; i < strs.length; i ++) {
theRequest[strs[i].split("=")[0]]=unescape(strs[i].split("=")[1]);
}
}
return theRequest;
}
},
3.根据code,获取用户信息,/user/publicInfo接口
/**
* 公众号获取用户信息
* @return
*/
@GetMapping(value = "/user/publicInfo")
@ResponseBody
public ResponseWrapper getAccessToken(@RequestParam Map<String, Object> params) {
String code = params.get("code").toString();
return userService.publicUserInfo(code);
}
@Override
public ResponseWrapper publicUserInfo(String code) {
//根据code获取accesstoken
JSONObject resultH5 = H5Util.getAccessToken(code);
if(resultH5.containsKey("errmsg")){
return ResponseWrapper.error("accessToken信息获取失败");
}
String accessToken = resultH5.getString("access_token");
String openid = resultH5.getString("openid");
//根据access_token和openid获取用户信息
JSONObject userInfoJSON = H5Util.getUserInfo(accessToken,openid);
if(userInfoJSON.containsKey("errmsg")){
return ResponseWrapper.error("userInfo信息获取失败");
}
User user = new User();
String token = null;
if(userInfoJSON.containsKey("openid")){
//因为是测试号,所以,是没有unionid的
String unionId = userInfoJSON.containsKey("unionId")==false?"11111111":userInfoJSON.getString("unionId");
String avatarUrl = userInfoJSON.getString("headimgurl");
String nickName = userInfoJSON.getString("nickname");
Integer gender = userInfoJSON.getInteger("sex");
token = JWTApiUtil.sign(user);
JSONObject result = new JSONObject();
result.put("sex", sex);
result.put("avatarUrl", avatarUrl);
result.put("nickName", nickName);
return ResponseWrapper.ok(result);
}
return ResponseWrapper.error("获取用户信息失败");
}
4.H5Util工具类
/**
* 公众号工具类
* @author bright
* @date 2019/3/13
*/
public class H5Util {
private static final Logger logger = LoggerFactory.getLogger(MiniProgramUtil.class);
/**
* 第一步:获取code,发起授权
* 第二步:通过code换取网页授权access_token(与基础支持中的access_token不同)
*/
public static JSONObject getAccessToken(String code) {
Map<String, String> params = new HashMap<>();
params.put("appid", H5Configuration.getH5Configuration().getAppId());
params.put("secret", H5Configuration.getH5Configuration().getSecret());
params.put("code", code);
params.put("grant_type", "authorization_code");
JSONObject resultObj = new JSONObject();
try {
String url = HttpUtils.buildUrl(H5Configuration.getH5Configuration().getAccessToken(), "", params);
HttpResponse response = null;
response = HttpUtils.doGet(url);
BufferedReader b = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"), 8 * 1024);
String line = b.readLine();
resultObj = JSONObject.parseObject(line);
if (resultObj.containsKey("errmsg")) {
String errmsg = resultObj.getString("errmsg");
if (!resultObj.getString("errcode").equals("0")) {
logger.info("获取access_token失败");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return resultObj;
}
/**
* 第三步:如果需要,开发者可以刷新网页授权access_token,避免过期
* 第四步:通过网页授权access_token和openid获取用户基本信息(支持UnionID机制)
*/
public static JSONObject getUserInfo(String accessToken, String openId) {
Map<String, String> params = new HashMap<>();
params.put("access_token", accessToken);
params.put("openid", openId);
params.put("lang", "zh_CN");
JSONObject resultObj = new JSONObject();
try {
String url = HttpUtils.buildUrl(H5Configuration.getH5Configuration().getUserInfo(), "", params);
HttpResponse response = null;
response = HttpUtils.doGet(url);
BufferedReader b = new BufferedReader(new InputStreamReader(response.getEntity().getContent(), "UTF-8"), 8 * 1024);
String line = b.readLine();
resultObj = JSONObject.parseObject(line);
if (resultObj.containsKey("errmsg")) {
String errmsg = resultObj.getString("errmsg");
if (!resultObj.getString("errcode").equals("0")) {
logger.info("获取unionid失败");
}
}
} catch (Exception e) {
e.printStackTrace();
}
return resultObj;
}
}
效果图 在开发工具中输入www.t.cn即可