package com.cyksj.service.user.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.cyksj.common.constant.Constant; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.task.GlobalThreadPoolTaskExecutor; import com.cyksj.common.util.Codec; import com.cyksj.common.util.Jsons; import com.cyksj.common.util.StringUtil; import com.cyksj.config.wxlogin.WxOpenPlatYHLXLoginConfig; import com.cyksj.dto.UserSharedDto; import com.cyksj.mapper.*; import com.cyksj.mapper.channel.ChannelPopularizeMapper; import com.cyksj.mapper.claudecode.ClaudeCodeUserPopularizeTrialTicketRecordMapper; import com.cyksj.mapper.corp.*; import com.cyksj.mapper.manage.coupon.CouponDistributePopularizeMapper; import com.cyksj.mapper.manage.coupon.CouponRecommendMapper; import com.cyksj.mapper.manage.cps.UserDistributePopularizeMapper; import com.cyksj.mapper.manage.distribute.UserDistributeMapper; import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper; import com.cyksj.mapper.market.task.UserBindDetailMapper; import com.cyksj.mapper.mirrorshop.UserMirrorShopMapper; import com.cyksj.mapper.station.CollegeStudentStationUserRelateMapper; import com.cyksj.mapper.vip.VipUserMapper; import com.cyksj.model.dto.*; import com.cyksj.model.entity.*; import com.cyksj.model.manage.views.GroupsRelationView; import com.cyksj.model.request.LoginReq; import com.cyksj.model.views.*; import com.cyksj.redis.RedisService; import com.cyksj.service.claude.ClaudeCodeService; import com.cyksj.service.distribute.DistributeService; import com.cyksj.service.distribute.equipment.EquipmentDistributeService; import com.cyksj.service.exchange.ExchangeCodeService; import com.cyksj.service.mange.coupon.CouponCommonService; import com.cyksj.service.market.task.BindTaskService; import com.cyksj.service.relation.GroupRelationFrontService; import com.cyksj.service.shop.YhShopDistributeService; import com.cyksj.service.sys.SysConfigService; import com.cyksj.service.user.*; import com.cyksj.service.wechat.WeChatService; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.param.Operator; import com.ejlchina.searcher.util.MapUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.dao.DuplicateKeyException; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.Assert; import javax.servlet.http.HttpServletRequest; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Optional; /** * @author chan * @date 2021/10/10 下午3:27 */ @Slf4j @Service @RequiredArgsConstructor public class UserServiceImpl extends ServiceImpl implements UserService { private final DistributeService distributeService; private final EquipmentDistributeService equipDistributeService; private final ChannelPopularizeMapper channelPopularizeMapper; private final CouponCommonService couponCommonService; private final RedisService redisService; private final SysConfigService sysConfigService; private final UserBindDetailMapper userBindDetailMapper; private final UserDistributePopularizeMapper distributePopularizeMapper; private final UserMapper userMapper; private final PhoneCodeMapper phoneCodeMapper; private final WeChatService weChatService; private final BindTaskService bindTaskService; private final WxOpenPlatYHLXLoginConfig wxOpenPlatYHLXLoginConfig; private final GiftCardUserRecordMapper giftCardUserRecordMapper; private final ExchangeCodeService exchangeCodeService; private final GoodsDonSkuMapper goodsDonSkuMapper; private final GroupsRelationMapper groupsRelationMapper; private final BeanSearcher beanSearcher; private final UserBindRelationService userBindRelationService; private final YhShopDistributeService yhShopDistributeService; private final CorpUserMapper corpUserMapper; private final CorpUserTagMapper corpUserTagMapper; private final CorpFollowActiveCodeMapper corpFollowActiveCodeMapper; private final CorpCustomerAcquisitionLinkMapper corpCustomerAcquisitionLinkMapper; private final CorpWelcomeTemplateMapper corpWelcomeTemplateMapper; private final UserLoginRecordService userLoginRecordService; private final UserDistributeSharedMapper userDistributeSharedMapper; private final BadIntentionOpService badIntentionOpService; private final CollegeStudentStationUserRelateMapper collegeStudentStationUserRelateMapper; private final GroupRelationFrontService groupRelationFrontService; private final UserMirrorShopMapper userMirrorShopMapper; private final UserCertRecordMapper userCertRecordMapper; private final UserStudentCertRecordMapper userStudentCertRecordMapper; private final OrderDonMapper orderDonMapper; private final UserCommonService userCommonService; private final VipUserMapper vipUserMapper; private final CouponDistributePopularizeMapper couponDistributePopularizeMapper; private final UserDistributeMapper userDistributeMapper; private final ClaudeCodeService claudeCodeService; private final ClaudeCodeUserPopularizeTrialTicketRecordMapper claudeCodeUserPopularizeTrialTicketRecordMapper; private final CouponRecommendMapper couponRecommendMapper; private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance(); @Override public User saveAuth(GzhOAuth2UserInfo info, AuthRedirect re, User.RegisterEnv registerEnv) throws Exception { Long sharedId = re.getSharedId(); Integer dsType = re.getDsType(); Long pid = re.getPid(); String dsCode = re.getDsCode(); String callback = re.getCk(); String callbackType = re.getCt(); String customId = re.getCd(); final String unionid = info.getUnionid(); if (StrUtil.isEmpty(unionid)) { throw BusinessRuntimeException.getInstance("授权操作异常,请刷新页面"); } User user = getSyncUser(info.getOpenid(), info.getUnionid(), null); user = Optional.ofNullable(user).orElseGet(() -> new User() .setUnionid(unionid)); user.setCountry(info.getCountry()) .setProvince(info.getProvince()) .setCity(info.getCity()); if (user.getSex() == null) { user.setSex(info.getSex()); } if (StrUtil.isEmpty(user.getHeadimgurl())) { user.setHeadimgurl(info.getHeadimgurl()); } if (StrUtil.isEmpty(user.getNickname())) { user.setNickname(info.getNickname()); } user.setUnionid(unionid); user.setOpenId(info.getOpenid()); Boolean isNewUser = false; if (user.getId() == null) { isNewUser = true; user.setPopularizeId(pid); user.setRegisterEnv(registerEnv.name()); if (!redisService.setNx(RedisService.key.REPEAT_USER_KEY.getNameFormat(user.getUnionid()), user.getUnionid(), RedisService.key.REPEAT_USER_KEY.getTimeout())) { return this.getOne(Wrappers.lambdaQuery(User.class) .eq(User::getUnionid, unionid).last("limit 1")); } this.save(user); //缓存用户注册 回传信息 if (StrUtil.isNotBlank(callback)) { OrderDonPostDataDto orderDonPostDataDto = new OrderDonPostDataDto().setCallback(callback) .setCallbackType(callbackType); redisService.set(RedisService.key.ORDER_DON_POST_DATA_USER_KEY.getName() + user.getId(), Jsons.toJson(orderDonPostDataDto)); } //发放新用户福利 final Long fUid = user.getId(); TASK_POOL.execute(() -> { // try { // sendNewUserWelfare(fUid); // } catch (Exception e) { // } //去关联对应企业微信用户 relateCorpUserAndSengWelfare(fUid, unionid); }); } else { if (StrUtil.isEmpty(user.getRegisterEnv())) { user.setRegisterEnv(registerEnv.name()); } this.updateById(user); } Long dsPopularizeId = null; if (StrUtil.isNotBlank(dsCode)) { UserSharedDto userSharedDto = getUserShredDtoByDsCode(dsCode); sharedId = userSharedDto.getSharedId(); dsPopularizeId = userSharedDto.getDsPopularizeId(); } if (sharedId != null && isNewUser) { if (dsType == null || dsType == 1) { distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId); } } //店铺注册用户 关联 if (isNewUser && StrUtil.isNotBlank(customId)) { yhShopDistributeService.saveDistributionInvitation(customId, user.getId(), re.getCmt()); } Long userId = user.getId(); if (isNewUser && pid != null) { TASK_POOL.execute(() -> { sendFixedCustomerCoupon(pid, userId, unionid); }); } //新旧用户都可实物分销 if (sharedId != null && dsType != null && dsType == 2) { equipDistributeService.saveDistributionInvitation(sharedId, isNewUser, user.getId()); } //查找渠道是否有设置了对应的claude code优惠码 setClaudeCodePopularize(sharedId, dsPopularizeId, user); //每日活跃记录 userLoginRecordService.saveUserLoginDayRecord(user.getId()); //是否是大学生快递站进来的用户 Integer cst = re.getCst(); if (cst != null) { TASK_POOL.execute(() -> { handlerCollegeStudentUser(userId, cst); }); } return user; } @Override public UserWhoami whoami(long userId, Boolean ccCode) { User user = this.getById(userId); Assert.notNull(user, "业务处理失败,请联系客服"); UserWhoami userWhoami = new UserWhoami(); if (StrUtil.isEmpty(user.getShowId())) { user.setShowId(userCommonService.getUserShowId(userId)); } BeanUtil.copyProperties(user, userWhoami); UserBindDetail bindPhone = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class) .eq(StrUtil.isNotEmpty(user.getUnionid()), UserBindDetail::getUserId, userId) .eq(StrUtil.isNotBlank(user.getLoginPhone()), UserBindDetail::getPhoneUserId, userId) .eq(StrUtil.isNotEmpty(user.getEmail()), UserBindDetail::getEmailUserId, userId).last("limit 1")); //手机号 if (bindPhone != null) { userWhoami.setBindPhone(bindPhone.getPhone()); userWhoami.setBindEmail(bindPhone.getEmail()); } Integer type = 3; if (StrUtil.isNotBlank(user.getLoginPhone())) { type = 1; } else if (StrUtil.isNotBlank(user.getEmail())) { type = 2; } userWhoami.setType(type); //是否加过企业微信 String unionId = user.getUnionid(); if (StrUtil.isEmpty(unionId)) { //获取绑定的微信用户id UserBindDetail bindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class) .and(qr -> qr.eq(UserBindDetail::getPhoneUserId, user.getId()).or().eq(UserBindDetail::getEmailUserId, user.getId())) .last("limit 1")); if (bindDetail != null && bindDetail.getUserId() != null) { User wxUser = userMapper.selectById(bindDetail.getUserId()); if (wxUser != null) { unionId = wxUser.getUnionid(); } } } if (StrUtil.isNotBlank(unionId)) { CorpUserFollowView corpUserFollowView = beanSearcher.searchFirst(CorpUserFollowView.class, MapUtils.builder() .field(CorpUserFollowView::getUnionId, unionId) .field(CorpUserFollowView::getStatus, 1).build()); if (corpUserFollowView != null) { userWhoami.setIsJoinWx(true); } } //是否下过单 List userIdList = userBindRelationService.getRelationUserIdList(userId, user); Integer selectCount = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class) .in(OrderDon::getUserId, userIdList) .notIn(OrderDon::getStatus, Constant.noOrderStatus)); userWhoami.setIsPay(selectCount > 0); if (ccCode != null) { Number number = beanSearcher.searchCount(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getUserId, userIdList).op(Operator.InList).field(GroupsRelationView::getSkuId, Constant.DISTRIBUTE_CLAUDE_CODE_TRIAL_SKU_ID).field(GroupsRelationView::getGoodsId, Constant.CLAUDE_CODE_GOODS_ID).build()); userWhoami.setCcCode(number.intValue() > 0); Integer selectCount1 = claudeCodeUserPopularizeTrialTicketRecordMapper.selectCount(Wrappers.lambdaQuery(ClaudeCodeUserPopularizeTrialTicketRecord.class).in(ClaudeCodeUserPopularizeTrialTicketRecord::getUserId, userIdList)); if (selectCount1 == 0) { ClaudeCodeUserPopularizeTrialTicketRecord record = new ClaudeCodeUserPopularizeTrialTicketRecord(); record.setUserId(userId); claudeCodeUserPopularizeTrialTicketRecordMapper.insert(record); } userWhoami.setTc(selectCount1 == 0); } return userWhoami; } @Override public User getSyncUser(String openId, String unionId, WxSyncLog wxSyncLog) { User user; //迁移公众号之后同步授权后信息 //是否是迁移用户 if (wxSyncLog != null) { user = this.getOne(Wrappers.lambdaQuery(User.class) .ne(User::getUnionid, unionId) .eq(User::getOpenId, wxSyncLog.getOriOpenid()).last("limit 1")); if (user != null) { user.setOpenId(wxSyncLog.getNewOpenid()); } else { // 查询用户是否存在 user = Optional.ofNullable( this.getOne(new LambdaQueryWrapper().eq(User::getUnionid, unionId) .orderByAsc(User::getId) .last("limit 1"))) .orElseGet(() -> this.getOne(new LambdaQueryWrapper().eq(User::getOpenId, openId) .orderByAsc(User::getId) .last("limit 1"))); } } else { // 查询用户是否存在 user = Optional.ofNullable( this.getOne(new LambdaQueryWrapper().eq(User::getUnionid, unionId) .orderByAsc(User::getId) .last("limit 1"))) .orElseGet(() -> this.getOne(new LambdaQueryWrapper().eq(User::getOpenId, openId) .orderByAsc(User::getId) .last("limit 1"))); } return user; } @Override public void sendFixedCustomerCoupon(Long popularizeId, Long userId, String unionId) { //若是百度渠道 添加固定客服 注册后直接发放优惠券 ChannelPopularize channelPopularize = channelPopularizeMapper.selectById(popularizeId); if (channelPopularize != null && channelPopularize.getChannelId() == 34) { // SysConfig corpConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class) // .eq(SysConfig::getSysKey, Constant.CORP_FIXED_CUSTOMER) // .last("limit 1")); // if (corpConfig != null) { // Optional.ofNullable(corpConfig.getSysValue()).ifPresent(value -> { // try { // if (StrUtil.isNotBlank(value)) { // List followIds = Jsons.parseList(value, String.class); // //添加固定客服发放优惠券 // CorpUserFollowView corpUserFollowView = beanSearcher.searchFirst(CorpUserFollowView.class, MapUtils.builder() // .field(CorpUserFollowView::getUnionId, unionId) // .field(CorpUserFollowView::getFollowId, followIds).op(Operator.InList).build()); // if (corpUserFollowView != null) { // Constant.FIXED_CUSTOMER_COUPON_IDS.forEach(couponId -> couponCommonService.sendCouponToUser(userId, couponId, 0l, 0l, 0l, CouponUser.Channel.wxCorp)); // } // } // } catch (Exception e) { // } // }); // // } SysConfig config = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class) .eq(SysConfig::getSysKey, Constant.BAIDU_POPULARIZE_COUPON_IDS).last("limit 1")); if (config != null) { String sysValue = config.getSysValue(); if (StrUtil.isNotBlank(sysValue)) { try { List couponIds = Jsons.parseList(sysValue, Long.class); couponIds.forEach(couponId -> couponCommonService.sendCouponToUser(userId, couponId, 0l, 0l, popularizeId, CouponUser.Channel.manual)); } catch (Exception e) { log.error("百度渠道优惠券解析错误"); } } } } } @Override public List getRelationUserIdList(Long userId, User selectUser) { List userIds = new ArrayList<>(); userIds.add(userId); UserBindDetail userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class) .eq(UserBindDetail::getUserId, userId).last("limit 1")); if (userBindDetail == null) { User user = Optional.ofNullable(selectUser).orElse(this.getById(userId)); if (StrUtil.isEmpty(user.getOpenId()) && StrUtil.isNotEmpty(user.getLoginPhone())) { userBindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class) .eq(UserBindDetail::getPhone, user.getLoginPhone()).last("limit 1")); if (userBindDetail != null) { userIds.add(userBindDetail.getUserId()); } } } else { if (StrUtil.isNotBlank(userBindDetail.getPhone())) { User otherUser = this.getOne(Wrappers.lambdaQuery(User.class) .eq(User::getLoginPhone, userBindDetail.getPhone()).last("limit 1")); if (otherUser != null) { userIds.add(otherUser.getId()); } } } return userIds; } @Override public List getUserIdsByNickname(String nickname) { return userMapper.selectListByNickname(nickname); } @Override public String getUserMirrorShopId(Long userId) { Integer update = 0; String showId = null; while (update != 1) { showId = StringUtil.randomString(5); try { update = userMirrorShopMapper.update(null, Wrappers.lambdaUpdate(UserMirrorShop.class) .set(UserMirrorShop::getCustomId, showId) .eq(UserMirrorShop::getUserId, userId)); } catch (DuplicateKeyException e) { update = 0; } } return showId; } @Override public Long getUserIdByShowId(String showId) { return userMapper.getUserIdByShowId(showId); } @Override public User webLogin(LoginReq loginReq, HttpServletRequest request) throws Exception { LambdaQueryWrapper wrapper = Wrappers.lambdaQuery(User.class).last("limit 1"); if (loginReq.getType() == null || loginReq.getType() < 1 || loginReq.getType() > 3) { throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重新操作"); } if (loginReq.getType() == 1) { if (StrUtil.hasEmpty(loginReq.getPhone(), loginReq.getCode())) { throw BusinessRuntimeException.getInstance("请输入对应信息"); } DateTime now = DateTime.now(); PhoneCode phoneCode = phoneCodeMapper.selectOne(Wrappers.lambdaQuery(PhoneCode.class).eq(PhoneCode::getPhone, loginReq.getPhone()).last("limit 1")); if (phoneCode == null || StrUtil.isEmpty(phoneCode.getCode())) { throw BusinessRuntimeException.getInstance("请重新获取手机验证码"); } //3分钟失效 Date updateTime = phoneCode.getUpdateTime(); DateTime afterFiveMinutes = DateUtil.offsetMinute(updateTime, 3); if (now.isAfter(afterFiveMinutes)) { throw BusinessRuntimeException.getInstance("手机验证码已失效,请重新获取"); } if (!StrUtil.equals(loginReq.getCode(), phoneCode.getCode())) { //是否是恶意用户 badIntentionOpService.isBadOpLoginPhone(request, loginReq.getPhone()); throw BusinessRuntimeException.getInstance("手机验证码错误,请重新输入"); } wrapper.eq(User::getLoginPhone, loginReq.getPhone()); } if (loginReq.getType() == 2) { if (StrUtil.isEmpty(loginReq.getEmail())) { throw BusinessRuntimeException.getInstance("邮箱不能为空"); } String code = redisService.getStr(RedisService.key.EMAIL_CODE_KEY.getNameFormat(loginReq.getEmail())); if (StrUtil.isEmpty(code)) { throw BusinessRuntimeException.getInstance("邮箱验证码已失效,请重新获取"); } if (!StrUtil.equals(loginReq.getCode(), code)) { throw BusinessRuntimeException.getInstance("邮箱验证码错误,请重新输入"); } redisService.del(RedisService.key.EMAIL_CODE_KEY.getNameFormat(loginReq.getEmail())); wrapper.eq(User::getEmail, loginReq.getEmail()); } if (loginReq.getType() == 3) { wrapper.eq(User::getEmail, loginReq.getEmail()); } //保存用户信息 User user = this.getOne(wrapper); String dsCode = loginReq.getDsCode(); Long sharedId = loginReq.getSharedId(); Long dsPopularizeId = null; Integer dsType = loginReq.getDsType(); String customId = loginReq.getCustomId(); Boolean isNewUser = false; if (StrUtil.isNotBlank(dsCode)) { UserSharedDto userSharedDto = getUserShredDtoByDsCode(dsCode); sharedId = userSharedDto.getSharedId(); dsPopularizeId = userSharedDto.getDsPopularizeId(); } if (user != null && loginReq.getType() == 3 && !user.getIsGoogle()) { user.setIsGoogle(true); this.updateById(user); } if (user == null) { user = new User(); isNewUser = true; StringBuilder name = new StringBuilder(); if (loginReq.getCmt() == 2) { name.append(Constant.DEFAULT_MIRROR_SHOP_USER_NAME); }else { name.append(Constant.DEFAULT_NAME); } if (loginReq.getPopularizeId() != null) { user.setPopularizeId(loginReq.getPopularizeId()); } if (loginReq.getType() == 1) { user.setLoginPhone(loginReq.getPhone()); } if (loginReq.getType() == 2 || loginReq.getType() == 3) { user.setEmail(loginReq.getEmail()); name.append("@"); } if (loginReq.getType() == 3) { user.setIsGoogle(true); } user.setNickname(String.format("%s%s", name.toString(), RandomUtil.randomString(6))); if (loginReq.getCmt() == 2) { user.setHeadimgurl(Constant.USER_MIRROR_SHOP_USER_DEFAULT_IMG); } else { //默认头像 user.setHeadimgurl(Constant.DEFAULT_HEAD_IMG); } String registerEnv = loginReq.getRegisterEnv(); user.setRegisterEnv(StrUtil.isEmpty(registerEnv) ? User.RegisterEnv.pc.name() : registerEnv); this.save(user); //新用户分销 if (sharedId != null) { distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId); } //店铺注册用户 关联 if (StrUtil.isNotBlank(customId)) { yhShopDistributeService.saveDistributionInvitation(customId, user.getId(), loginReq.getCmt()); } //缓存用户注册 回传信息 String callback = loginReq.getCallback(); String callbackType = loginReq.getCallbackType(); if (StrUtil.isNotBlank(callback)) { OrderDonPostDataDto orderDonPostDataDto = new OrderDonPostDataDto().setCallback(callback) .setCallbackType(callbackType); redisService.set(RedisService.key.ORDER_DON_POST_DATA_USER_KEY.getName() + user.getId(), Jsons.toJson(orderDonPostDataDto)); } //发放新用户福利 final Long fUid = user.getId(); // TASK_POOL.execute(() -> { // try { // sendNewUserWelfare(fUid); // } catch (Exception e) { // } // }); final String login_email = user.getEmail(); final String login_phone = user.getLoginPhone(); UserBindDetail bindDetail = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class) .and(ub -> ub.eq(StrUtil.isNotBlank(login_email), UserBindDetail::getEmail, login_email) .or().eq(StrUtil.isNotBlank(login_phone), UserBindDetail::getPhone, login_phone)) .last("limit 1")); if (bindDetail != null) { if (StrUtil.isNotBlank(login_phone)) { bindDetail.setPhoneUserId(user.getId()); } if (StrUtil.isNotBlank(login_email)) { bindDetail.setEmailUserId(user.getId()); } userBindDetailMapper.updateById(bindDetail); } } if (StrUtil.isEmpty(user.getShowId())) { user.setShowId(userCommonService.getUserShowId(user.getId())); } //新旧用户都可实物分销 if (sharedId != null && dsType != null && dsType == 2) { equipDistributeService.saveDistributionInvitation(sharedId, isNewUser, user.getId()); } //查找渠道是否有设置了对应的claude code优惠码 setClaudeCodePopularize(sharedId, dsPopularizeId, user); //每日活跃记录 userLoginRecordService.saveUserLoginDayRecord(user.getId()); return user; } @Override public String bindWxAccountRedirect(String code, String state) throws Exception { AuthToken token = weChatService.getAuthToken(code, wxOpenPlatYHLXLoginConfig.getAppId()); //重定向 // 根据openid 与 access_token 获取用户信息 GzhOAuth2UserInfo userinfo = weChatService.getUserInfo(token.getAccessToken(), token.getOpenid()); // 转跳参数 String json = Codec.DoBase64.custom().setData(state).decodeAsText(); AuthRedirect re = Jsons.parseObject(json, AuthRedirect.class); //保存用户信息 User user = saveAuth(userinfo, re, User.RegisterEnv.pc); if (user == null) { throw BusinessRuntimeException.getInstance("系统错误,请重新授权"); } String loginPhone = re.getLp(); String loginEmail = re.getLe(); if (StrUtil.isNotBlank(loginPhone)) { log.info("手机号phone:{}登录用户,微信扫描网页授权二维码进行用户信息绑定", loginPhone); try { bindTaskService.bindPhone(user, loginPhone, null); } catch (Exception e) { log.info(StringUtil.getErrorText(e)); } } if (StrUtil.isNotBlank(loginEmail)) { log.info("邮箱email:{}登录用户,微信扫描网页授权二维码进行用户信息绑定", loginEmail); try { bindTaskService.bindEmail(user, loginEmail, null); } catch (Exception e) { log.info(StringUtil.getErrorText(e)); } } return redisService.getStr(re.getMappingId().toString()); } @Override @Transactional(rollbackFor = Throwable.class) public void receiveGiftCardByRc(Long userId, String code, Long relationId) { GiftCardUserRecord giftCardUserRecord = giftCardUserRecordMapper.selectOne(Wrappers.lambdaQuery(GiftCardUserRecord.class) .eq(GiftCardUserRecord::getRc, code).last("limit 1")); if (giftCardUserRecord == null) { throw BusinessRuntimeException.getInstance("好友赠送礼品卡不存在"); } if (!giftCardUserRecord.getIsPay()) { throw BusinessRuntimeException.getInstance("无效礼品卡,好友未购买"); } List relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null); if (relationUserIdList.contains(giftCardUserRecord.getUserId())) { throw BusinessRuntimeException.getInstance("无法领取自己购买的礼品卡"); } if (giftCardUserRecord.getToUserId() != 0 && !giftCardUserRecord.getToUserId().equals(userId)) { throw BusinessRuntimeException.getInstance("好友赠送礼品卡已被领取"); } if (giftCardUserRecord.getToUserId().equals(userId)) { throw BusinessRuntimeException.getInstance("您已领取该礼品卡"); } giftCardUserRecord.setToUserId(userId); int update = giftCardUserRecordMapper.update(null, Wrappers.lambdaUpdate(GiftCardUserRecord.class) .set(giftCardUserRecord.getGcType() != 1, GiftCardUserRecord::getIsUsed, true) .set(GiftCardUserRecord::getToUserId, userId) .set(GiftCardUserRecord::getIsSend, true) .set(GiftCardUserRecord::getReceivedTime, DateTime.now()) .eq(GiftCardUserRecord::getId, giftCardUserRecord.getId()) .eq(GiftCardUserRecord::getIsPay, true) .eq(GiftCardUserRecord::getToUserId, 0)); if (update > 0) { //虚拟卡 //直接发送 对应规格车票 if (giftCardUserRecord.getGcType() != 1) { Long gcSkuId = giftCardUserRecord.getGcSkuId(); log.info("用户userId:{}领取礼品卡id:{},开始发放虚拟车票skuId:{}", userId, giftCardUserRecord.getId(), gcSkuId); GoodsDonSku sku = goodsDonSkuMapper.selectById(gcSkuId); if (sku == null) { log.info("礼品卡id:{}虚拟车票skuId:{}不存在", giftCardUserRecord.getId(), gcSkuId); throw BusinessRuntimeException.getInstance("该礼品卡对应的虚拟卡不存在,请联系客服"); } if (relationId != null) { GroupsRelation groupsRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .in(GroupsRelation::getUserId, relationUserIdList) .eq(GroupsRelation::getId, relationId) .in(GroupsRelation::getStatus, List.of(GroupsRelation.Status.validity, GroupsRelation.Status.outside)).last("limit 1")); if (groupsRelation == null) { throw BusinessRuntimeException.getInstance("您选择的车票不存在"); } Date expiryTime = groupsRelation.getExpiryTime(); if (expiryTime == null) { throw BusinessRuntimeException.getInstance("请等您该类型下的车票配置账号后再增加对应时长"); } if (sku.getDays() != null && sku.getDays() > 0) { expiryTime = DateUtil.offsetDay(expiryTime, sku.getDays()); } else { expiryTime = DateUtil.offsetMonth(expiryTime, sku.getMonths()); } log.info("userId:{}领取虚拟卡skuId:{},增加车票时长至:{}", userId, sku.getId(), expiryTime.toString()); groupsRelation.setExpiryTime(expiryTime); groupsRelationMapper.updateById(groupsRelation); return; } //是否存在对应车票 List ticketViews = beanSearcher.searchAll(UserTicketView.class, MapUtils.builder() .field(UserTicketView::getUserId, relationUserIdList).op(Operator.InList) .field(UserTicketView::getSkuId, giftCardUserRecord.getGcSkuId()) .field(RenewalView::getStatus, List.of("validity", "outside")).op(Operator.InList) .orderBy(UserTicketView::getRelationId).asc() .build()); if (CollUtil.isEmpty(ticketViews)) { GroupsRelation relationNoOrder = exchangeCodeService.getRelationNoOrder(sku, userId, null); giftCardUserRecordMapper.update(null, Wrappers.lambdaUpdate(GiftCardUserRecord.class) .set(GiftCardUserRecord::getRelationId, relationNoOrder.getId()) .eq(GiftCardUserRecord::getId, giftCardUserRecord.getId())); log.info("用户未有该规格:{}车票,发送至用户userId:{}礼品卡虚拟车票结束", gcSkuId, userId); return; } if (ticketViews.size() > 1) { throw BusinessRuntimeException.getInstance("您有多张该类型的车票,请选择一张增加时长"); } UserTicketView userTicketView = ticketViews.get(0); Date expiryTime = userTicketView.getExpiryTime(); if (expiryTime == null) { throw BusinessRuntimeException.getInstance("请等您该类型下的车票配置账号后再增加对应时长"); } if (sku.getDays() != null && sku.getDays() > 0) { expiryTime = DateUtil.offsetDay(expiryTime, sku.getDays()); } else { expiryTime = DateUtil.offsetMonth(expiryTime, sku.getMonths()); } groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getExpiryTime, expiryTime) .eq(GroupsRelation::getId, userTicketView.getRelationId())); } } } /** * 发放新用户福利 */ public void sendNewUserWelfare(Long userId) throws Exception { SysConfig newUserWelfareConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class) .eq(SysConfig::getSysKey, Constant.NEW_USER_WELFARE_KEY).last("limit 1")); if (StrUtil.isEmpty(newUserWelfareConfig.getSysValue())) { return; } NewUserWelfareDto newUserWelfareDto = Jsons.parseObject(newUserWelfareConfig.getSysValue(), NewUserWelfareDto.class); if (newUserWelfareDto != null) { List couponIds = newUserWelfareDto.getCouponIds(); couponIds.forEach(couponId -> couponCommonService.sendCouponToUser(userId, couponId, null, null, null, CouponUser.Channel.new_welfare)); } } /** * 关联企业微信用户 并发放福利 */ private void relateCorpUserAndSengWelfare(Long fUid, String unionid) { CorpUser corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class) .eq(CorpUser::getUnionid, unionid).last("limit 1")); Long msgId = null; CouponUser.Channel channel = null; if (corpUser != null) { corpUser.setUserId(fUid); corpUserMapper.updateById(corpUser); //活码福利 if (corpUser.getAcId() != null && corpUser.getAcId() > 0) { CorpFollowActiveCode corpFollowActiveCode = corpFollowActiveCodeMapper.selectById(corpUser.getAcId()); if (corpFollowActiveCode != null) { msgId = corpFollowActiveCode.getMsgId(); channel = CouponUser.Channel.corp_active_code; } } if (corpUser.getCustomerAcquisitionLinkId() != null && corpUser.getCustomerAcquisitionLinkId() > 0) { CorpCustomerAcquisitionLink corpCustomerAcquisitionLink = corpCustomerAcquisitionLinkMapper.selectById(corpUser.getCustomerAcquisitionLinkId()); if (corpCustomerAcquisitionLink != null) { msgId = corpCustomerAcquisitionLink.getMsgId(); channel = CouponUser.Channel.customer_link; } } if (msgId != null) { CorpWelcomeTemplate corpWelcomeTemplate = corpWelcomeTemplateMapper.selectById(msgId); if (corpWelcomeTemplate != null && StrUtil.isNotBlank(corpWelcomeTemplate.getCouponIds())) { final CouponUser.Channel fChannel = channel; try { List couponIds = Jsons.parseList(corpWelcomeTemplate.getCouponIds(), Long.class); couponIds.forEach(couponId -> couponCommonService.sendCouponToUser(fUid, couponId, 0l, 0l, 0l, fChannel)); } catch (Exception e) { } } } //是否有对应获客链接的标签 List tagIds = corpUserTagMapper.getTagIdByCorpUserId(corpUser.getId()); if (CollUtil.isNotEmpty(tagIds)) { List couponIdsStrList = corpCustomerAcquisitionLinkMapper.selectAcLinkCorpTemplateCouponIdsByTagIds(tagIds); if (CollUtil.isNotEmpty(couponIdsStrList)) { log.info("用户userId:{}存在获客链接标记的标签:{}", fUid, tagIds); couponIdsStrList.forEach(couponIdsStr -> { try { Jsons.parseList(couponIdsStr, Long.class).forEach(couponId -> couponCommonService.sendCouponToUser(fUid, couponId, 0l, 0l, 0l, CouponUser.Channel.customer_link)); } catch (Exception e) { } }); } } } } @Override public UserSharedDto getUserShredDtoByDsCode(String dsCode) { Long sharedId = 0l; Long dsPopularizeId = 0l; dsCode = dsCode.trim(); User sharedUser = getOne(Wrappers.lambdaQuery(User.class) .eq(User::getShowId, dsCode).last("limit 1")); if (sharedUser != null) { sharedId = sharedUser.getId(); } else { UserDistributePopularize distributePopularize = distributePopularizeMapper.selectOne(Wrappers.lambdaQuery(UserDistributePopularize.class) .eq(UserDistributePopularize::getCode, dsCode) .select(UserDistributePopularize::getUserId, UserDistributePopularize::getId).last("limit 1")); if (distributePopularize != null) { log.info("渠道sharedId:{}设置固定推广链接用户分销", distributePopularize.getUserId()); sharedId = distributePopularize.getUserId(); dsPopularizeId = distributePopularize.getId(); } } UserSharedDto sharedDto = new UserSharedDto(); sharedDto.setSharedId(sharedId); sharedDto.setDsPopularizeId(dsPopularizeId); return sharedDto; } @Override public Long getSharedIdByUserId(Long userId) { UserDistributeShared distributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class) .eq(UserDistributeShared::getUserId, userId) .last("limit 1") .select(UserDistributeShared::getSharedId)); if (distributeShared == null) { return 0l; } return distributeShared.getSharedId(); } @Override public void bindUserDistributeShared(Long userId, String dsCode) { User user = userMapper.selectById(userId); if (StrUtil.equals(user.getShowId(), dsCode)) { return; } UserSharedDto userSharedDto = getUserShredDtoByDsCode(dsCode); Long sharedId = userSharedDto.getSharedId(); Long dsPopularizeId = userSharedDto.getDsPopularizeId(); //建立绑定关系 log.info("建立用户userId:{}与sharedId:{}绑定关系", userId, sharedId); distributeService.saveDistributionInvitation(sharedId, user.getId(), dsPopularizeId); } @Override public void saveEpDistributeShared(Long userId, String dsCode) { if (StrUtil.isEmpty(dsCode)) { log.info("设备好友邀请userId:{},code为空", userId); return; } User user = getById(userId); Date createdTime = user.getCreatedTime(); String createDate = new DateTime(createdTime).toDateStr(); Boolean isNewUser = false; if (StrUtil.equals(createDate, DateTime.now().toDateStr())) { isNewUser = true; } UserSharedDto userSharedDto = getUserShredDtoByDsCode(dsCode); if (userSharedDto != null) { log.info("实物好友分销邀请sharedId:{},被邀请用户id:{}", userSharedDto.getSharedId(), userId); equipDistributeService.saveDistributionInvitation(userSharedDto.getSharedId(), isNewUser, user.getId()); } } @Override public UserCertInfoView getCertOverView(long userId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); UserCertRecord record = userCertRecordMapper.selectOne(Wrappers.lambdaQuery(UserCertRecord.class) .in(UserCertRecord::getUserId, userIdList) .select(UserCertRecord::getName, UserCertRecord::getIdent) .last("limit 1")); if (record != null) { record.setIdent(StringUtil.enIndent(record.getIdent())); record.setName(StringUtil.enName(record.getName())); } UserStudentCertRecord userStudentCertRecord = userStudentCertRecordMapper.selectOne(Wrappers.lambdaQuery(UserStudentCertRecord.class) .in(UserStudentCertRecord::getUserId, userIdList) .select(UserStudentCertRecord::getSchool) .last("limit 1")); UserCertInfoView userCertInfoView = new UserCertInfoView(); userCertInfoView.setIndent(record); userCertInfoView.setStudentCert(userStudentCertRecord); return userCertInfoView; } @Override public UserSyncInfoView getUserSyncInfo(long userId) { UserSyncInfoView syncInfoView = new UserSyncInfoView(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); //是否是会员 VipUser vipUser = vipUserMapper.selectOne(Wrappers.lambdaQuery(VipUser.class) .in(VipUser::getUserId, userIdList) .gt(VipUser::getExpiryTime, DateTime.now()) .last("limit 1")); if (vipUser != null) { syncInfoView.setIsVip(Boolean.TRUE); syncInfoView.setVipStartTime(vipUser.getStartTime()); syncInfoView.setVipExpiryTime(vipUser.getExpiryTime()); } User user = userMapper.selectById(userId); syncInfoView.setGalaxyCoin(user.getGalaxyCoin()); return syncInfoView; } /** * 处理大学生快递站用户 */ public void handlerCollegeStudentUser(Long userId, Integer cst) { try { CollegeStudentStationUserRelate cstRelate = new CollegeStudentStationUserRelate(); cstRelate.setType(cst); cstRelate.setUserId(userId); collegeStudentStationUserRelateMapper.insert(cstRelate); //赠送1天的GPT镜像车票 groupRelationFrontService.getCollegeStudentUserGptTicket(userId); } catch (DuplicateKeyException e) { } } /** * 查找渠道是否有设置了对应的claude code优惠码 */ public void setClaudeCodePopularize(Long sharedId, Long dsPopularizeId, User user) { //查找渠道是否有设置了对应的claude code优惠码 if (sharedId != null) { UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, sharedId).eq(UserDistribute::getDeleted, Boolean.TRUE).last("limit 1")); if (userDistribute != null) { if (dsPopularizeId == null) { return; } UserDistributePopularize userDistributePopularize = distributePopularizeMapper.selectById(dsPopularizeId); if (userDistributePopularize == null) { return; } //是否是cc推广 if (StrUtil.isEmpty(userDistributePopularize.getOtherUrl()) || !"cc".equals(userDistributePopularize.getOtherUrl())) { return; } Integer selectCount = couponDistributePopularizeMapper.selectCount(Wrappers.lambdaQuery(CouponDistributePopularize.class).eq(CouponDistributePopularize::getDistributeId, userDistribute.getId()).eq(CouponDistributePopularize::getDeleted, Boolean.TRUE).eq(CouponDistributePopularize::getCouponId, Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID)); //是否设置claude cod优惠券 if (selectCount > 0) { //设置了 直接发送优惠券 couponCommonService.sendCouponToUser(user.getId(), Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID, 0l, 0l, dsPopularizeId, CouponUser.Channel.manual); if (redisService.setNx(RedisService.key.CLAUDE_CODE_TY_DAY_CARD_KEY.getName() + user.getId(), user.getId(), RedisService.key.CLAUDE_CODE_TY_DAY_CARD_KEY.getTimeout())) { //存在Claude code车票不发送体验卡 if (!claudeCodeService.checkClaudeCodeUser(user.getId())) { //发送claude code 体验卡 groupRelationFrontService.getTrialTicketByUserIdAndGoodsId(user.getId(), Constant.DISTRIBUTE_CLAUDE_CODE_TRIAL_SKU_ID, 1); } } } else { //该优惠券是否处于推荐中 int isTj = couponRecommendMapper.checkPresentRecommendByCouponId(Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID); if (isTj != 0) { //发送无优惠码的 优惠券 couponCommonService.sendCouponToUser(user.getId(), Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID, 0l, 0l, dsPopularizeId, CouponUser.Channel.manual); } } } } } }