提交 87c2a1b2 编写于 作者: 不合群的混子's avatar 不合群的混子

增加微信登录支持

上级 2e0262ed
......@@ -31,6 +31,11 @@
<email>yadong.zhang0415@gmail.com</email>
<url>https://www.zhyd.me</url>
</developer>
<developer>
<name>Yangkai.Shen</name>
<email>shenyangkai1994@gmail.com</email>
<url>https://xkcoding.com</url>
</developer>
</developers>
<properties>
......@@ -46,6 +51,7 @@
<junit-version>4.11</junit-version>
<fastjson-version>1.2.44</fastjson-version>
<google-api-version>1.28.0</google-api-version>
<guava-version>27.1-jre</guava-version>
<alipay-sdk-version>3.7.4.ALL</alipay-sdk-version>
</properties>
......
......@@ -329,6 +329,35 @@ public enum ApiUrl {
public String refresh() {
throw new AuthException(ResponseStatus.UNSUPPORTED);
}
},
/**
* 微信
*/
WECHAT {
@Override
public String authorize() {
return "https://open.weixin.qq.com/connect/oauth2/authorize";
}
@Override
public String accessToken() {
return "https://api.weixin.qq.com/sns/oauth2/access_token";
}
@Override
public String userInfo() {
return "https://api.weixin.qq.com/sns/userinfo";
}
@Override
public String revoke() {
throw new AuthException(ResponseStatus.UNSUPPORTED);
}
@Override
public String refresh() {
return "https://api.weixin.qq.com/sns/oauth2/refresh_token";
}
};
public abstract String authorize();
......
package me.zhyd.oauth.request;
import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSONObject;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.exception.AuthException;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.model.AuthSource;
import me.zhyd.oauth.model.AuthUser;
import me.zhyd.oauth.model.AuthUserGender;
import me.zhyd.oauth.utils.UrlBuilder;
/**
* <p>
* 微信登录
* </p>
*
* @package: me.zhyd.oauth.request
* @description: 微信登录
* @author: yangkai.shen
* @date: Created in 2019-05-17 11:11
* @copyright: Copyright (c) 2019
* @version: V1.0
* @modified: yangkai.shen
*/
public class AuthWeChatRequest extends BaseAuthRequest {
public AuthWeChatRequest(AuthConfig config) {
super(config, AuthSource.WECHAT);
}
/**
* 微信的特殊性,此时返回的信息同时包含 openid 和 access_token
*
* @param code 授权码
* @return 所有信息
*/
@Override
protected String getAccessToken(String code) {
String accessTokenUrl = UrlBuilder.getWeChatAccessTokenUrl(config.getClientId(), config.getClientSecret(), code);
HttpResponse response = HttpRequest.get(accessTokenUrl).execute();
JSONObject accessTokenObject = JSONObject.parseObject(response.body());
if (!accessTokenObject.containsKey("access_token") || !accessTokenObject.containsKey("openid") || !accessTokenObject
.containsKey("refresh_token")) {
throw new AuthException("Unable to get access_token or openid or refresh_token from wechat using code [" + code + "]");
}
return response.body();
}
@Override
protected AuthUser getUserInfo(String accessToken) {
String token = this.getToken(accessToken);
String openId = this.getOpenId(accessToken);
HttpResponse response = HttpRequest.get(UrlBuilder.getWeChatUserInfoUrl(token, openId)).execute();
JSONObject object = JSONObject.parseObject(response.body());
if (object.containsKey("errcode")) {
throw new AuthException(object.getString("errmsg"));
}
return AuthUser.builder()
.username(object.getString("nickname"))
.nickname(object.getString("nickname"))
.avatar(object.getString("headimgurl"))
.location(object.getString("country") + "-" + object.getString("province") + "-" + object.getString("city"))
.gender(AuthUserGender.getRealGender(object.getString("sex")))
.accessToken(accessToken)
.source(AuthSource.WECHAT)
.build();
}
/**
* 刷新access token (续期)
*
* @param accessToken 登录成功后返回的accessToken
* @return AuthResponse
*/
@Override
public AuthResponse refresh(String accessToken) {
String refreshToken = getRefreshToken(accessToken);
HttpResponse response = HttpRequest.get(UrlBuilder.getWeChatRefreshUrl(config.getClientId(), refreshToken))
.execute();
JSONObject object = JSONObject.parseObject(response.body());
if (object.containsKey("errcode")) {
throw new AuthException(object.getString("errmsg"));
}
return AuthResponse.builder().data(object).build();
}
private String getRefreshToken(String accessToken) {
JSONObject accessTokenObject = JSONObject.parseObject(accessToken);
return accessTokenObject.getString("refresh_token");
}
private String getOpenId(String accessToken) {
JSONObject accessTokenObject = JSONObject.parseObject(accessToken);
return accessTokenObject.getString("openid");
}
private String getToken(String accessToken) {
JSONObject accessTokenObject = JSONObject.parseObject(accessToken);
return accessTokenObject.getString("access_token");
}
}
......@@ -79,6 +79,7 @@ public abstract class BaseAuthRequest implements AuthRequest {
authorizeUrl = UrlBuilder.getQqAuthorizeUrl(config.getClientId(), config.getRedirectUri());
break;
case WECHAT:
authorizeUrl = UrlBuilder.getWeChatAuthorizeUrl(config.getClientId(), config.getRedirectUri());
break;
case GOOGLE:
break;
......
......@@ -56,6 +56,11 @@ public class UrlBuilder {
private static final String QQ_AUTHORIZE_PATTERN = "{0}?client_id={1}&response_type=code&redirect_uri={2}&state={3}";
private static final String QQ_OPENID_PATTERN = "{0}?access_token={1}";
private static final String WECHAT_AUTHORIZE_PATTERN = "{0}?appid={1}&redirect_uri={2}&response_type=code&scope=snsapi_userinfo#wechat_redirect";
private static final String WECHAT_ACCESS_TOKEN_PATTERN = "{0}?appid={1}&secret={2}&code={3}&grant_type=authorization_code";
private static final String WECHAT_REFRESH_TOKEN_PATTERN = "{0}?appid={1}&grant_type=refresh_token&refresh_token={2}";
private static final String WECHAT_USER_INFO_PATTERN = "{0}?access_token={1}&openid={2}&lang=zh_CN";
/**
* 获取githubtoken的接口地址
*
......@@ -415,4 +420,49 @@ public class UrlBuilder {
public static String getAlipayAuthorizeUrl(String clientId, String redirectUrl) {
return MessageFormat.format(ALIPAY_AUTHORIZE_PATTERN, ApiUrl.ALIPAY.authorize(), clientId, redirectUrl);
}
/**
* 获取微信 授权地址
*
* @param clientId 微信应用的appid
* @param redirectUrl 微信应用授权成功后的回调地址
* @return full url
*/
public static String getWeChatAuthorizeUrl(String clientId, String redirectUrl) {
return MessageFormat.format(WECHAT_AUTHORIZE_PATTERN, ApiUrl.WECHAT.authorize(), clientId, redirectUrl);
}
/**
* 获取微信 token的接口地址
*
* @param clientId 微信应用的appid
* @param clientSecret 微信应用的secret
* @param code 微信授权前的code,用来换token
* @return full url
*/
public static String getWeChatAccessTokenUrl(String clientId, String clientSecret, String code) {
return MessageFormat.format(WECHAT_ACCESS_TOKEN_PATTERN, ApiUrl.WECHAT.accessToken(), clientId, clientSecret, code);
}
/**
* 获取微信 用户详情的接口地址
*
* @param token 微信应用返回的 access token
* @param openId 微信应用返回的openId
* @return full url
*/
public static String getWeChatUserInfoUrl(String token, String openId) {
return MessageFormat.format(WECHAT_USER_INFO_PATTERN, ApiUrl.WECHAT.userInfo(), token, openId);
}
/**
* 获取微信 刷新令牌 地址
*
* @param clientId 微信应用的appid
* @param refreshToken 微信应用返回的刷新token
* @return full url
*/
public static String getWeChatRefreshUrl(String clientId, String refreshToken) {
return MessageFormat.format(WECHAT_REFRESH_TOKEN_PATTERN, ApiUrl.WECHAT.refresh(), clientId, refreshToken);
}
}
package me.zhyd.oauth;
import me.zhyd.oauth.config.AuthConfig;
import me.zhyd.oauth.model.AuthResponse;
import me.zhyd.oauth.request.*;
import org.junit.Test;
......@@ -114,4 +115,17 @@ public class AuthRequestTest {
// 授权登录后会返回一个code,用这个code进行登录
authRequest.login("code");
}
@Test
public void wechatTest() {
AuthRequest authRequest = new AuthWeChatRequest(AuthConfig.builder()
.clientId("clientId")
.clientSecret("clientSecret")
.redirectUri("redirectUri")
.build());
// 返回授权页面,可自行调整
String url = authRequest.authorize();
// 授权登录后会返回一个code,用这个code进行登录
AuthResponse login = authRequest.login("code");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册