package com.iailab.module.system.service.social;
|
|
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.lang.Assert;
|
import com.iailab.framework.common.exception.ServiceException;
|
import com.iailab.framework.common.pojo.PageResult;
|
import com.iailab.module.system.api.social.dto.SocialUserBindReqDTO;
|
import com.iailab.module.system.api.social.dto.SocialUserRespDTO;
|
import com.iailab.module.system.controller.admin.socail.vo.user.SocialUserPageReqVO;
|
import com.iailab.module.system.dal.dataobject.social.SocialUserBindDO;
|
import com.iailab.module.system.dal.dataobject.social.SocialUserDO;
|
import com.iailab.module.system.dal.mysql.social.SocialUserBindMapper;
|
import com.iailab.module.system.dal.mysql.social.SocialUserMapper;
|
import com.iailab.module.system.enums.social.SocialTypeEnum;
|
import com.xingyuv.jushauth.model.AuthUser;
|
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 com.iailab.framework.common.exception.util.ServiceExceptionUtil.exception;
|
import static com.iailab.framework.common.util.collection.CollectionUtils.convertSet;
|
import static com.iailab.framework.common.util.json.JsonUtils.toJsonString;
|
import static com.iailab.module.system.enums.ErrorCodeConstants.SOCIAL_USER_NOT_FOUND;
|
|
/**
|
* 社交用户 Service 实现类
|
*
|
* @author iailab
|
*/
|
@Service
|
@Validated
|
@Slf4j
|
public class SocialUserServiceImpl implements SocialUserService {
|
|
@Resource
|
private SocialUserBindMapper socialUserBindMapper;
|
@Resource
|
private SocialUserMapper socialUserMapper;
|
|
@Resource
|
private SocialClientService socialClientService;
|
|
@Override
|
public List<SocialUserDO> getSocialUserList(Long userId, Integer userType) {
|
// 获得绑定
|
List<SocialUserBindDO> socialUserBinds = socialUserBindMapper.selectListByUserIdAndUserType(userId, userType);
|
if (CollUtil.isEmpty(socialUserBinds)) {
|
return Collections.emptyList();
|
}
|
// 获得社交用户
|
return socialUserMapper.selectBatchIds(convertSet(socialUserBinds, SocialUserBindDO::getSocialUserId));
|
}
|
|
@Override
|
@Transactional(rollbackFor = Exception.class)
|
public String bindSocialUser(SocialUserBindReqDTO reqDTO) {
|
// 获得社交用户
|
SocialUserDO socialUser = authSocialUser(reqDTO.getSocialType(), reqDTO.getUserType(),
|
reqDTO.getCode(), reqDTO.getState());
|
Assert.notNull(socialUser, "社交用户不能为空");
|
|
// 社交用户可能之前绑定过别的用户,需要进行解绑
|
socialUserBindMapper.deleteByUserTypeAndSocialUserId(reqDTO.getUserType(), socialUser.getId());
|
|
// 用户可能之前已经绑定过该社交类型,需要进行解绑
|
socialUserBindMapper.deleteByUserTypeAndUserIdAndSocialType(reqDTO.getUserType(), reqDTO.getUserId(),
|
socialUser.getType());
|
|
// 绑定当前登录的社交用户
|
SocialUserBindDO socialUserBind = SocialUserBindDO.builder()
|
.userId(reqDTO.getUserId()).userType(reqDTO.getUserType())
|
.socialUserId(socialUser.getId()).socialType(socialUser.getType()).build();
|
socialUserBindMapper.insert(socialUserBind);
|
return socialUser.getOpenid();
|
}
|
|
@Override
|
public void unbindSocialUser(Long userId, Integer userType, Integer socialType, String openid) {
|
// 获得 openid 对应的 SocialUserDO 社交用户
|
SocialUserDO socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, openid);
|
if (socialUser == null) {
|
throw exception(SOCIAL_USER_NOT_FOUND);
|
}
|
|
// 获得对应的社交绑定关系
|
socialUserBindMapper.deleteByUserTypeAndUserIdAndSocialType(userType, userId, socialUser.getType());
|
}
|
|
@Override
|
public SocialUserRespDTO getSocialUserByUserId(Integer userType, Long userId, Integer socialType) {
|
// 获得绑定用户
|
SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserIdAndUserTypeAndSocialType(userId, userType, socialType);
|
if (socialUserBind == null) {
|
return null;
|
}
|
// 获得社交用户
|
SocialUserDO socialUser = socialUserMapper.selectById(socialUserBind.getSocialUserId());
|
Assert.notNull(socialUser, "社交用户不能为空");
|
return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(),
|
socialUserBind.getUserId());
|
}
|
|
@Override
|
public SocialUserRespDTO getSocialUserByCode(Integer userType, Integer socialType, String code, String state) {
|
// 获得社交用户
|
SocialUserDO socialUser = authSocialUser(socialType, userType, code, state);
|
Assert.notNull(socialUser, "社交用户不能为空");
|
|
// 获得绑定用户
|
SocialUserBindDO socialUserBind = socialUserBindMapper.selectByUserTypeAndSocialUserId(userType,
|
socialUser.getId());
|
return new SocialUserRespDTO(socialUser.getOpenid(), socialUser.getNickname(), socialUser.getAvatar(),
|
socialUserBind != null ? socialUserBind.getUserId() : null);
|
}
|
|
/**
|
* 授权获得对应的社交用户
|
* 如果授权失败,则会抛出 {@link ServiceException} 异常
|
*
|
* @param socialType 社交平台的类型 {@link SocialTypeEnum}
|
* @param userType 用户类型
|
* @param code 授权码
|
* @param state state
|
* @return 授权用户
|
*/
|
@NotNull
|
public SocialUserDO authSocialUser(Integer socialType, Integer userType, String code, String state) {
|
// 优先从 DB 中获取,因为 code 有且可以使用一次。
|
// 在社交登录时,当未绑定 User 时,需要绑定登录,此时需要 code 使用两次
|
SocialUserDO socialUser = socialUserMapper.selectByTypeAndCodeAnState(socialType, code, state);
|
if (socialUser != null) {
|
return socialUser;
|
}
|
|
// 请求获取
|
AuthUser authUser = socialClientService.getAuthUser(socialType, userType, code, state);
|
Assert.notNull(authUser, "三方用户不能为空");
|
|
// 保存到 DB 中
|
socialUser = socialUserMapper.selectByTypeAndOpenid(socialType, authUser.getUuid());
|
if (socialUser == null) {
|
socialUser = new SocialUserDO();
|
}
|
socialUser.setType(socialType).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;
|
}
|
|
// ==================== 社交用户 CRUD ====================
|
|
@Override
|
public SocialUserDO getSocialUser(Long id) {
|
return socialUserMapper.selectById(id);
|
}
|
|
@Override
|
public PageResult<SocialUserDO> getSocialUserPage(SocialUserPageReqVO pageReqVO) {
|
return socialUserMapper.selectPage(pageReqVO);
|
}
|
|
}
|