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(); } }