Prechádzať zdrojové kódy

saas:支持社交应用的多租户配置

YunaiV 1 rok pred
rodič
commit
d256275099
17 zmenil súbory, kde vykonal 375 pridanie a 140 odobranie
  1. 48 21
      sql/mysql/ruoyi-vue-pro.sql
  2. 0 4
      yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java
  3. 4 1
      yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java
  4. 22 0
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApi.java
  5. 0 10
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java
  6. 1 1
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserBindReqDTO.java
  7. 4 4
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java
  8. 12 6
      yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java
  9. 26 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java
  10. 1 6
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java
  11. 4 3
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
  12. 68 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialClientDO.java
  13. 15 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialClientMapper.java
  14. 34 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java
  15. 94 0
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java
  16. 0 22
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java
  17. 42 62
      yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java

Rozdielové dáta súboru neboli zobrazené, pretože súbor je príliš veľký
+ 48 - 21
sql/mysql/ruoyi-vue-pro.sql


+ 0 - 4
yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/framework/order/core/aop/TradeOrderLogAspect.java

@@ -58,10 +58,6 @@ public class TradeOrderLogAspect {
      */
     private static final ThreadLocal<Map<String, Object>> EXTS = new ThreadLocal<>();
 
-    public TradeOrderLogAspect() {
-        System.out.println();
-    }
-
     @Resource
     private TradeOrderLogService orderLogService;
 

+ 4 - 1
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/auth/MemberAuthServiceImpl.java

@@ -19,6 +19,7 @@ import cn.iocoder.yudao.module.system.api.oauth2.OAuth2TokenApi;
 import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenCreateReqDTO;
 import cn.iocoder.yudao.module.system.api.oauth2.dto.OAuth2AccessTokenRespDTO;
 import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
+import cn.iocoder.yudao.module.system.api.social.SocialClientApi;
 import cn.iocoder.yudao.module.system.api.social.SocialUserApi;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
@@ -56,6 +57,8 @@ public class MemberAuthServiceImpl implements MemberAuthService {
     @Resource
     private SocialUserApi socialUserApi;
     @Resource
+    private SocialClientApi socialClientApi;
+    @Resource
     private OAuth2TokenApi oauth2TokenApi;
 
     @Resource
@@ -154,7 +157,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
 
     @Override
     public String getSocialAuthorizeUrl(Integer type, String redirectUri) {
-        return socialUserApi.getAuthorizeUrl(type, redirectUri);
+        return socialClientApi.getAuthorizeUrl(type, UserTypeEnum.MEMBER.getValue(), redirectUri);
     }
 
     private MemberUserDO login0(String mobile, String password) {

+ 22 - 0
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApi.java

@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.system.api.social;
+
+import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
+
+/**
+ * 社交应用的 API 接口
+ *
+ * @author 芋道源码
+ */
+public interface SocialClientApi {
+
+    /**
+     * 获得社交平台的授权 URL
+     *
+     * @param type 社交平台的类型 {@link SocialTypeEnum}
+     * @param userType 用户类型
+     * @param redirectUri 重定向 URL
+     * @return 社交平台的授权 URL
+     */
+    String getAuthorizeUrl(Integer type, Integer userType, String redirectUri);
+
+}

+ 0 - 10
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApi.java

@@ -4,7 +4,6 @@ import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserUnbindReqDTO;
-import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
 
 import javax.validation.Valid;
 
@@ -16,15 +15,6 @@ import javax.validation.Valid;
 public interface SocialUserApi {
 
     /**
-     * 获得社交平台的授权 URL
-     *
-     * @param type 社交平台的类型 {@link SocialTypeEnum}
-     * @param redirectUri 重定向 URL
-     * @return 社交平台的授权 URL
-     */
-    String getAuthorizeUrl(Integer type, String redirectUri);
-
-    /**
      * 绑定社交用户
      *
      * @param reqDTO 绑定信息

+ 1 - 1
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserBindReqDTO.java

@@ -37,7 +37,7 @@ public class SocialUserBindReqDTO {
      */
     @InEnum(SocialTypeEnum.class)
     @NotNull(message = "社交平台的类型不能为空")
-    private Integer type;
+    private Integer socialType;
     /**
      * 授权码
      */

+ 4 - 4
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/social/dto/SocialUserUnbindReqDTO.java

@@ -33,12 +33,12 @@ public class SocialUserUnbindReqDTO {
      */
     @InEnum(SocialTypeEnum.class)
     @NotNull(message = "社交平台的类型不能为空")
-    private Integer type;
+    private Integer socialType;
 
     /**
-     * 社交平台的 unionId
+     * 社交平台的 openid
      */
-    @NotEmpty(message = "社交平台的 unionId 不能为空")
-    private String unionId;
+    @NotEmpty(message = "社交平台的 openid 不能为空")
+    private String openid;
 
 }

+ 12 - 6
yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/social/SocialTypeEnum.java

@@ -18,33 +18,39 @@ public enum SocialTypeEnum implements IntArrayValuable {
 
     /**
      * Gitee
-     * 文档链接:https://gitee.com/api/v5/oauth_doc#/
+     *
+     * @see <a href="https://gitee.com/api/v5/oauth_doc#/">接入文档</a>
      */
     GITEE(10, "GITEE"),
     /**
      * 钉钉
-     * 文档链接:https://developers.dingtalk.com/document/app/obtain-identity-credentials
+     *
+     * @see <a href="https://developers.dingtalk.com/document/app/obtain-identity-credentials">接入文档</a>
      */
     DINGTALK(20, "DINGTALK"),
 
     /**
      * 企业微信
-     * 文档链接:https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html
+     *
+     * @see <a href="https://xkcoding.com/2019/08/06/use-justauth-integration-wechat-enterprise.html">接入文档</a>
      */
     WECHAT_ENTERPRISE(30, "WECHAT_ENTERPRISE"),
     /**
      * 微信公众平台 - 移动端 H5
-     * 文档链接:https://www.cnblogs.com/juewuzhe/p/11905461.html
+     *
+     * @see <a href="https://www.cnblogs.com/juewuzhe/p/11905461.html">接入文档</a>
      */
     WECHAT_MP(31, "WECHAT_MP"),
     /**
      * 微信开放平台 - 网站应用 PC 端扫码授权登录
-     * 文档链接:https://justauth.wiki/guide/oauth/wechat_open/#_2-申请开发者资质认证
+     *
+     * @see <a href="https://justauth.wiki/guide/oauth/wechat_open/#_2-申请开发者资质认证">接入文档</a>
      */
     WECHAT_OPEN(32, "WECHAT_OPEN"),
     /**
      * 微信小程序
-     * 文档链接:https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html
+     *
+     * @see <a href="https://developers.weixin.qq.com/miniprogram/dev/framework/open-ability/login.html">接入文档</a>
      */
     WECHAT_MINI_APP(34, "WECHAT_MINI_APP"),
     ;

+ 26 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialClientApiImpl.java

@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.system.api.social;
+
+import cn.iocoder.yudao.module.system.service.social.SocialClientService;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import javax.annotation.Resource;
+
+/**
+ * 社交应用的 API 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class SocialClientApiImpl implements SocialClientApi {
+
+    @Resource
+    private SocialClientService socialClientService;
+
+    @Override
+    public String getAuthorizeUrl(Integer type, Integer userType, String redirectUri) {
+        return socialClientService.getAuthorizeUrl(type, userType, redirectUri);
+    }
+
+}

+ 1 - 6
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/social/SocialUserApiImpl.java

@@ -22,11 +22,6 @@ public class SocialUserApiImpl implements SocialUserApi {
     private SocialUserService socialUserService;
 
     @Override
-    public String getAuthorizeUrl(Integer type, String redirectUri) {
-        return socialUserService.getAuthorizeUrl(type, redirectUri);
-    }
-
-    @Override
     public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
         return socialUserService.bindSocialUser(reqDTO);
     }
@@ -34,7 +29,7 @@ public class SocialUserApiImpl implements SocialUserApi {
     @Override
     public void unbindSocialUser(SocialUserUnbindReqDTO reqDTO) {
         socialUserService.unbindSocialUser(reqDTO.getUserId(), reqDTO.getUserType(),
-                reqDTO.getType(), reqDTO.getUnionId());
+                reqDTO.getSocialType(), reqDTO.getOpenid());
     }
 
     @Override

+ 4 - 3
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java

@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.auth;
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
 import cn.iocoder.yudao.framework.common.pojo.CommonResult;
 import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
 import cn.iocoder.yudao.framework.security.config.SecurityProperties;
@@ -16,7 +17,7 @@ import cn.iocoder.yudao.module.system.service.auth.AdminAuthService;
 import cn.iocoder.yudao.module.system.service.permission.MenuService;
 import cn.iocoder.yudao.module.system.service.permission.PermissionService;
 import cn.iocoder.yudao.module.system.service.permission.RoleService;
-import cn.iocoder.yudao.module.system.service.social.SocialUserService;
+import cn.iocoder.yudao.module.system.service.social.SocialClientService;
 import cn.iocoder.yudao.module.system.service.user.AdminUserService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.Parameter;
@@ -57,7 +58,7 @@ public class AuthController {
     @Resource
     private PermissionService permissionService;
     @Resource
-    private SocialUserService socialUserService;
+    private SocialClientService socialClientService;
 
     @Resource
     private SecurityProperties securityProperties;
@@ -147,7 +148,7 @@ public class AuthController {
     })
     public CommonResult<String> socialLogin(@RequestParam("type") Integer type,
                                             @RequestParam("redirectUri") String redirectUri) {
-        return CommonResult.success(socialUserService.getAuthorizeUrl(type, redirectUri));
+        return success(socialClientService.getAuthorizeUrl(type, UserTypeEnum.ADMIN.getValue(), redirectUri));
     }
 
     @PostMapping("/social-login")

+ 68 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/social/SocialClientDO.java

@@ -0,0 +1,68 @@
+package cn.iocoder.yudao.module.system.dal.dataobject.social;
+
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
+import cn.iocoder.yudao.framework.tenant.core.db.TenantBaseDO;
+import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.xingyuv.jushauth.config.AuthConfig;
+import lombok.*;
+
+/**
+ * 社交客户端 DO
+ *
+ * 对应 {@link AuthConfig} 配置,满足不同租户,有自己的客户端配置,实现社交(三方)登录
+ *
+ * @author 芋道源码
+ */
+@TableName(value = "system_social_client", autoResultMap = true)
+@KeySequence("system_social_client_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class SocialClientDO extends TenantBaseDO {
+
+    /**
+     * 编号,自增
+     */
+    @TableId
+    private Long id;
+    /**
+     * 应用名
+     */
+    private String name;
+    /**
+     * 社交类型
+     *
+     * 枚举 {@link SocialTypeEnum}
+     */
+    private Integer socialType;
+    /**
+     * 用户类型
+     *
+     * 目的:不同用户类型,对应不同的小程序,需要自己的配置
+     *
+     * 枚举 {@link UserTypeEnum}
+     */
+    private Integer userType;
+    /**
+     * 状态
+     *
+     * 枚举 {@link CommonStatusEnum}
+     */
+    private Integer status;
+
+    /**
+     * 客户端 id
+     */
+    private String clientId;
+    /**
+     * 客户端 Secret
+     */
+    private String clientSecret;
+
+}

+ 15 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/mysql/social/SocialClientMapper.java

@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.module.system.dal.mysql.social;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO;
+import org.apache.ibatis.annotations.Mapper;
+
+@Mapper
+public interface SocialClientMapper extends BaseMapperX<SocialClientDO> {
+
+    default SocialClientDO selectBySocialTypeAndUserType(Integer socialType, Integer userType) {
+        return selectOne(SocialClientDO::getSocialType, socialType,
+                SocialClientDO::getUserType, userType);
+    }
+
+}

+ 34 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientService.java

@@ -0,0 +1,34 @@
+package cn.iocoder.yudao.module.system.service.social;
+
+import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
+import com.xingyuv.jushauth.model.AuthUser;
+
+/**
+ * 社交应用 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface SocialClientService {
+
+    /**
+     * 获得社交平台的授权 URL
+     *
+     * @param socialType 社交平台的类型 {@link SocialTypeEnum}
+     * @param userType 用户类型
+     * @param redirectUri 重定向 URL
+     * @return 社交平台的授权 URL
+     */
+    String getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri);
+
+    /**
+     * 请求社交平台,获得授权的用户
+     *
+     * @param socialType 社交平台的类型
+     * @param userType 用户类型
+     * @param code 授权码
+     * @param state 授权 state
+     * @return 授权的用户
+     */
+    AuthUser getAuthUser(Integer socialType, Integer userType, String code, String state);
+
+}

+ 94 - 0
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialClientServiceImpl.java

@@ -0,0 +1,94 @@
+package cn.iocoder.yudao.module.system.service.social;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.ReflectUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
+import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
+import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
+import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialClientDO;
+import cn.iocoder.yudao.module.system.dal.mysql.social.SocialClientMapper;
+import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
+import com.xingyuv.jushauth.config.AuthConfig;
+import com.xingyuv.jushauth.model.AuthCallback;
+import com.xingyuv.jushauth.model.AuthResponse;
+import com.xingyuv.jushauth.model.AuthUser;
+import com.xingyuv.jushauth.request.AuthRequest;
+import com.xingyuv.jushauth.utils.AuthStateUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Objects;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_AUTH_FAILURE;
+
+/**
+ * 社交应用 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Slf4j
+public class SocialClientServiceImpl implements SocialClientService {
+
+    @Resource // 由于自定义了 YudaoAuthRequestFactory 无法覆盖默认的 AuthRequestFactory,所以只能注入它
+    private YudaoAuthRequestFactory yudaoAuthRequestFactory;
+
+    @Resource
+    private SocialClientMapper socialClientMapper;
+
+    @Override
+    public String getAuthorizeUrl(Integer socialType, Integer userType, String redirectUri) {
+        // 获得对应的 AuthRequest 实现
+        AuthRequest authRequest = buildAuthRequest(socialType, userType);
+        // 生成跳转地址
+        String authorizeUri = authRequest.authorize(AuthStateUtils.createState());
+        return HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri);
+    }
+
+    @Override
+    public AuthUser getAuthUser(Integer socialType, Integer userType, String code, String state) {
+        // 构建请求
+        AuthRequest authRequest = buildAuthRequest(socialType, userType);
+        AuthCallback authCallback = AuthCallback.builder().code(code).state(state).build();
+        // 执行请求
+        AuthResponse<?> authResponse = authRequest.login(authCallback);
+        log.info("[getAuthUser][请求社交平台 type({}) request({}) response({})]", socialType,
+                toJsonString(authCallback), toJsonString(authResponse));
+        if (!authResponse.ok()) {
+            throw exception(SOCIAL_USER_AUTH_FAILURE, authResponse.getMsg());
+        }
+        return (AuthUser) authResponse.getData();
+    }
+
+    /**
+     * 构建 AuthRequest 对象,支持多租户配置
+     *
+     * @param socialType 社交类型
+     * @param userType 用户类型
+     * @return AuthRequest 对象
+     */
+    private AuthRequest buildAuthRequest(Integer socialType, Integer userType) {
+        // 1. 先查找默认的配置项,从 application-*.yaml 中读取
+        AuthRequest request = yudaoAuthRequestFactory.get(SocialTypeEnum.valueOfType(socialType).getSource());
+        Assert.notNull(request, String.format("社交平台(%d) 不存在", socialType));
+        // 2. 查询 DB 的配置项,如果存在则进行覆盖
+        SocialClientDO client = socialClientMapper.selectBySocialTypeAndUserType(socialType, userType);
+        if (client != null && Objects.equals(client.getStatus(), CommonStatusEnum.ENABLE.getStatus())) {
+            // 2.1 构造新的 AuthConfig 对象
+            AuthConfig authConfig = (AuthConfig) ReflectUtil.getFieldValue(request, "config");
+            AuthConfig newAuthConfig = ReflectUtil.newInstance(authConfig.getClass());
+            BeanUtil.copyProperties(authConfig, newAuthConfig);
+            // 2.2 修改对应的 clientId + clientSecret 密钥
+            newAuthConfig.setClientId(client.getClientId());
+            newAuthConfig.setClientSecret(client.getClientSecret());
+            // 2.3 设置会 request 里,进行后续使用
+            ReflectUtil.setFieldValue(request, "config", newAuthConfig);
+        }
+        return request;
+    }
+
+}

+ 0 - 22
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserService.java

@@ -7,7 +7,6 @@ import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
 
 import javax.validation.Valid;
-import javax.validation.constraints.NotNull;
 import java.util.List;
 
 /**
@@ -18,27 +17,6 @@ import java.util.List;
 public interface SocialUserService {
 
     /**
-     * 获得社交平台的授权 URL
-     *
-     * @param type 社交平台的类型 {@link SocialTypeEnum}
-     * @param redirectUri 重定向 URL
-     * @return 社交平台的授权 URL
-     */
-    String getAuthorizeUrl(Integer type, String redirectUri);
-
-    /**
-     * 授权获得对应的社交用户
-     * 如果授权失败,则会抛出 {@link ServiceException} 异常
-     *
-     * @param type 社交平台的类型 {@link SocialTypeEnum}
-     * @param code 授权码
-     * @param state state
-     * @return 授权用户
-     */
-    @NotNull
-    SocialUserDO authSocialUser(Integer type, String code, String state);
-
-    /**
      * 获得指定用户的社交用户列表
      *
      * @param userId 用户编号

+ 42 - 62
yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/social/SocialUserServiceImpl.java

@@ -2,8 +2,7 @@ package cn.iocoder.yudao.module.system.service.social;
 
 import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.lang.Assert;
-import cn.iocoder.yudao.framework.common.util.http.HttpUtils;
-import cn.iocoder.yudao.framework.social.core.YudaoAuthRequestFactory;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
 import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
 import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserBindDO;
@@ -11,24 +10,22 @@ import cn.iocoder.yudao.module.system.dal.dataobject.social.SocialUserDO;
 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserBindMapper;
 import cn.iocoder.yudao.module.system.dal.mysql.social.SocialUserMapper;
 import cn.iocoder.yudao.module.system.enums.social.SocialTypeEnum;
-import com.xingyuv.jushauth.model.AuthCallback;
-import com.xingyuv.jushauth.model.AuthResponse;
 import com.xingyuv.jushauth.model.AuthUser;
-import com.xingyuv.jushauth.request.AuthRequest;
-import com.xingyuv.jushauth.utils.AuthStateUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 
 import javax.annotation.Resource;
+import javax.validation.constraints.NotNull;
 import java.util.Collections;
 import java.util.List;
 
 import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
 import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
 import static cn.iocoder.yudao.framework.common.util.json.JsonUtils.toJsonString;
-import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.AUTH_THIRD_LOGIN_NOT_BIND;
+import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND;
 
 /**
  * 社交用户 Service 实现类
@@ -40,51 +37,13 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
 @Slf4j
 public class SocialUserServiceImpl implements SocialUserService {
 
-    @Resource// 由于自定义了 YudaoAuthRequestFactory 无法覆盖默认的 AuthRequestFactory,所以只能注入它
-    private YudaoAuthRequestFactory yudaoAuthRequestFactory;
-
     @Resource
     private SocialUserBindMapper socialUserBindMapper;
     @Resource
     private SocialUserMapper socialUserMapper;
 
-    @Override
-    public String getAuthorizeUrl(Integer type, String redirectUri) {
-        // 获得对应的 AuthRequest 实现
-        AuthRequest authRequest = yudaoAuthRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource());
-        // 生成跳转地址
-        String authorizeUri = authRequest.authorize(AuthStateUtils.createState());
-        return HttpUtils.replaceUrlQuery(authorizeUri, "redirect_uri", redirectUri);
-    }
-
-    @Override
-    public SocialUserDO authSocialUser(Integer type, String code, String state) {
-        // 优先从 DB 中获取,因为 code 有且可以使用一次。
-        // 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次
-        SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(type, code, state);
-        if (socialUser != null) {
-            return socialUser;
-        }
-
-        // 请求获取
-        AuthUser authUser = getAuthUser(type, code, state);
-        Assert.notNull(authUser, "三方用户不能为空");
-
-        // 保存到 DB 中
-        socialUser = socialUserMapper.selectByTypeAndOpenid(type, authUser.getUuid());
-        if (socialUser == null) {
-            socialUser = new SocialUserDO();
-        }
-        socialUser.setType(type).setCode(code).setState(state) // 需要保存 code + state 字段,保证后续可查询
-                .setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken()).setRawTokenInfo((toJsonString(authUser.getToken())))
-                .setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()).setRawUserInfo(toJsonString(authUser.getRawUserInfo()));
-        if (socialUser.getId() == null) {
-            socialUserMapper.insert(socialUser);
-        } else {
-            socialUserMapper.updateById(socialUser);
-        }
-        return socialUser;
-    }
+    @Resource
+    private SocialClientService socialClientService;
 
     @Override
     public List<SocialUserDO> getSocialUserList(Long userId, Integer userType) {
@@ -101,7 +60,8 @@ public class SocialUserServiceImpl implements SocialUserService {
     @Transactional
     public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
         // 获得社交用户
-        SocialUserDO socialUser = authSocialUser(reqDTO.getType(), reqDTO.getCode(), reqDTO.getState());
+        SocialUserDO socialUser = authSocialUser(reqDTO.getSocialType(), reqDTO.getUserType(),
+                reqDTO.getCode(), reqDTO.getState());
         Assert.notNull(socialUser, "社交用户不能为空");
 
         // 社交用户可能之前绑定过别的用户,需要进行解绑
@@ -134,7 +94,7 @@ public class SocialUserServiceImpl implements SocialUserService {
     @Override
     public SocialUserRespDTO getSocialUser(Integer userType, Integer type, String code, String state) {
         // 获得社交用户
-        SocialUserDO socialUser = authSocialUser(type, code, state);
+        SocialUserDO socialUser = authSocialUser(type, userType, code, state);
         Assert.notNull(socialUser, "社交用户不能为空");
 
         // 如果未绑定的社交用户,则无法自动登录,进行报错
@@ -146,24 +106,44 @@ public class SocialUserServiceImpl implements SocialUserService {
         return new SocialUserRespDTO(socialUser.getOpenid(), socialUserBind.getUserId());
     }
 
+    // TODO 芋艿:调整下单测
     /**
-     * 请求社交平台,获得授权的用户
+     * 授权获得对应的社交用户
+     * 如果授权失败,则会抛出 {@link ServiceException} 异常
      *
-     * @param type 社交平台的类型
+     * @param type 社交平台的类型 {@link SocialTypeEnum}
+     * @param userType 用户类型
      * @param code 授权码
-     * @param state 授权 state
-     * @return 授权用户
+     * @param state state
+     * @return 授权用户
      */
-    private AuthUser getAuthUser(Integer type, String code, String state) {
-        AuthRequest authRequest = yudaoAuthRequestFactory.get(SocialTypeEnum.valueOfType(type).getSource());
-        AuthCallback authCallback = AuthCallback.builder().code(code).state(state).build();
-        AuthResponse<?> authResponse = authRequest.login(authCallback);
-        log.info("[getAuthUser][请求社交平台 type({}) request({}) response({})]", type,
-                toJsonString(authCallback), toJsonString(authResponse));
-        if (!authResponse.ok()) {
-            throw exception(SOCIAL_USER_AUTH_FAILURE, authResponse.getMsg());
+    @NotNull
+    public SocialUserDO authSocialUser(Integer type, Integer userType, String code, String state) {
+        // 优先从 DB 中获取,因为 code 有且可以使用一次。
+        // 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次
+        SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(type, code, state);
+        if (socialUser != null) {
+            return socialUser;
         }
-        return (AuthUser) authResponse.getData();
+
+        // 请求获取
+        AuthUser authUser = socialClientService.getAuthUser(type, userType, code, state);
+        Assert.notNull(authUser, "三方用户不能为空");
+
+        // 保存到 DB 中
+        socialUser = socialUserMapper.selectByTypeAndOpenid(type, authUser.getUuid());
+        if (socialUser == null) {
+            socialUser = new SocialUserDO();
+        }
+        socialUser.setType(type).setCode(code).setState(state) // 需要保存 code + state 字段,保证后续可查询
+                .setOpenid(authUser.getUuid()).setToken(authUser.getToken().getAccessToken()).setRawTokenInfo((toJsonString(authUser.getToken())))
+                .setNickname(authUser.getNickname()).setAvatar(authUser.getAvatar()).setRawUserInfo(toJsonString(authUser.getRawUserInfo()));
+        if (socialUser.getId() == null) {
+            socialUserMapper.insert(socialUser);
+        } else {
+            socialUserMapper.updateById(socialUser);
+        }
+        return socialUser;
     }
 
 }