一、网页端的扫二维码绑定第三方的登录
1、发起微信授权登录请求
@Override
public ResponseData userLoginByThirdPlatformWeb(ThirdPlatformWebReqDTO thirdPlatformWebReqDTO, HttpServletRequest request) {
log.info("第三方web登录外部接口请求参数,{}", thirdPlatformWebReqDTO);
String referer = request.getHeader("Referer");
Integer platform = thirdPlatformWebReqDTO.getPlatform();
Integer sign = thirdPlatformWebReqDTO.getSign();
try {
if (StringUtils.isNotBlank(referer)) {
referer = URLEncoder.encode(referer, "UTF-8");
}
} catch (UnsupportedEncodingException e1) {
e1.printStackTrace();
return new ResponseData<>(LoginRegisterResultCode.FAILY);
}
log.debug("referer=========================>:{}", referer);
String redirectCallback = "";
String redirect = "";
boolean isWap = WebUtil.checkClientIsMobile(request);
if (Constant.QQ_PLATFROM.equals(platform.toString())) {
//配置项目的回调地址和所带参数
redirectCallback = Constant.HTTP_QQ_DOMAIN_URL + "?referer=" + referer + "&platform=" + platform + "&sign=" + sign;
redirect = QQUtil.getAuthorizationUrlJump(isWap, redirectCallback, "test");
} else {
//配置项目的回调地址和所带参数
redirectCallback = Constant.HTTP_WX_DOMAIN_URL + "?referer=" + referer + "&platform=" + platform + "&sign=" + sign;
redirect = WxUtil.getAuthorizationUrlJump(redirectCallback, "test");
}
ReturnUrlRespDTO returnUrl = new ReturnUrlRespDTO();
returnUrl.setUrl(redirect);
log.info("第三方web登录接口返回参数,{}", returnUrl);
return new ResponseData(LoginRegisterResultCode.SUCCESS, returnUrl);
}
QQUtil.getAuthorizationUrlJump()函数
public static String getAuthorizationUrlJump(boolean isWap, String redirect_uri, String state) {
isWap = false;
if (StringUtils.isNotBlank(redirect_uri)) {
try {
redirect_uri = URLEncoder.encode(redirect_uri, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.error("------------QQ2.0----getAuthorizationCode URLEncoder失败:" + redirect_uri, e);
}
}
String display = isWap ? "mobile" : "pc";
String requestUrl = "https://graph.qq.com/oauth2.0/authorize?";
requestUrl += "response_type=code&client_id=" + appid + "&redirect_uri=" + redirect_uri + "&state=" + state + "&scope=" + scope + "&display=" + display;
return requestUrl;
}
WxUtil.getAuthorizationUrlJump()函数
// 授权跳转地址
public static String getAuthorizationUrlJump(String redirect_callback, String state) {
if (StringUtils.isNotBlank(redirect_callback)) {
try {
redirect_callback = URLEncoder.encode(redirect_callback, "UTF-8");
} catch (UnsupportedEncodingException e) {
logger.error("---------WeixinUtil.getAuthorizationUrlJump() URLEncoder失败:" + redirect_callback, e);
}
}
String requestUrl = "https://open.weixin.qq.com/connect/qrconnect?";
requestUrl += "appid=" + weixin_AppID + "&redirect_uri=" + redirect_callback + "&response_type=code&scope=snsapi_login&state=" + state + "#wechat_redirect";
return requestUrl;
}
2、重定向到我们提供给腾讯回调地址并且给我们带过来code以及state参数,我们拿着临时凭证(code)去获取accessToken以及用户信息:
@Override
public String thirdLoginWebCallBack(HttpServletRequest request) {
String sign = request.getParameter("sign");
String platform = request.getParameter("platform");
// 第三方拼接好的参数code
String authorizationCode = request.getParameter("code");
String unionid = "";
String phone = "";
String userType = "";
String userName = "";
Integer isOrgUser = 0;
Integer hasOrgPackage = 0;
Integer isMonthPackageForLeave = 0;
String mobileArea = "";
String needRemid = "";
String redirectCallback = "";
//获取QQ或微信的unionid
boolean isWap = WebUtil.checkClientIsMobile(request);
if (Constant.QQ_PLATFROM.equals(platform)) {
redirectCallback = Constant.HTTP_QQ_DOMAIN_URL;
String accessToken = QQUtil.getAccessToken(isWap, authorizationCode, redirectCallback);
unionid = QQUtil.getUnionid(isWap, accessToken);
log.info("unionid=========================>:{}", unionid);
} else {
redirectCallback = Constant.HTTP_WX_DOMAIN_URL;
JSONObject jsonObj = WxUtil.getUnionid4login(authorizationCode, redirectCallback);
unionid = jsonObj.getString("unionid");
log.info("unionid=========================>:{}", unionid);
}
//进行业务逻辑的操作
TUserinfo userInfo = userInfoMapper.getUserInfoByUnionId(unionid, Integer.parseInt(platform));
Integer userId = userInfo.getUserId();
RedisUtil.saveUnionid(platform, authorizationCode, unionid);
//通过unionid查询是否绑定
//已绑定,跳转至学习大厅页面
if (userInfo != null && unionid != null) {
} else {
//已注册未绑定,来源是登录后 个人中心-修改个人资料 跳转至已有界面未绑定页面(能登陆证明是老用户)
if ("1".equals(sign)) {
return Constant.TALK_SERVER_ADDRESS + "/student/login?routerBtn=thirdWithAccount&phone=" + phone + "&unionid=" + unionid + "&type=" + platform + "&sign=" + sign;
}
//未注册未绑定,来源是未登录的学生端首页 跳转至第三方注册页面(因为未登录状态无法判断用户为新的还是老用户,统一跳到第三方注册页面)
else {
return Constant.TALK_SERVER_ADDRESS + "/student/login?routerBtn=third";
}
}
}
返回的链接,在controller层用重定向实现跳转 response.sendRedirect(refererUrl);
QQUtil.getAccessToken()函数
/**
* 获取Access Token
*
* @param authorization_code 授权第一步获得的authorization_code
* @param redirect_uri 回调地址和初次请求的回调地址保持一致
*/
public static String getAccessToken(boolean isWap, String authorization_code, String redirect_uri) {
isWap = false;
if (StringUtils.isBlank(authorization_code)) {
logger.error("authorization_code不能为空!");
return null;
}
String accessToken = "";
String requestUrl = "https://graph.qq.com/oauth2.0/token?";
if (isWap) {
requestUrl = "https://graph.z.qq.com/moc2/token?";
}
requestUrl += "grant_type=authorization_code&client_id=" + appid + "&client_secret=" + appkey + "&code=" + authorization_code + "&redirect_uri=" + redirect_uri;
String resultStr = httpGet(requestUrl);
boolean success = StringUtils.isNotBlank(resultStr) && resultStr.contains("access_token");
if (!success) {
logger.error("requestUrl : " + requestUrl);
logger.error("------------QQ2.0----getAccessToken error--backstr:" + resultStr);
return accessToken;
}
String[] array = resultStr.split("&");
String[] pair = array[0].split("=");
accessToken = pair[1];
return accessToken;
}
WxUtil.getUnionid4login()函数
// 获取Access Token / openid / unionid
public static JSONObject getUnionid4login(String authorization_code, String referer) {
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?";
requestUrl += "appid=" + weixin_AppID + "&secret=" + weixin_AppSecret + "&code=" + authorization_code + "&grant_type=authorization_code";
String resultStr = WebUtil.httpGet(requestUrl, null, null, null);
JSONObject jsonObj = JSONObject.parseObject(resultStr);
return jsonObj;
}
常见的报错处理:
1、微信回调出错没有出现二维码(redirect_uri 参数错误)
解决方法正式服配置回调地址:
1、QQ回调出错登录后没有出现QQ头像(redirect_uri 参数错误)
解决方法正式服配置回调地址(QQ回调地址可以配置多个):
二、APP端直接绑定第三方的登录
@Override
public ResponseData<UserLoginRespDTO> userLoginByThirdPlatformAPP(UserLoginByThirdPlatformReqDTO userLoginByThirdPlatformReqDTO, HttpServletRequest request) {
String platform = userLoginByThirdPlatformReqDTO.getPlatform();
Integer appPlatform = userLoginByThirdPlatformReqDTO.getAppPlatform();
String tempCode = userLoginByThirdPlatformReqDTO.getTempCode();
String sign = userLoginByThirdPlatformReqDTO.getSign();
QueryWrapper queryWrapper = new QueryWrapper();
UpdateWrapper updateWrapper = new UpdateWrapper();
String unionid = "";
// 通过 tempCode 获取 unionId
if ("1".equals(platform)) {
// QQ tempCode --> access_token
unionid = OAuthUtil.getUnionid4QQ(tempCode);
} else if ("2".equals(platform)) {
// 微信 tempCode --> code
JSONObject jsonObj = OAuthUtil.getUnionid4Wx(tempCode);
unionid = jsonObj.getString("unionid");
}
// 如果获取unionId失败
if (StringUtils.isBlank(unionid)) {
return ResponseData.getFail("获取第三方授权信息失败!");
}
//进行业务逻辑的操作
TUserinfo userInfo = userInfoMapper.getUserInfoByUnionId(unionid, Integer.parseInt(platform));
RedisUtil.saveUnionid(platform, tempCode, unionid);
//通过unionid查询是否绑定
//已绑定,跳转至APP的首页
if (userInfo != null && unionid != null) {
//调用普通登录方法跳转至APP首页
queryWrapper.eq("user_id", userInfo.getUserId());
TUserinfo tUserinfo = tUserInfoMapper.selectOne(queryWrapper);
UserLoginReqDTO userLoginReqDTO = new UserLoginReqDTO();
userLoginReqDTO.setLoginId(tUserinfo.getPhone());
userLoginReqDTO.setPassword(tUserinfo.getPassword());
userLoginReqDTO.setAppPlatform(appPlatform);
userLoginReqDTO.setIsApp(1);
userLoginReqDTO.setLoginMode(1);
userLoginReqDTO.setSkipPageApp("0");
return this.userLogin(userLoginReqDTO, request);
} else {
//已注册未绑定,来源是登录后 个人中心-修改个人资料 跳转至已有界面未绑定页面(能登陆证明是老用户)
if ("1".equals(sign)) {
UserLoginRespDTO userLoginRespDTO = new UserLoginRespDTO();
queryWrapper.eq("user_id", userInfo.getUserId());
TUserinfo tUserinfo = tUserInfoMapper.selectOne(queryWrapper);
userLoginRespDTO.setSkipPageApp("1");
userLoginRespDTO.setPhone(tUserinfo.getPhone());
userLoginRespDTO.setUnionid(unionid);
return ResponseData.getSuccess(userLoginRespDTO);
}
//未注册未绑定,来源是未登录的学生端首页 跳转至第三方注册页面(因为未登录状态无法判断用户为新的还是老用户,同一跳到第三方注册页面)
else {
UserLoginRespDTO userLoginRespDTO = new UserLoginRespDTO();
userLoginRespDTO.setSkipPageApp("2");
userLoginRespDTO.setUnionid(unionid);
return ResponseData.getSuccess(userLoginRespDTO);
}
}
}
QQ授权,OAuthUtil.getUnionid4QQ()函数
public static String getUnionid4QQ(String accessToken) {
if (StringUtils.isBlank(accessToken)) {
return null;
}
String requestUrl = "https://graph.qq.com/oauth2.0/me?";
requestUrl += "unionid=1&access_token=" + accessToken;
String resultStr = httpGet(requestUrl);
if (StringUtils.isBlank(resultStr)) {
return null;
}
// 返回格式为:callback(json数据);
Pattern p = Pattern.compile("\\{.*?\\}");
Matcher m = p.matcher(resultStr);
if (!m.find()) {
return null;
}
resultStr = m.group();
JSONObject jsonObj = JSONObject.parseObject(resultStr);
String unionid = jsonObj.getString("unionid");
return unionid;
}
微信授权,OAuthUtil.getUnionid4Wx()函数
public static JSONObject getUnionid4Wx(String authorization_code) {
if (StringUtils.isBlank(authorization_code)) {
return null;
}
String requestUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?";
requestUrl += "appid=" + weixin_AppID + "&secret=" + weixin_AppSecret + "&code=" + authorization_code + "&grant_type=authorization_code";
String resultStr = httpGet(requestUrl);
JSONObject jsonObj = JSONObject.parseObject(resultStr);
return jsonObj;
}
参考文章:
https://developers.weixin.qq.com/doc/oplatform/Mobile_App/WeChat_Login/Development_Guide.htmlhttps://cloud.tencent.com/developer/article/1677630https://mp.weixin.qq.com/debug/cgi-bin/sandboxinfo?action=showinfo&t=sandbox/index