登陆流程
小程序登陆
由code获取OpenId
@GetMapping("/get-openid-sessionKey")
public AjaxResult getMiniOpenid(@RequestParam(value = "code") String code) {
if (StringUtils.isBlank(code)) {
return AjaxResult.error("","传入code为空");
}
try {
GetOpenIdResponse getOpenIdResponse = new GetOpenIdResponse();
String json = WxSessionKeyUtil.getOpenIdUrl("appid=" + appid + "&secret=" + appSecret + "&js_code="+ code + "&grant_type=authorization_code");
if (StringUtils.isBlank(json)) {
return AjaxResult.error("","获取OPENID失败,请检查code");
}
WxJscode2session wxJscode2session = JacksonUtils.toObject(objectMapper, json, WxJscode2session.class);
if (!wxJscode2session.ok()) {
return AjaxResult.error("","获取OPENID失败,请检查code");
}
getOpenIdResponse.setOpenid(wxJscode2session.getOpenid());
getOpenIdResponse.setSessionKey(wxJscode2session.getSession_key());
return AjaxResult.success(getOpenIdResponse);
} catch (Exception e) {
return AjaxResult.error("",e.getMessage());
}
}
数据解密登陆 或者直接跳转用户绑定手机号
解析到手机号
@GetMapping("/get-phone")
public AjaxResult getPhoneNumber(@RequestParam(value = "openId") String openId,@RequestParam(value = "sessionKey") String sessionKey,
@RequestParam(value = "encryptedData") String encryptedData, @RequestParam(value = "iv") String iv)throws Exception{
String decrypt = WxEncodeUtil.decrypt(appid, encryptedData.replace(" ","+"), sessionKey, iv);
if (StringUtils.isBlank(decrypt)) {
return AjaxResult.error("解密数据为空,请检查小程序配置");
}
JSONObject jsonObject = JSONObject.parseObject(decrypt);
if (jsonObject == null) {
return AjaxResult.error("解密手机号失败,请检查小程序配置");
}
String phone = (String) jsonObject.get("phoneNumber");
if (StringUtils.isBlank(phone)) {
return AjaxResult.error("手机号解密为空");
}
return faithUserService.bindWechatAuth(openId,phone,"xcx");
}
解密工具类
package com.ruoyi.common.core.utils.wechat;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.codec.binary.Base64;
public class WxEncodeUtil {
private static final String WATERMARK = "watermark";
private static final String APPID = "appid";
public static String decrypt(String appId, String encryptedData, String sessionKey, String iv){
String result = "";
try {
AES aes = new AES();
byte[] resultByte = aes.decrypt(Base64.decodeBase64(encryptedData), Base64.decodeBase64(sessionKey), Base64.decodeBase64(iv));
if(null != resultByte && resultByte.length > 0){
result = new String(WxPKCS7Encoder.decode(resultByte));
JSONObject jsonObject = JSONObject.parseObject(result);
String decryptAppid = jsonObject.getJSONObject(WATERMARK).getString(APPID);
if(!appId.equals(decryptAppid)){
result = "";
}
}
} catch (Exception e) {
result = "";
e.printStackTrace();
}
return result;
}
public static void main(String[] args) throws Exception{
String appId = "";
String encryptedData = "";
String sessionKey = "";
String iv = "";
System.out.println(decrypt(appId, encryptedData, sessionKey, iv));
}
}
网站微信登录
三方微信登录权限认证 获取用户数据工具类
package com.ruoyi.user.wx.utils;
import cn.hutool.core.map.MapUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import com.ruoyi.common.core.enums.RequestSourceType;
import com.ruoyi.user.wx.domain.GetTokenResponse;
import com.ruoyi.user.wx.domain.ReTokenResponse;
import com.ruoyi.user.wx.domain.WXUserInfoResponse;
import com.ruoyi.user.wx.domain.WechatProperties;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.lang.reflect.Field;
import java.util.Map;
@NoArgsConstructor
@Component
@Slf4j
public class WXLoginUtils {
@Resource
private Environment env;
@Resource
private WechatProperties wxProperties;
public void confirmSource(RequestSourceType requestSource) {
if (requestSource == RequestSourceType.WEB) {
Field[] declaredFields = wxProperties.getClass().getDeclaredFields();
for (Field field : declaredFields) {
String property = env.getProperty("tencent.webWeChat"+"."+field.getName());
field.setAccessible(true);
try {
field.set(wxProperties, property);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
} else {
Field[] declaredFields = wxProperties.getClass().getDeclaredFields();
for (Field field : declaredFields) {
String property = env.getProperty("tencent.weChat"+"."+field.getName());
field.setAccessible(true);
try {
field.set(wxProperties, property);
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}
public GetTokenResponse getAccessToken(String code) {
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + wxProperties.getAppId() + "&secret=" + wxProperties.getAppSecret() + "&code=" + code + "&grant_type=authorization_code";
String result = HttpUtil.get(url);
log.info("获取access_token返回结果:" + result);
return JSONUtil.toBean(result, GetTokenResponse.class);
}
public Boolean checkAccessToken(String accessToken, String openId) {
String url = "https://api.weixin.qq.com/sns/auth?access_token=" + accessToken + "&openid=" + openId;
String result = HttpUtil.get(url);
log.info("校验access_token返回结果:" + result);
Map map = JSONUtil.toBean(result, Map.class);
if (MapUtil.getInt(map, "errcode") == 0 && MapUtil.getStr(map, "errmsg").equals("ok")) {
return true;
}
return false;
}
public ReTokenResponse refreshAccessToken(String refresh_token) {
String url = "https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=" + wxProperties.getAppId() + "&grant_type=refresh_token&refresh_token=" + refresh_token;
String result = HttpUtil.get(url);
log.info("刷新access_token返回结果:" + result);
return JSONUtil.toBean(result, ReTokenResponse.class);
}
public WXUserInfoResponse getUserInfo(String accessToken, String openId) {
String url = "https://api.weixin.qq.com/sns/userinfo?access_token=" + accessToken + "&openid=" + openId + "&lang=zh_CN";
String result = HttpUtil.get(url);
log.info("获取用户信息返回结果:" + result);
return JSONUtil.toBean(result, WXUserInfoResponse.class);
}
public WXUserInfoResponse getWXUserInfo(String code,RequestSourceType type){
confirmSource(type);
GetTokenResponse tokenResponse= getAccessToken(code);
if (!checkAccessToken(tokenResponse.getAccess_token(), tokenResponse.getOpenid())) {
ReTokenResponse reTokenResponse = refreshAccessToken(tokenResponse.getRefresh_token());
tokenResponse.setRefresh_token(reTokenResponse.getRefresh_token());
tokenResponse.setAccess_token(reTokenResponse.getAccess_token());
}
return getUserInfo(tokenResponse.getAccess_token(), tokenResponse.getOpenid());
}
}
pojo
token包装
import lombok.Data;
@Data
public class GetTokenResponse {
private String access_token;
private Integer expires_in;
private String refresh_token;
private String openid;
private String unionid;
}
token刷新封装
@Data
public class ReTokenResponse {
private String access_token;
private Integer expires_in;
private String refresh_token;
private String openid;
private String scope;
}
用户信息封装
@Data
public class WXUserInfoResponse {
private String openid;
private String nickname;
private int sex;
private String province;
private String country;
private String headimgurl;
private String[] privilege;
private String unionid;
}
请求来源字典
@Getter
@AllArgsConstructor
public enum RequestSourceType {
XCX("xcx"),
WEB("web"),
APP("app"),
;
private String value;
}
|