package com.cyksj.web.controller.group; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.BetweenFormater; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUnit; import cn.hutool.core.date.DateUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.cyksj.common.annotation.NoSubmit; 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.GoogleGenerator; import com.cyksj.common.util.Jsons; import com.cyksj.common.util.StringUtil; import com.cyksj.dto.Result; import com.cyksj.enums.GatewayResponse; import com.cyksj.mapper.*; import com.cyksj.mapper.manage.form.FormFieldsDataMapper; import com.cyksj.mapper.manage.form.QuestionnairePromotionMapper; import com.cyksj.mapper.shop.YhShopMapper; import com.cyksj.model.dto.DoubleVerifyDto; import com.cyksj.model.dto.GalaxyCoinPayConfigDto; import com.cyksj.model.dto.QuestionnaireView; import com.cyksj.model.entity.*; import com.cyksj.model.manage.views.AccountView; import com.cyksj.model.manage.views.GroupsRelationView; import com.cyksj.model.request.*; import com.cyksj.model.response.GptStandbyResp; 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.ChatGptAuthService; import com.cyksj.service.mange.CmsOrderDonService; import com.cyksj.service.mange.coupon.CouponCommonService; import com.cyksj.service.mange.ticket.TicketAdvertiseConfigClickRecordService; import com.cyksj.service.order.OrderDonService; import com.cyksj.service.relation.GroupRelationFrontService; import com.cyksj.service.relation.GroupsRelationNetflixService; import com.cyksj.service.sys.SysConfigService; import com.cyksj.service.translations.BackInfoTranslationsFrontService; import com.cyksj.service.user.UserBindRelationService; import com.cyksj.service.user.UserService; import com.cyksj.web.util.StpUserUtil; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.SearchResult; import com.ejlchina.searcher.operator.LessEqual; import com.ejlchina.searcher.param.Operator; import com.ejlchina.searcher.util.MapBuilder; import com.ejlchina.searcher.util.MapUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Collectors; /** * @author chan * @date 2022/9/27 11:48 AM */ @Slf4j @RequiredArgsConstructor @RestController @RequestMapping("/applets/group/relation") public class GroupRelationController { private final BeanSearcher beanSearcher; private final OrderDonService orderDonService; private final GroupsRelationMapper relationMapper; private final GroupRelationFrontService groupRelationFrontService; private final UserService userService; private final UserBindRelationService userBindRelationService; private final TicketPwdViewRecordMapper ticketPwdViewRecordMapper; private final HttpServletRequest request; private final AccountDoubleVerifyRecordMapper accountDoubleVerifyRecordMapper; private final DoubleVerifyClickRecordMapper doubleVerifyRecordMapper; private final RedisService redisService; private final DoubleVerifyClickRefreshRecordMapper refreshRecordMapper; private final QuestionResponseRecordMapper questionResponseRecordMapper; private final CouponCommonService couponCommonService; private final FormFieldsDataMapper formFieldsDataMapper; private final QuestionnairePromotionMapper questionnairePromotionMapper; private final TicketAdvertiseConfigClickRecordService ticketAdvertiseConfigClickRecordService; private final GlobalThreadPoolTaskExecutor THREAD_POOL; private final ChatGptAuthService chatGptAuthService; private final GoodsCoursewareFileMapper goodsCoursewareFileMapper; private final GptTicketStandbyMapper gptTicketStandbyMapper; private final CmsOrderDonService cmsOrderDonService; private final GoodsDonSkuMapper goodsDonSkuMapper; private final AccountBlockedReplaceRecordMapper accountBlockedReplaceRecordMapper; private final OrderDonMapper orderDonMapper; private final UserGoodsNewbieGuideRecordMapper userGoodsNewbieGuideRecordMapper; private final GroupsRelationNetflixService groupsRelationNetflixService; private final ChatgptUserMapper chatgptUserMapper; private final UpgradeOrderDonMapper upgradeOrderDonMapper; private final UserBenefitsOrderRecordMapper userBenefitsOrderRecordMapper; private final ClaudeUserMapper claudeUserMapper; private final UserMapper userMapper; private final SysConfigService sysConfigService; private final BackInfoTranslationsFrontService backInfoTranslationsFrontService; private final YhShopMapper yhShopMapper; private final GroupsMapper groupsMapper; private final static Sequence SEQUENCE = new Sequence(0); @RequestMapping("/get/renewal") public Result> get(Boolean isLoginPopularize, String customId, String account, String orderNo, Integer cmt) { long userId = StpUserUtil.getLoginIdAsLong(); SearchResult list = groupRelationFrontService.getMyTicket(userId, isLoginPopularize, customId, account, orderNo, cmt); return GatewayResponse.SUCCESS.newBuilder().toResult(list); } @GetMapping("/get/pay/goods") public Result> getHasPayGoods() { long userId = StpUserUtil.getLoginIdAsLong(); List hasPayGoods = groupRelationFrontService.getHasPayGoods(userId); return GatewayResponse.SUCCESS.newBuilder().toResult(hasPayGoods); } @PostMapping("/post/renewal") public Result renewal(@RequestBody OrderPayRequest payRequest) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); payRequest.setUserId(userId); String ip = ServletUtil.getClientIP(request); payRequest.setIp(ip); OrderDon orderDon = orderDonService.renewal(payRequest); return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon); } /** * 邀请制绑定账号 */ @PutMapping("/update/set/account") public Result setAccount(@RequestBody @Validated InviteBindAccountReq req) { long userId = StpUserUtil.getLoginIdAsLong(); Long relationId = req.getId(); List userIds = userBindRelationService.getRelationUserIdList(userId, null); GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getId, relationId) .in(GroupsRelation::getUserId, userIds) .last(" limit 1")); if (relation == null) { throw new BusinessRuntimeException("该车票不存在,请联系客服."); } String account = req.getAccount(); String password = req.getPassword(); String contact = req.getContact(); String bpVerifyCode = req.getBpVerifyCode(); LambdaUpdateWrapper updateWrapper = Wrappers.lambdaUpdate(GroupsRelation.class) .set(GroupsRelation::getAccount, account) .set(GroupsRelation::getPassword, password) .set(GroupsRelation::getContact, contact) .set(GroupsRelation::getBpVerifyCode, bpVerifyCode) .eq(GroupsRelation::getId, relationId); if (relation.getRechargeStatus() != null) { if (relation.getRechargeStatus() == GroupsRelation.RechargeStatus.complete) { throw BusinessRuntimeException.getInstance("代充账号已充值"); } if (StrUtil.isEmpty(account)) { throw BusinessRuntimeException.getInstance("请输入正确的账号信息"); } if (relation.getRechargeStatus() == GroupsRelation.RechargeStatus.error) { updateWrapper.set(GroupsRelation::getRechargeStatus, GroupsRelation.RechargeStatus.waiting); } relationMapper.update(relation, updateWrapper); } return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 查询是否加入了企业微信 并是否买了奈飞 */ @GetMapping("/check/joinCorpWx") public Result isJoinCorpWx() { long userId = StpUserUtil.getLoginIdAsLong(); Boolean flag = groupRelationFrontService.isJoinCorpWx(userId, false, false); return GatewayResponse.SUCCESS.newBuilder().toResult(flag); } /** * 获取全部车票 */ @GetMapping("/get") public Result> getUserTicketView(Long goodsId, Long skuId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userBindRelationService.getRelationUserIdList(userId, null); List tickets = relationMapper.selectUserTickets(userIds, goodsId, skuId); return GatewayResponse.SUCCESS.newBuilder().toResult(tickets); } /** * 记录查看ChatGPT车票密码 */ @GetMapping("/recordView/{relationId}") public Result recordGPTPwdView(@PathVariable Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userBindRelationService.getRelationUserIdList(userId, null); GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder() .field(GroupsRelationView::getUserId, userIds).op(Operator.InList) .field(GroupsRelationView::getId, relationId).build()); if (groupsRelationView == null) { log.info("userId:{}查看relationId:{}车票不存在", userId, relationId); throw BusinessRuntimeException.getInstance("该车票已不存在"); } if (groupsRelationView.getAccountId() == null) throw BusinessRuntimeException.getInstance("该车队未配置账号"); if (groupRelationFrontService == null) throw BusinessRuntimeException.getInstance("车票已不存在"); TicketPwdViewRecord viewRecord = new TicketPwdViewRecord(); viewRecord.setUserId(userId); viewRecord.setRelationId(relationId); viewRecord.setSkuId(groupsRelationView.getSkuId()); viewRecord.setOperateLocation(ServletUtil.getClientIP(request)); viewRecord.setAccount(groupsRelationView.getTripsAccount()); viewRecord.setPassword(groupsRelationView.getTripsPassword()); ticketPwdViewRecordMapper.insert(viewRecord); if (groupsRelationView.getGoodsId() == 18 && StrUtil.isEmpty(groupsRelationView.getApiSecret())) { THREAD_POOL.execute(() -> { //车队所有人查看密码 Integer num = groupsRelationView.getGtNum(); Integer viewNum = relationMapper.selectViewPwdCount(groupsRelationView.getGroupsId()); if (num <= viewNum) { AccountDoubleVerifyRecord exist = accountDoubleVerifyRecordMapper.selectOne(Wrappers.lambdaQuery(AccountDoubleVerifyRecord.class) .eq(AccountDoubleVerifyRecord::getAccountId, groupsRelationView.getAccountId()) .eq(AccountDoubleVerifyRecord::getDeleted, true).last("limit 1")); if (exist == null) { if (redisService.setNx(String.format("%s-%s", groupsRelationView.getAccountId(), groupsRelationView.getId()), groupsRelationView.getId(), 60l)) { //记录 AccountDoubleVerifyRecord accountDoubleVerifyRecord = new AccountDoubleVerifyRecord(); accountDoubleVerifyRecord.setAccountId(groupsRelationView.getAccountId()); accountDoubleVerifyRecord.setAccount(groupsRelationView.getTripsAccount()); accountDoubleVerifyRecord.setGroupsId(groupsRelationView.getGroupsId()); accountDoubleVerifyRecord.setSkuId(groupsRelationView.getSkuId()); accountDoubleVerifyRecord.setRemark("车队所有人看过密码"); accountDoubleVerifyRecordMapper.insert(accountDoubleVerifyRecord); } } } }); } return GatewayResponse.SUCCESS.newBuilder().toResult(groupsRelationView.getTripsPassword()); } /** * 是否有查看过密码记录 */ @GetMapping("/get/pwd/view/record") public Result getPwdViewRecord(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userBindRelationService.getRelationUserIdList(userId, null); Integer selectCount = ticketPwdViewRecordMapper.selectCount(Wrappers.lambdaQuery(TicketPwdViewRecord.class).eq(TicketPwdViewRecord::getRelationId, relationId).in(TicketPwdViewRecord::getUserId, userIds)); return GatewayResponse.SUCCESS.newBuilder().toResult(selectCount > 0); } /** * 获取AI类 ChatGPT产品谷歌验证码 */ @GetMapping("/get/authCode") public Result getAuthCode(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userBindRelationService.getRelationUserIdList(userId, null); if (relationId == null) throw BusinessRuntimeException.getInstance("车票不存在"); GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder() .field(GroupsRelationView::getId, relationId) .field(GroupsRelationView::getUserId, userIds).op(Operator.InList).build()); if (groupsRelationView == null) throw BusinessRuntimeException.getInstance("车票不存在"); if (StrUtil.isEmpty(groupsRelationView.getApiSecret())) throw BusinessRuntimeException.getInstance("未开启验证"); DateTime now = DateTime.now(); Integer count = doubleVerifyRecordMapper.selectCount(Wrappers.lambdaQuery(DoubleVerifyClickRecord.class) .in(DoubleVerifyClickRecord::getUserId, userIds) .eq(DoubleVerifyClickRecord::getRelationId, relationId) .eq(DoubleVerifyClickRecord::getAccountId, groupsRelationView.getAccountId()) .between(DoubleVerifyClickRecord::getCreatedTime, DateUtil.beginOfMonth(now), DateUtil.endOfMonth(now))); //获取双重验证码 Boolean isHasVerifyCode = StrUtil.isNotBlank(groupsRelationView.getVerifyCode()) ? true : false; //出去亚马逊 获取限制 if (groupsRelationView.getGoodsId() != 6) { Integer num = groupRelationFrontService.getUserCodeNumBySkuId(userId, groupsRelationView.getSkuId(), isHasVerifyCode); if (count >= num) throw BusinessRuntimeException.getInstance("获取双重验证码次数上限"); } //一分钟内 只能一人获取 boolean b = redisService.setNx(RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getName() + groupsRelationView.getTripsAccount(), relationId, RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getTimeout()); if (!b) { throw BusinessRuntimeException.getInstance("一分钟内已有人获取该账号验证码,请稍后获取.."); } int second = now.second(); if (second < 30 && 30 - second < 3) { ThreadUtil.sleep(30 - second + 1, TimeUnit.SECONDS); } else if (second > 30 && 60 - second < 3) { ThreadUtil.sleep(60 - second + 1, TimeUnit.SECONDS); } StringBuilder sb = new StringBuilder(); JSONObject re = new JSONObject(); try { long code = GoogleGenerator.getCode(groupsRelationView.getApiSecret(), now.getTime()); sb.append(code); while (sb.length() < 6) { sb.insert(0, 0); } re.putOpt("code", sb.toString()); int nowSecond = DateTime.now().second(); int time = 0; if (nowSecond < 30) { time = 30 - nowSecond; } else { time = 60 - nowSecond; } re.putOpt("time", time); DoubleVerifyClickRecord doubleVerifyClickRecord = new DoubleVerifyClickRecord(); doubleVerifyClickRecord.setRelationId(relationId); doubleVerifyClickRecord.setUserId(userId); doubleVerifyClickRecord.setAccountId(groupsRelationView.getAccountId()); doubleVerifyClickRecord.setAccount(groupsRelationView.getTripsAccount()); doubleVerifyClickRecord.setSkuId(groupsRelationView.getSkuId()); doubleVerifyClickRecord.setCode(sb.toString()); doubleVerifyClickRecord.setRemainTime(time); doubleVerifyRecordMapper.insert(doubleVerifyClickRecord); DoubleVerifyDto doubleVerifyDto = new DoubleVerifyDto(); doubleVerifyDto.setClickId(doubleVerifyClickRecord.getId()); doubleVerifyDto.setApiSecret(groupsRelationView.getApiSecret()); redisService.set(String.format("%s-%s", userId, sb.toString()), 0, 60 * 10l); redisService.set(String.format("%s/%s", userId, sb.toString()), Jsons.toJson(doubleVerifyDto), 60 * 10l); } catch (Exception e) { throw BusinessRuntimeException.getInstance("获取双重验证码错误,请联系客服"); } return GatewayResponse.SUCCESS.newBuilder().toResult(re.toString()); } /** * 刷新验证码 */ @GetMapping("/refresh/code") public Result refreshCode(String code) { long userId = StpUserUtil.getLoginIdAsLong(); String numKey = String.format("%s-%s", userId, code); Object num = redisService.get(numKey); String objKey = String.format("%s/%s", userId, code); Object objValue = redisService.get(objKey); if (objValue == null || num == null) { throw BusinessRuntimeException.getInstance("请重新获取双重验证码"); } Integer refreshNum = Integer.parseInt(num.toString()); String apiSecret = null; Long clickId = 0l; try { DoubleVerifyDto dto = Jsons.parseObject(objValue.toString(), DoubleVerifyDto.class); apiSecret = dto.getApiSecret(); clickId = dto.getClickId(); } catch (Exception e) { apiSecret = objValue.toString(); } if (refreshNum >= 3) { redisService.del(numKey); redisService.del(objKey); throw BusinessRuntimeException.getInstance("刷新次数已达到3次,请重新获取验证码"); } if (apiSecret == null) { throw BusinessRuntimeException.getInstance("请重新获取双重验证码"); } StringBuilder sb = new StringBuilder(); try { long c = GoogleGenerator.getCode(apiSecret, DateTime.now().getTime()); sb.append(c); while (sb.length() < 6) { sb.insert(0, 0); } redisService.incr(numKey, 1l); } catch (Exception e) { throw BusinessRuntimeException.getInstance("刷新双重验证码错误,请联系客服"); } if (clickId != 0) { int nowSecond = DateTime.now().second(); int time = 0; if (nowSecond < 30) { time = 30 - nowSecond; } else { time = 60 - nowSecond; } //刷新双重验证码记录 DoubleVerifyClickRefreshRecord refreshRecord = new DoubleVerifyClickRefreshRecord(); refreshRecord.setClickId(clickId); refreshRecord.setUserId(userId); refreshRecord.setCode(sb.toString()); refreshRecord.setRemainTime(time); refreshRecordMapper.insert(refreshRecord); } return GatewayResponse.SUCCESS.newBuilder().toResult(sb.toString()); } /** * 获取双重验证码记录 */ @GetMapping("/get/doubleVerify/codeList") public Result> getDoubleVerifyCodeList(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List views = doubleVerifyRecordMapper.getDoubleVerifyCodeList(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(views); } /** * 用户是不是自然流量渠道 * 且未回答答题 */ @GetMapping("/natural/channel") public Result isNaturalChannel() { long userId = StpUserUtil.getLoginIdAsLong(); String question_key = RedisService.key.QUESTION_RESPONSE_KEY.getNameFormat(userId); if (redisService.get(question_key) != null) { return GatewayResponse.SUCCESS.newBuilder().toResult(false); } User user = userService.getById(userId); if (user.getPopularizeId() != 0) { redisService.set(question_key, userId, RedisService.key.QUESTION_RESPONSE_KEY.getTimeout()); return GatewayResponse.SUCCESS.newBuilder().toResult(false); } if (user.getPopularizeId() == 0) { QuestionResponseRecord record = questionResponseRecordMapper.selectOne(Wrappers.lambdaQuery(QuestionResponseRecord.class) .eq(QuestionResponseRecord::getUserId, userId).select(QuestionResponseRecord::getId).last("limit 1")); if (record != null) { redisService.set(question_key, userId, RedisService.key.QUESTION_RESPONSE_KEY.getTimeout()); return GatewayResponse.SUCCESS.newBuilder().toResult(false); } return GatewayResponse.SUCCESS.newBuilder().toResult(true); } return GatewayResponse.SUCCESS.newBuilder().toResult(false); } /** * 问卷记录 */ @PostMapping("/record/replyQuestion") public Result recordReplyQuestion(@RequestBody @Validated QuestionResponseRecord record) { long userId = StpUserUtil.getLoginIdAsLong(); User user = userService.getById(userId); String nickname = user.getNickname(); String question_key = RedisService.key.QUESTION_RESPONSE_KEY.getNameFormat(userId); QuestionResponseRecord dbRecord = questionResponseRecordMapper.selectOne(Wrappers.lambdaQuery(QuestionResponseRecord.class) .eq(QuestionResponseRecord::getUserId, userId).select(QuestionResponseRecord::getId).last("limit 1")); if (dbRecord == null) { if (redisService.setNx(String.format("%s-%s", userId, nickname), userId, 10l)) { record.setUserId(userId); record.setNickname(nickname); questionResponseRecordMapper.insert(record); //发放优惠券 couponCommonService.sendCouponToUser(userId, 100l, 0l, 0l, 0l, CouponUser.Channel.ques_response); redisService.set(question_key, userId, RedisService.key.QUESTION_RESPONSE_KEY.getTimeout()); } } return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 获取对应的动态问卷 */ @GetMapping("/get/questionnaire") public Result> getQuestionnaireView(Long promotionId) { QuestionnairePromotion promotion = questionnairePromotionMapper.selectById(promotionId); if (promotion == null || !promotion.getDeleted()) throw BusinessRuntimeException.getInstance("问卷不存在"); Long templateId = promotion.getTemplateId(); List questionnaireViews = beanSearcher.searchAll(QuestionnaireView.class, MapUtils.builder() .field(QuestionnaireView::getPromotionId, promotionId) .orderBy(QuestionnaireView::getSorted).asc() .orderBy(QuestionnaireView::getFieldsId).asc() .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(questionnaireViews); } /** * 记录问卷 */ @PostMapping("/record/questionnaire/{promotionId}") @Transactional(rollbackFor = Exception.class) @NoSubmit public Result recordQuestionnaire(@PathVariable Long promotionId, String showId, @RequestBody List answers) { Long userId = StpUserUtil.getUserIdAfterLogin(); Long groupsId = SEQUENCE.nextId(); List promotionFieldsListViews = beanSearcher.searchAll(QuestionnairePromotionFieldsListView.class, MapUtils.builder().field(QuestionnairePromotionFieldsListView::getPromotionId, promotionId).build()); if (CollUtil.isEmpty(promotionFieldsListViews)) throw BusinessRuntimeException.getInstance("问卷已结束"); if (promotionFieldsListViews.size() != answers.size()) throw BusinessRuntimeException.getInstance("请完成所有问题"); log.info("开始记录问卷:{}", promotionId); answers.forEach(answer -> { // if (StringUtil.isNotBlank(showId)) { // answer.setUserId(userService.getUserIdByShowId(showId)); // } answer.setUserId(userId); Long fieldsId = answer.getFieldsId(); String content = answer.getContent(); if (fieldsId == null || StrUtil.isBlank(content)) { throw BusinessRuntimeException.getInstance("必填项为空"); } answer.setPromotionId(promotionId); answer.setGroupsId(groupsId); formFieldsDataMapper.insert(answer); }); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 查询用户是否填写问卷 */ @GetMapping("/check/questionnaire/{promotionId}") public Result checkQuestionnaire(@PathVariable Long promotionId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); Integer count = formFieldsDataMapper.selectCount(Wrappers.lambdaQuery(FormFieldsData.class).in(FormFieldsData::getUserId, userIdList).eq(FormFieldsData::getPromotionId, promotionId)); return GatewayResponse.SUCCESS.newBuilder().toResult(count > 0); } /** * 对应平台车票 广告配置列表 */ @GetMapping("/get/advertise") public Result> getTicketAdvertiseConfig() { long userId = StpUserUtil.getLoginIdAsLong(); List hasPayGoods = groupRelationFrontService.getHasPayGoods(userId); if (CollUtil.isEmpty(hasPayGoods)) { return GatewayResponse.SUCCESS.newBuilder().toResult(); } List goodsIds = hasPayGoods.stream().map(RenewalView::getGoodsId).collect(Collectors.toList()); log.info("userId:{}获取广告位配置", userId); List views = beanSearcher.searchAll(TicketAdvertiseConfigFrontView.class, MapUtils.flatBuilder(request.getParameterMap()) .field(TicketAdvertiseConfigFrontView::getGoodsId, goodsIds).op(Operator.InList) .orderBy(TicketAdvertiseConfigFrontView::getSorted).desc() .orderBy(TicketAdvertiseConfigFrontView::getGoodsId).asc() .orderBy(TicketAdvertiseConfigFrontView::getConfigId).desc() .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(views); } /** * 记录用户点击车票广告 */ @PostMapping("/click/ticket/advertise/record/{configId}") public Result recordClickTicketAdvertise(@PathVariable Long configId) { long userId = StpUserUtil.getLoginIdAsLong(); ticketAdvertiseConfigClickRecordService.recordUserClickTicketAdvertise(userId, configId); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 推荐平台 */ @GetMapping("/get/recommend/goods") public Result> getRecommendGoodsViews(@RequestParam(defaultValue = "0") Integer start, @RequestParam(defaultValue = "5") Integer limit, String customId) { //推荐用户未购买的车票平台 优先展示ai类平台 然后是影视流媒体 long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userBindRelationService.getRelationUserIdList(userId, null); List filter_goods_id = relationMapper.getTicketGoodsId(userIds, List.of("validity", "overdue", "outside")); //用户是否购买过奈飞产品 Boolean isPayNf = false; if (filter_goods_id.contains(1l)) { isPayNf = true; } else { int count = orderDonService.count(Wrappers.lambdaQuery(OrderDon.class) .eq(OrderDon::getGoodsId, 1) .eq(OrderDon::getUserId, userId) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)); if (count > 0) { //优先展示路由器、ai、流媒体 isPayNf = true; } } Boolean filterCourseGoods = false; //GPT Plus基础2月 课程不展示 Integer orders = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class) .in(OrderDon::getUserId, userIds) .eq(OrderDon::getSkuId, 444) .notIn(OrderDon::getStatus, Constant.noOrderStatus)); if (orders > 0) { filterCourseGoods = true; } List yhShopGoodsIds = null; if (StrUtil.isNotBlank(customId)) { YhShop yhShop = yhShopMapper.selectOne(Wrappers.lambdaQuery(YhShop.class) .eq(YhShop::getCustomId, customId) .last("limit 1")); if (yhShop != null) { //获取可用的平台 yhShopGoodsIds = yhShopMapper.getGoodsIdsByShop(yhShop.getId()); } } Page page = groupRelationFrontService.getRecommendGoodsViews(yhShopGoodsIds, isPayNf, filter_goods_id, filterCourseGoods, start, limit); return GatewayResponse.SUCCESS.newBuilder().toResult(page); } /** * 查看GPT token */ @GetMapping("/get/gptAccessToken") public Result getGptAccessToken(Long relationId) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userBindRelationService.getRelationUserIdList(userId, null); //存在该车票 RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder() .field(RenewalView::getRelationId, relationId) .field(RenewalView::getUserId, userIds).op(Operator.InList).build()); Assert.notNull(renewalView, "您的车票不存在"); if (renewalView.getGoodsId() != 42) { throw BusinessRuntimeException.getInstance("该平台类型车票无法获取GPT直连token"); } String account = renewalView.getAccount(); String accessToken = chatGptAuthService.getAccessToken(account); return GatewayResponse.SUCCESS.newBuilder().toResult(accessToken); } /** * 获取特殊类型课程 通过邮件发送课程 * 领取课件 */ @PostMapping("/courseware") public Result getCourseWare(@RequestBody SpecialGoodsTicketReq request) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); request.setUserId(userId); groupRelationFrontService.sendCourseWare(request); return GatewayResponse.SUCCESS.newBuilder().toResult(); } //获取课程云盘链接 @GetMapping("/get/courseware") public Result getGoodsCourseware(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); RenewalView relationView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder() .field(RenewalView::getUserId, userIdList).op(Operator.InList) .field(RenewalView::getRelationId, relationId).build()); if (relationView == null) { throw BusinessRuntimeException.getInstance("您的车票不存在"); } GoodsCoursewareFile goodsCoursewareFile = goodsCoursewareFileMapper.selectOne(Wrappers.lambdaQuery(GoodsCoursewareFile.class) .eq(GoodsCoursewareFile::getGoodsId, relationView.getGoodsId()) .eq(GoodsCoursewareFile::getStatus, true) .select(GoodsCoursewareFile::getLink, GoodsCoursewareFile::getCode) .last("limit 1")); if (goodsCoursewareFile == null) { throw BusinessRuntimeException.getInstance("暂未配置课件链接地址,请联系客服"); } return GatewayResponse.SUCCESS.newBuilder().toResult(goodsCoursewareFile); } /** * 读取车票账号登录验证码 */ @PostMapping("/get/verifyCode") public Result getAiVerifyCode(@RequestBody TicketLoginReq loginReq) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); loginReq.setUserId(userId); return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.getAiVerifyCode(loginReq)); } /** * 车票后台登录 */ @PostMapping("/ticket/login") public Result ticketLogin(@RequestBody TicketLoginReq loginReq) { GroupsRelation relation = groupRelationFrontService.ticketLogin(loginReq); return GatewayResponse.SUCCESS.newBuilder().toResult(relation); } /** * 奈飞验证校验 */ @PostMapping("/ticket/verify") public Result outsideTicketVerify(@RequestBody TicketLoginReq loginReq) { return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.outsideTicketVerify(loginReq)); } /** * 是否有mid车票可候补 */ @GetMapping("/get/standby") public Result getGptStandby() { long userId = StpUserUtil.getLoginIdAsLong(); List relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null); String condition = "(a.account like '%@yinhe.ac.cn%' or exists (select id from account_blocked_replace_record abrr where abrr.account = a.account and abrr.goods_id = g.id limit 1))"; List renewalViewList = beanSearcher.searchAll(RenewalView.class, MapUtils.builder() .field(RenewalView::getUserId, relationUserIdList).op(Operator.InList) .field(RenewalView::getGoodsId, 26) .put("condition", condition) .field(RenewalView::getExpiryTime).op(Operator.NotNull) .onlySelect(RenewalView::getAccount, RenewalView::getExpiryTime) .build()); GptStandbyResp gptStandbyResp = new GptStandbyResp(); if (renewalViewList.isEmpty()) { gptStandbyResp.setIsHasAccount(false); return GatewayResponse.SUCCESS.newBuilder().toResult(gptStandbyResp); } List overTen = new ArrayList<>(); List underTen = new ArrayList<>(); DateTime now = DateTime.now(); renewalViewList.forEach(e -> { if (e.getExpiryTime().compareTo(DateUtil.offsetDay(now, 10)) > 0) { overTen.add(e); } else underTen.add(e); }); Integer accountBlockedCount = 1; if (overTen.size() > 1) { List accountList = overTen.stream().map(RenewalView::getAccount).distinct().collect(Collectors.toList()); accountBlockedCount = accountBlockedReplaceRecordMapper.selectCount(Wrappers.lambdaQuery(AccountBlockedReplaceRecord.class) .eq(AccountBlockedReplaceRecord::getGoodsId, 26) .in(AccountBlockedReplaceRecord::getAccount, accountList)); } if (accountBlockedCount > 1) { gptStandbyResp.setIsHasAccount(false); return GatewayResponse.SUCCESS.newBuilder().toResult(gptStandbyResp); } gptStandbyResp.setIsHasAccount(true); gptStandbyResp.setOverTen(overTen); gptStandbyResp.setUnderTen(underTen); Integer count = gptTicketStandbyMapper.selectCount(Wrappers.lambdaQuery(GptTicketStandby.class) .in(GptTicketStandby::getUserId, relationUserIdList)); gptStandbyResp.setIsApply(count > 0 ? true : false); return GatewayResponse.SUCCESS.newBuilder().toResult(gptStandbyResp); } /** * 申请候补 */ @PostMapping("/apply/standby") @NoSubmit public Result applyGptStandby() { long userId = StpUserUtil.getLoginIdAsLong(); List relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null); String condition = "(a.account like '%@yinhe.ac.cn%' or exists (select id from account_blocked_replace_record abrr where abrr.account = a.account and abrr.goods_id = g.id limit 1))"; List renewalViewList = beanSearcher.searchAll(RenewalView.class, MapUtils.builder() .field(RenewalView::getUserId, relationUserIdList).op(Operator.InList) .field(RenewalView::getGoodsId, 26) .put("condition", condition) .field(RenewalView::getExpiryTime, DateUtil.offsetDay(DateTime.now(), 10)).op(Operator.GreaterThan) .onlySelect(RenewalView::getAccount) .build()); if (renewalViewList.isEmpty()) { throw BusinessRuntimeException.getInstance("你未有车票账号"); } Integer count = gptTicketStandbyMapper.selectCount(Wrappers.lambdaQuery(GptTicketStandby.class) .in(GptTicketStandby::getUserId, relationUserIdList)); if (count > 0) { throw BusinessRuntimeException.getInstance("你已申请车票账号候补"); } if (renewalViewList.size() > 1) { Set accountSet = renewalViewList.stream().map(RenewalView::getAccount).collect(Collectors.toSet()); Integer accountBlockedCount = accountBlockedReplaceRecordMapper.selectCount(Wrappers.lambdaQuery(AccountBlockedReplaceRecord.class) .eq(AccountBlockedReplaceRecord::getGoodsId, 26) .in(AccountBlockedReplaceRecord::getAccount, accountSet)); if (accountBlockedCount > 1) { return GatewayResponse.SUCCESS.newBuilder().toResult(true); } } GptTicketStandby gptTicketStandby = new GptTicketStandby(); gptTicketStandby.setUserId(userId); gptTicketStandbyMapper.insert(gptTicketStandby); return GatewayResponse.SUCCESS.newBuilder().toResult(true); } /** * midjourney车票退款 */ @PutMapping("/refund/ticketOrder/{relationId}") @NoSubmit public Result ticketRefundOrders(@PathVariable Long relationId) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); List relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null); String condition = "(a.account like '%@yinhe.ac.cn%' or exists (select id from account_blocked_replace_record abrr where abrr.account = a.account and abrr.goods_id = g.id limit 1))"; RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder() .field(RenewalView::getRelationId, relationId) .field(RenewalView::getUserId, relationUserIdList).op(Operator.InList) .put("condition", condition) .field(RenewalView::getGoodsId, 26) .field(RenewalView::getExpiryTime, DateUtil.offsetDay(DateTime.now(), 10)).op(Operator.LessEqual) .build()); if (renewalView == null) { throw BusinessRuntimeException.getInstance("你车票不存在或不符合退款要求"); } OrderDon orderDon = orderDonService.getOne(Wrappers.lambdaQuery(OrderDon.class) .in(OrderDon::getUserId, relationUserIdList) .eq(OrderDon::getRelationId, relationId) .notIn(OrderDon::getStatus, Constant.noOrderAllStatus) .orderByDesc(OrderDon::getId) .last("limit 1")); if (orderDon == null) { throw BusinessRuntimeException.getInstance("你对应车票的订单不存在"); } GoodsDonSku sku = goodsDonSkuMapper.selectById(orderDon.getSkuId()); if (sku == null) { throw BusinessRuntimeException.getInstance("该车票规格不存在,请联系客服进行人工退款.."); } Date expiryTime = renewalView.getExpiryTime(); long remainDay = DateUtil.between(DateTime.now(), expiryTime, DateUnit.DAY) + 1; BigDecimal money = orderDon.getMoney(); BigDecimal refundMoney = null; BigDecimal refundBalance= null; String refundType = null; if (money.compareTo(BigDecimal.ZERO) > 0) { BigDecimal dayMoney = money.divide(BigDecimal.valueOf(sku.getMonths()).multiply(BigDecimal.valueOf(30)), 2, RoundingMode.HALF_DOWN); refundMoney = BigDecimal.valueOf(remainDay).multiply(dayMoney); refundType = "money"; } OrderRefundReq refundReq = new OrderRefundReq(); if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) { BigDecimal dayMoney = orderDon.getBalance().divide(BigDecimal.valueOf(sku.getMonths()).multiply(BigDecimal.valueOf(30)), 2, RoundingMode.HALF_DOWN); refundBalance = BigDecimal.valueOf(remainDay).multiply(dayMoney); refundReq.setIsOnly(true); } refundReq.setOrderId(orderDon.getId()); refundReq.setRefundDesc("失效车票退款"); refundReq.setRefundMoney(Optional.ofNullable(refundMoney).orElse(BigDecimal.ZERO)); refundReq.setRefundBalance(Optional.ofNullable(refundBalance).orElse(BigDecimal.ZERO)); refundReq.setRefundType(Optional.ofNullable(refundType).orElse("balance")); cmsOrderDonService.unifiedRefund(refundReq); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 每日车票到期弹窗 */ @GetMapping("/get/expiry/notify") public Result> getExpiryRenewalNotify() { Long userId = StpUserUtil.getLoginIdAsLong(); List expiryRenewals = groupRelationFrontService.getExpiryRenewalNotify(userId); return GatewayResponse.SUCCESS.newBuilder().toResult(expiryRenewals); } /** * 车票详情 */ @GetMapping("/get/detail") public Result getTicketDetail(Long relationId) { if (relationId == null) { return GatewayResponse.SUCCESS.newBuilder().toResult(); } long userId = StpUserUtil.getLoginIdAsLong(); RenewalView ticketDetail = groupRelationFrontService.getTicketDetail(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(ticketDetail); } /** * 车票售后常见问题 */ @GetMapping("/get/questions/{goodsId}") public Result> getTicketQuestions(@PathVariable Long goodsId, @RequestParam(defaultValue = "1") Integer type) { long userId = StpUserUtil.getLoginIdAsLong(); log.info("userId:{}查看车票:{}售后问题", userId, goodsId); if (type < 1 || type > 2) { return GatewayResponse.SUCCESS.newBuilder().toResult(); } String key = RedisService.key.YH_GOODS_QUESTIONS_DETAIL.getNameFormat(type, goodsId); Object o = redisService.get(key); if (o == null) { List donQaFrontViews = beanSearcher.searchAll(GoodsDonQaFrontView.class, MapUtils.builder().field(GoodsDonQaFrontView::getGoodsId, goodsId).field(GoodsDonQaFrontView::getType, type).build()); if (CollUtil.isEmpty(donQaFrontViews)) { return GatewayResponse.SUCCESS.newBuilder().toResult(); } redisService.setNx(key, donQaFrontViews, RedisService.key.YH_GOODS_QUESTIONS_DETAIL.getTimeout()); o = redisService.get(key); } List donQaFrontViews = Jsons.parseList(o, GoodsDonQaFrontView.class); return GatewayResponse.SUCCESS.newBuilder().toResult(donQaFrontViews); } /** * 车票所有常见问题 */ @GetMapping("/get/questions") public Result> getAllTicketQuestions(String participle) { MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()); if (StrUtil.isNotBlank(participle)) { char[] charArray = participle.toCharArray(); StringBuilder p = new StringBuilder(); p.append("and ("); for (int i = 0; i < charArray.length; i++) { char c = charArray[i]; p.append(String.format(" ga.problem like '%%%s%%'", c)); if (i != charArray.length - 1) { p.append(" or "); } } p.append(")"); builder.put("p", p); } List donQaFrontViews = beanSearcher.searchAll(GoodsDonQaFrontView.class, builder.build()); return GatewayResponse.SUCCESS.newBuilder().toResult(donQaFrontViews); } /** * 车票常见问题 分页 */ @GetMapping("/get/questions/page") public Result> getTicketQuestionsPage(String participle) { MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap()); if (StrUtil.isNotBlank(participle)) { char[] charArray = participle.toCharArray(); StringBuilder p = new StringBuilder(); p.append("and ("); for (int i = 0; i < charArray.length; i++) { char c = charArray[i]; p.append(String.format(" ga.problem like '%%%s%%'", c)); if (i != charArray.length - 1) { p.append(" or "); } } p.append(")"); builder.put("p", p); } SearchResult donQaFrontViews = beanSearcher.search(GoodsDonQaFrontView.class, builder.build()); return GatewayResponse.SUCCESS.newBuilder().toResult(donQaFrontViews); } /** * 是否首次购买车票 */ @GetMapping("/get/first/pay/{goodsId}") public Result getFirstPay(@PathVariable Long goodsId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); Number number = beanSearcher.searchCount(OrderDon.class, MapUtils.builder() .field(OrderDon::getGoodsId, goodsId) .field(OrderDon::getCreatedTime, new DateTime().toDateStr()).op(Operator.LessEqual) .field(OrderDon::getUserId, userIdList).op(Operator.InList) .field(OrderDon::getStatus, Constant.noOrderStatus).op(Operator.NotIn) .build()); if (number.intValue() == 0) { UserGoodsNewbieGuideRecord userGoodsNewbieGuideRecord = new UserGoodsNewbieGuideRecord(); userGoodsNewbieGuideRecord.setGoodsId(goodsId); userGoodsNewbieGuideRecord.setUserId(userId); userGoodsNewbieGuideRecordMapper.insert(userGoodsNewbieGuideRecord); return GatewayResponse.SUCCESS.newBuilder().toResult(true); } return GatewayResponse.SUCCESS.newBuilder().toResult(false); } /** * 设置pin码 */ @PutMapping("/set/pin/{relationId}") public Result setPin(@PathVariable Long relationId, String code) { long userId = StpUserUtil.getLoginIdAsLong(); JSONObject data = groupsRelationNetflixService.setNetflixPin(relationId, userId, code); return GatewayResponse.SUCCESS.newBuilder().toResult(data.toString()); } /** * 查询是否设置成功 */ @GetMapping("/get/pin/status/{taskId}") public Result getPinStatus(@PathVariable String taskId) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); log.info("userId:{}查看设置pin码状态", userId); return GatewayResponse.SUCCESS.newBuilder().toResult(groupsRelationNetflixService.getPinStatus(taskId)); } /** * 踢出奈飞设备 */ @PostMapping("/kickOut/nf/{relationId}") public Result nfKickOut(@PathVariable Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); JSONObject data = groupsRelationNetflixService.nfKickOut(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(data.toString()); } /** * 奈飞同户装置链接 */ @GetMapping("/get/nf/household/device") public Result getNfHouseholdDevice(@NotNull Long relationId) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); String url = groupRelationFrontService.getNfHouseholdDevice(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(url); } /** * 代点奈飞同户装置 */ @PostMapping("/click/nf/household/device") public void clickNfHouseholdDevice(@RequestBody NfDeviceReq nfDeviceReq) { groupsRelationNetflixService.clickNfHouseholdDevice(nfDeviceReq); } /** * 可选 续费升级车票 */ @GetMapping("/get/renew/skus/{relationId}/{skuId}") public Result> getRenewSkus(@PathVariable Long relationId, @PathVariable Long skuId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class) .eq(ChatgptUser::getRelationId, relationId) .last("limit 1")); if (chatgptUser == null) return GatewayResponse.SUCCESS.newBuilder().toResult(); //目前续费升级的规格 Long renewSkuId = chatgptUser.getRenewSkuId(); GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId); AtomicInteger minMonths = new AtomicInteger(sku.getMonths()); AtomicInteger minNum = new AtomicInteger(chatgptUser.getLimitNum()); AtomicLong minTime = new AtomicLong(chatgptUser.getLimitTime()); if (renewSkuId != null) { GoodsDonSku presentRenew = goodsDonSkuMapper.selectById(renewSkuId); minMonths.set(presentRenew.getMonths()); } if (chatgptUser.getPackageId() != 0) { Long packageId = chatgptUser.getPackageId(); UpgradeOrderDon upgradeOrderDon = upgradeOrderDonMapper.selectOne(Wrappers.lambdaQuery(UpgradeOrderDon.class) .eq(UpgradeOrderDon::getPackageId, packageId) .eq(UpgradeOrderDon::getRelationId, relationId) .in(UpgradeOrderDon::getUserId, userIdList) .last("limit 1")); Long upgradeOrderDonSkuId = upgradeOrderDon.getSkuId(); GoodsDonSku upgradeSku = goodsDonSkuMapper.selectById(upgradeOrderDonSkuId); if (upgradeSku != null) { if (upgradeSku.getMonths() > minMonths.get()) { minMonths.set(upgradeSku.getMonths()); } } } String lang = request.getHeader("lang"); List renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build()); renewUpgradePackageFrontViews.forEach(renew -> { try { List upgradeSkuIds = Jsons.parseList(renew.getUpgradeSkuIds(), Long.class); //年付展示 MapBuilder builder = MapUtils.builder(); // if (minMonths.get() == 12) { // builder.field(RenewUpgradePackageFrontView.RenewSkuView::getMonths, minMonths.get()).op(Operator.GreaterEqual); // if (renewSkuId != null) { // upgradeSkuIds.remove(renewSkuId); // } // } else { // builder.field(RenewUpgradePackageFrontView.RenewSkuView::getMonths, minMonths.get()).op(Operator.GreaterEqual); // } //GPT镜像2月规格 特殊处理 if (sku.getGoodsId() == 18 && sku.getMonths() == 2) { } else { //同续费时间规格 builder.field(RenewUpgradePackageFrontView.RenewSkuView::getMonths, minMonths.get()).op(Operator.GreaterEqual); } if (renewSkuId != null) { upgradeSkuIds.remove(renewSkuId); } List renewSkuViews = new ArrayList<>(); if (CollUtil.isNotEmpty(upgradeSkuIds)) { renewSkuViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.RenewSkuView.class, builder .field(RenewUpgradePackageFrontView.RenewSkuView::getGptLimitNum, minNum.get()).op(Operator.GreaterEqual) .field(RenewUpgradePackageFrontView.RenewSkuView::getGptLimitTime, minTime.get()).op(LessEqual.class) .field(RenewUpgradePackageFrontView.RenewSkuView::getSkuId, upgradeSkuIds).op(Operator.InList) .build()); if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) { renewSkuViews.forEach(renewSku->{ String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(renewSku.getSkuId(), lang); if (StrUtil.isNotBlank(languageSpecVal)) { renewSku.setSpecVal(languageSpecVal); } }); } } renew.setRenewSkus(renewSkuViews); } catch (Exception e) { } }); return GatewayResponse.SUCCESS.newBuilder().toResult(renewUpgradePackageFrontViews); } /** * 独立规格续费套餐列表 */ @GetMapping("/get/independent/renew/skus/{skuId}") public Result> getRenewSkus(@PathVariable Long skuId) { long userId = StpUserUtil.getLoginIdAsLong(); List renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build()); renewUpgradePackageFrontViews.forEach(renew -> { try { List upgradeSkuIds = Jsons.parseList(renew.getUpgradeSkuIds(), Long.class); MapBuilder builder = MapUtils.builder(); List renewSkuViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.RenewSkuView.class, builder .field(RenewUpgradePackageFrontView.RenewSkuView::getSkuId, upgradeSkuIds).op(Operator.InList) .build()); renew.setRenewSkus(renewSkuViews); } catch (Exception e) { } }); return GatewayResponse.SUCCESS.newBuilder().toResult(renewUpgradePackageFrontViews); } /** * claude pro续费升级 */ @GetMapping("/get/claude/renew/skus/{relationId}/{skuId}") public Result > getClaudeRenewSkus(@PathVariable Long relationId, @PathVariable Long skuId) { long userId = StpUserUtil.getLoginIdAsLong(); ClaudeUser claudeUser = claudeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeUser.class) .eq(ClaudeUser::getRelationId, relationId) .last("limit 1")); if (claudeUser == null) return GatewayResponse.SUCCESS.newBuilder().toResult(); List renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build()); renewUpgradePackageFrontViews.forEach(renew -> { try { List upgradeSkuIds = Jsons.parseList(renew.getUpgradeSkuIds(), Long.class); MapBuilder builder = MapUtils.builder(); List renewSkuViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.RenewSkuView.class, builder .field(RenewUpgradePackageFrontView.RenewSkuView::getSkuId, upgradeSkuIds).op(Operator.InList) .field(RenewUpgradePackageFrontView.RenewSkuView::getGptLimitNum, claudeUser.getLimitNum()).op(Operator.GreaterEqual) .build()); renew.setRenewSkus(renewSkuViews); } catch (Exception e) { } }); return GatewayResponse.SUCCESS.newBuilder().toResult(renewUpgradePackageFrontViews); } /** * 已配置的续费升级规格ids */ @GetMapping("/get/renew/skus/configured") public Result > getClaudeRenewSkus() { long userId = StpUserUtil.getLoginIdAsLong(); List renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().onlySelect(RenewUpgradePackageFrontView::getSkuId).build()); List collect = renewUpgradePackageFrontViews.stream().map(RenewUpgradePackageFrontView::getSkuId).collect(Collectors.toList()); return GatewayResponse.SUCCESS.newBuilder().toResult(collect); } /** * 获取GPT PLUS登录验证码 */ @GetMapping("/get/verify/code") public Result getVerifyCode(@NotEmpty String account) throws Exception { String code = groupRelationFrontService.getVerifyCode(account); if (StrUtil.isEmpty(code)) { throw BusinessRuntimeException.getInstance("请重新发送验证码"); } return GatewayResponse.SUCCESS.newBuilder().toResult(code); } /** * 独立规格续费减免 */ @GetMapping("/get/renew/reduce") public Result getRenewReduce(Long skuId, Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); UserBenefitsFrontView data = beanSearcher.searchFirst(UserBenefitsFrontView.class, MapUtils.builder().field(UserBenefitsFrontView::getSkuId, skuId).field(UserBenefitsFrontView::getType, UserBenefits.Type.RENEW.name()).build()); if (data == null) { return GatewayResponse.SUCCESS.newBuilder().toResult(); } Date startTime = null; if (relationId != null) { GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getId, relationId) .in(GroupsRelation::getUserId, userIdList)); if (relation == null) { throw BusinessRuntimeException.getInstance("车票不存在"); } startTime = relation.getStartTime(); } Integer renewCount = userBenefitsOrderRecordMapper.selectUseComboRecordByUid(userIdList, data.getType(), data.getGoodsId(), data.getSkuId(), Constant.noOrderAllStatus, null, startTime, relationId); data.setRenewCount(renewCount); return GatewayResponse.SUCCESS.newBuilder().toResult(data); } /** * 申请更换车票 */ @PostMapping("/change/ticket") @Deprecated public Result changeTicket(@RequestBody ChangeTicketReq changeTicketReq) { long userId = StpUserUtil.getLoginIdAsLong(); List relationIds = changeTicketReq.getRelationIds(); if (CollUtil.isEmpty(relationIds)) { return GatewayResponse.SUCCESS.newBuilder().toResult(); } List userIdList = userBindRelationService.getRelationUserIdList(userId, null); //奈飞超过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 GatewayResponse.SUCCESS.newBuilder().toResult(); } relationIds.forEach(relationId -> { try { groupRelationFrontService.changeTicket(userId, relationId); } catch (Exception e) { log.error("更换车票失败:{}", StringUtil.getErrorText(e)); if (relationIds.size() == 1) { throw BusinessRuntimeException.getInstance(e.getMessage()); } } }); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 查看临时账号 */ @GetMapping("/get/temp/account/{relationId}") public Result getTempAccount(@PathVariable Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); AccountView accountView = groupRelationFrontService.getTempAccount(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(accountView); } /** * 申请提交记录 */ @GetMapping("/get/netflix/get/error/submit/record") public Result> getUserNetflixSubmitRecord() { long userId = StpUserUtil.getLoginIdAsLong(); List netflixUserAccountStatusRecords = groupRelationFrontService.getUserNetflixSubmitRecord(userId); return GatewayResponse.SUCCESS.newBuilder().toResult(netflixUserAccountStatusRecords); } /** * 奈飞账号异常检测提交 */ @PostMapping("/netflix/error/account/submit/{relationId}") public Result nfErrorAccountSubmit(@PathVariable Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); groupRelationFrontService.nfErrorAccountSubmit(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 奈飞账号检测结果 */ @GetMapping("/get/netflix/error/account/status/{relationId}") public Result getNetflixErrorAccountStatus(@PathVariable Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); NetflixErrorAccountStatus status = groupRelationFrontService.getNetflixErrorAccountStatus(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(status); } /** * 奈飞可替换其他规格车票列表 */ @GetMapping("/get/netflix/replace/other/skus/{relationId}") public Result> getNetflixReplaceOtherSkus(@PathVariable Long relationId) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); List goodsCategorySkuViews = groupRelationFrontService.getNetflixReplaceOtherSkus(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(goodsCategorySkuViews); } /** * 奈飞账号申请恢复 */ @PostMapping("/netflix/submit/recover") public Result netflixSubmitRecover(@RequestBody ErrorNetflixChangeReq req) { long userId = StpUserUtil.getLoginIdAsLong(); req.setUserId(userId); NetflixRecoverResp recoverResp = groupRelationFrontService.netflixSubmitRecover(req); return GatewayResponse.SUCCESS.newBuilder().toResult(recoverResp); } /** * 奈飞申请冻结 */ @PostMapping("/netflix/submit/frozen") public Result netflixSubmitFrozen(@RequestBody ErrorNetflixChangeReq req) { long userId = StpUserUtil.getLoginIdAsLong(); req.setUserId(userId); groupRelationFrontService.netflixSubmitFrozen(req); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 奈飞更换其他车票 */ @PostMapping("/netflix/submit/change/otherTicket") public Result errorNetflixSubmitChangeOtherTicket(@RequestBody ErrorNetflixChangeReq req) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); req.setUserId(userId); groupRelationFrontService.errorNetflixSubmitChangeOtherTicket(req); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 不超过30天 奈飞退款info */ @GetMapping("/netflix/refund/info/{relationId}") public Result refundNetflixInfo(@PathVariable Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); //是否可进行退款 true可 false否 走恢复账号流程 NetflixRefundInfoResp refundInfoResp = groupRelationFrontService.refundNetflixInfo(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(refundInfoResp); } /** * 奈飞不超过30天有效期进行退款 * 是否可进行退款 true可 false否 走恢复账号流程 */ @PostMapping("/netflix/refund") public Result refundNetflix(@RequestBody ErrorNetflixChangeReq req) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); req.setUserId(userId); //是否可进行退款 true可 false否 走恢复账号流程 Boolean availableRefund = groupRelationFrontService.refundNetflix(req); return GatewayResponse.SUCCESS.newBuilder().toResult(availableRefund); } /** * AI镜像车票 每周弹窗 */ @GetMapping("/get/mirror/popups") public Result getMirrorPopups() { long userId = StpUserUtil.getLoginIdAsLong(); Boolean flag = groupRelationFrontService.getMirrorPopups(userId); return GatewayResponse.SUCCESS.newBuilder().toResult(flag); } /** * 银河币续费车票列表 */ @GetMapping("/get/galaxyCoin/tickets") public Result> getGalaxyCoinTickets() throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); DateTime now = DateTime.now(); //非独立账号 String conditionSql = String.format("(gr.expiry_time is null or gr.expiry_time > '%s' or (sku.is_mirror and gr.expiry_time > '%s')) and (sku.months is null or sku.months != 300)", now, DateUtil.offsetDay(now, -7)); SearchResult search = beanSearcher.search(GalaxyCoinRenewTicketsView.class, MapUtils.flatBuilder(request.getParameterMap()) .field(GalaxyCoinRenewTicketsView::getUserId, userIdList).op(Operator.InList) .put("condition", conditionSql) .field(GalaxyCoinRenewTicketsView::getIsVip, Boolean.FALSE) //购买 .field(GalaxyCoinRenewTicketsView::getAqType, 1) //非代充 .field(GalaxyCoinRenewTicketsView::getRechargeStatus).op(Operator.IsNull) //车队状态 .field(GalaxyCoinRenewTicketsView::getGroupsStatus, GroupsTrips.Status.waiting.name()).op(Operator.NotEqual) .field(GalaxyCoinRenewTicketsView::getStatus, List.of(GroupsRelation.Status.validity.name(), GroupsRelation.Status.outside.name())).op(Operator.InList) .field(GalaxyCoinRenewTicketsView::getSecondType, 2) .orderBy(GalaxyCoinRenewTicketsView::getExpiryTime).asc() .build()); User user = userMapper.selectById(userId); if (user.getGalaxyCoin().compareTo(BigDecimal.ZERO) == 0) { return GatewayResponse.SUCCESS.newBuilder().toResult(search); } BigDecimal userGalaxyCoin = user.getGalaxyCoin(); SysConfig payDeductConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class) .eq(SysConfig::getSysKey, Constant.GALAXY_COIN_PAY_DEDUCT_KEY) .last("limit 1")); GalaxyCoinPayConfigDto galaxyCoinPayConfigDto = Jsons.parseObject(payDeductConfig.getSysValue(), GalaxyCoinPayConfigDto.class); BigDecimal maxRate = galaxyCoinPayConfigDto.getMaxRate(); BigDecimal payGalaxyCoin = galaxyCoinPayConfigDto.getGalaxyCoin(); BigDecimal payMoney = galaxyCoinPayConfigDto.getMoney(); for (GalaxyCoinRenewTicketsView galaxyCoinRenewTicketsView : search.getDataList()) { Long skuId = galaxyCoinRenewTicketsView.getSkuId(); BigDecimal maxSkuPrice = BigDecimal.ZERO; if (galaxyCoinRenewTicketsView.getIsMirror() != null && galaxyCoinRenewTicketsView.getIsMirror()) { List renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build()); for (RenewUpgradePackageFrontView renew : renewUpgradePackageFrontViews) { try { List upgradeSkuIds = Jsons.parseList(renew.getUpgradeSkuIds(), Long.class); GoodsDonSku maxPriceSku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class) .eq(GoodsDonSku::getStatus, Boolean.TRUE) .in(GoodsDonSku::getId, upgradeSkuIds) .orderByDesc(GoodsDonSku::getPrice) .last("limit 1")); BigDecimal discountMoney = maxPriceSku.getPrice().multiply(renew.getDiscount()); if (discountMoney.compareTo(maxSkuPrice) > 0) { maxSkuPrice = discountMoney; } } catch (Exception e) { } } } if (maxSkuPrice.compareTo(BigDecimal.ZERO) == 0) { if (galaxyCoinRenewTicketsView.getGoodsId() == Constant.NETFLIX_GID) { GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class) .eq(GoodsDonSku::getStatus, Boolean.TRUE) .orderByDesc(GoodsDonSku::getPrice) .last("limit 1")); if (sku != null) { maxSkuPrice = sku.getPrice(); } } else { maxSkuPrice = goodsDonSkuMapper.selectById(skuId).getPrice(); } } //此次最大可抵扣银河币数量 BigDecimal maxDeductGalaxyCoin = maxSkuPrice.multiply(maxRate).divide(payMoney).multiply(payGalaxyCoin); galaxyCoinRenewTicketsView.setMaxGalaxyCoinDeduct(userGalaxyCoin.compareTo(maxDeductGalaxyCoin) > 0 ? maxDeductGalaxyCoin : userGalaxyCoin); if (galaxyCoinRenewTicketsView.getExpiryTime() != null && galaxyCoinRenewTicketsView.getGoodsType() == 1) { String remainDays = DateUtil.formatBetween(now, galaxyCoinRenewTicketsView.getExpiryTime(), BetweenFormater.Level.DAY); if ("0天".equals(remainDays)) { remainDays = "小于1天"; } else { //当天也算 int days = Integer.parseInt(remainDays.substring(0, remainDays.indexOf("天"))); remainDays = days + 1 + "天"; } galaxyCoinRenewTicketsView.setRemainDays(remainDays); } } return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * 镜像车票列表 */ @GetMapping("/get/mirror/ticket") public Result> getMirrorTicket() { long userId = StpUserUtil.getLoginIdAsLong(); List list = groupRelationFrontService.getMirrorTicket(userId); return GatewayResponse.SUCCESS.newBuilder().toResult(list); } /** * 镜像车票续费升级信息 */ @GetMapping("/get/renewInfo") public Result getRenewUpgradeInfo(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); TicketRenewUpgradeView renewView = groupRelationFrontService.getRenewUpgradeInfo(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(renewView); } /** * 代充记录 */ @GetMapping("/get/recharge/record") public Result> getRechargeRecord(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); GroupsRelation relation = relationMapper.selectById(relationId); if (relation == null || !userIdList.contains(relation.getUserId())) { return GatewayResponse.SUCCESS.newBuilder().toResult(); } Date filterDate = relation.getSubmitTime(); if (filterDate == null) { filterDate = relation.getStartTime(); } List search = beanSearcher.searchAll(GptUserRechargeNumRecordView.class, MapUtils.flatBuilder(request.getParameterMap()) .field(GptUserRechargeNumRecordView::getUserId, userIdList).op(Operator.InList) .field(GptUserRechargeNumRecordView::getRelationId, relationId) .field(GptUserRechargeNumRecordView::getCreatedTime, filterDate).op(Operator.GreaterEqual) .orderBy(GptUserRechargeNumRecordView::getCreatedTime).desc() .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(search); } /** * claude code+codex 套餐情况 */ @GetMapping("/get/cc/codex/info") public Result getCcCodexInfo() { long userId = StpUserUtil.getLoginIdAsLong(); List userIdList = userBindRelationService.getRelationUserIdList(userId, null); ClaudeCodeUser claudeCodeUser = beanSearcher.searchFirst(ClaudeCodeUser.class, MapUtils.builder().field(ClaudeCodeUser::getUserId, userIdList).op(Operator.InList).build()); CodexUser codexUser = beanSearcher.searchFirst(CodexUser.class, MapUtils.builder().field(CodexUser::getUserId, userIdList).op(Operator.InList).build()); //cc codex CcCodexInfoView ccCodexInfoView = new CcCodexInfoView(); ccCodexInfoView.setClaudeCodeUser(claudeCodeUser); ccCodexInfoView.setCodexUser(codexUser); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 账号下架操作记录 */ @GetMapping("/get/account/down/logs/{accountId}") public Result> getAccountDownLogs(@PathVariable Long accountId) { GroupsTrips groupsTrips = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getAccountId, accountId).select(GroupsTrips::getId).last("limit 1")); List sysLogs = null; if (groupsTrips != null) { sysLogs = beanSearcher.searchAll(SysLog.class, MapUtils.flatBuilder(request.getParameterMap()) .field(SysLog::getModule, "过期账号/上下架过期车队") .field(SysLog::getOperateParams, groupsTrips.getId()) .onlySelect(SysLog::getOperator, SysLog::getOperateIp, SysLog::getOperateLocation, SysLog::getCreatedTime) .build()); } return GatewayResponse.SUCCESS.newBuilder().toResult(sysLogs); } /** * 查看sora邀请码 */ @GetMapping("/get/sora/code/{relationId}") public Result getSoraCode(@PathVariable Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); String soraCode = groupRelationFrontService.getSoraCode(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(soraCode); } }