做的是谷粒学院的微信登录,这里他提供的微信开放平台的信息好像出了问题,没有办法正常操作,这里做出如下改变:
原来的配置文件信息:
wx.open.app_id=wxed9954c01bb89b47
wx.open.app_secret=a7482517235173ddb4083788de60b90e
wx.open.redirect_url=http://guli.shop/api/ucenter/wx/callback
现在修改为:
wx.open.app_id=wxed9954c01bb89b47
wx.open.app_secret=a7482517235173ddb4083788de60b90e
wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback
还要修改项目启动端口为8160。
ConstantWxUtil取到配置文件的信息:
@Component
public class ConstantWxUtil implements InitializingBean {
@Value("${wx.open.app_id}")
private String appId;
@Value("${wx.open.app_secret}")
private String appSecret;
@Value("${wx.open.redirect_url}")
private String redirectUrl;
public static String WX_OPEN_APP_ID;
public static String WX_OPEN_APP_SECRET;
public static String WX_OPEN_REDIRECT_URL;
@Override
public void afterPropertiesSet() throws Exception {
WX_OPEN_APP_ID = appId;
WX_OPEN_APP_SECRET = appSecret;
WX_OPEN_REDIRECT_URL = redirectUrl;
}
}
生成二维码方法:
@GetMapping("login")
public String genQrConnect(HttpSession session) {
// 微信开放平台授权baseUrl
String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
"?appid=%s" +
"&redirect_uri=%s" +
"&response_type=code" +
"&scope=snsapi_login" +
"&state=%s" +
"#wechat_redirect";
// 回调地址
String redirectUrl = ConstantWxUtil.WX_OPEN_REDIRECT_URL;
try {
redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8"); //url编码
} catch (UnsupportedEncodingException e) {
throw new GuliException(20001, e.getMessage());
}
String state = "imhelen";
System.out.println("state = " + state);
//生成qrcodeUrl
String qrcodeUrl = String.format(
baseUrl,
ConstantWxUtil.WX_OPEN_APP_ID,
redirectUrl,
state);
return "redirect:" + qrcodeUrl;
}
扫码登录方法:
@Autowired
private UcenterMemberService memberService;
@GetMapping("callback")
public String callback(String code, String state, HttpSession session) {
//获取到code
//拿着code请求微信固定地址,得到access_token和openid
//得到授权临时票据code
System.out.println("code = " + code);
System.out.println("state = " + state);
try{
String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
"?appid=%s" +
"&secret=%s" +
"&code=%s" +
"&grant_type=authorization_code";
String accessTokenUrl = String.format(baseAccessTokenUrl,
ConstantWxUtil.WX_OPEN_APP_ID,
ConstantWxUtil.WX_OPEN_APP_SECRET,
code);
String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);
//获取accessToken和openid
String result = null;
Gson gson=new Gson();
HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class);
String access_token = (String) mapAccessToken.get("access_token");
String openid = (String) mapAccessToken.get("openid");
//将扫码人信息添加到数据库
//判断数据库中是否有重复微信信息
UcenterMember member=memberService.getOpenIdMember(openid);
if (member==null){
String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
"?access_token=%s" +
"&openid=%s";
String userInfoUrl = String.format(
baseUserInfoUrl,
access_token,
openid
);
String userInfo = HttpClientUtils.get(userInfoUrl);
HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);
String nickname = (String) userInfoMap.get("nickname");
String headimgurl = (String) userInfoMap.get("headimgurl");
//添加
member=new UcenterMember();
member.setNickname(nickname);
member.setAvatar(headimgurl);
member.setOpenid(openid);
memberService.save(member);
}
//使用jwt根据member对象生成token字符串
String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());
return "redirect:http://localhost:3000?token="+jwtToken;
}catch (Exception e){
throw new GuliException(20001,"登录失败");
}
}
前端页面方法:意义:当页面初始化的时候,判断路径中是否有token参数,如果有,调用wxLogin方法,把token放到cookie中,再调用获取用户信息方法,根据token获取用户信息展示。
created() {
//获取路径中的token的值
this.token=this.$route.query.token
if(this.token){
this.wxLogin()
}
},
methods: {
//微信登录
wxLogin(){
cookie.set("guli_token",this.token,{domain: 'localhost'})
cookie.set('guli_ucenter','', { domain: 'localhost' })
loginApi.getLoginInfo()
.then(response=>{
this.loginInfo= response.data.data.userInfo
cookie.set('guli_ucenter', this.loginInfo, { domain: 'localhost' })
})
}
}
图解如下:
简单概括一下:首先拿着app_id,app_secret,redirect_url去请求微信的一个接口,微信会返回来一个二维码,用户扫码确认登录以后,执行callback回调方法,会传过来两个值,一个state,一个code,,然后拿着code请求微信提供的一个接口,得到两个值,一个access_token为访问凭证,一个openid为每个微信的唯一标识,拿着这两个值再去请求微信的一个接口,就可以得到扫码人的微信头像昵称等信息。
个人理解为,拿着微信应用的钥匙打开一道门,得到一张地图,扫描地图得到钥匙,通过钥匙打开一道门,又得到一个钥匙,再打开一道门,才得到有用的信息。