1、controller类
package com.myfutech.unif.insure.ctr;
import com.myfutech.common.util.Responses;
import com.myfutech.common.util.vo.CodeVO;
import com.myfutech.common.util.vo.CodeValueVO;
import com.myfutech.unif.insure.util.WeChatUtil;
import com.myfutech.unif.insure.vo.request.UserAuthVO;
import com.myfutech.unif.insure.vo.response.TokenInfoVO;
import com.myfutech.unif.insure.vo.response.WxUserInfoVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.http.MediaType;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.net.URLEncoder;
/**
* 相关接口
*/
@Api(tags = "用户信息_相关接口", description = "",
consumes = MediaType.APPLICATION_JSON_UTF8_VALUE,
produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
@RestController
@RequestMapping("/user")
public class UserCtrl {
private static final Logger log = LoggerFactory.getLogger(UserCtrl.class);
private static final String URL_KEY = "QD_WX_BACK_URL_";
@Value("${wx.auth.backUrl}")
private String backUrl;
@Resource
private StringRedisTemplate stringRedisTemplate;
@ApiOperation(value = "微信授权")
@PostMapping("/auth")
public Responses<String> auth(@Validated @RequestBody CodeValueVO codeValueVO) throws Exception {
String value = stringRedisTemplate.opsForValue().get(URL_KEY + codeValueVO.getCode());
if (StringUtils.isBlank(value) || !value.equals(codeValueVO.getValue())) {
stringRedisTemplate.opsForValue().set(URL_KEY + codeValueVO.getCode(), codeValueVO.getValue());
}
String url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=" + "wxd4cc" +
"&redirect_uri=" + URLEncoder.encode(backUrl + "?urlCode=" + codeValueVO.getCode(), "UTF-8") +
"&response_type=code" +
"&scope=snsapi_userinfo" +
"&state=STATE#wechat_redirect";
return Responses.success(url);
}
@ApiOperation(value = "微信授权回调接口")
@GetMapping("callback")
public void callback(UserAuthVO userAuthVO, HttpServletResponse response) throws Exception {
String url = stringRedisTemplate.opsForValue().get(URL_KEY + userAuthVO.getUrlCode());
TokenInfoVO tokenInfoVO = WeChatUtil.getAccessToken(userAuthVO.getCode());
response.sendRedirect(url + "?openId=" + tokenInfoVO.getOpenid());
}
@ApiOperation(value = "微信用户信息")
@PostMapping("wxUserInfo")
public Responses<WxUserInfoVO> wxUserInfo(@Validated @RequestBody CodeVO codeVO) {
TokenInfoVO tokenInfoVO = WeChatUtil.getAccessToken(codeVO.getCode());
WxUserInfoVO wxUserInfoVO = WeChatUtil.getUserInfo(tokenInfoVO.getAccess_token(), tokenInfoVO.getOpenid());
return Responses.success(wxUserInfoVO);
}
}
2、yml文件
wx:
auth:
backUrl: http://kang360970725.vicp.cc/user/callback
3、工具类
package com.myfutech.unif.insure.util;
import com.alibaba.fastjson.JSON;
import com.myfutech.common.util.enums.ResponseCode;
import com.myfutech.common.util.exception.BusinessException;
import com.myfutech.common.util.http.HttpClientUtils;
import com.myfutech.unif.insure.vo.response.TokenInfoVO;
import com.myfutech.unif.insure.vo.response.WxUserInfoVO;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class WeChatUtil {
public static final String appId = "wxd4";
public static final String secret = "b553a";
/**
* 通过code换取网页授权access_token
*
* @param code
* @return
*/
public static TokenInfoVO getAccessToken(String code) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId +
"&secret=" + secret +
"&code=" + code +
"&grant_type=authorization_code";
String result = HttpClientUtils.doGet(url, null);
log.info("微信_获取access_token结果: {}", result);
if (result.contains("errcode")) {
throw new BusinessException(ResponseCode.EXIST_CODE, "通过code换取网页授权access_token失败");
}
TokenInfoVO vo = JSON.parseObject(result, TokenInfoVO.class);
return vo;
}
/**
* 刷新access_token(如果需要)
*
* @param appId
* @param refresh_token
* @return
*/
public static TokenInfoVO refreshToken(String refresh_token) {
String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + appId + "&grant_type=refresh_token&refresh_token=" + refresh_token + "";
String result = HttpClientUtils.doGet(url, null);
log.info("微信_刷新access_token结果: {}", result);
if (result.contains("errcode")) {
throw new BusinessException(ResponseCode.EXIST_CODE, "刷新access_token失败");
}
TokenInfoVO vo = JSON.parseObject(result, TokenInfoVO.class);
return vo;
}
/**
* 拉取用户信息(需scope为 snsapi_userinfo)
* 获取用户信息UNIONID
*
* @param access_token
* @param openid
* @return
*/
public static WxUserInfoVO getUserInfo(String access_token, String openid) {
String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid + "&lang=zh_CN";
String result = HttpClientUtils.doGet(url, null);
log.info("微信_获取snsapi_userinfo结果: {}", result);
if (result.contains("errcode")) {
throw new BusinessException(ResponseCode.EXIST_CODE, "拉取微信用户信息失败");
}
WxUserInfoVO vo = JSON.parseObject(result, WxUserInfoVO.class);
return vo;
}
}
4、vo
package com.myfutech.unif.insure.vo.response;
import lombok.Data;
@Data
public class TokenInfoVO {
private String access_token;
private String expires_in;
private String refresh_token;
private String openid;
private String scope;
}
package com.myfutech.unif.insure.vo.response;
import lombok.Data;
import java.util.List;
@Data
public class WxUserInfoVO {
private String openid;
private String nickname;
private String sex;
private String province;
private String city;
private String country;
private String headimgurl;
private List<String> privilege;
private String unionid;
}
参考官方文档地址:
https://mp.weixin.qq.com/wiki?t=resource/res_main&id=mp1421140842