前言
1.首先,调用微信公众平台的OAuth2.0授权接口,获取用户的授权信息。具体的,在用户点击授权登录按钮时,向微信服务器发送请求,微信服务器会返回一个授权链接,用户点击授权链接后,微信服务器会跳转到你配置的回调地址,并带上授权码(code)。
2.使用授权码(code)调用微信公众平台的OAuth2.0接口,获取公众号的access_token。
3.使用access_token调用微信公众平台的用户信息接口,获取ticket。
4.在微信应用服务器端生成一个二维码用ticket换取,然后等候用户扫码。
5.用户扫码后回调获取到用户的openId,客户端可以通过openId来标识用户,并在之后的操作中使用。
上代码
一、导入Maven
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.3.0</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>2.0.20</version>
<scope>compile</scope>
</dependency>
二、配置类
/**
* @author My.Peng
*/
@Data
@Configuration
public class WechatConfig {
/**
* APPID
*/
@Value("${tools.wechat.appid}")
public String appid;
@Value("${tools.wechat.secret}")
public String appSecret;
}
三、工具类
/**
* @author My.Peng
*/
public class JsonUtil {
/**
* 字符串Json格式转换为对象Map
*
* @param strJson {"username":"lp"}
* @return 根据json转换为Map对象
*/
public static Map<String, Object> jsonToMap(String strJson) {
Map<String, Object> jsoMap = new HashMap<String, Object>();
try {
jsoMap = JSONObject.parseObject(strJson, Map.class);
} catch (JSONException e) {
System.out.println("json转换Map出错:" + e.getMessage());
}
return jsoMap;
}
/**
* 字符串Json格式转换为对象Map
*
* @param strJson {"username":"lp"}
* @return 根据json转换为Map对象
*/
public static Map<String, String> jsonToMapString(String strJson) {
Map<String, String> jsoMap = new HashMap<String, String>();
try {
jsoMap = JSONObject.parseObject(strJson, Map.class);
} catch (JSONException e) {
System.out.println("json转换Map出错:" + e.getMessage());
}
return jsoMap;
}
/**
* 字符串Json 转换为对象List
*
* @param strJson [{"username":"lp"}]
* @return 根据json转换List
*/
public static List<Map<String, Object>> jsonToList(String strJson) {
List<Map<String, Object>> list = new ArrayList<>();
try {
list = JSONObject.parseObject(strJson, List.class);
} catch (JSONException e) {
System.out.println("json转换List出错:" + e.getMessage());
}
return list;
}
}
四、上核心代码
/**
* @author Mr.Peng
*/
@Slf4j
@Controller
@RequestMapping("/oauth2")
public class WechatLoginController {
@Resource
private WechatConfig wechatConfig;
@GetMapping(value = "/wechat/login")
@SneakyThrows
public void wechatLoginPage(HttpServletResponse response, @RequestParam("ticket") String ticket) {
log.info("请求二维码{}", ticket);
String url = String.format(Constant.GET_QR_CODE_WX, ticket);
HttpGet httpGet = new HttpGet(url);
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse resp = httpclient.execute(httpGet);
byte[] data = EntityUtils.toByteArray(resp.getEntity());
response.getOutputStream().write(data);
}
/**
* 获取ticket
*
* @return ticket
*/
@PostMapping("/wechat/ticket")
@SneakyThrows
@ResponseBody
public Result<String> getTicket() {
String accessToken = this.getAccessToken();
String url = String.format(Constant.GET_QR_CODE, accessToken);
HttpPost httpPost = new HttpPost(url);
httpPost.setHeader("Accept", "application/json");
httpPost.addHeader("Content-type", "application/json; charset=utf-8");
String param = new JSONObject()
.put("expire_seconds", "120")
.put("action_name", "QR_STR_SCENE")
.put("action_info", new JSONObject()
.put("scene", "scene"))
.toString();
httpPost.setEntity(new StringEntity(param, "utf-8"));
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = httpclient.execute(httpPost);
String body = EntityUtils.toString(response.getEntity(), "utf-8");
return Result.ok(JsonUtil.jsonToMapString(body).get("ticket"));
}
/**
* 获取Access token
*
* @return access_token
*/
@SneakyThrows
public String getAccessToken() {
String url = String.format(Constant.GET_ACCESS_TOKEN, wechatConfig.getAppid(), wechatConfig.getAppSecret());
HttpGet httpGet = new HttpGet(url);
CloseableHttpClient httpclient = HttpClients.createDefault();
CloseableHttpResponse response = httpclient.execute(httpGet);
String body = EntityUtils.toString(response.getEntity(), "utf-8");
Map<String, String> stringStringMap = JsonUtil.jsonToMapString(body);
if (stringStringMap.get("errmsg") != null) {
log.error(stringStringMap.get("errmsg"));
}
return stringStringMap.get("access_token");
}
}
/**
* @author Mr.Peng
*/
@Slf4j
@RestController
@RequestMapping("/login/notify/wechat")
public class WechatLoginNotifyController {
@Resource
private UserService userService;
@RequestMapping("/checkSign")
public void checkSign(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setCharacterEncoding("UTF-8");
response.setContentType("text/html;charset=UTF-8");
WxMpXmlMessage message = WxMpXmlMessage.fromXml(request.getInputStream());
String userName = message.getToUser();
String openid = message.getFromUser();
assert openid != null;
String content = "\uD83D\uDC4B Hey Guys I'm Li Peng. \n\n" +
"\uD83D\uDC7E My Blog : https://lruri.com !";
String replyMsg = "<xml>"
+ "<ToUserName><![CDATA[" + openid + "]]></ToUserName>"
+ "<FromUserName><![CDATA[" + userName + "]]></FromUserName>"
+ "<CreateTime>1531553112194</CreateTime>"
+ "<MsgType><![CDATA[text]]></MsgType>"
+ "<Content><![CDATA[" + content + "]]></Content>"
+ "<MsgId>1234567890123456</MsgId> "
+ " </xml>";
log.info("用户扫码 | 关注 | openId:{},userName:{}", openid, userName);
User buildUser = User.builder()
.username(openid)
.nickname("微信用户")
.ticket(message.getTicket())
.build();
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("username", message.getFromUser());
userService.saveOrUpdate(buildUser, wrapper);
response.getWriter().print(replyMsg);
}
/**
* 验签token
*
* @param request
* @return
*/
//@RequestMapping("/checkSign")
@SneakyThrows
public String checkSign(HttpServletRequest request) {
// Token
String token = "token_li_peng";
String[] params = new String[]{
request.getParameter("timestamp"),
request.getParameter("nonce"),
token};
Arrays.sort(params);
String param = params[0] + params[1] + params[2];
// 内容加密
MessageDigest.getInstance("SHA-1")
.digest(param.getBytes(StandardCharsets.UTF_8));
// 接入服务器 验证Token签名
return request.getParameter("echostr");
}
}