package com.cyksj.service.relation.impl; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.date.BetweenFormater; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Validator; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.cyksj.common.constant.Constant; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.snowflake.Sequence; import com.cyksj.common.task.GlobalThreadPoolTaskExecutor; import com.cyksj.common.util.Jsons; import com.cyksj.common.util.StringUtil; import com.cyksj.enums.GatewayApiCode; import com.cyksj.mapper.*; import com.cyksj.mapper.codex.CodexUserRenewExpiryRecordMapper; import com.cyksj.mapper.manage.distribute.DistributeGeneralSkuRateMapper; import com.cyksj.mapper.manage.distribute.UserDistributeMapper; import com.cyksj.mapper.manage.distribute.UserPlatDistributeRateMapper; import com.cyksj.mapper.manage.distribute.UserPlatSkuDistributeRateMapper; import com.cyksj.mapper.mirrorshop.UserMirrorShopMapper; import com.cyksj.mapper.renew.RenewUpgradePackageMapper; import com.cyksj.mapper.sys.SysConfigMapper; import com.cyksj.mapper.sys.SysEmailMapper; import com.cyksj.mapper.vip.VipGoodsSkuMapper; import com.cyksj.mapper.vip.VipUserMapper; import com.cyksj.model.dto.ErrorNetflixChangeOtherSkuTicketDto; import com.cyksj.model.dto.TicketChangeDto; import com.cyksj.model.entity.*; import com.cyksj.model.manage.views.AccountView; import com.cyksj.model.manage.views.GroupsRelationView; import com.cyksj.model.request.ErrorNetflixChangeReq; import com.cyksj.model.request.OrderRefundReq; import com.cyksj.model.request.SpecialGoodsTicketReq; import com.cyksj.model.request.TicketLoginReq; import com.cyksj.model.response.NetflixErrorAccountStatus; import com.cyksj.model.response.NetflixRecoverResp; import com.cyksj.model.response.NetflixRefundInfoResp; import com.cyksj.model.views.*; import com.cyksj.redis.RedisService; import com.cyksj.service.chatgpt.ChatGptAccountService; import com.cyksj.service.chatgpt.ChatGptAuthService; import com.cyksj.service.claude.ClaudeCodeService; import com.cyksj.service.claude.ClaudeService; import com.cyksj.service.codex.CodexService; import com.cyksj.service.groups.GroupsFuncService; import com.cyksj.service.luma.LumaService; import com.cyksj.service.mail.CommonMailService; import com.cyksj.service.mail.MailService; import com.cyksj.service.mange.coupon.CouponCommonService; import com.cyksj.service.midjourney.MidjourneyAccountService; import com.cyksj.service.order.OrderRefundService; import com.cyksj.service.relation.GroupRelationClearService; import com.cyksj.service.relation.GroupRelationFrontService; import com.cyksj.service.relation.GroupsRelationChangeService; import com.cyksj.service.sora.SoraCodeFrontService; import com.cyksj.service.translations.BackInfoTranslationsFrontService; import com.cyksj.service.user.UserBenefitsService; import com.cyksj.service.user.UserBindRelationService; import com.cyksj.service.user.UserLoginRecordService; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.SearchResult; import com.ejlchina.searcher.param.Operator; import com.ejlchina.searcher.util.MapBuilder; import com.ejlchina.searcher.util.MapUtils; import com.github.rholder.retry.*; 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 javax.servlet.http.HttpServletRequest; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_ALREADY_BE_USER; import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_NOT_FIND; /* *项目名: netflix *文件名: GroupRelationFrontServiceImpl *创建者: JavaZou *创建时间:2022/12/29 15:42 */ @Service @RequiredArgsConstructor @Slf4j public class GroupRelationFrontServiceImpl implements GroupRelationFrontService { private final UserBindRelationService userBindRelationService; private final UserMapper userMapper; private final BeanSearcher beanSearcher; private final CouponCommonService couponCommonService; private final GroupsRelationMapper groupsRelationMapper; private final GroupsMapper groupsMapper; private final ChatGptAuthService chatGptAuthService; private final RedisService redisService; private final MailService mailService; private final OrderDonMapper orderDonMapper; private final GroupsRelationExpiryNotifyRecordMapper groupsRelationExpiryNotifyRecordMapper; private final HttpServletRequest request; private final GroupsFuncService groupsFuncService; private final OrderDiscountPlusPurchaseSkuRelationMapper orderDiscountPlusPurchaseSkuRelationMapper; private final GroupsRelationLoginCodeRecordMapper groupsRelationLoginCodeRecordMapper; private final SysEmailMapper sysEmailMapper; private final GoodsDonSkuMapper goodsDonSkuMapper; private final UserFuncPropertyMapper userFuncPropertyMapper; private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance(); private final UserLoginRecordService userLoginRecordService; private final UserCertRecordMapper userCertRecordMapper; private final MidjourneyAccountService midjourneyAccountService; private final ChatGptAccountService chatGptAccountService; private final UpgradePackageMapper upgradePackageMapper; private final LumaService lumaService; private final BackInfoTranslationsFrontService backInfoTranslationsFrontService; private final UserDistributeMapper userDistributeMapper; private final UserPlatDistributeRateMapper userPlatDistributeRateMapper; private final GoodsDonMapper goodsDonMapper; private final UserPlatSkuDistributeRateMapper userPlatSkuDistributeRateMapper; private final DistributeGeneralSkuRateMapper distributeGeneralSkuRateMapper; private final RenewUpgradePackageMapper renewUpgradePackageMapper; private final ClaudeService claudeService; private final UserDistributePosterRecordMapper userDistributePosterRecordMapper; private final OrderDonRenewRecordMapper orderDonRenewRecordMapper; private final AccountMapper accountMapper; private final UserBenefitsMapper userBenefitsMapper; private final GroupsRelationChangeService changeTickerRelation; private final NetflixTempAccountUserMapper netflixTempAccountUserMapper; private final NetflixUserAccountStatusRecordMapper netflixUserAccountStatusRecordMapper; private final AccountNetflixStateMapper accountNetflixStateMapper; private final UserMirrorShopMapper userMirrorShopMapper; private final CommonMailService commonMailService; private final SysConfigMapper sysConfigMapper; private final GptMirrorDayCardGiveawayActivityMapper gptMirrorDayCardGiveawayActivityMapper; private final MirrorTicketPopupsRecordMapper mirrorTicketPopupsRecordMapper; private final VipUserMapper vipUserMapper; private final VipGoodsSkuMapper vipGoodsSkuMapper; private static final Sequence SEQUENCE = new Sequence(0); private final NetflixUserChangeOtherTicketRecordMapper netflixUserChangeOtherTicketRecordMapper; private final NetflixUserAccountSubmitRecoverRecordMapper netflixUserAccountSubmitRecoverRecordMapper; private final OrderRefundService orderRefundService; private final GroupRelationClearService clearService; private final UserBenefitsService userBenefitsService; private final ChatgptUserMapper chatgptUserMapper; private final ClaudeCodeUserRenewExpiryRecordMapper claudeCodeUserRenewExpiryRecordMapper; private final GoodsDonCategoryRelateMapper goodsDonCategoryRelateMapper; private final ClaudeCodeService claudeCodeService; private final NanoUserQuotaMapper nanoUserQuotaMapper; private final CodexService codexService; private final CodexUserRenewExpiryRecordMapper codexUserRenewExpiryRecordMapper; private final CodexUserMapper codexUserMapper; private final AccountNetflixFrozenTicketReceivedRecordMapper accountNetflixFrozenTicketReceivedRecordMapper; private final SoraCodeMapper soraCodeMapper; private final SoraCodeFrontService soraCodeFrontService; @Override public SearchResult getMyTicket(long userId, Boolean isLoginPopularize, String customId, String account, String orderNo, Integer cmt) { User u = userMapper.selectById(userId); if (u == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID); if (u.getIsBlack()) { return new SearchResult<>(); } List userIds = userBindRelationService.getRelationUserIdList(userId, u); MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()); if (cmt != null && cmt == 2 && StrUtil.isNotBlank(customId)) { UserMirrorShop userMirrorShop = userMirrorShopMapper.selectOne(Wrappers.lambdaQuery(UserMirrorShop.class) .eq(UserMirrorShop::getCustomId, customId) .last("limit 1")); if (userMirrorShop != null) { builder.field(RenewalView::getCmt, cmt).field(RenewalView::getYhsId, userMirrorShop.getId()); } } if (cmt == null || cmt != 2) { builder.field(RenewalView::getCmt, 2).op(Operator.NotEqual); } // Long yhsId = yhShopFrontService.getYhsIdByCustomId(customId); DateTime now = DateTime.now(); if (StrUtil.isNotBlank(account)) { builder.field(RenewalView::getAccount, account).op(Operator.Contain); } //代充剩余次数大于0/未发车/过期时间/冻结时 String conditionSql = String.format("(gr.recharge_remain_num > 0 or gr.expiry_time is null or gr.expiry_time > '%s' or gr.is_frozen = true", now); //镜像车票 过期7天后清除 //个人店铺和AI店铺 暂不支持过期续费 if (cmt == null && StrUtil.isEmpty(customId)) { conditionSql += String.format(" or (sku.is_mirror and gr.expiry_time > '%s')", DateUtil.offsetDay(now, -7)); } conditionSql += ")"; if (StrUtil.isNotEmpty(orderNo)) { OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getOrderNo, orderNo) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus) .last("limit 1")); Long orderId = orderDon != null ? orderDon.getId() : 0l; conditionSql += String.format(" and exists(select 1 from order_don o where o.relation_id = gr.id and o.user_id = gr.user_id and o.id = %s)", orderId); } SearchResult list = beanSearcher.search(RenewalView.class, builder .field(RenewalView::getUserId, 0).op(Operator.GreaterThan) .field(RenewalView::getUserId, userIds).op(Operator.InList) .put("condition", conditionSql) .field(RenewalView::getStatus, List.of("validity", "overdue", "outside")).op(Operator.InList) .orderBy(RenewalView::getExpiryTime).asc() .build()); if (list.getDataList().size() > 0) { String lang = request.getHeader("lang"); //过滤邀请制、已失效的车位 Integer size = list.getTotalCount().intValue(); //赠送GPT日卡 参与平台ids List renewReduceSkuIds = userBenefitsMapper.selectList(Wrappers.lambdaQuery(UserBenefits.class) .eq(UserBenefits::getType, UserBenefits.Type.RENEW).eq(UserBenefits::getStatus, 1).select(UserBenefits::getSkuId)).stream().map(UserBenefits::getSkuId).collect(Collectors.toList()); List gptBuyGids = getGptMirrorGiveawayBuyGids(); //gpt日卡活动 GptMirrorDayCardGiveawayActivity gptMirrorDayCardGiveawayActivity = gptMirrorDayCardGiveawayActivityMapper.selectOne(Wrappers.lambdaQuery(GptMirrorDayCardGiveawayActivity.class) .last("limit 1")); SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class) .eq(SysConfig::getSysKey, Constant.EMAIL_PWD_SHOW_GID_KEY) .last("limit 1")); List showEmailPwdGids = new ArrayList<>(); if (sysConfig != null && StrUtil.isNotBlank(sysConfig.getSysValue())) { try { showEmailPwdGids.addAll(Jsons.parseList(sysConfig.getSysValue(), Long.class)); } catch (Exception e) { } } List vipSkuIds = vipGoodsSkuMapper.selectList(null).stream().map(VipGoodsSku::getSkuId).collect(Collectors.toList()); Set vipGoodsIds = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class) .in(GoodsDonSku::getId, vipSkuIds)).stream().map(GoodsDonSku::getGoodsId).collect(Collectors.toSet()); Integer vipUserCount = vipUserMapper.selectCount(Wrappers.lambdaQuery(VipUser.class) .in(VipUser::getUserId, userIds) .gt(VipUser::getExpiryTime, now)); list.getDataList().forEach(ticket -> { if (ticket.getSkuId() == null || ticket.getGoodsId() == null) { return; } if (ticket.getGoodsId() == 18 && ticket.getSkuNum() > 1) { ticket.setPassword(null); } ticket.setIsMulti(false); if (ticket.getSkuNum() > 1) { ticket.setIsMulti(true); } //分类ids ticket.setCategoryIdList(goodsDonCategoryRelateMapper.selectCategoryIdsByGid(ticket.getGoodsId())); //chatGPT直连 if (ticket.getGoodsId().equals(42l)) { if (StrUtil.isNotBlank(ticket.getAccount())) { String accessToken; try { accessToken = chatGptAuthService.getAccessToken(ticket.getAccount()); ticket.setGptRefreshToken(accessToken); } catch (Exception e) { redisService.set(RedisService.key.CHAT_GPT_TOKEN_EXCEPTION_KEY.getName() + ticket.getAccount(), ticket.getAccount()); } } ticket.setAccount(null); ticket.setPassword(null); } else { ticket.setGptRefreshToken(null); } if (ticket.getSecondType() == 1) { ticket.setAccount(null); ticket.setPassword(null); } //gpt 2月的独立账号可看到邮箱密码 if (ticket.getGoodsId() == 18l && ticket.getSkuNum() == 1 && ticket.getAccount() != null && ticket.getCreatedTime().compareTo(DateUtil.parse("2025-02-01")) > 0) { } else { if (!showEmailPwdGids.contains(ticket.getGoodsId())) { ticket.setGptEmailPwd(null); } } if (isLoginPopularize != null && isLoginPopularize) { GoodsDonViews views = beanSearcher.searchFirst(GoodsDonViews.class, MapUtils.builder().field(GoodsDonViews::getId, ticket.getGoodsId()).build()); views.setSpecs(beanSearcher.searchFirst(GoodsDonSpecFrontView.class, MapUtils.builder().field(GoodsDonSpecFrontView::getGoodsId, views.getId()).build())); views.setSkuList(beanSearcher.searchAll(GoodsDonSkuFrontView.class, MapUtils.builder().field(GoodsDonSkuFrontView::getGoodsId, views.getId()).field(GoodsDonSkuFrontView::getStatus, true).build())); ticket.setGoodsDonViews(views); } if (ticket.getMonths() != null && ticket.getMonths() >= 300) { ticket.setExpiryTime(null); } if (ticket.getExpiryTime() != null && ticket.getGoodsType() == 1) { String remainDays = DateUtil.formatBetween(now, ticket.getExpiryTime(), BetweenFormater.Level.DAY); if ("0天".equals(remainDays)) { remainDays = "小于1天"; } else { //当天也算 int days = Integer.parseInt(remainDays.substring(0, remainDays.indexOf("天"))); remainDays = days + 1 + "天"; } ticket.setRemainDays(remainDays); ticket.setTotal(DateUtil.betweenDay(ticket.getStartTime(), ticket.getExpiryTime(), false) + 1); } OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getRelationId, ticket.getRelationId()) .in(OrderDon::getUserId, userIds) .eq(OrderDon::getOrderType, 1) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon != null) { ticket.setOrderNo(orderDon.getOrderNo()); ticket.setOrderId(orderDon.getId()); ticket.setTransactionId(orderDon.getTransactionId()); ticket.setOrderCreatedTime(orderDon.getCreatedTime()); if (ticket.getSecondType() == 1) { //是否完成邀请 根据订单状态 ticket.setIsComplete(orderDon.getStatus() == OrderDon.Status.complete ? true : false); } } if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) { String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(ticket.getSkuId(), lang); if (StrUtil.isNotBlank(languageSpecVal)) { ticket.setSpecVal(languageSpecVal); } } if (size > 1 && ticket.getGoodsId() != 18) { Date payTime = null; if (orderDon != null) { payTime = Optional.ofNullable(orderDon.getPayTime()).orElse(orderDon.getCreatedTime()); } //加购订单 if (orderDon == null) { List plusPurchaseSkuRelations = orderDiscountPlusPurchaseSkuRelationMapper.selectPlusRelationByIdAndUserId(ticket.getRelationId(), ticket.getUserId()); for (OrderDiscountPlusPurchaseSkuRelation data : plusPurchaseSkuRelations) { String relationIds = data.getRelationIds(); if (StrUtil.isEmpty(relationIds)) { return; } try { List relationList = Jsons.parseList(relationIds, Long.class); if (relationList.contains(ticket.getRelationId())) { OrderDon plusOrder = orderDonMapper.selectById(data.getOrderId()); if (plusOrder != null) { payTime = Optional.ofNullable(plusOrder.getPayTime()).orElse(plusOrder.getCreatedTime()); } break; } } catch (Exception e) { } } } ticket.setPayTime(payTime); } if (ticket.getSkuNum() != null && ticket.getSkuNum() == 1) { } //奈飞、gpt if (ticket.getGoodsId() == 1 || ticket.getGoodsId() == 18 || ticket.getGoodsId() == 33l) { ticket.setEmail(null); } //设置镜像车票信息 // setMirrorTicketInfo(ticket); // List relationUserViews = groupsRelationMapper.getUserRelationUserViews(ticket.getGroupId(), ticket.getRelationId(), ticket.getUserId(), List.of(GroupsRelation.Status.validity, GroupsRelation.Status.outside)); // ticket.setRelationViews(relationUserViews); if (ticket.getExpiryTime() != null) { ticket.setExpiryTimeStr(DateUtil.format(ticket.getExpiryTime(), "yyyy-MM-dd")); } //查看双重验证码 if (StrUtil.isNotEmpty(ticket.getApiSecret())) { Boolean isHasVerifyCode = StrUtil.isNotBlank(ticket.getVerifyCode()) ? true : false; Integer codeNum = getUserCodeNumBySkuId(ticket.getUserId(), ticket.getSkuId(), isHasVerifyCode); ticket.setCodeNum(codeNum); } Long qaId = groupsRelationMapper.selectGoodsDonQaByGoodsId(ticket.getGoodsId()); ticket.setQa(qaId > 0 ? true : false); //是否存在海报 ticket.setPosterInfo(setGoodsPoster(ticket, u, userIds)); //续费升级折扣 BigDecimal renewDiscount = getRenewDiscount(ticket.getGoodsId(), ticket.getSkuId(), ticket.getIsMirror(), ticket.getSkuNum()); ticket.setDiscount(renewDiscount); if (CollUtil.isNotEmpty(renewReduceSkuIds) && renewReduceSkuIds.contains(ticket.getSkuId())) { ticket.setIsRenewReduce(true); } if (CollUtil.isNotEmpty(gptBuyGids) && gptBuyGids.contains(ticket.getGoodsId())) { if (gptMirrorDayCardGiveawayActivity != null && orderDon != null && orderDon.getCreatedTime().compareTo(gptMirrorDayCardGiveawayActivity.getCreatedTime()) > 0) { //是否领取过GPT日卡 Long orderId = orderDon.getId(); Number count = beanSearcher.searchCount(GptMirrorDayCardActivityRecord.class, MapUtils.builder().field(GptMirrorDayCardActivityRecord::getOrderId, orderId).build()); ticket.setReceivedGptGift(count.intValue() > 0); } } markVipDeductTicket(userIds, ticket, vipGoodsIds, vipUserCount > 0); if (ticket.getIsVipDeduct() != null && ticket.getIsVipDeduct()) { //订单不存在 if (orderDon == null) { ticket.setIsVipDeduct(Boolean.FALSE); } } //codex if (ticket.getGoodsId() == Constant.CODEX_GOODS_ID) { CodexUser codexUser = codexUserMapper.selectOne(Wrappers.lambdaQuery(CodexUser.class).eq(CodexUser::getRelationId, ticket.getRelationId()).last("limit 1")); if (codexUser != null) { ticket.setIsPay(codexUser.getIsPay()); } } }); } userLoginRecordService.saveUserLoginDayRecord(userId); return list; } @Override public Boolean isJoinCorpWx(Long userId, Boolean isJoin, Boolean noCoupon) { if (!isJoin) { User user = userMapper.selectById(userId); if (user == null || StrUtil.isEmpty(user.getUnionid())) { return true; } // CorpUser corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class) // .ne(CorpUser::getUnionid, "") // .eq(CorpUser::getUnionid, user.getUnionid()) // .last("limit 1") // .select(CorpUser::getId) // ); CorpUserFollowView corpUserFollowView = beanSearcher.searchFirst(CorpUserFollowView.class, MapUtils.builder() .field(CorpUserFollowView::getUnionId, user.getUnionid()) .field(CorpUserFollowView::getStatus, 1).build()); if (corpUserFollowView == null) { return false; } } //用户是否买了奈飞车票 Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder() .field(RenewalView::getUserId, userId) .field(RenewalView::getGoodsId, 1) .field(RenewalView::getStatus, List.of("validity", "overdue")).op(Operator.InList) .build()); if (number.intValue() > 0 && !noCoupon) { couponCommonService.sendCouponToUser(userId, 34l, 0l, 0l, 0l, CouponUser.Channel.wxCorp); } return true; } @Override public GroupsRelation getSimilarExpiredGroupRelation(GoodsDonSku sku, List errorsRelationIds, String ip) { Long skuId = sku.getId(); Integer days = sku.getDays(); Integer months = sku.getMonths(); Integer maxNum = sku.getNum(); DateTime expiryTime = null; if (days != null && days > 0) { expiryTime = DateUtil.offsetDay(DateTime.now(), days); } else { expiryTime = DateUtil.offsetMonth(DateTime.now(), months); } Integer extraNum = 5; if (sku.getId() == 178l) { extraNum = 2; } maxNum += extraNum; DateTime minExpiryTime = DateUtil.offsetDay(expiryTime, -5); Long groupsId = groupsRelationMapper.selectSimilarExpiredRelation(skuId, minExpiryTime, maxNum, ip); if (groupsId == null) { log.info("暂无相似过期时间车队"); return null; } GroupsRelation relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .notIn(errorsRelationIds != null && errorsRelationIds.size() > 0, GroupsRelation::getId, errorsRelationIds) .eq(GroupsRelation::getGroupsId, groupsId) .eq(GroupsRelation::getStatus, GroupsRelation.Status.none) .eq(GroupsRelation::getUserId, 0) .orderByAsc(GroupsRelation::getNum) .last("limit 1")); if (relation != null) { log.info("用户userId:{},获取相似车队的车位relationId:{}", relation.getId()); } return relation; } @Override public Page getRecommendGoodsViews(List yhShopGoodsIds, Boolean isPayNf, List filter_goods_id, Boolean filterCourseGoods, Integer start, Integer limit) { return groupsRelationMapper.getRecommendGoodsViews(new Page<>(start, limit), filter_goods_id, isPayNf, filterCourseGoods, yhShopGoodsIds); } @Override @Transactional(rollbackFor = Throwable.class) public void sendCourseWare(SpecialGoodsTicketReq request) throws Exception { Long userId = request.getUserId(); Long relationId = request.getRelationId(); String email = request.getEmail(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); RenewalView relation = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder().field(RenewalView::getRelationId, relationId).build()); Assert.notNull(relation, "您的车票不存在"); Long relationUserId = relation.getUserId(); if (!userIdList.contains(relationUserId)) { throw BusinessRuntimeException.getInstance("您的车票不存在"); } if (relation.getSpecialType() != GoodsDon.SpecialType.courseware) { throw BusinessRuntimeException.getInstance(""); } //是否已发送 if (StrUtil.isNotBlank(relation.getGrAccount())) { throw BusinessRuntimeException.getInstance("已领取课件,请前往邮箱查看"); } if (!Validator.isEmail(email)) { throw BusinessRuntimeException.getInstance("请输入正确的邮箱"); } int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getAccount, email) .and(qr -> qr.isNull(GroupsRelation::getAccount).or().eq(GroupsRelation::getAccount, StrUtil.EMPTY)) .eq(GroupsRelation::getId, relationId)); if (update > 0) { orderDonMapper.update(null, Wrappers.lambdaUpdate(OrderDon.class) .set(OrderDon::getStatus, OrderDon.Status.complete) .eq(OrderDon::getRelationId, relationId) .eq(OrderDon::getUserId, userId) .eq(OrderDon::getStatus, OrderDon.Status.hasPayment)); mailService.sendCoursewareByGoodsId(relation.getGoodsId(), relation.getRelationId(), relation.getUserId(), relation.getTitle(), email); } } @Override public GroupsRelation getRelation(Long payRelationId, Long userId, GoodsDonSku sku, String ip) { GroupsRelation relation = null; Integer maxNum = sku.getNum(); if (payRelationId != null && payRelationId > 0) { relation = groupsRelationMapper.selectById(payRelationId); if (relation == null) { throw new BusinessRuntimeException(GROUP_INDEX_NOT_FIND.getCode(), GROUP_INDEX_NOT_FIND.getMsg()); } if (relation.getUserId() != null && relation.getUserId() > 0L) { throw new BusinessRuntimeException(GROUP_INDEX_ALREADY_BE_USER.getCode(), GROUP_INDEX_ALREADY_BE_USER.getMsg()); } } else { GroupsTrips groups = null; //ChatGpt Plus、Midjourney非独立规格 上车先获取硬塞座位 硬塞5个座位 //主账号过期时间25天以外 //23-12-06 MidJourney 不硬塞 if (sku.getNum() > 1 && Constant.AI_goodsIds.get(0) == sku.getGoodsId()) { Integer extraNum = 5; if (sku.getId() == 178l || sku.getId() == 423l) { extraNum = 2; } maxNum += extraNum; DateTime time = DateUtil.offsetDay(DateUtil.beginOfDay(DateTime.now()), 25); //不塞存在该用户的车队 Long groupsId = groupsRelationMapper.getOutSideGroupsTripsRelationByGoodsId(sku.getId(), time, extraNum, userId, sku.getNum(), maxNum); if (groupsId != null) { relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getGroupsId, groupsId) .eq(GroupsRelation::getUserId, 0) .eq(GroupsRelation::getStatus, GroupsRelation.Status.outside) .last("limit 1")); if (relation == null) { relation = new GroupsRelation(); relation.setStatus(GroupsRelation.Status.outside); relation.setGroupsId(groupsId); GroupsRelation maxNumRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getGroupsId, groupsId).orderByDesc(GroupsRelation::getNum).last("limit 1")); Integer nextNum = maxNumRelation.getNum() + 1; if (redisService.setNx(RedisService.key.GROUPS_TRIPS_OUTSIDE_RELATION.getNameFormat(groupsId, nextNum), nextNum, RedisService.key.GROUPS_TRIPS_OUTSIDE_RELATION.getTimeout())) { relation.setNum(nextNum); groupsRelationMapper.insert(relation); } else { throw BusinessRuntimeException.getInstance("系统繁忙,请重试..."); } } groups = groupsMapper.selectById(groupsId); } } if (groups == null) { //寻找差不多过期时间规格的车位 relation = getSimilarExpiredGroupRelation(sku, null, ip); if (relation == null) { //TODO 如果没指定座位,等待逻辑确认 DateTime filterAccountTime = null; //奈飞过滤6月23号之前的车队 if (sku.getGoodsId() == Constant.NETFLIX_GID) { filterAccountTime = DateUtil.parse("2025-06-23"); } groups = groupsMapper.selectTicketGroups(sku.getId(), GroupsTrips.Status.validity, maxNum, ip, filterAccountTime); if (groups == null) { //待发车 groups = groupsMapper.selectTicketGroups(sku.getId(), GroupsTrips.Status.waiting, maxNum, ip, null); } //新增空车队 if (groups == null) { relation = groupsFuncService.createNewGroupsTrips(sku); } //获取车位 if (relation == null) { //寻找快满编车队进行占座 relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId()); if (relation == null) { Long groupsId = groups.getId(); TASK_EXECUTOR.execute(() -> groupsMapper.updateAvailableNum(groupsId)); throw BusinessRuntimeException.getInstance("系统繁忙,请重试..."); } } } } if (groups == null) { groups = groupsMapper.selectById(relation.getGroupsId()); } //车队目前可用停车数 relation.setGroupsAvailParkingNum(groups.getAvailableParkingNum()); relation.setMaxNum(maxNum); } return relation; } @Override public String getAiVerifyCode(TicketLoginReq loginReq) throws Exception { Integer type = loginReq.getType(); RenewalView renewalView; String account; Long userId = 0l; Long relationId = 0l; if (loginReq.getMerchants()) { renewalView = new RenewalView(); renewalView.setGoodsId(loginReq.getGoodsId()); renewalView.setAccount(loginReq.getAccount()); if (loginReq.getAccountId() != null && loginReq.getAccountId() != 0l) { GroupsTrips groupsTrips = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class) .eq(GroupsTrips::getAccountId, loginReq.getAccountId()) .last("limit 1")); if (groupsTrips != null) { renewalView.setSkuId(groupsTrips.getSkuId()); } } renewalView.setUserId(userId); account = loginReq.getAccount(); } else { userId = loginReq.getUserId(); relationId = loginReq.getRelationId(); List relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null); renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder().field(RenewalView::getUserId, relationUserIdList).op(Operator.InList) .field(RenewalView::getRelationId, relationId).build()); if (renewalView == null) { throw BusinessRuntimeException.getInstance("您的车票不存在..."); } if (StrUtil.isEmpty(renewalView.getAccount())) { throw BusinessRuntimeException.getInstance("车票未配置账号"); } account = renewalView.getAccount(); String password = renewalView.getPassword(); if (StrUtil.hasEmpty(account, password)) { throw BusinessRuntimeException.getInstance("您的车票账号密码异常,请联系客服..."); } } if (renewalView.getGoodsId() == 1l) { Integer linkType = loginReq.getLinkType(); if (type == null && linkType == null) { throw BusinessRuntimeException.getInstance("系统异常"); } if (linkType != null) { String key = RedisService.key.NF_UPGRAD_USER_LIMIT_KEY.getNameFormat(DateUtil.hour(DateTime.now(), true), linkType, renewalView.getUserId()); if (!redisService.hasKey(key)) { redisService.set(key, 0l, RedisService.key.NF_UPGRAD_USER_LIMIT_KEY.getTimeout()); } else { Integer value = (Integer) redisService.get(key); if (value >= 5) { throw BusinessRuntimeException.getInstance("获取奈飞同步更新装置过于频繁"); } } } } String code = commonMailService.getTicketMailCode(renewalView.getGoodsId(), account, renewalView.getRelateEmail(), renewalView.getGptEmailPwd(), renewalView.getCreatedTime(), type, loginReq.getLinkType(), false); GroupsRelationLoginCodeRecord record = new GroupsRelationLoginCodeRecord(); record.setUserId(userId); record.setRelationId(relationId); record.setAccount(renewalView.getAccount()); record.setGoodsId(renewalView.getGoodsId()); record.setSkuId(renewalView.getSkuId()); groupsRelationLoginCodeRecordMapper.insert(record); //奈飞同步装置 if (renewalView.getGoodsId() == 1l && loginReq.getLinkType() != null) { String key = RedisService.key.NF_UPGRAD_USER_LIMIT_KEY.getNameFormat(DateUtil.hour(DateTime.now(), true), loginReq.getLinkType(), renewalView.getUserId()); redisService.incr(key, 1L); } return code; } @Override public void checkGroupsAvailParkingNum(Long skuId, Long groupsId, Integer availableParkingNum, Integer maxNum) { //GPT10人月付、4人月付 if (skuId == 161l || skuId == 178l) { //为0时,不参与限制 if (availableParkingNum == 0) { return; } //目前车队可用停车数 //目前上车人数 Integer currentParkingNum = groupsRelationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getGroupsId, groupsId) .ne(GroupsRelation::getUserId, 0) .le(GroupsRelation::getNum, maxNum)); if (currentParkingNum > availableParkingNum) { throw BusinessRuntimeException.getInstance("系统繁忙,请重试..."); } } } @Override public void adjustGroupsParkingTime(Long relationId, GoodsDonSku sku) { if (sku == null) { return; } Long skuId = sku.getId(); //更新GPT Plus10人、4人月付车队状态 待优化 if (skuId == 161l || skuId == 178l || skuId == 422l || skuId == 423l) { GroupsRelation relation = groupsRelationMapper.selectById(relationId); Long groupsId = relation.getGroupsId(); GroupsTrips groupsTrips = groupsMapper.selectById(groupsId); Integer availableParkingNum = groupsTrips.getAvailableParkingNum(); //为0时 不参与限制 if (availableParkingNum == 0) { return; } Integer extraNum = 5; if (skuId == 178l || skuId == 423l) { extraNum = 2; } Integer maxNum = sku.getNum() + extraNum; if (availableParkingNum >= maxNum) { return; } //目前上车人数 Integer currentParkingNum = groupsRelationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getGroupsId, groupsId) .ne(GroupsRelation::getUserId, 0) .le(GroupsRelation::getNum, maxNum)); if (currentParkingNum >= availableParkingNum) { //锁住 DateTime parkingTime = DateUtil.offsetDay(DateTime.now(), 1); groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class) .eq(GroupsTrips::getId, groupsTrips.getId()) .set(GroupsTrips::getParkingTime, parkingTime) .isNull(GroupsTrips::getParkingTime)); } } } @Override public void setGroupsTripsParkingTimeEmpty(GoodsDonSku sku, Long relationId) { if (sku == null) { return; } Long skuId = sku.getId(); if (skuId == 161l || skuId == 178l) { GroupsRelation relation = groupsRelationMapper.selectById(relationId); Long groupsId = relation.getGroupsId(); GroupsTrips groupsTrips = groupsMapper.selectById(groupsId); Integer availableParkingNum = groupsTrips.getAvailableParkingNum(); if (groupsTrips.getParkingTime() == null || availableParkingNum == 0) { return; } Integer extraNum = 5; if (skuId == 178l) { extraNum = 2; } Integer skuNum = sku.getNum(); if (availableParkingNum >= skuNum + extraNum) { return; } //目前上车人数 Integer currentParkingNum = groupsRelationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getGroupsId, groupsId) .ne(GroupsRelation::getUserId, 0)); if (currentParkingNum < availableParkingNum) { groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class) .eq(GroupsTrips::getId, groupsTrips.getId()) .set(GroupsTrips::getParkingTime, null) .isNotNull(GroupsTrips::getParkingTime)); } } } @Override public Integer getUserCodeNumBySkuId(Long userId, Long skuId, Boolean isHasVerifyCode) { //查看双重验证码 UserFuncProperty userFuncProperty = userFuncPropertyMapper.selectOne(Wrappers.lambdaQuery(UserFuncProperty.class).eq(UserFuncProperty::getUserId, userId).last("limit 1")); //默认2次 int num = 2; //有安全码查看次数 置为0 if (isHasVerifyCode) { num = 0; //存在身份实名认证有两次机会 List userIdList = userBindRelationService.getRelationUserIdList(userId, null); Integer selectCount = userCertRecordMapper.selectCount(Wrappers.lambdaQuery(UserCertRecord.class) .in(UserCertRecord::getUserId, userIdList)); if (selectCount > 0) { num = 2; } return num; } //查看双重验证码次数 GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId); if (sku.getCodeNum() > 0) { num = sku.getCodeNum(); } if (userFuncProperty != null) num = userFuncProperty.getVerifyCheckNum(); return num; } @Override public List getHasPayGoods(long userId) { User user = userMapper.selectById(userId); List userIds = userBindRelationService.getRelationUserIdList(userId, user); DateTime now = DateTime.now(); List list = groupsRelationMapper.getUserHasPayGoods(userIds, now); return list; } @Override public List getExpiryRenewalNotify(Long userId) { DateTime now = DateTime.now(); DateTime thisZero = DateUtil.beginOfDay(now); String thisDate = thisZero.toDateStr(); Object exists = redisService.get(RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getNameFormat(thisDate, userId)); if (exists != null) { return null; } User u = userMapper.selectById(userId); if (u == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID); if (u.getIsBlack()) { redisService.setNx(RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getNameFormat(thisDate, userId), userId, RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getTimeout()); return null; } List userIds = userBindRelationService.getRelationUserIdList(userId, u); MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()); List list = beanSearcher.searchAll(RenewalView.class, builder .field(RenewalView::getUserId, 0).op(Operator.GreaterThan) .field(RenewalView::getUserId, userIds).op(Operator.InList) .field(RenewalView::getExpiryTime, now).op(Operator.GreaterThan) .field(RenewalView::getStatus, List.of("validity", "overdue", "outside")).op(Operator.InList) .field(RenewalView::getAqType, 1) .field(RenewalView::getIsVip, Boolean.TRUE) .orderBy(RenewalView::getExpiryTime).asc() .build()); if (list.size() > 5) { redisService.setNx(RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getNameFormat(thisDate, userId), userId, RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getTimeout()); return null; } List renewReduceSkuIds = userBenefitsMapper.selectList(Wrappers.lambdaQuery(UserBenefits.class) .eq(UserBenefits::getType, UserBenefits.Type.RENEW).eq(UserBenefits::getStatus, 1).select(UserBenefits::getSkuId)).stream().map(UserBenefits::getSkuId).collect(Collectors.toList()); //提前7天 AtomicInteger day = new AtomicInteger(7); List expiryTickets = list.stream().filter(ticket -> { //下架 if (ticket.getGoodsStatus() == null || ticket.getSkuStatus() == null || !ticket.getGoodsStatus() || !ticket.getSkuStatus()) { return false; } Integer skuMonths = ticket.getMonths(); if (skuMonths == null) { return false; } Date expiryTime = ticket.getExpiryTime(); //年付 提前一个月 if (skuMonths >= 12) { day.set(30); } else { day.set(7); } if (DateUtil.beginOfDay(expiryTime).compareTo(DateUtil.offsetDay(thisZero, day.get())) <= 0) { ticket.setExpiryTimeStr(DateUtil.format(ticket.getExpiryTime(), "yyyy-MM-dd")); //GPT镜像信息 setGptMirrorInfo(ticket); ticket.setExpiryTime(null); if (CollUtil.isNotEmpty(renewReduceSkuIds) && renewReduceSkuIds.contains(ticket.getSkuId())) { ticket.setIsRenewReduce(true); } return true; } return false; }).collect(Collectors.toList()); redisService.setNx(RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getNameFormat(thisDate, userId), userId, RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getTimeout()); if (CollUtil.isNotEmpty(expiryTickets)) { groupsRelationExpiryNotifyRecordMapper.batchInsert(userId, expiryTickets); } return expiryTickets; } @Override public void getCollegeStudentUserGptTicket(Long userId) { Retryer build = RetryerBuilder.newBuilder() .retryIfException() //运行时异常重试 .retryIfRuntimeException() //false重试 .retryIfResult(res -> Objects.equals(res, false)) //1s 间隔 .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS)) //停止策略 : 尝试请求3次 .withStopStrategy(StopStrategies.stopAfterAttempt(3)).build(); try { build.call(() -> { //体验规格 Long gptMirrorSkuId = Constant.GPT_MIRROR_SKU_ID; GroupsTrips groups = groupsMapper.selectCollegeStudentUserGptTicket(gptMirrorSkuId); if (groups == null) { groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class) .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting) .eq(GroupsTrips::getSkuId, gptMirrorSkuId) .last("limit 1")); } GroupsRelation relation = null; if (groups != null) { relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId()); } if (relation == null) { //生成空车队 GoodsDonSku sku = goodsDonSkuMapper.selectById(gptMirrorSkuId); relation = groupsFuncService.createNewGroupsTrips(sku); } DateTime startTime = DateTime.now(); DateTime expiryTime = DateUtil.offsetDay(startTime, 1); int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getUserId, userId) .set(GroupsRelation::getStartTime, startTime) .set(GroupsRelation::getExpiryTime, expiryTime) .set(GroupsRelation::getStatus, GroupsRelation.Status.validity) .set(GroupsRelation::getAqType, 2) .eq(GroupsRelation::getId, relation.getId()) .eq(GroupsRelation::getUserId, 0)); if (update > 0) { groupsMapper.decrAvailableNum(relation.getGroupsId()); return true; } log.error("发送用户:{} GPT镜像车票体验失败,进行重试", userId); return false; }); } catch (ExecutionException | RetryException e) { log.error("发送用户GPT镜像体验失败:{}", StringUtil.getErrorText(e)); } } @Override public RenewalView getTicketDetail(long userId, Long relationId) { User u = userMapper.selectById(userId); List userIds = userBindRelationService.getRelationUserIdList(userId, u); MapBuilder builder = MapUtils.builder(); RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, builder .field(RenewalView::getRelationId, relationId) .field(RenewalView::getUserId, 0).op(Operator.GreaterThan) .field(RenewalView::getUserId, userIds).op(Operator.InList) .field("condition", String.format("(gr.expiry_time is null or gr.expiry_time > '%s')", DateTime.now())) .field(RenewalView::getStatus, List.of("validity", "outside")).op(Operator.InList) .orderBy(RenewalView::getExpiryTime).asc() .onlySelect(RenewalView::getRelationId, RenewalView::getExpiryTime, RenewalView::getTitle, RenewalView::getSpecVal, RenewalView::getGoodsId, RenewalView::getSkuId, RenewalView::getSkuNum, RenewalView::getSkuStatus, RenewalView::getGoodsStatus) .build()); if (renewalView != null) { renewalView.setExpiryTimeStr(DateUtil.format(renewalView.getExpiryTime(), "yyyy-MM-dd")); } return renewalView; } @Override public GroupsRelation ticketLogin(TicketLoginReq loginReq) { String account = loginReq.getAccount(); if (StrUtil.isEmpty(account)) { throw BusinessRuntimeException.getInstance("请输入对应账号"); } if (loginReq.getMerchants()) { if (account.contains(Constant.YH_EMAIL_DOMAIN_SUFFIX)) { SysEmail sysEmail = sysEmailMapper.selectOne(Wrappers.lambdaQuery(SysEmail.class) .eq(SysEmail::getEmail, account) .last("limit 1")); if (sysEmail == null) { throw BusinessRuntimeException.getInstance("账号错误,请联系客服"); } } GroupsRelation relation = new GroupsRelation(); relation.setId(0l); return relation; } String password = loginReq.getPassword(); Integer num = loginReq.getNum(); if (ObjectUtil.hasEmpty(password, num)) { throw BusinessRuntimeException.getInstance("参数错误"); } Long goodsId = Optional.ofNullable(loginReq.getGoodsId()).orElse(1l); GroupsRelation relation = groupsRelationMapper.selectRelationByAccountAndNum(account, password, goodsId, num); if (relation == null) { log.info("外部入口使用账号account:{},pwd:{},座位num:{}登录失败...", account, password, num); if (StrUtil.equals(loginReq.getLang(), Constant.EN_US)) { throw BusinessRuntimeException.getInstance("Please enter the correct account information"); } throw BusinessRuntimeException.getInstance("请输入正确的账号信息"); } return relation; } @Override public String outsideTicketVerify(TicketLoginReq loginReq) { String account = loginReq.getAccount(); if (StrUtil.isEmpty(account)) { throw BusinessRuntimeException.getInstance("账号错误"); } if (loginReq.getMerchants()) { if (account.contains(Constant.YH_EMAIL_DOMAIN_SUFFIX)) { SysEmail sysEmail = sysEmailMapper.selectOne(Wrappers.lambdaQuery(SysEmail.class) .eq(SysEmail::getEmail, account) .last("limit 1")); if (sysEmail == null) { throw BusinessRuntimeException.getInstance("账号错误,请联系客服"); } } loginReq.setGoodsId(1l); loginReq.setAccountId(0l); } else { String password = loginReq.getPassword(); Integer num = loginReq.getNum(); if (ObjectUtil.hasEmpty(password, num)) { throw BusinessRuntimeException.getInstance("参数错误"); } Long goodsId = Optional.ofNullable(loginReq.getGoodsId()).orElse(1l); GroupsRelation relation = groupsRelationMapper.selectRelationByAccountAndNum(account, password, goodsId, num); if (relation == null) { log.info("外部入口使用账号account:{},pwd:{},座位num:{}同步验证链接失败...", account, password, num); if (StrUtil.equals(loginReq.getLang(), Constant.EN_US)) { throw BusinessRuntimeException.getInstance("This account is no longer valid"); } throw BusinessRuntimeException.getInstance("该账号已失效"); } loginReq.setUserId(relation.getUserId()); loginReq.setRelationId(relation.getId()); loginReq.setGoodsId(goodsId); } try { String aiVerifyCode = getAiVerifyCode(loginReq); if (StrUtil.isEmpty(aiVerifyCode)) { throw BusinessRuntimeException.getInstance(""); } return aiVerifyCode; } catch (Exception e) { if (StrUtil.equals(loginReq.getLang(), Constant.EN_US)) { throw BusinessRuntimeException.getInstance("Please verify that the link was sent"); } throw BusinessRuntimeException.getInstance("请校验链接是否已发送"); } } @Override public String getNfHouseholdDevice(long userId, Long relationId) throws Exception { List relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null); RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder().field(RenewalView::getUserId, relationUserIdList).op(Operator.InList) .field(RenewalView::getRelationId, relationId).build()); if (renewalView == null) { throw BusinessRuntimeException.getInstance("您的车票不存在..."); } if (StrUtil.isEmpty(renewalView.getAccount())) { throw BusinessRuntimeException.getInstance("车票未配置账号"); } String account = renewalView.getAccount(); String password = renewalView.getPassword(); if (StrUtil.hasEmpty(account, password)) { throw BusinessRuntimeException.getInstance("您的车票账号密码异常,请联系客服..."); } String code = commonMailService.getTicketMailCode(renewalView.getGoodsId(), account, renewalView.getRelateEmail(), renewalView.getGptEmailPwd(), renewalView.getCreatedTime(), null, 1, true); return code; } @Override public String getVerifyCode(String account) throws Exception { Account at = accountMapper.selectOne(Wrappers.lambdaQuery(Account.class) .eq(Account::getAccount, account) .eq(Account::getGoodsId, 18)); if (at == null) { return null; } String password = at.getPassword(); if (StrUtil.hasEmpty(account, password)) { throw BusinessRuntimeException.getInstance("账号异常"); } String code = commonMailService.getTicketMailCode(at.getGoodsId(), account, at.getRelateEmail(), at.getGptEmailPwd(), at.getCreatedTime(), null, null, false); return code; } @Override public void changeTicket(long userId, Long relationId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder() .field(RenewalView::getUserId, userIdList).op(Operator.InList) .field(RenewalView::getRelationId, relationId) .field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan) .build()); if (renewalView == null) { throw BusinessRuntimeException.getInstance("车票不存在"); } if (renewalView.getGoodsId() != 1) { throw BusinessRuntimeException.getInstance("只针对奈飞车票"); } AccountNetflixState accountNetflixState = accountNetflixStateMapper.selectOne(Wrappers.lambdaQuery(AccountNetflixState.class) .eq(AccountNetflixState::getAccount, renewalView.getAccount()) .orderByDesc(AccountNetflixState::getId) .last("limit 1")); if (accountNetflixState == null || accountNetflixState.getState() != 3) { throw BusinessRuntimeException.getInstance("只支持异常账号更换车票"); } String key = RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getName() + relationId; if (!redisService.setNx(key, relationId, RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getTimeout())) { throw BusinessRuntimeException.getInstance("正在更换车票中.."); } Long groupId = renewalView.getGroupId(); Long skuId = renewalView.getSkuId(); Date expiryTime = renewalView.getExpiryTime(); //随机选择同规格得车票 Long item_groupsId = groupsMapper.selectRandomGroupsTripsBySkuId(groupId, skuId, expiryTime); GroupsRelation newRelation = null; if (item_groupsId != null) { //存在就随机分配一个,没有就不做处理 newRelation = changeTickerRelation.changeTicket(renewalView.getUserId(), relationId, item_groupsId, renewalView.getSkuId()); } //若无移至空车队 if (newRelation == null) { newRelation = changeTickerRelation.getEmptyGroupsRelation(renewalView.getUserId(), renewalView.getRelationId(), renewalView.getSkuId()); } if (newRelation == null) { throw BusinessRuntimeException.getInstance("更换异常,请重新提交"); } NetflixUserAccountStatusRecord netflixUserAccountStatusRecord = netflixUserAccountStatusRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class) .eq(NetflixUserAccountStatusRecord::getRelationId, relationId) .last("limit 1")); if (netflixUserAccountStatusRecord != null) { netflixUserAccountStatusRecord.setDeleted(false); netflixUserAccountStatusRecordMapper.updateById(netflixUserAccountStatusRecord); } redisService.del(key); } @Override public AccountView getTempAccount(long userId, Long relationId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder() .field(RenewalView::getRelationId, relationId) .field(RenewalView::getUserId, userIdList).op(Operator.InList) .field(RenewalView::getGroupsStatus, GroupsTrips.Status.waiting.name()) .field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan) .build()); if (renewalView == null) { throw BusinessRuntimeException.getInstance("车票不存在"); } AccountView accountView = new AccountView(); //奈飞超过3帐车票不给看 Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder() .field(RenewalView::getUserId, userIdList).op(Operator.InList) .field(RenewalView::getGoodsId, 1) .field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan) .build()); if (number.intValue() > 2) { return accountView; } NetflixTempAccountUser netflixTempAccountUser = netflixTempAccountUserMapper.selectOne(Wrappers.lambdaQuery(NetflixTempAccountUser.class) .eq(NetflixTempAccountUser::getRelationId, relationId) .in(NetflixTempAccountUser::getUserId, userIdList) .last("limit 1")); Account account; if (netflixTempAccountUser == null) { account = accountMapper.selectNetflixTempAccount(); if (account != null) { netflixTempAccountUser = new NetflixTempAccountUser(); netflixTempAccountUser.setAccountId(account.getId()); netflixTempAccountUser.setRelationId(relationId); netflixTempAccountUser.setUserId(renewalView.getUserId()); netflixTempAccountUserMapper.insert(netflixTempAccountUser); } } else { account = accountMapper.selectById(netflixTempAccountUser.getAccountId()); } if (account != null) { accountView.setAccount(account.getAccount()); accountView.setPassword(account.getPassword()); } return accountView; } @Override public void nfErrorAccountSubmit(long userId, Long relationId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder() .field(RenewalView::getUserId, userIdList).op(Operator.InList) .field(RenewalView::getRelationId, relationId) .field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan).build()); if (renewalView == null) { throw BusinessRuntimeException.getInstance("车票不存在"); } if (renewalView.getGoodsId() != 1) { throw BusinessRuntimeException.getInstance("只支持奈飞车票"); } String account = renewalView.getAccount(); String password = renewalView.getPassword(); Integer selectCount = netflixUserAccountStatusRecordMapper.selectCount(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class) .eq(NetflixUserAccountStatusRecord::getRelationId, relationId) .in(NetflixUserAccountStatusRecord::getUserId, userIdList) .eq(NetflixUserAccountStatusRecord::getAccount, account) .eq(NetflixUserAccountStatusRecord::getState, 0) .eq(NetflixUserAccountStatusRecord::getDeleted, 1)); if (selectCount > 0) { throw BusinessRuntimeException.getInstance("该账号正在检测中"); } AccountNetflixState accountNetflixState = accountNetflixStateMapper.selectOne(Wrappers.lambdaQuery(AccountNetflixState.class) .eq(AccountNetflixState::getAccount, account) .last("limit 1")); Integer state = 0; if (accountNetflixState != null && accountNetflixState.getState() == 3) { state = accountNetflixState.getState(); } //非正常状态 if (state != 1) { //20号之前得校验 直接失败 if (renewalView.getCreatedTime().compareTo(DateUtil.parse("2025-06-20")) < 0) { state = 3; } //如果账号下架了 直接失败 if (StrUtil.equals(GroupsTrips.Status.down.name(), renewalView.getGroupsStatus()) && renewalView.getSkuNum() > 1) { state = 3; } } NetflixUserAccountStatusRecord netflixUserAccountStatusRecord = new NetflixUserAccountStatusRecord(); netflixUserAccountStatusRecord.setAccount(account); netflixUserAccountStatusRecord.setRelationId(relationId); netflixUserAccountStatusRecord.setPassword(password); netflixUserAccountStatusRecord.setUserId(renewalView.getUserId()); netflixUserAccountStatusRecord.setState(state); OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getRelationId, renewalView.getRelationId()) .in(OrderDon::getUserId, userIdList) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon != null) { netflixUserAccountStatusRecord.setOrderId(orderDon.getId()); } netflixUserAccountStatusRecordMapper.insert(netflixUserAccountStatusRecord); } @Override public NetflixErrorAccountStatus getNetflixErrorAccountStatus(long userId, Long relationId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); NetflixUserAccountStatusRecord netflixUseAccountStatusRecord = netflixUserAccountStatusRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class) .eq(NetflixUserAccountStatusRecord::getRelationId, relationId) .eq(NetflixUserAccountStatusRecord::getDeleted, 1) .in(NetflixUserAccountStatusRecord::getUserId, userIdList) .orderByDesc(NetflixUserAccountStatusRecord::getId) .last("limit 1")); NetflixErrorAccountStatus status = new NetflixErrorAccountStatus(); if (netflixUseAccountStatusRecord == null) { //是否已经更换 NetflixUserAccountSubmitRecoverRecord replaceRecover = netflixUserAccountSubmitRecoverRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class) .eq(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList) .eq(NetflixUserAccountSubmitRecoverRecord::getReplaceRelationId, relationId) .last("limit 1")); if (replaceRecover != null) { status.setRecoverStatus(replaceRecover.getStatus()); } return status; } Integer state = netflixUseAccountStatusRecord.getState(); //2是登录失败 3是被封号 // if (state == 3) { // if (netflixUseAccountStatusRecord.getCreatedTime().compareTo(DateUtil.offsetMinute(DateTime.now(), -10)) > 0) { // state = 0; // } // } //登录失败 可继续申请检测 if (state == 2) { return status; } //未异常 if (state != 3) { //车队是否已下架 GroupsRelation relation = groupsRelationMapper.selectById(relationId); GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId()); if (groupsTrips != null && groupsTrips.getStatus() == GroupsTrips.Status.down) { state = 3; //下架 异常 if (netflixUseAccountStatusRecord != null) { netflixUseAccountStatusRecord.setState(state); netflixUserAccountStatusRecordMapper.updateById(netflixUseAccountStatusRecord); } } } //账号检测状态 status.setNfStatus(state); NetflixUserAccountSubmitRecoverRecord recoverRecord = netflixUserAccountSubmitRecoverRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class) .in(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList) .eq(NetflixUserAccountSubmitRecoverRecord::getRelationId, relationId) .last("limit 1")); if (recoverRecord != null) { //申请恢复状态 status.setRecoverStatus(recoverRecord.getStatus()); status.setSubmitTime(recoverRecord.getCreatedTime()); } return status; } @Override public List getUserNetflixSubmitRecord(long userId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); List netflixUseAccountStatusRecords = netflixUserAccountStatusRecordMapper.selectList(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class) .in(NetflixUserAccountStatusRecord::getUserId, userIdList) .eq(NetflixUserAccountStatusRecord::getDeleted, 1) .select(NetflixUserAccountStatusRecord::getOrderId, NetflixUserAccountStatusRecord::getRelationId, NetflixUserAccountStatusRecord::getState, NetflixUserAccountStatusRecord::getCreatedTime)); return netflixUseAccountStatusRecords; } @Override public Long getTrialTicketByUserIdAndGoodsId(Long userId, Long trialSkuId, Integer ticketType) { Retryer build = RetryerBuilder.newBuilder() .retryIfException() //运行时异常重试 .retryIfRuntimeException() //false重试 .retryIfResult(res -> res == null) //1s 间隔 .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS)) //停止策略 : 尝试请求3次 .withStopStrategy(StopStrategies.stopAfterAttempt(3)).build(); try { return build.call(() -> { //体验规格 GroupsTrips groups = groupsMapper.selectCollegeStudentUserGptTicket(trialSkuId); GroupsRelation relation = null; if (groups == null) { groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class) .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting) .eq(GroupsTrips::getSkuId, trialSkuId) .last("limit 1")); } if (groups != null) { relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId()); } if (relation == null) { //生成空车队 GoodsDonSku sku = goodsDonSkuMapper.selectById(trialSkuId); relation = groupsFuncService.createNewGroupsTrips(sku); } DateTime startTime = DateTime.now(); DateTime expiryTime = DateUtil.offsetDay(startTime, 1); int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getUserId, userId) .set(GroupsRelation::getStartTime, startTime) .set(GroupsRelation::getExpiryTime, expiryTime) .set(GroupsRelation::getStatus, GroupsRelation.Status.validity) .set(GroupsRelation::getAqType, ticketType) .eq(GroupsRelation::getId, relation.getId()) .eq(GroupsRelation::getUserId, 0)); if (update > 0) { groupsMapper.decrAvailableNum(relation.getGroupsId()); return relation.getId(); } log.error("发送用户:{} GPT镜像车票体验失败,进行重试", userId); return null; }); } catch (ExecutionException | RetryException e) { log.error("发送用户GPT镜像体验失败:{}", StringUtil.getErrorText(e)); return null; } } @Override public Boolean getMirrorPopups(long userId) { //是否弹窗 默认否 Boolean flag = false; List userIdList = userBindRelationService.getRelationUserIdList(userId, null); Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder() .field(RenewalView::getUserId, userIdList).op(Operator.InList) .field(RenewalView::getStatus, GroupsRelation.Status.validity.name()) .field(RenewalView::getIsMirror, true) .build()); if (number.intValue() == 0) { flag = true; } if (!flag) { String thisWeekBegin = DateUtil.beginOfWeek(DateTime.now()).toDateStr(); Integer selectCount = mirrorTicketPopupsRecordMapper.selectCount(Wrappers.lambdaQuery(MirrorTicketPopupsRecord.class) .in(MirrorTicketPopupsRecord::getUserId, userIdList) .eq(MirrorTicketPopupsRecord::getThisWeek, thisWeekBegin)); if (selectCount == 0) { MirrorTicketPopupsRecord mirrorTicketPopupsRecord = new MirrorTicketPopupsRecord(); mirrorTicketPopupsRecord.setThisWeek(thisWeekBegin); mirrorTicketPopupsRecord.setUserId(userId); mirrorTicketPopupsRecordMapper.insert(mirrorTicketPopupsRecord); } else { flag = true; } } return flag; } @Override public Long getTicket(Long userId, Long skuId, Boolean isVip) { Retryer build = RetryerBuilder.newBuilder() .retryIfException() //运行时异常重试 .retryIfRuntimeException() //false重试 .retryIfResult(res -> res == null) //1s 间隔 .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS)) //停止策略 : 尝试请求1次 .withStopStrategy(StopStrategies.stopAfterAttempt(1)).build(); try { return build.call(() -> { GroupsTrips groups = groupsMapper.selectCollegeStudentUserGptTicket(skuId); GroupsRelation relation = null; if (groups == null) { groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class) .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting) .eq(GroupsTrips::getSkuId, skuId) .last("limit 1")); } if (groups != null) { relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId()); } GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId); //生成空车队 if (relation == null) { relation = groupsFuncService.createNewGroupsTrips(sku); } DateTime startTime = DateTime.now(); DateTime expiryTime; if (sku.getDays() != null) { expiryTime = DateUtil.offsetDay(startTime, sku.getDays()); } else { expiryTime = DateUtil.offsetMonth(startTime, sku.getMonths()); } int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getUserId, userId) .set(GroupsRelation::getStartTime, startTime) .set(GroupsRelation::getExpiryTime, expiryTime) .set(GroupsRelation::getStatus, GroupsRelation.Status.validity) .set(GroupsRelation::getIsVip, isVip) .eq(GroupsRelation::getId, relation.getId()) .eq(GroupsRelation::getUserId, 0)); if (update > 0) { groupsMapper.decrAvailableNum(relation.getGroupsId()); return relation.getId(); } log.error("发送用户:{} GPT镜像车票失败,进行重试", userId); return null; }); } catch (ExecutionException | RetryException e) { log.error("发送用户GPT镜像失败:{}", StringUtil.getErrorText(e)); return null; } } @Override public Boolean getVipMirrorTicketIfEmpty(long userId, Long skuId) { Integer selectCount = vipGoodsSkuMapper.selectCount(Wrappers.lambdaQuery(VipGoodsSku.class) .eq(VipGoodsSku::getSkuId, skuId)); if (selectCount == 0) { return false; } 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) { return false; } Number number = beanSearcher.searchCount(GroupsRelationView.class, MapUtils.builder() .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList) .field(GroupsRelationView::getSkuId, skuId) .field(GroupsRelationView::getIsVip, Boolean.TRUE) .build()); if (number.intValue() == 0) { Long relationId = getTicket(vipUser.getUserId(), skuId, Boolean.TRUE); //同步时间 groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getExpiryTime, vipUser.getExpiryTime()) .eq(GroupsRelation::getUserId, vipUser.getUserId()) .eq(GroupsRelation::getId, relationId)); return true; } return false; } @Override @Transactional(rollbackFor = Throwable.class) public NetflixRecoverResp netflixSubmitRecover(ErrorNetflixChangeReq req) { NetflixRecoverResp recoverResp = new NetflixRecoverResp(); Long relationId = req.getRelationId(); Long userId = req.getUserId(); //校验奈飞账号状态 GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId); if (netflixRelationView.getIsFrozen()) { int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getIsFrozen, Boolean.FALSE) .eq(GroupsRelation::getId, netflixRelationView.getId()) .eq(GroupsRelation::getIsFrozen, Boolean.TRUE)); if (update == 0) { throw BusinessRuntimeException.getInstance("申请恢复账号失败,请重试"); } try { //获取同规格的车票 Long skuId = netflixRelationView.getSkuId(); GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId); GroupsRelation relation = getRelation(null, userId, sku, null); if (relation != null) { Long groupsId = relation.getGroupsId(); GroupsTrips groupsTrips = groupsMapper.selectById(groupsId); //已发车 if (groupsTrips.getStatus() == GroupsTrips.Status.validity) { resetUserTicket(netflixRelationView, relation); recoverResp.setIsReset(Boolean.TRUE); return recoverResp; } } } catch (Exception e) { throw BusinessRuntimeException.getInstance("申请恢复账号失败,请重试"); } } Date expiryTime = netflixRelationView.getExpiryTime(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); NetflixUserAccountSubmitRecoverRecord recoverRecord = netflixUserAccountSubmitRecoverRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class) .eq(NetflixUserAccountSubmitRecoverRecord::getRelationId, relationId) .in(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList) .eq(NetflixUserAccountSubmitRecoverRecord::getStatus, 0) .last("limit 1")); if (recoverRecord == null) { recoverRecord = new NetflixUserAccountSubmitRecoverRecord(); recoverRecord.setRelationId(relationId); recoverRecord.setUserId(netflixRelationView.getUserId()); recoverRecord.setSkuId(netflixRelationView.getSkuId()); recoverRecord.setAccount(netflixRelationView.getAccount()); Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1; recoverRecord.setRemainDays(betweenDay); recoverRecord.setAccount(netflixRelationView.getTripsAccount()); try { netflixUserAccountSubmitRecoverRecordMapper.insert(recoverRecord); } catch (DuplicateKeyException e) { throw BusinessRuntimeException.getInstance("您已申请恢复"); } } //等待位数 Integer selectCount = netflixUserAccountSubmitRecoverRecordMapper.selectCount(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class) .lt(NetflixUserAccountSubmitRecoverRecord::getCreatedTime, recoverRecord.getCreatedTime()) .eq(NetflixUserAccountSubmitRecoverRecord::getStatus, 0)); //往前加100位 recoverResp.setIndex(100 + selectCount + 1); recoverResp.setRemainDays(recoverRecord.getRemainDays()); return recoverResp; } private void resetUserTicket(GroupsRelationView oldRelation, GroupsRelation newRelation) { Long userId = oldRelation.getUserId(); Long oldRelationId = oldRelation.getId(); //清除车票 List userIdList; try { userIdList = userBindRelationService.getRelationUserIdList(userId, null); } catch (Exception e) { userIdList = List.of(userId); } GroupsRelation clearRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getId, oldRelationId) .in(GroupsRelation::getUserId, userIdList) .last("limit 1")); if (clearRelation != null) { clearRelation.setNewRelationId(newRelation.getId()); clearService.clearTicket(clearRelation, UserTicketClearedRecord.Source.ticket_replace); } newRelation.setUserId(userId); //校验座位 int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getUserId, userId) .eq(GroupsRelation::getUserId, 0) .eq(GroupsRelation::getId, newRelation.getId())); if (update == 0) { throw BusinessRuntimeException.getInstance("申请恢复账号失败,请重试"); } //恢复状态 newRelation.setStartTime(oldRelation.getStartTime()); newRelation.setExpiryTime(DateUtil.offsetDay(DateTime.now(), oldRelation.getReservedDays())); newRelation.setStatus(GroupsRelation.Status.validity); groupsRelationMapper.updateById(newRelation); //原订单座位id更新 OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .in(OrderDon::getUserId, userIdList) .eq(OrderDon::getRelationId, oldRelationId) .notIn(OrderDon::getStatus, Constant.noOrderStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon != null) { orderDon.setRelationId(newRelation.getId()); orderDonMapper.updateById(orderDon); } } @Override @Transactional(rollbackFor = Throwable.class) public void errorNetflixSubmitChangeOtherTicket(ErrorNetflixChangeReq req) throws Exception { Long relationId = req.getRelationId(); Long userId = req.getUserId(); //校验奈飞账号状态 GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId); Date expiryTime = netflixRelationView.getExpiryTime(); //小于15 不可替换其他车票 Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1; if (betweenDay <= 30) { throw BusinessRuntimeException.getInstance("您的车票有效期未超过30天"); } List userIdList = userBindRelationService.getRelationUserIdList(userId, null); NetflixUserAccountSubmitRecoverRecord recoverRecord = netflixUserAccountSubmitRecoverRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class) .eq(NetflixUserAccountSubmitRecoverRecord::getRelationId, relationId) .in(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList) .orderByDesc(NetflixUserAccountSubmitRecoverRecord::getId).last("limit 1")); if (recoverRecord != null) { if (recoverRecord.getCreatedTime().after(DateUtil.offsetDay(DateTime.now(), -1))) { throw BusinessRuntimeException.getInstance("您的车票申请恢复中..."); } recoverRecord.setStatus(2); int update = netflixUserAccountSubmitRecoverRecordMapper.update(recoverRecord, Wrappers.lambdaUpdate(NetflixUserAccountSubmitRecoverRecord.class) .eq(NetflixUserAccountSubmitRecoverRecord::getStatus, 0) .eq(NetflixUserAccountSubmitRecoverRecord::getId, recoverRecord.getId())); if (update == 0) { throw BusinessRuntimeException.getInstance("系统异常,请重试"); } } String key = RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getName() + relationId; if (!redisService.setNx(key, relationId, RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getTimeout())) { throw BusinessRuntimeException.getInstance("正在更换其他车票中.."); } try { Long skuId = req.getSkuId(); SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class) .eq(SysConfig::getSysKey, Constant.ERROR_NETFLIX_CHANGE_OTHER_SKU_KEY) .last("limit 1")); List errorNetflixChangeOtherSkuTicketDtos = Jsons.parseList(sysConfig.getSysValue(), ErrorNetflixChangeOtherSkuTicketDto.class); ErrorNetflixChangeOtherSkuTicketDto errorNetflixChangeOtherSkuTicketDto; //自定义顺序 直接获取 if (betweenDay <= 60) { //检验规格 errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(0); } else if (betweenDay <= 120) { errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(1); } else { errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(2); } List availableSkuIds = errorNetflixChangeOtherSkuTicketDto.getSkuIds(); if (!availableSkuIds.contains(skuId)) { throw BusinessRuntimeException.getInstance("不支持更换该类型车票"); } //替换车票 TicketChangeDto changeDto = getTicketAndGenerateOrder(userId, skuId, null, null); if (changeDto == null) { throw BusinessRuntimeException.getInstance("系统繁忙,请重试"); } //替换记录 NetflixUserChangeOtherTicketRecord changeOtherTicketRecord = new NetflixUserChangeOtherTicketRecord(); changeOtherTicketRecord.setUserId(userId); changeOtherTicketRecord.setRelationId(relationId); changeOtherTicketRecord.setOtherRelationId(changeDto.getOtherRelationId()); changeOtherTicketRecord.setRelateOrderId(changeDto.getOtherOrderId()); //该车票订单id changeOtherTicketRecord.setOrderId(netflixRelationView.getNfOriOrderId()); changeOtherTicketRecord.setStartTime(netflixRelationView.getStartTime()); changeOtherTicketRecord.setExpiryTime(expiryTime); netflixUserChangeOtherTicketRecordMapper.insert(changeOtherTicketRecord); if (netflixRelationView.getNfCheckId() != null) { netflixUserAccountStatusRecordMapper.update(null, Wrappers.lambdaUpdate(NetflixUserAccountStatusRecord.class) .set(NetflixUserAccountStatusRecord::getDeleted, false) .eq(NetflixUserAccountStatusRecord::getId, netflixRelationView.getNfCheckId())); } Long ticketUserId = null; //清除车票 GroupsRelation clearRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getId, relationId) .in(GroupsRelation::getUserId, userIdList) .last("limit 1")); if (clearRelation != null) { ticketUserId = clearRelation.getUserId(); clearService.clearTicket(clearRelation, UserTicketClearedRecord.Source.ticket_replace); } OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getRelationId, relationId) .in(OrderDon::getUserId, userIdList) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon != null) { if (ticketUserId == null) { ticketUserId = orderDon.getUserId(); } //替换sku GoodsDonSku replaceSku = goodsDonSkuMapper.selectById(skuId); GoodsDonSku oriTicketSku = goodsDonSkuMapper.selectById(orderDon.getSkuId()); //每天单价 BigDecimal dayPrice = oriTicketSku.getPrice().divide(BigDecimal.valueOf(oriTicketSku.getMonths() * 30), RoundingMode.DOWN); //需要退款金额 BigDecimal refundMoney = dayPrice.multiply(BigDecimal.valueOf(betweenDay)); BigDecimal balance = Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO); BigDecimal finalOrderMoney = orderDon.getMoney().add(balance); if (refundMoney.compareTo(finalOrderMoney) > 0) { refundMoney = finalOrderMoney; } //车票价格高于替换的规格价格 退余额 if (refundMoney.compareTo(replaceSku.getPrice()) > 0) { BigDecimal refundBalance = refundMoney.subtract(replaceSku.getPrice()); if (refundBalance.compareTo(BigDecimal.ZERO) > 0) { userBenefitsService.addUserBalance(ticketUserId, refundBalance, UserBalanceSourceRecord.Source.TICKET_REPLACE, 0L, orderDon.getId(), UserBalanceSourceRecord.Source.TICKET_REPLACE.getDesc(), true); } } } } finally { redisService.del(key); } } @Override public List getNetflixReplaceOtherSkus(long userId, Long relationId) throws Exception { //校验奈飞账号状态 GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId); Date expiryTime = netflixRelationView.getExpiryTime(); //小于15 不可替换其他车票 Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1; SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class) .eq(SysConfig::getSysKey, Constant.ERROR_NETFLIX_CHANGE_OTHER_SKU_KEY) .last("limit 1")); List errorNetflixChangeOtherSkuTicketDtos = Jsons.parseList(sysConfig.getSysValue(), ErrorNetflixChangeOtherSkuTicketDto.class); ErrorNetflixChangeOtherSkuTicketDto errorNetflixChangeOtherSkuTicketDto; if (betweenDay <= 30) { return null; } //自定义顺序 直接获取 if (betweenDay <= 60) { //检验规格 errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(0); } else if (betweenDay <= 120) { errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(1); } else { errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(2); } List goodsCategorySkuViews = beanSearcher.searchAll(GoodsCategorySkuView.class, MapUtils.builder() .field(GoodsCategorySkuView::getSkuId, errorNetflixChangeOtherSkuTicketDto.getSkuIds()).op(Operator.InList) .orderBy(GoodsCategorySkuView::getPrice).desc() .build()); return goodsCategorySkuViews; } @Override public NetflixRefundInfoResp refundNetflixInfo(Long userId, Long relationId) { //校验奈飞账号状态 GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId); Date expiryTime = netflixRelationView.getExpiryTime(); //小于15 Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1; NetflixRefundInfoResp refundInfoResp = new NetflixRefundInfoResp(); refundInfoResp.setIsRefund(true); if (betweenDay > 30) { refundInfoResp.setIsRefund(false); } List userIdList = userBindRelationService.getRelationUserIdList(userId, null); OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getRelationId, relationId) .in(OrderDon::getUserId, userIdList) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon == null) { refundInfoResp.setIsRefund(false); } Long skuId = netflixRelationView.getSkuId(); GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId); BigDecimal orderMoney = orderDon == null ? BigDecimal.ZERO : orderDon.getMoney(); if (orderMoney.compareTo(BigDecimal.ZERO) == 0) { refundInfoResp.setIsRefund(false); } //每天单价 BigDecimal dayPrice = sku.getPrice().divide(BigDecimal.valueOf(sku.getMonths() * 30), RoundingMode.DOWN); //需要退款金额 BigDecimal refundMoney = dayPrice.multiply(BigDecimal.valueOf(betweenDay)); refundInfoResp.setPrice(refundMoney); BigDecimal balance = orderDon == null ? BigDecimal.ZERO : Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO); //超过本身订单金额 不允许退款 if (refundMoney.compareTo(orderMoney) > 0) { refundInfoResp.setIsRefund(false); } if (refundMoney.compareTo(orderMoney.add(balance)) > 0) { refundInfoResp.setPrice(orderMoney.add(balance)); } refundInfoResp.setRemainDays(betweenDay); return refundInfoResp; } @Override public Boolean refundNetflix(ErrorNetflixChangeReq req) throws Exception { Long relationId = req.getRelationId(); Long userId = req.getUserId(); //校验奈飞账号状态 GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId); Date expiryTime = netflixRelationView.getExpiryTime(); //小于15 Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1; if (betweenDay > 30) { throw BusinessRuntimeException.getInstance("车票有效期不超过30天可退款"); } List userIdList = userBindRelationService.getRelationUserIdList(userId, null); OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getRelationId, relationId) .in(OrderDon::getUserId, userIdList) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon == null) { throw BusinessRuntimeException.getInstance("对应车票订单不存在,请联系客服"); } Long skuId = netflixRelationView.getSkuId(); GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId); BigDecimal orderMoney = orderDon.getMoney(); if (orderMoney.compareTo(BigDecimal.ZERO) == 0) { throw BusinessRuntimeException.getInstance("不符合退款条件"); } //每天单价 BigDecimal dayPrice = sku.getPrice().divide(BigDecimal.valueOf(sku.getMonths() * 30), RoundingMode.DOWN); //需要退款金额 BigDecimal refundMoney = dayPrice.multiply(BigDecimal.valueOf(betweenDay)); if (refundMoney.compareTo(orderMoney) > 0) { throw BusinessRuntimeException.getInstance("不符合退款条件"); } //调用第三方接口退款 OrderRefundReq refundReq = new OrderRefundReq(); refundReq.setRefundMoney(refundMoney); refundReq.setRefundType("money"); String outNo = orderRefundService.centerRefund(refundReq, orderDon); orderDon.setStatus(OrderDon.Status.refund); orderDon.setRefundMoney(refundMoney); GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId()); orderDonMapper.updateById(orderDon); orderRefundService.refundRecord(orderDon, refundMoney, null, "系统", goodsDon, sku, outNo, orderDon.getType().name(), null); //清除车票 GroupsRelation relation = groupsRelationMapper.selectById(relationId); clearService.clearTicket(relation, UserTicketClearedRecord.Source.refund); if (netflixRelationView.getNfCheckId() != null) { netflixUserAccountStatusRecordMapper.update(null, Wrappers.lambdaUpdate(NetflixUserAccountStatusRecord.class) .set(NetflixUserAccountStatusRecord::getDeleted, false) .eq(NetflixUserAccountStatusRecord::getId, netflixRelationView.getNfCheckId())); } return true; } @Override public List getMirrorTicket(long userId) { User u = userMapper.selectById(userId); if (u == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID); if (u.getIsBlack()) { return null; } List userIds = userBindRelationService.getRelationUserIdList(userId, u); MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()); DateTime now = DateTime.now(); String lang = request.getHeader("lang"); List list = beanSearcher.searchAll(UserMirrorTicketView.class, builder .field(UserMirrorTicketView::getUserId, userIds).op(Operator.InList) .field(UserMirrorTicketView::getIsMirror, Boolean.TRUE) //过期7天内的镜像车票都展示 .field(UserMirrorTicketView::getExpiryTime, DateUtil.offsetDay(now, -7)).op(Operator.GreaterThan) .orderBy(RenewalView::getExpiryTime).asc() .build()); list.forEach(ticket -> { if (ticket.getExpiryTime() != null) { String remainDays = DateUtil.formatBetween(now, ticket.getExpiryTime(), BetweenFormater.Level.DAY); if ("0天".equals(remainDays)) { remainDays = "小于1天"; } else { //当天也算 int days = Integer.parseInt(remainDays.substring(0, remainDays.indexOf("天"))); remainDays = days + 1 + "天"; } ticket.setRemainDays(remainDays); ticket.setTotal(DateUtil.betweenDay(ticket.getStartTime(), ticket.getExpiryTime(), false) + 1); } if (ticket.getExpiryTime() != null) { ticket.setExpiryTimeStr(DateUtil.format(ticket.getExpiryTime(), "yyyy-MM-dd")); } //续费升级折扣 BigDecimal renewDiscount = getRenewDiscount(ticket.getGoodsId(), ticket.getSkuId(), ticket.getIsMirror(), ticket.getSkuNum()); ticket.setDiscount(renewDiscount); setAIZoneMirrorTicketInfo(ticket); if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) { String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(ticket.getSkuId(), lang); if (StrUtil.isNotBlank(languageSpecVal)) { ticket.setSpecVal(languageSpecVal); } } OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getRelationId, ticket.getRelationId()) .eq(OrderDon::getUserId, ticket.getUserId()) .eq(OrderDon::getOrderType, 1) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon != null) { ticket.setOrderId(orderDon.getId()); } }); userLoginRecordService.saveUserLoginDayRecord(userId); return list; } @Override public TicketRenewUpgradeView getRenewUpgradeInfo(long userId, Long relationId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder() .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList) .field(GroupsRelationView::getId, relationId) .field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan) .build()); TicketRenewUpgradeView ticketRenewUpgradeView = new TicketRenewUpgradeView(); if (groupsRelationView != null) { String lang = request.getHeader("lang"); //clause pro if (groupsRelationView.getGoodsId() == Constant.CLAUDE_PRO_GID) { try { ClaudeUserView userInfo = claudeService.getUserInfo(groupsRelationView.getUserId(), groupsRelationView.getId()); Long renewSkuId = userInfo.getRenewSkuId(); if (renewSkuId != null) { GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build()); ticketRenewUpgradeView.setRenewSku(renewSku); } ticketRenewUpgradeView.setGptUserLimitNum(userInfo.getLimitNum()); ticketRenewUpgradeView.setGptUserLimitTime(userInfo.getLimitTime()); } catch (Exception e) { } } if (groupsRelationView.getGoodsId() == Constant.GPT_PLUS_GID) { try { //gpt用户镜像 ChatGptUserView userInfo = chatGptAccountService.getUserInfo(groupsRelationView.getUserId(), groupsRelationView.getId()); Integer count = upgradePackageMapper.selectCount(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + groupsRelationView.getSkuId() + "\"')") .gt(UpgradePackage::getNum, userInfo.getLimitNum()) .eq(UpgradePackage::getStatus, Boolean.TRUE) .eq(UpgradePackage::getGptType, 0) .eq(UpgradePackage::getDeleted, Boolean.TRUE)); ticketRenewUpgradeView.setUpgrade(count > 0 ? true : false); ticketRenewUpgradeView.setPackageId(userInfo.getPackageId()); ticketRenewUpgradeView.setGptUserLimitNum(userInfo.getLimitNum()); ticketRenewUpgradeView.setGptUserLimitTime(userInfo.getLimitTime()); ticketRenewUpgradeView.setUserDsLimitNum(userInfo.getDsLimitNum()); ticketRenewUpgradeView.setUserDsLimitTime(userInfo.getDsLimitTime()); ticketRenewUpgradeView.setUserOtherLimitNum(userInfo.getOtherLimitNum()); ticketRenewUpgradeView.setUserOtherLimitTime(userInfo.getOtherLimitTime()); if (userInfo.getPackageId() != 0) { UpgradePackage upgradePackage = upgradePackageMapper.selectById(userInfo.getPackageId()); ticketRenewUpgradeView.setPackagePrice(upgradePackage.getPrice()); Long upgradeOrderDonSkuId = upgradePackage.getUpgradeSkuId(); GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, upgradeOrderDonSkuId).build()); renewSku.setPackageId(userInfo.getPackageId()); ticketRenewUpgradeView.setRenewSku(renewSku); } ticketRenewUpgradeView.setIsRenewPackage(userInfo.getIsRenewPackage()); Long renewSkuId = userInfo.getRenewSkuId(); if (renewSkuId != null) { GoodsDonSkuRenewView upgradeSkuRenewView = ticketRenewUpgradeView.getRenewSku(); GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build()); //续费升级是更高级规格 if (upgradeSkuRenewView == null || (renewSku.getGptUserLimitNum() >= upgradeSkuRenewView.getGptUserLimitNum() && renewSku.getMonths() >= userInfo.getMonths())) { Optional.ofNullable(orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class) .eq(OrderDonRenewRecord::getOrderId, userInfo.getRenewOrderId()) .last("limit 1"))).ifPresent(e -> renewSku.setOriginalOrderId(e.getOrderId())); if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) { String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(renewSku.getSkuId(), lang); if (StrUtil.isNotBlank(languageSpecVal)) { renewSku.setSpecVal(languageSpecVal); } } ticketRenewUpgradeView.setRenewSku(renewSku); } } } catch (Exception e) { } } //claude code if (groupsRelationView.getGoodsId() == Constant.CLAUDE_CODE_GOODS_ID) { try { //cc用户镜像 ClaudeCodeUserInfoView userInfo = claudeCodeService.getClaudeCodeUserSubsInfo(userId); ticketRenewUpgradeView.setClaudeDailyLimit(userInfo.getClaudeDailyLimit()); ticketRenewUpgradeView.setClaudeQuota(userInfo.getClaudeQuota()); ticketRenewUpgradeView.setIsRenewPackage(userInfo.getRenewSkuId() != null ? true : false); ticketRenewUpgradeView.setHighestUsage(userInfo.getHighestUsage()); Long renewSkuId = userInfo.getRenewSkuId(); if (renewSkuId != null) { GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build()); Optional.ofNullable(claudeCodeUserRenewExpiryRecordMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUserRenewExpiryRecord.class) .eq(ClaudeCodeUserRenewExpiryRecord::getOrderId, userInfo.getRenewOrderId()) .last("limit 1"))).ifPresent(e -> renewSku.setOriginalOrderId(e.getOrderId())); if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) { String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(renewSku.getSkuId(), lang); if (StrUtil.isNotBlank(languageSpecVal)) { renewSku.setSpecVal(languageSpecVal); } } ticketRenewUpgradeView.setRenewSku(renewSku); } } catch (Exception e) { } } //codex if (groupsRelationView.getGoodsId() == Constant.CODEX_GOODS_ID) { try { //codex用户镜像 CodexUserInfoView userInfo = codexService.getUserSubsInfo(userId); ticketRenewUpgradeView.setOpenaiDailyLimit(userInfo.getOpenaiDailyLimit()); ticketRenewUpgradeView.setOpenaiQuota(userInfo.getOpenaiQuota()); ticketRenewUpgradeView.setIsRenewPackage(userInfo.getRenewSkuId() != null ? true : false); Long renewSkuId = userInfo.getRenewSkuId(); if (renewSkuId != null) { GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build()); Optional.ofNullable(codexUserRenewExpiryRecordMapper.selectOne(Wrappers.lambdaQuery(CodexUserRenewExpiryRecord.class) .eq(CodexUserRenewExpiryRecord::getOrderId, userInfo.getRenewOrderId()) .last("limit 1"))).ifPresent(e -> renewSku.setOriginalOrderId(e.getOrderId())); if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) { String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(renewSku.getSkuId(), lang); if (StrUtil.isNotBlank(languageSpecVal)) { renewSku.setSpecVal(languageSpecVal); } } ticketRenewUpgradeView.setRenewSku(renewSku); } } catch (Exception e) { } } } return ticketRenewUpgradeView; } @Override public void netflixSubmitFrozen(ErrorNetflixChangeReq req) { Long relationId = req.getRelationId(); Long userId = req.getUserId(); //校验奈飞账号状态 GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); Integer recoverCount = netflixUserAccountSubmitRecoverRecordMapper.selectCount(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class) .eq(NetflixUserAccountSubmitRecoverRecord::getRelationId, relationId) .in(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList) .eq(NetflixUserAccountSubmitRecoverRecord::getStatus, 0)); if (recoverCount > 0) { throw BusinessRuntimeException.getInstance("你已申请恢复账号,无法再申请冻结"); } if (netflixRelationView.getIsFrozen()) { throw BusinessRuntimeException.getInstance("你已申请冻结,无法再申请冻结"); } Date expiryTime = netflixRelationView.getExpiryTime(); //保留天数 Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1; groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getIsFrozen, Boolean.TRUE) //冻结2个月 .set(GroupsRelation::getUnfrozenTime, DateUtil.offsetMonth(DateTime.now(), 2)) .set(GroupsRelation::getReservedDays, betweenDay) .eq(GroupsRelation::getId, netflixRelationView.getId()) .eq(GroupsRelation::getUserId, netflixRelationView.getUserId())); //送一个月GPT基础月付 Long sendRelationId = getTicket(userId, Constant.GPT_MIRROR_COMMON_SKU_ID, Boolean.FALSE); if (sendRelationId != null) { AccountNetflixFrozenTicketReceivedRecord receivedRecord = new AccountNetflixFrozenTicketReceivedRecord(); receivedRecord.setUserId(userId); receivedRecord.setRelationId(relationId); receivedRecord.setSendRelationId(sendRelationId); accountNetflixFrozenTicketReceivedRecordMapper.insert(receivedRecord); } } @Override public String getSoraCode(Long userId, Long relationId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); GroupsRelation relation = groupsRelationMapper.selectById(relationId); if (relation == null) { throw BusinessRuntimeException.getInstance("车票不存在"); } if (!userIdList.contains(relation.getUserId())) { throw BusinessRuntimeException.getInstance("车票不存在"); } if (relation.getStatus() != GroupsRelation.Status.validity) { throw BusinessRuntimeException.getInstance("车票不存在"); } if (relation.getExpiryTime() != null && relation.getExpiryTime().before(DateTime.now())) { throw BusinessRuntimeException.getInstance("车票已过期"); } GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId()); GoodsDonSku sku = goodsDonSkuMapper.selectById(groupsTrips.getSkuId()); //非GPT独立 if (sku.getGoodsId() != Constant.GPT_PLUS_GID || sku.getNum() != 1) { throw BusinessRuntimeException.getInstance("非GPT独立会员车票"); } OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class).in(OrderDon::getUserId, userIdList).eq(OrderDon::getRelationId, relationId).notIn(OrderDon::getStatus, Constant.noOrderAllStatus).orderByDesc(OrderDon::getId).last("limit 1")); SoraCode soraCode = soraCodeMapper.selectOne(Wrappers.lambdaQuery(SoraCode.class).eq(SoraCode::getOrderId, orderDon.getId()).last("limit 1")); if (soraCode == null) { try { if (orderDon.getCreatedTime().before(DateUtil.parse("2025-10-14 17:30:00"))) { throw BusinessRuntimeException.getInstance("系统异常"); } soraCodeFrontService.grantSoraCodeForGptMember(relation.getUserId(), orderDon.getId()); soraCode = soraCodeMapper.selectOne(Wrappers.lambdaQuery(SoraCode.class).eq(SoraCode::getOrderId, orderDon.getId()).last("limit 1")); } catch (Exception e) { } } if (soraCode == null) { throw BusinessRuntimeException.getInstance("暂无可用sora邀请码,请联系客服"); } return soraCode.getCode(); } private DistributePosterGoodsDetailView setGoodsPoster(RenewalView ticket, User user, List userIds) { DistributePosterGoodsDetailView distributePosterGoodsDetailView = beanSearcher.searchFirst(DistributePosterGoodsDetailView.class, MapUtils.flatBuilder(request.getParameterMap()) .field(DistributePosterGoodsFrontView::getGoodsId, ticket.getGoodsId()).build()); if (distributePosterGoodsDetailView == null) { return null; } distributePosterGoodsDetailView.setNickname(user.getNickname()); UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class) .eq(UserDistribute::getUserId, user.getId()) .eq(UserDistribute::getDeleted, 1) .last("limit 1")); if (userDistribute != null) { UserPlatDistributeRate userPlatDistributeRate = userPlatDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatDistributeRate.class) .eq(UserPlatDistributeRate::getDistributeId, userDistribute.getId()) .eq(UserPlatDistributeRate::getGoodsId, ticket.getGoodsId()) .last("limit 1")); if (userPlatDistributeRate != null) { distributePosterGoodsDetailView.setRate(userPlatDistributeRate.getRate()); } } GoodsDon goodsDon = goodsDonMapper.selectById(ticket.getGoodsId()); if (goodsDon.getIsSkuDistribute()) { if (userDistribute != null) { UserPlatSkuDistributeRate userPlatSkuDistributeRate = userPlatSkuDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatSkuDistributeRate.class) .eq(UserPlatSkuDistributeRate::getDistributeId, userDistribute.getId()) .eq(UserPlatSkuDistributeRate::getSkuId, ticket.getSkuId()) .last("limit 1")); if (userPlatSkuDistributeRate != null) { distributePosterGoodsDetailView.setRate(userPlatSkuDistributeRate.getRate()); } } else { DistributeGeneralSkuRate distributeGeneralSkuRate = distributeGeneralSkuRateMapper.selectOne(Wrappers.lambdaQuery(DistributeGeneralSkuRate.class) .eq(DistributeGeneralSkuRate::getSkuId, ticket.getSkuId()) .last("limit 1")); if (distributeGeneralSkuRate != null) { distributePosterGoodsDetailView.setRate(distributeGeneralSkuRate.getRate()); } } } //用户推广海报记录id Optional.ofNullable(userDistributePosterRecordMapper.selectOne(Wrappers.lambdaQuery(UserDistributePosterRecord.class) .eq(UserDistributePosterRecord::getPosterId, distributePosterGoodsDetailView.getId()) .in(UserDistributePosterRecord::getUserId, userIds) .last("limit 1"))).ifPresent(re -> distributePosterGoodsDetailView.setRid(re.getId())); return distributePosterGoodsDetailView; } private BigDecimal getRenewDiscount(Long goodsId, Long skuId, Boolean isMirror, Integer skuNum) { //镜像或者独立规格 if (goodsId == Constant.CODEX_GOODS_ID || goodsId == Constant.CLAUDE_CODE_GOODS_ID || isMirror || (skuNum != null && skuNum == 1)) { RenewUpgradePackage renewUpgradePackage = renewUpgradePackageMapper.selectOne(Wrappers.lambdaQuery(RenewUpgradePackage.class) .eq(RenewUpgradePackage::getGoodsId, goodsId) .eq(RenewUpgradePackage::getStatus, 1) .eq(RenewUpgradePackage::getDeleted, 1) .eq(RenewUpgradePackage::getSkuId, skuId) .orderByAsc(RenewUpgradePackage::getDiscount) .last("limit 1") .select(RenewUpgradePackage::getId, RenewUpgradePackage::getDiscount)); if (renewUpgradePackage != null) { return renewUpgradePackage.getDiscount(); } } return null; } private void setMirrorTicketInfo(RenewalView ticket) { //// //设置MJ镜像信息 // setMjMirrorInfo(ticket); //设置GPT镜像信息 setGptMirrorInfo(ticket); //// //clause pro // setClaudeProInfo(ticket); //// //luma // setLumaInfo(ticket); } private void setMjMirrorInfo(RenewalView ticket) { if (ticket.getGoodsId() == 26 && ticket.getIsMirror()) { List upgradePackages = upgradePackageMapper.selectList(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + ticket.getSkuId() + "\"')").eq(UpgradePackage::getStatus, Boolean.TRUE).eq(UpgradePackage::getDeleted, Boolean.TRUE)); if (CollectionUtil.isNotEmpty(upgradePackages)) { upgradePackages.stream().map(e -> e.getPrice().divide(BigDecimal.valueOf(e.getNum()), 2, RoundingMode.HALF_UP)).min(BigDecimal::compareTo).ifPresent(ticket::setMjPackagePrice); } try { MidjourneyUserView search = beanSearcher.searchFirst(MidjourneyUserView.class, MapUtils.flatBuilder(request.getParameterMap()) .field(MidjourneyUserView::getUserId, ticket.getUserId()).field(MidjourneyUserView::getRelationId, ticket.getRelationId()) .onlySelect(MidjourneyUserView::getMjUserRelaxNum, MidjourneyUserView::getMjUserFastNum,MidjourneyUserView::getMjUserUpgradeNum, MidjourneyUserView::getIsCar) .build()); if (search == null) { MidjourneyUser midjourneyUser = midjourneyAccountService.getMidjourneyUserToken(ticket.getUserId(), ticket.getRelationId()); ticket.setMjUserFastNum(midjourneyUser.getMjFastNum()); ticket.setMjUserUpgradeNum(midjourneyUser.getMjUpgradeNum()); ticket.setMjUserRelaxNum(midjourneyUser.getMjRelaxNum()); ticket.setIsCar(false); } else { ticket.setIsCar(search.getIsCar()); ticket.setMjUserFastNum(search.getMjUserFastNum()); ticket.setMjUserUpgradeNum(search.getMjUserUpgradeNum()); ticket.setMjUserRelaxNum(search.getMjUserRelaxNum()); } midjourneyAccountService.updateUserExpiryTime(ticket.getRelationId(), ticket.getExpiryTime()); } catch (Exception e) { } } } public void setGptMirrorInfo(RenewalView ticket) { if (ticket.getGoodsId() == 18 && ticket.getIsCar() && ticket.getExpiryTime() != null) { try { //gpt用户镜像 ChatGptUserView userInfo = chatGptAccountService.getUserInfo(ticket.getUserId(), ticket.getRelationId()); ticket.setGptUserLimitNum(userInfo.getLimitNum()); ticket.setGptUserLimitTime(userInfo.getLimitTime()); ticket.setUserDsLimitNum(userInfo.getDsLimitNum()); ticket.setUserDsLimitTime(userInfo.getDsLimitTime()); ticket.setUserOtherLimitNum(userInfo.getOtherLimitNum()); ticket.setUserOtherLimitTime(userInfo.getOtherLimitTime()); ticket.setUserToken(userInfo.getUserToken()); ticket.setUse(userInfo.getUse()); ticket.setModel(userInfo.getModel()); // Integer count = upgradePackageMapper.selectCount(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + ticket.getSkuId() + "\"')") // .gt(UpgradePackage::getNum, userInfo.getLimitNum()) // .eq(UpgradePackage::getStatus, Boolean.TRUE) // .eq(UpgradePackage::getGptType, 0) // .eq(UpgradePackage::getDeleted, Boolean.TRUE)); // ticket.setUpgrade(count > 0 ? true : false); // ticket.setPackageId(userInfo.getPackageId()); // if (userInfo.getPackageId() != 0) { // UpgradePackage upgradePackage = upgradePackageMapper.selectById(userInfo.getPackageId()); // ticket.setPackagePrice(upgradePackage.getPrice()); // Long upgradeOrderDonSkuId = upgradePackage.getUpgradeSkuId(); // GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, upgradeOrderDonSkuId).build()); // renewSku.setPackageId(userInfo.getPackageId()); // ticket.setRenewSku(renewSku); // } // ticket.setIsRenewPackage(userInfo.getIsRenewPackage()); // Long renewSkuId = userInfo.getRenewSkuId(); // if (renewSkuId != null) { // GoodsDonSkuRenewView upgradeSkuRenewView = ticket.getRenewSku(); // GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build()); // //续费升级是更高级规格 // if (upgradeSkuRenewView == null || (renewSku.getGptUserLimitNum() >= upgradeSkuRenewView.getGptUserLimitNum() && renewSku.getMonths() >= userInfo.getMonths())) { // Optional.ofNullable(orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class) // .eq(OrderDonRenewRecord::getOrderId, userInfo.getRenewOrderId()) // .last("limit 1"))).ifPresent(e -> renewSku.setOriginalOrderId(e.getOrderId())); // ticket.setRenewSku(renewSku); // } // } } catch (Exception e) { } } } public void setClaudeProInfo(RenewalView ticket) { //clause pro if (ticket.getGoodsId() == 75l && ticket.getExpiryTime() != null) { try { ClaudeUserView userInfo = claudeService.getUserInfo(ticket.getUserId(), ticket.getRelationId()); ticket.setGptUserLimitNum(userInfo.getLimitNum()); ticket.setGptUserLimitTime(userInfo.getLimitTime()); ticket.setUse(userInfo.getUse()); Long renewSkuId = userInfo.getRenewSkuId(); if (renewSkuId != null) { GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build()); ticket.setRenewSku(renewSku); } } catch (Exception e) { } } } public void setLumaInfo(RenewalView ticket) { if (ticket.getGoodsId() == Constant.LUMA_GOODS_ID && ticket.getExpiryTime() != null) { try { List upgradePackages = upgradePackageMapper.selectList(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + ticket.getSkuId() + "\"')").eq(UpgradePackage::getStatus, Boolean.TRUE).eq(UpgradePackage::getDeleted, Boolean.TRUE)); if (CollectionUtil.isNotEmpty(upgradePackages)){ upgradePackages.stream().map(e -> e.getPrice().divide(BigDecimal.valueOf(e.getNum()), 2, RoundingMode.HALF_UP)).min(BigDecimal::compareTo).ifPresent(ticket::setLumaPackagePrice); } LumaUser lumaUser = lumaService.getLumaUser(ticket.getUserId(), ticket.getRelationId()); ticket.setLumaUserNum(lumaUser.getNum()); } catch (Exception e) { } } } /** * 获取gpt镜像天卡活动参与平台ids * @return */ private List getGptMirrorGiveawayBuyGids() { GptMirrorDayCardGiveawayActivity gptMirrorDayCardGiveawayActivity = beanSearcher.searchFirst(GptMirrorDayCardGiveawayActivity.class, MapUtils.builder().build()); if (gptMirrorDayCardGiveawayActivity != null) { String buyGoodsIds = gptMirrorDayCardGiveawayActivity.getBuyGoodsIds(); try { return Jsons.parseList(buyGoodsIds, Long.class); } catch (Exception e) { } } return null; } /** * 标记是否可抵扣会员车票 */ private void markVipDeductTicket(List userIds, RenewalView ticket, Set vipGoodsIds, Boolean isVip) { if (CollUtil.isNotEmpty(vipGoodsIds) && ticket.getIsMirror() != null && ticket.getIsMirror() && !isVip) { Long goodsId = ticket.getGoodsId(); //只购买 if (ticket.getAqType() != 1) { return; } if (vipGoodsIds.contains(goodsId)) { if (goodsId == Constant.NANO_GOODS_ID) { NanoUserQuota nanoUserQuota = nanoUserQuotaMapper.selectOne(Wrappers.lambdaQuery(NanoUserQuota.class).in(NanoUserQuota::getUid, userIds).orderByDesc(NanoUserQuota::getRemainingQuota).last("limit 1")); if (nanoUserQuota != null) { if (ObjectUtil.equal(nanoUserQuota.getRelationId(), ticket.getRelationId())) { ticket.setIsVipDeduct(true); } return; } RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder() .field(RenewalView::getGoodsId, goodsId) .field(RenewalView::getUserId, userIds).op(Operator.InList) .orderBy(RenewalView::getSkuNanoQuota).desc() .onlySelect(RenewalView::getRelationId) .build()); if (renewalView != null && ObjectUtil.equal(renewalView.getRelationId(), ticket.getRelationId())) { ticket.setIsVipDeduct(true); } return; } //是否时长最长 Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder() .field(RenewalView::getRelationId, ticket.getRelationId()).op(Operator.NotEqual) .field(RenewalView::getGoodsId, goodsId) .field(RenewalView::getUserId, userIds).op(Operator.InList) .field(RenewalView::getExpiryTime, ticket.getExpiryTime()).op(Operator.GreaterThan) .build()); if (number.intValue() == 0) { ticket.setIsVipDeduct(true); } } } } /** * 检验奈飞账号状态 */ public GroupsRelationView checkNetflixErrorStatus(Long relationId, Long userId) { List userIdList = userBindRelationService.getRelationUserIdList(userId, null); NetflixUserAccountStatusRecord netflixUseAccountStatusRecord = netflixUserAccountStatusRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class) .eq(NetflixUserAccountStatusRecord::getRelationId, relationId) .eq(NetflixUserAccountStatusRecord::getDeleted, 1) .in(NetflixUserAccountStatusRecord::getUserId, userIdList) .orderByDesc(NetflixUserAccountStatusRecord::getId) .last("limit 1")); if (netflixUseAccountStatusRecord == null) { throw BusinessRuntimeException.getInstance("请先提交账号检测"); } Integer state = netflixUseAccountStatusRecord.getState(); if (state == 0) { throw BusinessRuntimeException.getInstance("您的账号检测中"); } //2是登录失败 3是被封号 if (state != 3) { throw BusinessRuntimeException.getInstance("您的账号未封禁"); } GroupsRelationView netflixRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder() .field(GroupsRelationView::getId, relationId) .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList) .field(GroupsRelationView::getGoodsId, Constant.NETFLIX_GID) .build()); if (netflixRelationView == null) { throw BusinessRuntimeException.getInstance("奈飞车票已过期"); } if (netflixRelationView != null) { if (netflixRelationView.getIsFrozen() && netflixRelationView.getUnfrozenTime().after(DateTime.now())) { throw BusinessRuntimeException.getInstance("冻结未结束"); } if (netflixRelationView.getIsFrozen()) { //重新设置车票时长 netflixRelationView.setExpiryTime(DateUtil.offsetDay(DateTime.now(), netflixRelationView.getReservedDays())); } if (netflixRelationView.getExpiryTime().before(DateTime.now())) { throw BusinessRuntimeException.getInstance("奈飞车票已过期"); } } netflixRelationView.setNfCheckId(netflixUseAccountStatusRecord.getId()); netflixRelationView.setNfOriOrderId(netflixUseAccountStatusRecord.getOrderId()); return netflixRelationView; } /** * 获取车票 并生成订单 */ public TicketChangeDto getTicketAndGenerateOrder(Long userId, Long skuId, Date startTime, Date expiryTime) { Retryer build = RetryerBuilder.newBuilder() .retryIfException() //运行时异常重试 .retryIfRuntimeException() //false重试 .retryIfResult(res -> res == null) //1s 间隔 .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS)) //停止策略 : 尝试请求1次 .withStopStrategy(StopStrategies.stopAfterAttempt(1)).build(); if (startTime == null) { startTime = DateTime.now(); } GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId); if (expiryTime == null) { if (sku.getDays() != null) { expiryTime = DateUtil.offsetDay(startTime, sku.getDays()); } else { expiryTime = DateUtil.offsetMonth(startTime, sku.getMonths()); } } Date finalStartTime = startTime; Date finalExpiryTime = expiryTime; try { return build.call(() -> { GroupsTrips groups = groupsMapper.selectCollegeStudentUserGptTicket(skuId); if (groups == null) { groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class) .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting) .eq(GroupsTrips::getSkuId, skuId) .last("limit 1")); } GroupsRelation relation = null; if (groups != null) { relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId()); } //生成空车队 if (relation == null) { relation = groupsFuncService.createNewGroupsTrips(sku); } int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getUserId, userId) .set(GroupsRelation::getStartTime, finalStartTime) .set(GroupsRelation::getExpiryTime, finalExpiryTime) .set(GroupsRelation::getStatus, GroupsRelation.Status.validity) .eq(GroupsRelation::getId, relation.getId()) .eq(GroupsRelation::getUserId, 0)); if (update > 0) { groupsMapper.decrAvailableNum(relation.getGroupsId()); Long relationId = relation.getId(); //生成新的订单 OrderDon otherOrderDon = generateNewTicketOrder(relationId, userId, sku); TicketChangeDto ticketChangeDto = new TicketChangeDto(); ticketChangeDto.setOtherRelationId(relationId); ticketChangeDto.setOtherOrderId(otherOrderDon.getId()); return ticketChangeDto; } log.error("发送用户:{} GPT镜像车票失败,进行重试", userId); return null; }); } catch (ExecutionException | RetryException e) { log.error("发送用户GPT镜像失败:{}", StringUtil.getErrorText(e)); return null; } } private OrderDon generateNewTicketOrder(Long relationId, Long userId, GoodsDonSku sku) { OrderDon orderDon = new OrderDon(); orderDon.setUserId(userId); orderDon.setOrderNo(SEQUENCE.nextId().toString()); orderDon.setMoney(BigDecimal.ZERO); orderDon.setRelationId(relationId); orderDon.setGoodsId(sku.getGoodsId()); orderDon.setSkuId(sku.getId()); orderDon.setType(OrderDon.Type.TICKET_REPLACE); orderDon.setStatus(OrderDon.Status.complete); orderDonMapper.insert(orderDon); return orderDon; } private void setAIZoneMirrorTicketInfo(UserMirrorTicketView ticket) { setAIZoneGptMirrorInfo(ticket); } private void setAIZoneGptMirrorInfo(UserMirrorTicketView ticket) { if (ticket.getGoodsId() != null && ticket.getGoodsId() == Constant.GPT_PLUS_GID) { ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class) .eq(ChatgptUser::getRelationId, ticket.getRelationId()) .last("limit 1")); if (chatgptUser != null) { ticket.setModel(chatgptUser.getModel()); } } } }