From cdcf9a5e8dfb3466f27f14de279e5cc71ba08f2e Mon Sep 17 00:00:00 2001 From: "yadong.zhang" Date: Sat, 14 Dec 2024 17:02:33 +0800 Subject: [PATCH] =?UTF-8?q?:fire:=20=E6=94=AF=E6=8C=81=E6=94=AF=E4=BB=98?= =?UTF-8?q?=E5=AE=9D=E8=AF=81=E4=B9=A6=E6=A8=A1=E5=BC=8F=E7=99=BB=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOGS.md | 5 +- pom.xml | 2 +- .../oauth/request/AuthAlipayCertRequest.java | 152 ++++++++++++++++++ .../zhyd/oauth/request/AuthAlipayRequest.java | 2 +- 4 files changed, 157 insertions(+), 4 deletions(-) create mode 100644 src/main/java/me/zhyd/oauth/request/AuthAlipayCertRequest.java diff --git a/CHANGELOGS.md b/CHANGELOGS.md index aa90ed54..695f0329 100644 --- a/CHANGELOGS.md +++ b/CHANGELOGS.md @@ -1,14 +1,15 @@ ## 1.16.7 -### 2024/08/03 +### 2024/12/14 - 新增 - 添加`appleid`社交登录能力。 [Github#192](https://github.com/justauth/JustAuth/pull/192) + - 添加`支付宝证书模式`登录能力(原支持的公钥登录模式依然可用)。 - 添加`figma`社交登录能力。 [Gitee#41](https://gitee.com/yadong.zhang/JustAuth/pulls/41) - 添加新版`企业微信扫码`登录能力。 [Github Issue#165](https://github.com/justauth/JustAuth/issues/165) - 添加新版`钉钉扫码`登录能力。 [Gitee Issue#I73FZL](https://gitee.com/yadong.zhang/JustAuth/issues/I73FZL) - 添加新版`华为`登录能力,原`AuthHuaweiRequest`会在后面版本被弃用,如有使用,请切换到`AuthHuaweiV3Request` - - 新增微信小程序授权登录 + - 添加`微信小程序`登录能力。 - 优化 - 更新 Google 端点地址。[Github #198](https://github.com/justauth/JustAuth/pull/198) - Amazon PKCE 中的 `code_verifier` 基于 `state` 缓存 diff --git a/pom.xml b/pom.xml index 020ea2df..a60abfcc 100644 --- a/pom.xml +++ b/pom.xml @@ -61,7 +61,7 @@ 1.18.30 4.13.2 1.2.83 - 4.17.5.ALL + 4.39.165.ALL 0.8.2 0.12.3 1.78 diff --git a/src/main/java/me/zhyd/oauth/request/AuthAlipayCertRequest.java b/src/main/java/me/zhyd/oauth/request/AuthAlipayCertRequest.java new file mode 100644 index 00000000..6277ec98 --- /dev/null +++ b/src/main/java/me/zhyd/oauth/request/AuthAlipayCertRequest.java @@ -0,0 +1,152 @@ +package me.zhyd.oauth.request; + + +import com.alibaba.fastjson.JSONObject; +import com.alipay.api.AlipayApiException; +import com.alipay.api.AlipayClient; +import com.alipay.api.AlipayConfig; +import com.alipay.api.DefaultAlipayClient; +import com.alipay.api.request.AlipaySystemOauthTokenRequest; +import com.alipay.api.request.AlipayUserInfoShareRequest; +import com.alipay.api.response.AlipaySystemOauthTokenResponse; +import com.alipay.api.response.AlipayUserInfoShareResponse; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.enums.AuthResponseStatus; +import me.zhyd.oauth.enums.AuthUserGender; +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthResponse; +import me.zhyd.oauth.model.AuthToken; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.utils.StringUtils; +import me.zhyd.oauth.utils.UrlBuilder; + +import static me.zhyd.oauth.config.AuthDefaultSource.ALIPAY; + +/** + * 支付宝证书模式登录 + * + * @since 1.16.7 + */ +public class AuthAlipayCertRequest extends AuthDefaultRequest { + + private final AlipayClient alipayClient; + + public AuthAlipayCertRequest(AuthConfig config, AlipayConfig alipayConfig) { + super(config, ALIPAY); + try { + this.alipayClient = new DefaultAlipayClient(alipayConfig); + } catch (AlipayApiException e) { + throw new AuthException(e); + } + } + + @Override + protected void checkCode(AuthCallback authCallback) { + if (StringUtils.isEmpty(authCallback.getAuth_code())) { + throw new AuthException(AuthResponseStatus.ILLEGAL_CODE, source); + } + } + + @Override + public AuthToken getAccessToken(AuthCallback authCallback) { + AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest(); + request.setGrantType("authorization_code"); + request.setCode(authCallback.getAuth_code()); + AlipaySystemOauthTokenResponse response; + try { + response = this.alipayClient.certificateExecute(request); + } catch (Exception e) { + throw new AuthException(e); + } + if (!response.isSuccess()) { + throw new AuthException(response.getSubMsg()); + } + return AuthToken.builder() + .accessToken(response.getAccessToken()) + .uid(response.getUserId()) + .expireIn(Integer.parseInt(response.getExpiresIn())) + .refreshToken(response.getRefreshToken()) + .build(); + } + + + /** + * 刷新access token (续期) + * + * @param authToken 登录成功后返回的Token信息 + * @return AuthResponse + */ + @Override + public AuthResponse refresh(AuthToken authToken) { + AlipaySystemOauthTokenRequest request = new AlipaySystemOauthTokenRequest(); + request.setGrantType("refresh_token"); + request.setRefreshToken(authToken.getRefreshToken()); + AlipaySystemOauthTokenResponse response = null; + try { + response = this.alipayClient.certificateExecute(request); + } catch (Exception e) { + throw new AuthException(e); + } + if (!response.isSuccess()) { + throw new AuthException(response.getSubMsg()); + } + return AuthResponse.builder() + .code(AuthResponseStatus.SUCCESS.getCode()) + .data(AuthToken.builder() + .accessToken(response.getAccessToken()) + .uid(response.getUserId()) + .expireIn(Integer.parseInt(response.getExpiresIn())) + .refreshToken(response.getRefreshToken()) + .build()) + .build(); + } + + @Override + public AuthUser getUserInfo(AuthToken authToken) { + String accessToken = authToken.getAccessToken(); + AlipayUserInfoShareRequest request = new AlipayUserInfoShareRequest(); + AlipayUserInfoShareResponse response = null; + try { + response = this.alipayClient.certificateExecute(request, accessToken); + } catch (AlipayApiException e) { + throw new AuthException(e.getErrMsg(), e); + } + if (!response.isSuccess()) { + throw new AuthException(response.getSubMsg()); + } + + String province = response.getProvince(), city = response.getCity(); + String location = String.format("%s %s", StringUtils.isEmpty(province) ? "" : province, StringUtils.isEmpty(city) ? "" : city); + + return AuthUser.builder() + .rawUserInfo(JSONObject.parseObject(JSONObject.toJSONString(response))) + .uuid(response.getOpenId()) + .username(StringUtils.isEmpty(response.getUserName()) ? response.getNickName() : response.getUserName()) + .nickname(response.getNickName()) + .avatar(response.getAvatar()) + .location(location) + .gender(AuthUserGender.getRealGender(response.getGender())) + .token(authToken) + .source(source.toString()) + .build(); + } + + + /** + * 返回带{@code state}参数的授权url,授权回调时会带上这个{@code state} + * + * @param state state 验证授权流程的参数,可以防止csrf + * @return 返回授权地址 + * @since 1.9.3 + */ + @Override + public String authorize(String state) { + return UrlBuilder.fromBaseUrl(source.authorize()) + .queryParam("app_id", config.getClientId()) + .queryParam("scope", "auth_user") + .queryParam("redirect_uri", config.getRedirectUri()) + .queryParam("state", getRealState(state)) + .build(); + } +} diff --git a/src/main/java/me/zhyd/oauth/request/AuthAlipayRequest.java b/src/main/java/me/zhyd/oauth/request/AuthAlipayRequest.java index b8323468..428ca869 100644 --- a/src/main/java/me/zhyd/oauth/request/AuthAlipayRequest.java +++ b/src/main/java/me/zhyd/oauth/request/AuthAlipayRequest.java @@ -26,7 +26,7 @@ import java.net.InetSocketAddress; /** - * 支付宝登录 + * 支付宝公钥模式登录 * * @author yadong.zhang (yadong.zhang0415(a)gmail.com) * @since 1.0.1