微信开放平台官网
https://developers.weixin.qq.com/doc/oplatform/Website_App/WeChat_Login/Wechat_Login.html
1. 环境准备 所需依赖
<!--httpclient-->
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<!--commons-io-->
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<!--gson 这个包是为了后续转换格式需要-->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
</dependency>
2. application.yml
这个配置文件是为了创建一个常量类方便以后的修改不创建这个直接写入代码也可以
wx:
open:
# 微信开放平台 appid
appid: xxxxx
# 微信开放平台 appsecret
appsecret: xxxxxx
# 微信开放平台 重定向url(guli.shop需要在微信开放平台配置)
redirecturl: xxxxxx
package com.systop.eduucenter.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ConstantWxUtils implements InitializingBean {
@Value("${wx.open.appid}")
private String appId;
@Value("${wx.open.appsecret}")
private String appSecret;
@Value("${wx.open.redirecturl}")
private String redirectUrl;
public static String WX_OPEN_APPID;
public static String WX_OPEN_APPSECRET;
public static String WX_OPEN_REDIRECT_URL;
@Override
public void afterPropertiesSet() throws Exception {
WX_OPEN_APPID = appId;
WX_OPEN_APPSECRET = appSecret;
WX_OPEN_REDIRECT_URL = redirectUrl;
}
}
3. 准备工作已经完成
3.1 根据官方文档第一步需要生成登录的二维码
主要内容就是发送固定的地址得到你的登录二维码 其中使用了 String.format() 进行占位符填充
还有URLEncoder进行地址的转码
/**
* 生成微信登录的二维码
* @return
*/
@GetMapping("/login")
public String getWxCode(){
/**
*
* https://open.weixin.qq.com/connect/qrconnect?
* appid=APPID&
* redirect_uri=REDIRECT_URI&
* response_type=code&
* scope=snsapi_login&
* state=%s
* #wechat_redirect
*/
// 微信开放平台授权baseUrl %s 相当于?占位符
String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
"?appid=%s" +
"&redirect_uri=%s" +
"&response_type=code" +
"&scope=snsapi_login" +
"&state=%s" +
"#wechat_redirect";
// 对redirect_url进行URLEncode编码
String redirectUrl = ConstantWxUtils.WX_OPEN_REDIRECT_URL;
System.out.println(redirectUrl);
try {
redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 设置%里面的值
String url = String.format(
baseUrl,
ConstantWxUtils.WX_OPEN_APPID,
redirectUrl,
"duyizhou"
);
// 重定向到请求微信的地址
return "redirect:"+url;
}
3.2 生成access_token
@GetMapping("/callback")
public String callback(String code,String state){
// 通过code获取access_token
// 官网固定地址
/**
* https://api.weixin.qq.com/sns/oauth2/access_token
* ?appid=APPID
* &secret=SECRET&code=CODE
* &grant_type=authorization_code
*/
try {
String baseAccessTokenUrl =
"https://api.weixin.qq.com/sns/oauth2/access_token" +
"?appid=%s" +
"&secret=%s" +
"&code=%s" +
"&grant_type=authorization_code";
String accessToekenUrl = String.format(
baseAccessTokenUrl,
ConstantWxUtils.WX_OPEN_APPID,
ConstantWxUtils.WX_OPEN_APPSECRET,
code
);
// 根据这个地址获取到 accsess_token 和 openid
String accessTokenInfo = HttpClientUtils.get(accessToekenUrl);
Gson gson = new Gson();
HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class);
String accessToken = (String) mapAccessToken.get("access_token");
String openid = (String) mapAccessToken.get("openid");
// UcenterMember member = memberService.getMemberByOpenId(openid);
// if (member == null){
// 第三步:通过access_token调用接口
String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
"?access_token=%s" +
"&openid=%s";
// 拼接两个参数
String userInfoUrl = String.format(
baseUserInfoUrl,
accessToken,
openid
);
// 发送请求
String userInfo = HttpClientUtils.get(userInfoUrl);
// 获取返回userInfo字符串扫描人信息
HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);
String nickname = (String) userInfoMap.get("nickname"); // 昵称
String headimgurl = (String) userInfoMap.get("headimgurl"); // 头像
System.out.println(nickname);
System.out.println(headimgurl);
// 存入数据库
UcenterMember member = new UcenterMember();
member.setNickname(nickname);
member.setOpenid(openid);
member.setAvatar(headimgurl);
memberService.save(member);
// }
// 携带着token信息发送请求到前端
String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());
// 返回首页
return "redirect:http://localhost:3000?token=" + jwtToken;
} catch (Exception e) {
e.printStackTrace();
throw new GuliException(20001,"登录失败!");
}
}
完整代码
package com.systop.eduucenter.controller;
import com.google.gson.Gson;
import com.systop.commonutils.JwtUtils;
import com.systop.eduucenter.entity.UcenterMember;
import com.systop.eduucenter.service.UcenterMemberService;
import com.systop.eduucenter.utils.ConstantWxUtils;
import com.systop.eduucenter.utils.HttpClientUtils;
import com.systop.servicebase.exception.GuliException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.EmptyStackException;
import java.util.HashMap;
@CrossOrigin
@Controller
@RequestMapping("/api/ucenter/wx")
public class WxApiController {
@Autowired
private UcenterMemberService memberService;
@GetMapping("/callback")
public String callback(String code,String state){
// 通过code获取access_token
// 官网固定地址
/**
* https://api.weixin.qq.com/sns/oauth2/access_token
* ?appid=APPID
* &secret=SECRET&code=CODE
* &grant_type=authorization_code
*/
try {
String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +
"?appid=%s" +
"&secret=%s" +
"&code=%s" +
"&grant_type=authorization_code";
String accessToekenUrl = String.format(
baseAccessTokenUrl,
ConstantWxUtils.WX_OPEN_APPID,
ConstantWxUtils.WX_OPEN_APPSECRET,
code
);
// 根据这个地址获取到 accsess_token 和 openid
String accessTokenInfo = HttpClientUtils.get(accessToekenUrl);
Gson gson = new Gson();
HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class);
String accessToken = (String) mapAccessToken.get("access_token");
String openid = (String) mapAccessToken.get("openid");
// UcenterMember member = memberService.getMemberByOpenId(openid);
// if (member == null){
// 第三步:通过access_token调用接口
String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +
"?access_token=%s" +
"&openid=%s";
// 拼接两个参数
String userInfoUrl = String.format(
baseUserInfoUrl,
accessToken,
openid
);
// 发送请求
String userInfo = HttpClientUtils.get(userInfoUrl);
// 获取返回userInfo字符串扫描人信息
HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);
String nickname = (String) userInfoMap.get("nickname"); // 昵称
String headimgurl = (String) userInfoMap.get("headimgurl"); // 头像
System.out.println(nickname);
System.out.println(headimgurl);
// 存入数据库
UcenterMember member = new UcenterMember();
member.setNickname(nickname);
member.setOpenid(openid);
member.setAvatar(headimgurl);
memberService.save(member);
// }
// 携带着token信息发送请求到前端
String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());
// 返回首页
return "redirect:http://localhost:3000?token=" + jwtToken;
} catch (Exception e) {
e.printStackTrace();
throw new GuliException(20001,"登录失败!");
}
}
/**
* 生成微信登录的二维码
* @return
*/
@GetMapping("/login")
public String getWxCode(){
/**
*
* https://open.weixin.qq.com/connect/qrconnect?
* appid=APPID&
* redirect_uri=REDIRECT_URI&
* response_type=code&
* scope=snsapi_login&
* state=%s
* #wechat_redirect
*/
// 微信开放平台授权baseUrl %s 相当于?占位符
String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +
"?appid=%s" +
"&redirect_uri=%s" +
"&response_type=code" +
"&scope=snsapi_login" +
"&state=%s" +
"#wechat_redirect";
// 对redirect_url进行URLEncodebianma
String redirectUrl = ConstantWxUtils.WX_OPEN_REDIRECT_URL;
System.out.println(redirectUrl);
try {
redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
// 设置%里面的值
String url = String.format(
baseUrl,
ConstantWxUtils.WX_OPEN_APPID,
redirectUrl,
"duyizhou"
);
// 重定向到请求微信的地址
return "redirect:"+url;
}
}
4. 之后发送前端地址会携带带有用户信息的token通过token获取用户的信息