1. 逻辑说明
1.java拼接生成一个二维码的访问地址;(包含回调地址)
2.扫码,微信平台获取到用户信息,然后回调java,平台把结果返回给前端(可以返回openid或者用户信息之类的,逻辑自己定)
2. 正式使用
2.1 微信开放平台申请
2.1.1 网站应用申请
需要有自己的网站(备过案的)才可申请;(反正挺麻烦的)
2.1.2 账号密码
需要微信开放平台网站应用的(appid和appsecret)
2.2 代码
2.2.1 具体实现
package com.init.employee.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.init.common.result.*;
import com.init.employee.dto.TokenDTO;
import com.init.mbg.mapper.EmployeeMapper;
import com.init.employee.service.IEmployeeService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.init.mbg.model.Employee;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.*;
@Service
@Slf4j
public class EmployeeServiceImpl extends ServiceImpl<EmployeeMapper, Employee> implements IEmployeeService {
//调接口
@Autowired
private RestTemplate restTemplate;
@Value("${wx.qr.appId}")
private String appId;//在配置文件里写,或者用的时候直接定义
@Value("${wx.qr.secret}")
private String secret;
@Override
public String getLoginQr() {
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 = "http://www.xxxx.cn/employee/open/login/back";//这里的地址需要在开放平台设置回调域名,测试的时候项目需要是80端口
//在hosts文件里添加域名解析
//# 将www.txjava.cn 解析成127.0.0.1
//127.0.0.1 www.txjava.cn
try {
redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
}
String state = "xxxx";
log.info("state = {}", state);
String qrCodeUrl = String.format(baseUrl, appId, redirectUrl, state);
log.info("生成微信扫描二维码重定向地址为:{}", qrCodeUrl);
return "redirect:" + qrCodeUrl;
}
@Override
public Result loginBack(String code, String state) {
TokenDTO dto = new TokenDTO();
log.info("当前code:{},当前state:{}", code, state);
if (code == null) {
return new Result("操作失败");
}
OpenTokenResult openToken = getOpenToken(code, state);
if (openToken == null) {
return new Result("操作失败");
}
String accessToken = openToken.getAccess_token();
String openId = openToken.getOpenid();
if (StringUtils.isAnyBlank(accessToken, openId)) {
return new Result("操作失败");
}
dto.setOpenId(openId);
OpenUserResult openUserInfo = getOpenUserInfo(accessToken, openId);
return new Result(openUserInfo);
}
@Override
public String getOpenIdQr() {
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 = "http://www.xxxx.cn/employee/open/openid/back";//这里的地址需要在开放平台设置回调域名,测试的时候项目需要是80端口。
//在hosts文件里添加域名解析
//# 将www.txjava.cn 解析成127.0.0.1
//127.0.0.1 www.txjava.cn
try {
redirectUrl = URLEncoder.encode(redirectUrl, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e.getMessage(), e);
}
String state = "xxxx";
log.info("state = {}", state);
String qrCodeUrl = String.format(baseUrl, appId, redirectUrl, state);
log.info("生成微信扫描二维码重定向地址为:{}", qrCodeUrl);
return "redirect:" + qrCodeUrl;
}
@Override
public Result openIdBack(String code, String state) {
log.info("当前code:{},当前state:{}", code, state);
if (code == null) {
return new Result(ResultCode.USER_CODE_LESS);
}
OpenTokenResult openToken = getOpenToken(code, state);
if (openToken == null) {
return new Result(ResultCode.USER_TOKEN_FAILED);
}
return new Result(openToken.getOpenid());
}
//回调方法里的第一个请求,获取用户openid和accesstoken
private OpenTokenResult getOpenToken(String code, String state) {
String token_url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + secret + "&code=" + code + "&grant_type=authorization_code";
Map<String, Object> param = new HashMap<>();
HttpHeaders headers = new HttpHeaders();
ResponseEntity<String> entity = null;
try {
entity = restTemplate.exchange(
token_url,
HttpMethod.GET,
new HttpEntity<String>(headers),
String.class,
param);
} catch (RestClientException e) {
log.info("请求生成token失败");
return null;
}
if (entity == null) {
return null;
}
String response = JSONObject.toJSONString(entity);
ResponseResult resultTemp = JSONObject.parseObject(response, ResponseResult.class);
String body = resultTemp.getBody();
OpenTokenResult openTokenResult = JSONObject.parseObject(body, OpenTokenResult.class);
return openTokenResult;
}
//回调方法里的第二个请求,获取用户info
private OpenUserResult getOpenUserInfo(String accessToken, String openId) {
String getInfo_url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId;
Map<String, Object> infoParam = new HashMap<>();
HttpHeaders infoHeader = new HttpHeaders();
ResponseEntity<String> infoEntity = null;
try {
infoEntity = restTemplate.exchange(
getInfo_url,
HttpMethod.GET,
new HttpEntity<String>(infoHeader),
String.class,
infoParam);
} catch (RestClientException e) {
log.info("请求用户信息失败");
return null;
}
if (infoEntity == null) {
return null;
}
String infoResponse = JSONObject.toJSONString(infoEntity);
ResponseResult infoResult = JSONObject.parseObject(infoResponse, ResponseResult.class);
String infoBody = infoResult.getBody();
OpenUserResult openUserResult = JSONObject.parseObject(infoBody, OpenUserResult.class);
return openUserResult;
}
}
2.2.2 封装类
- OpenTokenResult
package com.init.common.result;
import lombok.Data;
import java.io.Serializable;
@Data
public class OpenTokenResult implements Serializable {
private String access_token;
private Integer expires_in;
private String refresh_token;
private String openid;
private String scope;
private Integer errcode;
private String errmsg;
}
- OpenUserResult
package com.init.common.result;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
@Data
public class OpenUserResult implements Serializable {
private String openid;
private String nickname;
private String sex;
private String province;
private String city;
private String country;
private String headimgurl;
private List privilege;
private String unionid;
private Integer errcode;
private String errmsg;
}