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