GroupRelationFrontServiceImpl.java 114 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591
  1. package com.cyksj.service.relation.impl;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.collection.CollectionUtil;
  4. import cn.hutool.core.date.BetweenFormater;
  5. import cn.hutool.core.date.DateTime;
  6. import cn.hutool.core.date.DateUtil;
  7. import cn.hutool.core.lang.Assert;
  8. import cn.hutool.core.lang.Validator;
  9. import cn.hutool.core.util.ObjectUtil;
  10. import cn.hutool.core.util.StrUtil;
  11. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  12. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  13. import com.cyksj.common.constant.Constant;
  14. import com.cyksj.common.exception.BusinessRuntimeException;
  15. import com.cyksj.common.snowflake.Sequence;
  16. import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
  17. import com.cyksj.common.util.Jsons;
  18. import com.cyksj.common.util.StringUtil;
  19. import com.cyksj.enums.GatewayApiCode;
  20. import com.cyksj.mapper.*;
  21. import com.cyksj.mapper.codex.CodexUserRenewExpiryRecordMapper;
  22. import com.cyksj.mapper.manage.distribute.DistributeGeneralSkuRateMapper;
  23. import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
  24. import com.cyksj.mapper.manage.distribute.UserPlatDistributeRateMapper;
  25. import com.cyksj.mapper.manage.distribute.UserPlatSkuDistributeRateMapper;
  26. import com.cyksj.mapper.mirrorshop.UserMirrorShopMapper;
  27. import com.cyksj.mapper.renew.RenewUpgradePackageMapper;
  28. import com.cyksj.mapper.sys.SysConfigMapper;
  29. import com.cyksj.mapper.sys.SysEmailMapper;
  30. import com.cyksj.mapper.vip.VipGoodsSkuMapper;
  31. import com.cyksj.mapper.vip.VipUserMapper;
  32. import com.cyksj.model.dto.ErrorNetflixChangeOtherSkuTicketDto;
  33. import com.cyksj.model.dto.TicketChangeDto;
  34. import com.cyksj.model.entity.*;
  35. import com.cyksj.model.manage.views.AccountView;
  36. import com.cyksj.model.manage.views.GroupsRelationView;
  37. import com.cyksj.model.request.ErrorNetflixChangeReq;
  38. import com.cyksj.model.request.OrderRefundReq;
  39. import com.cyksj.model.request.SpecialGoodsTicketReq;
  40. import com.cyksj.model.request.TicketLoginReq;
  41. import com.cyksj.model.response.NetflixErrorAccountStatus;
  42. import com.cyksj.model.response.NetflixRecoverResp;
  43. import com.cyksj.model.response.NetflixRefundInfoResp;
  44. import com.cyksj.model.views.*;
  45. import com.cyksj.redis.RedisService;
  46. import com.cyksj.service.chatgpt.ChatGptAccountService;
  47. import com.cyksj.service.chatgpt.ChatGptAuthService;
  48. import com.cyksj.service.claude.ClaudeCodeService;
  49. import com.cyksj.service.claude.ClaudeService;
  50. import com.cyksj.service.codex.CodexService;
  51. import com.cyksj.service.groups.GroupsFuncService;
  52. import com.cyksj.service.luma.LumaService;
  53. import com.cyksj.service.mail.CommonMailService;
  54. import com.cyksj.service.mail.MailService;
  55. import com.cyksj.service.mange.coupon.CouponCommonService;
  56. import com.cyksj.service.midjourney.MidjourneyAccountService;
  57. import com.cyksj.service.order.OrderRefundService;
  58. import com.cyksj.service.relation.GroupRelationClearService;
  59. import com.cyksj.service.relation.GroupRelationFrontService;
  60. import com.cyksj.service.relation.GroupsRelationChangeService;
  61. import com.cyksj.service.sora.SoraCodeFrontService;
  62. import com.cyksj.service.translations.BackInfoTranslationsFrontService;
  63. import com.cyksj.service.user.UserBenefitsService;
  64. import com.cyksj.service.user.UserBindRelationService;
  65. import com.cyksj.service.user.UserLoginRecordService;
  66. import com.ejlchina.searcher.BeanSearcher;
  67. import com.ejlchina.searcher.SearchResult;
  68. import com.ejlchina.searcher.param.Operator;
  69. import com.ejlchina.searcher.util.MapBuilder;
  70. import com.ejlchina.searcher.util.MapUtils;
  71. import com.github.rholder.retry.*;
  72. import lombok.RequiredArgsConstructor;
  73. import lombok.extern.slf4j.Slf4j;
  74. import org.springframework.dao.DuplicateKeyException;
  75. import org.springframework.stereotype.Service;
  76. import org.springframework.transaction.annotation.Transactional;
  77. import javax.servlet.http.HttpServletRequest;
  78. import java.math.BigDecimal;
  79. import java.math.RoundingMode;
  80. import java.util.*;
  81. import java.util.concurrent.ExecutionException;
  82. import java.util.concurrent.TimeUnit;
  83. import java.util.concurrent.atomic.AtomicInteger;
  84. import java.util.stream.Collectors;
  85. import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_ALREADY_BE_USER;
  86. import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_NOT_FIND;
  87. /*
  88. *项目名: netflix
  89. *文件名: GroupRelationFrontServiceImpl
  90. *创建者: JavaZou
  91. *创建时间:2022/12/29 15:42
  92. */
  93. @Service
  94. @RequiredArgsConstructor
  95. @Slf4j
  96. public class GroupRelationFrontServiceImpl implements GroupRelationFrontService {
  97. private final UserBindRelationService userBindRelationService;
  98. private final UserMapper userMapper;
  99. private final BeanSearcher beanSearcher;
  100. private final CouponCommonService couponCommonService;
  101. private final GroupsRelationMapper groupsRelationMapper;
  102. private final GroupsMapper groupsMapper;
  103. private final ChatGptAuthService chatGptAuthService;
  104. private final RedisService redisService;
  105. private final MailService mailService;
  106. private final OrderDonMapper orderDonMapper;
  107. private final GroupsRelationExpiryNotifyRecordMapper groupsRelationExpiryNotifyRecordMapper;
  108. private final HttpServletRequest request;
  109. private final GroupsFuncService groupsFuncService;
  110. private final OrderDiscountPlusPurchaseSkuRelationMapper orderDiscountPlusPurchaseSkuRelationMapper;
  111. private final GroupsRelationLoginCodeRecordMapper groupsRelationLoginCodeRecordMapper;
  112. private final SysEmailMapper sysEmailMapper;
  113. private final GoodsDonSkuMapper goodsDonSkuMapper;
  114. private final UserFuncPropertyMapper userFuncPropertyMapper;
  115. private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
  116. private final UserLoginRecordService userLoginRecordService;
  117. private final UserCertRecordMapper userCertRecordMapper;
  118. private final MidjourneyAccountService midjourneyAccountService;
  119. private final ChatGptAccountService chatGptAccountService;
  120. private final UpgradePackageMapper upgradePackageMapper;
  121. private final LumaService lumaService;
  122. private final BackInfoTranslationsFrontService backInfoTranslationsFrontService;
  123. private final UserDistributeMapper userDistributeMapper;
  124. private final UserPlatDistributeRateMapper userPlatDistributeRateMapper;
  125. private final GoodsDonMapper goodsDonMapper;
  126. private final UserPlatSkuDistributeRateMapper userPlatSkuDistributeRateMapper;
  127. private final DistributeGeneralSkuRateMapper distributeGeneralSkuRateMapper;
  128. private final RenewUpgradePackageMapper renewUpgradePackageMapper;
  129. private final ClaudeService claudeService;
  130. private final UserDistributePosterRecordMapper userDistributePosterRecordMapper;
  131. private final OrderDonRenewRecordMapper orderDonRenewRecordMapper;
  132. private final AccountMapper accountMapper;
  133. private final UserBenefitsMapper userBenefitsMapper;
  134. private final GroupsRelationChangeService changeTickerRelation;
  135. private final NetflixTempAccountUserMapper netflixTempAccountUserMapper;
  136. private final NetflixUserAccountStatusRecordMapper netflixUserAccountStatusRecordMapper;
  137. private final AccountNetflixStateMapper accountNetflixStateMapper;
  138. private final UserMirrorShopMapper userMirrorShopMapper;
  139. private final CommonMailService commonMailService;
  140. private final SysConfigMapper sysConfigMapper;
  141. private final GptMirrorDayCardGiveawayActivityMapper gptMirrorDayCardGiveawayActivityMapper;
  142. private final MirrorTicketPopupsRecordMapper mirrorTicketPopupsRecordMapper;
  143. private final VipUserMapper vipUserMapper;
  144. private final VipGoodsSkuMapper vipGoodsSkuMapper;
  145. private static final Sequence SEQUENCE = new Sequence(0);
  146. private final NetflixUserChangeOtherTicketRecordMapper netflixUserChangeOtherTicketRecordMapper;
  147. private final NetflixUserAccountSubmitRecoverRecordMapper netflixUserAccountSubmitRecoverRecordMapper;
  148. private final OrderRefundService orderRefundService;
  149. private final GroupRelationClearService clearService;
  150. private final UserBenefitsService userBenefitsService;
  151. private final ChatgptUserMapper chatgptUserMapper;
  152. private final ClaudeCodeUserRenewExpiryRecordMapper claudeCodeUserRenewExpiryRecordMapper;
  153. private final GoodsDonCategoryRelateMapper goodsDonCategoryRelateMapper;
  154. private final ClaudeCodeService claudeCodeService;
  155. private final NanoUserQuotaMapper nanoUserQuotaMapper;
  156. private final CodexService codexService;
  157. private final CodexUserRenewExpiryRecordMapper codexUserRenewExpiryRecordMapper;
  158. private final CodexUserMapper codexUserMapper;
  159. private final AccountNetflixFrozenTicketReceivedRecordMapper accountNetflixFrozenTicketReceivedRecordMapper;
  160. private final SoraCodeMapper soraCodeMapper;
  161. private final SoraCodeFrontService soraCodeFrontService;
  162. @Override
  163. public SearchResult<RenewalView> getMyTicket(long userId, Boolean isLoginPopularize, String customId, String account, String orderNo, Integer cmt) {
  164. User u = userMapper.selectById(userId);
  165. if (u == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
  166. if (u.getIsBlack()) {
  167. return new SearchResult<>();
  168. }
  169. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, u);
  170. MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
  171. if (cmt != null && cmt == 2 && StrUtil.isNotBlank(customId)) {
  172. UserMirrorShop userMirrorShop = userMirrorShopMapper.selectOne(Wrappers.lambdaQuery(UserMirrorShop.class)
  173. .eq(UserMirrorShop::getCustomId, customId)
  174. .last("limit 1"));
  175. if (userMirrorShop != null) {
  176. builder.field(RenewalView::getCmt, cmt).field(RenewalView::getYhsId, userMirrorShop.getId());
  177. }
  178. }
  179. if (cmt == null || cmt != 2) {
  180. builder.field(RenewalView::getCmt, 2).op(Operator.NotEqual);
  181. }
  182. // Long yhsId = yhShopFrontService.getYhsIdByCustomId(customId);
  183. DateTime now = DateTime.now();
  184. if (StrUtil.isNotBlank(account)) {
  185. builder.field(RenewalView::getAccount, account).op(Operator.Contain);
  186. }
  187. //代充剩余次数大于0/未发车/过期时间/冻结时
  188. 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);
  189. //镜像车票 过期7天后清除
  190. //个人店铺和AI店铺 暂不支持过期续费
  191. if (cmt == null && StrUtil.isEmpty(customId)) {
  192. conditionSql += String.format(" or (sku.is_mirror and gr.expiry_time > '%s')", DateUtil.offsetDay(now, -7));
  193. }
  194. conditionSql += ")";
  195. if (StrUtil.isNotEmpty(orderNo)) {
  196. OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
  197. .eq(OrderDon::getOrderNo, orderNo)
  198. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
  199. .last("limit 1"));
  200. Long orderId = orderDon != null ? orderDon.getId() : 0l;
  201. 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);
  202. }
  203. SearchResult<RenewalView> list = beanSearcher.search(RenewalView.class, builder
  204. .field(RenewalView::getUserId, 0).op(Operator.GreaterThan)
  205. .field(RenewalView::getUserId, userIds).op(Operator.InList)
  206. .put("condition", conditionSql)
  207. .field(RenewalView::getStatus, List.of("validity", "overdue", "outside")).op(Operator.InList)
  208. .orderBy(RenewalView::getExpiryTime).asc()
  209. .build());
  210. if (list.getDataList().size() > 0) {
  211. String lang = request.getHeader("lang");
  212. //过滤邀请制、已失效的车位
  213. Integer size = list.getTotalCount().intValue();
  214. //赠送GPT日卡 参与平台ids
  215. List<Long> renewReduceSkuIds = userBenefitsMapper.selectList(Wrappers.lambdaQuery(UserBenefits.class)
  216. .eq(UserBenefits::getType, UserBenefits.Type.RENEW).eq(UserBenefits::getStatus, 1).select(UserBenefits::getSkuId)).stream().map(UserBenefits::getSkuId).collect(Collectors.toList());
  217. List<Long> gptBuyGids = getGptMirrorGiveawayBuyGids();
  218. //gpt日卡活动
  219. GptMirrorDayCardGiveawayActivity gptMirrorDayCardGiveawayActivity = gptMirrorDayCardGiveawayActivityMapper.selectOne(Wrappers.lambdaQuery(GptMirrorDayCardGiveawayActivity.class)
  220. .last("limit 1"));
  221. SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
  222. .eq(SysConfig::getSysKey, Constant.EMAIL_PWD_SHOW_GID_KEY)
  223. .last("limit 1"));
  224. List<Long> showEmailPwdGids = new ArrayList<>();
  225. if (sysConfig != null && StrUtil.isNotBlank(sysConfig.getSysValue())) {
  226. try {
  227. showEmailPwdGids.addAll(Jsons.parseList(sysConfig.getSysValue(), Long.class));
  228. } catch (Exception e) {
  229. }
  230. }
  231. List<Long> vipSkuIds = vipGoodsSkuMapper.selectList(null).stream().map(VipGoodsSku::getSkuId).collect(Collectors.toList());
  232. Set<Long> vipGoodsIds = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class)
  233. .in(GoodsDonSku::getId, vipSkuIds)).stream().map(GoodsDonSku::getGoodsId).collect(Collectors.toSet());
  234. Integer vipUserCount = vipUserMapper.selectCount(Wrappers.lambdaQuery(VipUser.class)
  235. .in(VipUser::getUserId, userIds)
  236. .gt(VipUser::getExpiryTime, now));
  237. list.getDataList().forEach(ticket -> {
  238. if (ticket.getSkuId() == null || ticket.getGoodsId() == null) {
  239. return;
  240. }
  241. if (ticket.getGoodsId() == 18 && ticket.getSkuNum() > 1) {
  242. ticket.setPassword(null);
  243. }
  244. ticket.setIsMulti(false);
  245. if (ticket.getSkuNum() > 1) {
  246. ticket.setIsMulti(true);
  247. }
  248. //分类ids
  249. ticket.setCategoryIdList(goodsDonCategoryRelateMapper.selectCategoryIdsByGid(ticket.getGoodsId()));
  250. //chatGPT直连
  251. if (ticket.getGoodsId().equals(42l)) {
  252. if (StrUtil.isNotBlank(ticket.getAccount())) {
  253. String accessToken;
  254. try {
  255. accessToken = chatGptAuthService.getAccessToken(ticket.getAccount());
  256. ticket.setGptRefreshToken(accessToken);
  257. } catch (Exception e) {
  258. redisService.set(RedisService.key.CHAT_GPT_TOKEN_EXCEPTION_KEY.getName() + ticket.getAccount(), ticket.getAccount());
  259. }
  260. }
  261. ticket.setAccount(null);
  262. ticket.setPassword(null);
  263. } else {
  264. ticket.setGptRefreshToken(null);
  265. }
  266. if (ticket.getSecondType() == 1) {
  267. ticket.setAccount(null);
  268. ticket.setPassword(null);
  269. }
  270. //gpt 2月的独立账号可看到邮箱密码
  271. if (ticket.getGoodsId() == 18l && ticket.getSkuNum() == 1 && ticket.getAccount() != null && ticket.getCreatedTime().compareTo(DateUtil.parse("2025-02-01")) > 0) {
  272. } else {
  273. if (!showEmailPwdGids.contains(ticket.getGoodsId())) {
  274. ticket.setGptEmailPwd(null);
  275. }
  276. }
  277. if (isLoginPopularize != null && isLoginPopularize) {
  278. GoodsDonViews views = beanSearcher.searchFirst(GoodsDonViews.class, MapUtils.builder().field(GoodsDonViews::getId, ticket.getGoodsId()).build());
  279. views.setSpecs(beanSearcher.searchFirst(GoodsDonSpecFrontView.class, MapUtils.builder().field(GoodsDonSpecFrontView::getGoodsId, views.getId()).build()));
  280. views.setSkuList(beanSearcher.searchAll(GoodsDonSkuFrontView.class, MapUtils.builder().field(GoodsDonSkuFrontView::getGoodsId, views.getId()).field(GoodsDonSkuFrontView::getStatus, true).build()));
  281. ticket.setGoodsDonViews(views);
  282. }
  283. if (ticket.getMonths() != null && ticket.getMonths() >= 300) {
  284. ticket.setExpiryTime(null);
  285. }
  286. if (ticket.getExpiryTime() != null && ticket.getGoodsType() == 1) {
  287. String remainDays = DateUtil.formatBetween(now, ticket.getExpiryTime(), BetweenFormater.Level.DAY);
  288. if ("0天".equals(remainDays)) {
  289. remainDays = "小于1天";
  290. } else {
  291. //当天也算
  292. int days = Integer.parseInt(remainDays.substring(0, remainDays.indexOf("天")));
  293. remainDays = days + 1 + "天";
  294. }
  295. ticket.setRemainDays(remainDays);
  296. ticket.setTotal(DateUtil.betweenDay(ticket.getStartTime(), ticket.getExpiryTime(), false) + 1);
  297. }
  298. OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
  299. .eq(OrderDon::getRelationId, ticket.getRelationId())
  300. .in(OrderDon::getUserId, userIds)
  301. .eq(OrderDon::getOrderType, 1)
  302. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
  303. .orderByDesc(OrderDon::getId)
  304. .last("limit 1"));
  305. if (orderDon != null) {
  306. ticket.setOrderNo(orderDon.getOrderNo());
  307. ticket.setOrderId(orderDon.getId());
  308. ticket.setTransactionId(orderDon.getTransactionId());
  309. ticket.setOrderCreatedTime(orderDon.getCreatedTime());
  310. if (ticket.getSecondType() == 1) {
  311. //是否完成邀请 根据订单状态
  312. ticket.setIsComplete(orderDon.getStatus() == OrderDon.Status.complete ? true : false);
  313. }
  314. }
  315. if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
  316. String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(ticket.getSkuId(), lang);
  317. if (StrUtil.isNotBlank(languageSpecVal)) {
  318. ticket.setSpecVal(languageSpecVal);
  319. }
  320. }
  321. if (size > 1 && ticket.getGoodsId() != 18) {
  322. Date payTime = null;
  323. if (orderDon != null) {
  324. payTime = Optional.ofNullable(orderDon.getPayTime()).orElse(orderDon.getCreatedTime());
  325. }
  326. //加购订单
  327. if (orderDon == null) {
  328. List<OrderDiscountPlusPurchaseSkuRelation> plusPurchaseSkuRelations = orderDiscountPlusPurchaseSkuRelationMapper.selectPlusRelationByIdAndUserId(ticket.getRelationId(), ticket.getUserId());
  329. for (OrderDiscountPlusPurchaseSkuRelation data : plusPurchaseSkuRelations) {
  330. String relationIds = data.getRelationIds();
  331. if (StrUtil.isEmpty(relationIds)) {
  332. return;
  333. }
  334. try {
  335. List<Long> relationList = Jsons.parseList(relationIds, Long.class);
  336. if (relationList.contains(ticket.getRelationId())) {
  337. OrderDon plusOrder = orderDonMapper.selectById(data.getOrderId());
  338. if (plusOrder != null) {
  339. payTime = Optional.ofNullable(plusOrder.getPayTime()).orElse(plusOrder.getCreatedTime());
  340. }
  341. break;
  342. }
  343. } catch (Exception e) {
  344. }
  345. }
  346. }
  347. ticket.setPayTime(payTime);
  348. }
  349. if (ticket.getSkuNum() != null && ticket.getSkuNum() == 1) {
  350. }
  351. //奈飞、gpt
  352. if (ticket.getGoodsId() == 1 || ticket.getGoodsId() == 18 || ticket.getGoodsId() == 33l) {
  353. ticket.setEmail(null);
  354. }
  355. //设置镜像车票信息
  356. // setMirrorTicketInfo(ticket);
  357. // List<GroupsRelationUserView> relationUserViews = groupsRelationMapper.getUserRelationUserViews(ticket.getGroupId(), ticket.getRelationId(), ticket.getUserId(), List.of(GroupsRelation.Status.validity, GroupsRelation.Status.outside));
  358. // ticket.setRelationViews(relationUserViews);
  359. if (ticket.getExpiryTime() != null) {
  360. ticket.setExpiryTimeStr(DateUtil.format(ticket.getExpiryTime(), "yyyy-MM-dd"));
  361. }
  362. //查看双重验证码
  363. if (StrUtil.isNotEmpty(ticket.getApiSecret())) {
  364. Boolean isHasVerifyCode = StrUtil.isNotBlank(ticket.getVerifyCode()) ? true : false;
  365. Integer codeNum = getUserCodeNumBySkuId(ticket.getUserId(), ticket.getSkuId(), isHasVerifyCode);
  366. ticket.setCodeNum(codeNum);
  367. }
  368. Long qaId = groupsRelationMapper.selectGoodsDonQaByGoodsId(ticket.getGoodsId());
  369. ticket.setQa(qaId > 0 ? true : false);
  370. //是否存在海报
  371. ticket.setPosterInfo(setGoodsPoster(ticket, u, userIds));
  372. //续费升级折扣
  373. BigDecimal renewDiscount = getRenewDiscount(ticket.getGoodsId(), ticket.getSkuId(), ticket.getIsMirror(), ticket.getSkuNum());
  374. ticket.setDiscount(renewDiscount);
  375. if (CollUtil.isNotEmpty(renewReduceSkuIds) && renewReduceSkuIds.contains(ticket.getSkuId())) {
  376. ticket.setIsRenewReduce(true);
  377. }
  378. if (CollUtil.isNotEmpty(gptBuyGids) && gptBuyGids.contains(ticket.getGoodsId())) {
  379. if (gptMirrorDayCardGiveawayActivity != null && orderDon != null && orderDon.getCreatedTime().compareTo(gptMirrorDayCardGiveawayActivity.getCreatedTime()) > 0) {
  380. //是否领取过GPT日卡
  381. Long orderId = orderDon.getId();
  382. Number count = beanSearcher.searchCount(GptMirrorDayCardActivityRecord.class, MapUtils.builder().field(GptMirrorDayCardActivityRecord::getOrderId, orderId).build());
  383. ticket.setReceivedGptGift(count.intValue() > 0);
  384. }
  385. }
  386. markVipDeductTicket(userIds, ticket, vipGoodsIds, vipUserCount > 0);
  387. if (ticket.getIsVipDeduct() != null && ticket.getIsVipDeduct()) {
  388. //订单不存在
  389. if (orderDon == null) {
  390. ticket.setIsVipDeduct(Boolean.FALSE);
  391. }
  392. }
  393. //codex
  394. if (ticket.getGoodsId() == Constant.CODEX_GOODS_ID) {
  395. CodexUser codexUser = codexUserMapper.selectOne(Wrappers.lambdaQuery(CodexUser.class).eq(CodexUser::getRelationId, ticket.getRelationId()).last("limit 1"));
  396. if (codexUser != null) {
  397. ticket.setIsPay(codexUser.getIsPay());
  398. }
  399. }
  400. });
  401. }
  402. userLoginRecordService.saveUserLoginDayRecord(userId);
  403. return list;
  404. }
  405. @Override
  406. public Boolean isJoinCorpWx(Long userId, Boolean isJoin, Boolean noCoupon) {
  407. if (!isJoin) {
  408. User user = userMapper.selectById(userId);
  409. if (user == null || StrUtil.isEmpty(user.getUnionid())) {
  410. return true;
  411. }
  412. // CorpUser corpUser = corpUserMapper.selectOne(Wrappers.lambdaQuery(CorpUser.class)
  413. // .ne(CorpUser::getUnionid, "")
  414. // .eq(CorpUser::getUnionid, user.getUnionid())
  415. // .last("limit 1")
  416. // .select(CorpUser::getId)
  417. // );
  418. CorpUserFollowView corpUserFollowView = beanSearcher.searchFirst(CorpUserFollowView.class, MapUtils.builder()
  419. .field(CorpUserFollowView::getUnionId, user.getUnionid())
  420. .field(CorpUserFollowView::getStatus, 1).build());
  421. if (corpUserFollowView == null) {
  422. return false;
  423. }
  424. }
  425. //用户是否买了奈飞车票
  426. Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder()
  427. .field(RenewalView::getUserId, userId)
  428. .field(RenewalView::getGoodsId, 1)
  429. .field(RenewalView::getStatus, List.of("validity", "overdue")).op(Operator.InList)
  430. .build());
  431. if (number.intValue() > 0 && !noCoupon) {
  432. couponCommonService.sendCouponToUser(userId, 34l, 0l, 0l, 0l, CouponUser.Channel.wxCorp);
  433. }
  434. return true;
  435. }
  436. @Override
  437. public GroupsRelation getSimilarExpiredGroupRelation(GoodsDonSku sku, List<Long> errorsRelationIds, String ip) {
  438. Long skuId = sku.getId();
  439. Integer days = sku.getDays();
  440. Integer months = sku.getMonths();
  441. Integer maxNum = sku.getNum();
  442. DateTime expiryTime = null;
  443. if (days != null && days > 0) {
  444. expiryTime = DateUtil.offsetDay(DateTime.now(), days);
  445. } else {
  446. expiryTime = DateUtil.offsetMonth(DateTime.now(), months);
  447. }
  448. Integer extraNum = 5;
  449. if (sku.getId() == 178l) {
  450. extraNum = 2;
  451. }
  452. maxNum += extraNum;
  453. DateTime minExpiryTime = DateUtil.offsetDay(expiryTime, -5);
  454. Long groupsId = groupsRelationMapper.selectSimilarExpiredRelation(skuId, minExpiryTime, maxNum, ip);
  455. if (groupsId == null) {
  456. log.info("暂无相似过期时间车队");
  457. return null;
  458. }
  459. GroupsRelation relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
  460. .notIn(errorsRelationIds != null && errorsRelationIds.size() > 0, GroupsRelation::getId, errorsRelationIds)
  461. .eq(GroupsRelation::getGroupsId, groupsId)
  462. .eq(GroupsRelation::getStatus, GroupsRelation.Status.none)
  463. .eq(GroupsRelation::getUserId, 0)
  464. .orderByAsc(GroupsRelation::getNum)
  465. .last("limit 1"));
  466. if (relation != null) {
  467. log.info("用户userId:{},获取相似车队的车位relationId:{}", relation.getId());
  468. }
  469. return relation;
  470. }
  471. @Override
  472. public Page<UserRecommendGoodsFrontView> getRecommendGoodsViews(List<Long> yhShopGoodsIds, Boolean isPayNf, List<Long> filter_goods_id, Boolean filterCourseGoods, Integer start, Integer limit) {
  473. return groupsRelationMapper.getRecommendGoodsViews(new Page<>(start, limit), filter_goods_id, isPayNf, filterCourseGoods, yhShopGoodsIds);
  474. }
  475. @Override
  476. @Transactional(rollbackFor = Throwable.class)
  477. public void sendCourseWare(SpecialGoodsTicketReq request) throws Exception {
  478. Long userId = request.getUserId();
  479. Long relationId = request.getRelationId();
  480. String email = request.getEmail();
  481. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  482. RenewalView relation = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder().field(RenewalView::getRelationId, relationId).build());
  483. Assert.notNull(relation, "您的车票不存在");
  484. Long relationUserId = relation.getUserId();
  485. if (!userIdList.contains(relationUserId)) {
  486. throw BusinessRuntimeException.getInstance("您的车票不存在");
  487. }
  488. if (relation.getSpecialType() != GoodsDon.SpecialType.courseware) {
  489. throw BusinessRuntimeException.getInstance("");
  490. }
  491. //是否已发送
  492. if (StrUtil.isNotBlank(relation.getGrAccount())) {
  493. throw BusinessRuntimeException.getInstance("已领取课件,请前往邮箱查看");
  494. }
  495. if (!Validator.isEmail(email)) {
  496. throw BusinessRuntimeException.getInstance("请输入正确的邮箱");
  497. }
  498. int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  499. .set(GroupsRelation::getAccount, email)
  500. .and(qr -> qr.isNull(GroupsRelation::getAccount).or().eq(GroupsRelation::getAccount, StrUtil.EMPTY))
  501. .eq(GroupsRelation::getId, relationId));
  502. if (update > 0) {
  503. orderDonMapper.update(null, Wrappers.lambdaUpdate(OrderDon.class)
  504. .set(OrderDon::getStatus, OrderDon.Status.complete)
  505. .eq(OrderDon::getRelationId, relationId)
  506. .eq(OrderDon::getUserId, userId)
  507. .eq(OrderDon::getStatus, OrderDon.Status.hasPayment));
  508. mailService.sendCoursewareByGoodsId(relation.getGoodsId(), relation.getRelationId(), relation.getUserId(), relation.getTitle(), email);
  509. }
  510. }
  511. @Override
  512. public GroupsRelation getRelation(Long payRelationId, Long userId, GoodsDonSku sku, String ip) {
  513. GroupsRelation relation = null;
  514. Integer maxNum = sku.getNum();
  515. if (payRelationId != null && payRelationId > 0) {
  516. relation = groupsRelationMapper.selectById(payRelationId);
  517. if (relation == null) {
  518. throw new BusinessRuntimeException(GROUP_INDEX_NOT_FIND.getCode(), GROUP_INDEX_NOT_FIND.getMsg());
  519. }
  520. if (relation.getUserId() != null && relation.getUserId() > 0L) {
  521. throw new BusinessRuntimeException(GROUP_INDEX_ALREADY_BE_USER.getCode(), GROUP_INDEX_ALREADY_BE_USER.getMsg());
  522. }
  523. } else {
  524. GroupsTrips groups = null;
  525. //ChatGpt Plus、Midjourney非独立规格 上车先获取硬塞座位 硬塞5个座位
  526. //主账号过期时间25天以外
  527. //23-12-06 MidJourney 不硬塞
  528. if (sku.getNum() > 1 && Constant.AI_goodsIds.get(0) == sku.getGoodsId()) {
  529. Integer extraNum = 5;
  530. if (sku.getId() == 178l || sku.getId() == 423l) {
  531. extraNum = 2;
  532. }
  533. maxNum += extraNum;
  534. DateTime time = DateUtil.offsetDay(DateUtil.beginOfDay(DateTime.now()), 25);
  535. //不塞存在该用户的车队
  536. Long groupsId = groupsRelationMapper.getOutSideGroupsTripsRelationByGoodsId(sku.getId(), time, extraNum, userId, sku.getNum(), maxNum);
  537. if (groupsId != null) {
  538. relation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
  539. .eq(GroupsRelation::getGroupsId, groupsId)
  540. .eq(GroupsRelation::getUserId, 0)
  541. .eq(GroupsRelation::getStatus, GroupsRelation.Status.outside)
  542. .last("limit 1"));
  543. if (relation == null) {
  544. relation = new GroupsRelation();
  545. relation.setStatus(GroupsRelation.Status.outside);
  546. relation.setGroupsId(groupsId);
  547. GroupsRelation maxNumRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getGroupsId, groupsId).orderByDesc(GroupsRelation::getNum).last("limit 1"));
  548. Integer nextNum = maxNumRelation.getNum() + 1;
  549. if (redisService.setNx(RedisService.key.GROUPS_TRIPS_OUTSIDE_RELATION.getNameFormat(groupsId, nextNum), nextNum, RedisService.key.GROUPS_TRIPS_OUTSIDE_RELATION.getTimeout())) {
  550. relation.setNum(nextNum);
  551. groupsRelationMapper.insert(relation);
  552. } else {
  553. throw BusinessRuntimeException.getInstance("系统繁忙,请重试...");
  554. }
  555. }
  556. groups = groupsMapper.selectById(groupsId);
  557. }
  558. }
  559. if (groups == null) {
  560. //寻找差不多过期时间规格的车位
  561. relation = getSimilarExpiredGroupRelation(sku, null, ip);
  562. if (relation == null) {
  563. //TODO 如果没指定座位,等待逻辑确认
  564. DateTime filterAccountTime = null;
  565. //奈飞过滤6月23号之前的车队
  566. if (sku.getGoodsId() == Constant.NETFLIX_GID) {
  567. filterAccountTime = DateUtil.parse("2025-06-23");
  568. }
  569. groups = groupsMapper.selectTicketGroups(sku.getId(), GroupsTrips.Status.validity, maxNum, ip, filterAccountTime);
  570. if (groups == null) {
  571. //待发车
  572. groups = groupsMapper.selectTicketGroups(sku.getId(), GroupsTrips.Status.waiting, maxNum, ip, null);
  573. }
  574. //新增空车队
  575. if (groups == null) {
  576. relation = groupsFuncService.createNewGroupsTrips(sku);
  577. }
  578. //获取车位
  579. if (relation == null) {
  580. //寻找快满编车队进行占座
  581. relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId());
  582. if (relation == null) {
  583. Long groupsId = groups.getId();
  584. TASK_EXECUTOR.execute(() -> groupsMapper.updateAvailableNum(groupsId));
  585. throw BusinessRuntimeException.getInstance("系统繁忙,请重试...");
  586. }
  587. }
  588. }
  589. }
  590. if (groups == null) {
  591. groups = groupsMapper.selectById(relation.getGroupsId());
  592. }
  593. //车队目前可用停车数
  594. relation.setGroupsAvailParkingNum(groups.getAvailableParkingNum());
  595. relation.setMaxNum(maxNum);
  596. }
  597. return relation;
  598. }
  599. @Override
  600. public String getAiVerifyCode(TicketLoginReq loginReq) throws Exception {
  601. Integer type = loginReq.getType();
  602. RenewalView renewalView;
  603. String account;
  604. Long userId = 0l;
  605. Long relationId = 0l;
  606. if (loginReq.getMerchants()) {
  607. renewalView = new RenewalView();
  608. renewalView.setGoodsId(loginReq.getGoodsId());
  609. renewalView.setAccount(loginReq.getAccount());
  610. if (loginReq.getAccountId() != null && loginReq.getAccountId() != 0l) {
  611. GroupsTrips groupsTrips = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
  612. .eq(GroupsTrips::getAccountId, loginReq.getAccountId())
  613. .last("limit 1"));
  614. if (groupsTrips != null) {
  615. renewalView.setSkuId(groupsTrips.getSkuId());
  616. }
  617. }
  618. renewalView.setUserId(userId);
  619. account = loginReq.getAccount();
  620. } else {
  621. userId = loginReq.getUserId();
  622. relationId = loginReq.getRelationId();
  623. List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
  624. renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder().field(RenewalView::getUserId, relationUserIdList).op(Operator.InList)
  625. .field(RenewalView::getRelationId, relationId).build());
  626. if (renewalView == null) {
  627. throw BusinessRuntimeException.getInstance("您的车票不存在...");
  628. }
  629. if (StrUtil.isEmpty(renewalView.getAccount())) {
  630. throw BusinessRuntimeException.getInstance("车票未配置账号");
  631. }
  632. account = renewalView.getAccount();
  633. String password = renewalView.getPassword();
  634. if (StrUtil.hasEmpty(account, password)) {
  635. throw BusinessRuntimeException.getInstance("您的车票账号密码异常,请联系客服...");
  636. }
  637. }
  638. if (renewalView.getGoodsId() == 1l) {
  639. Integer linkType = loginReq.getLinkType();
  640. if (type == null && linkType == null) {
  641. throw BusinessRuntimeException.getInstance("系统异常");
  642. }
  643. if (linkType != null) {
  644. String key = RedisService.key.NF_UPGRAD_USER_LIMIT_KEY.getNameFormat(DateUtil.hour(DateTime.now(), true), linkType, renewalView.getUserId());
  645. if (!redisService.hasKey(key)) {
  646. redisService.set(key, 0l, RedisService.key.NF_UPGRAD_USER_LIMIT_KEY.getTimeout());
  647. } else {
  648. Integer value = (Integer) redisService.get(key);
  649. if (value >= 5) {
  650. throw BusinessRuntimeException.getInstance("获取奈飞同步更新装置过于频繁");
  651. }
  652. }
  653. }
  654. }
  655. String code = commonMailService.getTicketMailCode(renewalView.getGoodsId(), account, renewalView.getRelateEmail(), renewalView.getGptEmailPwd(), renewalView.getCreatedTime(), type, loginReq.getLinkType(), false);
  656. GroupsRelationLoginCodeRecord record = new GroupsRelationLoginCodeRecord();
  657. record.setUserId(userId);
  658. record.setRelationId(relationId);
  659. record.setAccount(renewalView.getAccount());
  660. record.setGoodsId(renewalView.getGoodsId());
  661. record.setSkuId(renewalView.getSkuId());
  662. groupsRelationLoginCodeRecordMapper.insert(record);
  663. //奈飞同步装置
  664. if (renewalView.getGoodsId() == 1l && loginReq.getLinkType() != null) {
  665. String key = RedisService.key.NF_UPGRAD_USER_LIMIT_KEY.getNameFormat(DateUtil.hour(DateTime.now(), true), loginReq.getLinkType(), renewalView.getUserId());
  666. redisService.incr(key, 1L);
  667. }
  668. return code;
  669. }
  670. @Override
  671. public void checkGroupsAvailParkingNum(Long skuId, Long groupsId, Integer availableParkingNum, Integer maxNum) {
  672. //GPT10人月付、4人月付
  673. if (skuId == 161l || skuId == 178l) {
  674. //为0时,不参与限制
  675. if (availableParkingNum == 0) {
  676. return;
  677. }
  678. //目前车队可用停车数
  679. //目前上车人数
  680. Integer currentParkingNum = groupsRelationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class)
  681. .eq(GroupsRelation::getGroupsId, groupsId)
  682. .ne(GroupsRelation::getUserId, 0)
  683. .le(GroupsRelation::getNum, maxNum));
  684. if (currentParkingNum > availableParkingNum) {
  685. throw BusinessRuntimeException.getInstance("系统繁忙,请重试...");
  686. }
  687. }
  688. }
  689. @Override
  690. public void adjustGroupsParkingTime(Long relationId, GoodsDonSku sku) {
  691. if (sku == null) {
  692. return;
  693. }
  694. Long skuId = sku.getId();
  695. //更新GPT Plus10人、4人月付车队状态 待优化
  696. if (skuId == 161l || skuId == 178l || skuId == 422l || skuId == 423l) {
  697. GroupsRelation relation = groupsRelationMapper.selectById(relationId);
  698. Long groupsId = relation.getGroupsId();
  699. GroupsTrips groupsTrips = groupsMapper.selectById(groupsId);
  700. Integer availableParkingNum = groupsTrips.getAvailableParkingNum();
  701. //为0时 不参与限制
  702. if (availableParkingNum == 0) {
  703. return;
  704. }
  705. Integer extraNum = 5;
  706. if (skuId == 178l || skuId == 423l) {
  707. extraNum = 2;
  708. }
  709. Integer maxNum = sku.getNum() + extraNum;
  710. if (availableParkingNum >= maxNum) {
  711. return;
  712. }
  713. //目前上车人数
  714. Integer currentParkingNum = groupsRelationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class)
  715. .eq(GroupsRelation::getGroupsId, groupsId)
  716. .ne(GroupsRelation::getUserId, 0)
  717. .le(GroupsRelation::getNum, maxNum));
  718. if (currentParkingNum >= availableParkingNum) {
  719. //锁住
  720. DateTime parkingTime = DateUtil.offsetDay(DateTime.now(), 1);
  721. groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class)
  722. .eq(GroupsTrips::getId, groupsTrips.getId())
  723. .set(GroupsTrips::getParkingTime, parkingTime)
  724. .isNull(GroupsTrips::getParkingTime));
  725. }
  726. }
  727. }
  728. @Override
  729. public void setGroupsTripsParkingTimeEmpty(GoodsDonSku sku, Long relationId) {
  730. if (sku == null) {
  731. return;
  732. }
  733. Long skuId = sku.getId();
  734. if (skuId == 161l || skuId == 178l) {
  735. GroupsRelation relation = groupsRelationMapper.selectById(relationId);
  736. Long groupsId = relation.getGroupsId();
  737. GroupsTrips groupsTrips = groupsMapper.selectById(groupsId);
  738. Integer availableParkingNum = groupsTrips.getAvailableParkingNum();
  739. if (groupsTrips.getParkingTime() == null || availableParkingNum == 0) {
  740. return;
  741. }
  742. Integer extraNum = 5;
  743. if (skuId == 178l) {
  744. extraNum = 2;
  745. }
  746. Integer skuNum = sku.getNum();
  747. if (availableParkingNum >= skuNum + extraNum) {
  748. return;
  749. }
  750. //目前上车人数
  751. Integer currentParkingNum = groupsRelationMapper.selectCount(Wrappers.lambdaQuery(GroupsRelation.class)
  752. .eq(GroupsRelation::getGroupsId, groupsId)
  753. .ne(GroupsRelation::getUserId, 0));
  754. if (currentParkingNum < availableParkingNum) {
  755. groupsMapper.update(null, Wrappers.lambdaUpdate(GroupsTrips.class)
  756. .eq(GroupsTrips::getId, groupsTrips.getId())
  757. .set(GroupsTrips::getParkingTime, null)
  758. .isNotNull(GroupsTrips::getParkingTime));
  759. }
  760. }
  761. }
  762. @Override
  763. public Integer getUserCodeNumBySkuId(Long userId, Long skuId, Boolean isHasVerifyCode) {
  764. //查看双重验证码
  765. UserFuncProperty userFuncProperty = userFuncPropertyMapper.selectOne(Wrappers.lambdaQuery(UserFuncProperty.class).eq(UserFuncProperty::getUserId, userId).last("limit 1"));
  766. //默认2次
  767. int num = 2;
  768. //有安全码查看次数 置为0
  769. if (isHasVerifyCode) {
  770. num = 0;
  771. //存在身份实名认证有两次机会
  772. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  773. Integer selectCount = userCertRecordMapper.selectCount(Wrappers.lambdaQuery(UserCertRecord.class)
  774. .in(UserCertRecord::getUserId, userIdList));
  775. if (selectCount > 0) {
  776. num = 2;
  777. }
  778. return num;
  779. }
  780. //查看双重验证码次数
  781. GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId);
  782. if (sku.getCodeNum() > 0) {
  783. num = sku.getCodeNum();
  784. }
  785. if (userFuncProperty != null) num = userFuncProperty.getVerifyCheckNum();
  786. return num;
  787. }
  788. @Override
  789. public List<RenewalView> getHasPayGoods(long userId) {
  790. User user = userMapper.selectById(userId);
  791. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, user);
  792. DateTime now = DateTime.now();
  793. List<RenewalView> list = groupsRelationMapper.getUserHasPayGoods(userIds, now);
  794. return list;
  795. }
  796. @Override
  797. public List<RenewalView> getExpiryRenewalNotify(Long userId) {
  798. DateTime now = DateTime.now();
  799. DateTime thisZero = DateUtil.beginOfDay(now);
  800. String thisDate = thisZero.toDateStr();
  801. Object exists = redisService.get(RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getNameFormat(thisDate, userId));
  802. if (exists != null) {
  803. return null;
  804. }
  805. User u = userMapper.selectById(userId);
  806. if (u == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
  807. if (u.getIsBlack()) {
  808. redisService.setNx(RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getNameFormat(thisDate, userId), userId, RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getTimeout());
  809. return null;
  810. }
  811. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, u);
  812. MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
  813. List<RenewalView> list = beanSearcher.searchAll(RenewalView.class, builder
  814. .field(RenewalView::getUserId, 0).op(Operator.GreaterThan)
  815. .field(RenewalView::getUserId, userIds).op(Operator.InList)
  816. .field(RenewalView::getExpiryTime, now).op(Operator.GreaterThan)
  817. .field(RenewalView::getStatus, List.of("validity", "overdue", "outside")).op(Operator.InList)
  818. .field(RenewalView::getAqType, 1)
  819. .field(RenewalView::getIsVip, Boolean.TRUE)
  820. .orderBy(RenewalView::getExpiryTime).asc()
  821. .build());
  822. if (list.size() > 5) {
  823. redisService.setNx(RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getNameFormat(thisDate, userId), userId, RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getTimeout());
  824. return null;
  825. }
  826. List<Long> renewReduceSkuIds = userBenefitsMapper.selectList(Wrappers.lambdaQuery(UserBenefits.class)
  827. .eq(UserBenefits::getType, UserBenefits.Type.RENEW).eq(UserBenefits::getStatus, 1).select(UserBenefits::getSkuId)).stream().map(UserBenefits::getSkuId).collect(Collectors.toList());
  828. //提前7天
  829. AtomicInteger day = new AtomicInteger(7);
  830. List<RenewalView> expiryTickets = list.stream().filter(ticket -> {
  831. //下架
  832. if (ticket.getGoodsStatus() == null || ticket.getSkuStatus() == null || !ticket.getGoodsStatus() || !ticket.getSkuStatus()) {
  833. return false;
  834. }
  835. Integer skuMonths = ticket.getMonths();
  836. if (skuMonths == null) {
  837. return false;
  838. }
  839. Date expiryTime = ticket.getExpiryTime();
  840. //年付 提前一个月
  841. if (skuMonths >= 12) {
  842. day.set(30);
  843. } else {
  844. day.set(7);
  845. }
  846. if (DateUtil.beginOfDay(expiryTime).compareTo(DateUtil.offsetDay(thisZero, day.get())) <= 0) {
  847. ticket.setExpiryTimeStr(DateUtil.format(ticket.getExpiryTime(), "yyyy-MM-dd"));
  848. //GPT镜像信息
  849. setGptMirrorInfo(ticket);
  850. ticket.setExpiryTime(null);
  851. if (CollUtil.isNotEmpty(renewReduceSkuIds) && renewReduceSkuIds.contains(ticket.getSkuId())) {
  852. ticket.setIsRenewReduce(true);
  853. }
  854. return true;
  855. }
  856. return false;
  857. }).collect(Collectors.toList());
  858. redisService.setNx(RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getNameFormat(thisDate, userId), userId, RedisService.key.TICKET_EXPIRY_NOTIFY_DAY.getTimeout());
  859. if (CollUtil.isNotEmpty(expiryTickets)) {
  860. groupsRelationExpiryNotifyRecordMapper.batchInsert(userId, expiryTickets);
  861. }
  862. return expiryTickets;
  863. }
  864. @Override
  865. public void getCollegeStudentUserGptTicket(Long userId) {
  866. Retryer<Boolean> build = RetryerBuilder.<Boolean>newBuilder()
  867. .retryIfException()
  868. //运行时异常重试
  869. .retryIfRuntimeException()
  870. //false重试
  871. .retryIfResult(res -> Objects.equals(res, false))
  872. //1s 间隔
  873. .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
  874. //停止策略 : 尝试请求3次
  875. .withStopStrategy(StopStrategies.stopAfterAttempt(3)).build();
  876. try {
  877. build.call(() -> {
  878. //体验规格
  879. Long gptMirrorSkuId = Constant.GPT_MIRROR_SKU_ID;
  880. GroupsTrips groups = groupsMapper.selectCollegeStudentUserGptTicket(gptMirrorSkuId);
  881. if (groups == null) {
  882. groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
  883. .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting)
  884. .eq(GroupsTrips::getSkuId, gptMirrorSkuId)
  885. .last("limit 1"));
  886. }
  887. GroupsRelation relation = null;
  888. if (groups != null) {
  889. relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId());
  890. }
  891. if (relation == null) {
  892. //生成空车队
  893. GoodsDonSku sku = goodsDonSkuMapper.selectById(gptMirrorSkuId);
  894. relation = groupsFuncService.createNewGroupsTrips(sku);
  895. }
  896. DateTime startTime = DateTime.now();
  897. DateTime expiryTime = DateUtil.offsetDay(startTime, 1);
  898. int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  899. .set(GroupsRelation::getUserId, userId)
  900. .set(GroupsRelation::getStartTime, startTime)
  901. .set(GroupsRelation::getExpiryTime, expiryTime)
  902. .set(GroupsRelation::getStatus, GroupsRelation.Status.validity)
  903. .set(GroupsRelation::getAqType, 2)
  904. .eq(GroupsRelation::getId, relation.getId())
  905. .eq(GroupsRelation::getUserId, 0));
  906. if (update > 0) {
  907. groupsMapper.decrAvailableNum(relation.getGroupsId());
  908. return true;
  909. }
  910. log.error("发送用户:{} GPT镜像车票体验失败,进行重试", userId);
  911. return false;
  912. });
  913. } catch (ExecutionException | RetryException e) {
  914. log.error("发送用户GPT镜像体验失败:{}", StringUtil.getErrorText(e));
  915. }
  916. }
  917. @Override
  918. public RenewalView getTicketDetail(long userId, Long relationId) {
  919. User u = userMapper.selectById(userId);
  920. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, u);
  921. MapBuilder builder = MapUtils.builder();
  922. RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, builder
  923. .field(RenewalView::getRelationId, relationId)
  924. .field(RenewalView::getUserId, 0).op(Operator.GreaterThan)
  925. .field(RenewalView::getUserId, userIds).op(Operator.InList)
  926. .field("condition", String.format("(gr.expiry_time is null or gr.expiry_time > '%s')", DateTime.now()))
  927. .field(RenewalView::getStatus, List.of("validity", "outside")).op(Operator.InList)
  928. .orderBy(RenewalView::getExpiryTime).asc()
  929. .onlySelect(RenewalView::getRelationId, RenewalView::getExpiryTime, RenewalView::getTitle, RenewalView::getSpecVal, RenewalView::getGoodsId, RenewalView::getSkuId, RenewalView::getSkuNum, RenewalView::getSkuStatus, RenewalView::getGoodsStatus)
  930. .build());
  931. if (renewalView != null) {
  932. renewalView.setExpiryTimeStr(DateUtil.format(renewalView.getExpiryTime(), "yyyy-MM-dd"));
  933. }
  934. return renewalView;
  935. }
  936. @Override
  937. public GroupsRelation ticketLogin(TicketLoginReq loginReq) {
  938. String account = loginReq.getAccount();
  939. if (StrUtil.isEmpty(account)) {
  940. throw BusinessRuntimeException.getInstance("请输入对应账号");
  941. }
  942. if (loginReq.getMerchants()) {
  943. if (account.contains(Constant.YH_EMAIL_DOMAIN_SUFFIX)) {
  944. SysEmail sysEmail = sysEmailMapper.selectOne(Wrappers.lambdaQuery(SysEmail.class)
  945. .eq(SysEmail::getEmail, account)
  946. .last("limit 1"));
  947. if (sysEmail == null) {
  948. throw BusinessRuntimeException.getInstance("账号错误,请联系客服");
  949. }
  950. }
  951. GroupsRelation relation = new GroupsRelation();
  952. relation.setId(0l);
  953. return relation;
  954. }
  955. String password = loginReq.getPassword();
  956. Integer num = loginReq.getNum();
  957. if (ObjectUtil.hasEmpty(password, num)) {
  958. throw BusinessRuntimeException.getInstance("参数错误");
  959. }
  960. Long goodsId = Optional.ofNullable(loginReq.getGoodsId()).orElse(1l);
  961. GroupsRelation relation = groupsRelationMapper.selectRelationByAccountAndNum(account, password, goodsId, num);
  962. if (relation == null) {
  963. log.info("外部入口使用账号account:{},pwd:{},座位num:{}登录失败...", account, password, num);
  964. if (StrUtil.equals(loginReq.getLang(), Constant.EN_US)) {
  965. throw BusinessRuntimeException.getInstance("Please enter the correct account information");
  966. }
  967. throw BusinessRuntimeException.getInstance("请输入正确的账号信息");
  968. }
  969. return relation;
  970. }
  971. @Override
  972. public String outsideTicketVerify(TicketLoginReq loginReq) {
  973. String account = loginReq.getAccount();
  974. if (StrUtil.isEmpty(account)) {
  975. throw BusinessRuntimeException.getInstance("账号错误");
  976. }
  977. if (loginReq.getMerchants()) {
  978. if (account.contains(Constant.YH_EMAIL_DOMAIN_SUFFIX)) {
  979. SysEmail sysEmail = sysEmailMapper.selectOne(Wrappers.lambdaQuery(SysEmail.class)
  980. .eq(SysEmail::getEmail, account)
  981. .last("limit 1"));
  982. if (sysEmail == null) {
  983. throw BusinessRuntimeException.getInstance("账号错误,请联系客服");
  984. }
  985. }
  986. loginReq.setGoodsId(1l);
  987. loginReq.setAccountId(0l);
  988. } else {
  989. String password = loginReq.getPassword();
  990. Integer num = loginReq.getNum();
  991. if (ObjectUtil.hasEmpty(password, num)) {
  992. throw BusinessRuntimeException.getInstance("参数错误");
  993. }
  994. Long goodsId = Optional.ofNullable(loginReq.getGoodsId()).orElse(1l);
  995. GroupsRelation relation = groupsRelationMapper.selectRelationByAccountAndNum(account, password, goodsId, num);
  996. if (relation == null) {
  997. log.info("外部入口使用账号account:{},pwd:{},座位num:{}同步验证链接失败...", account, password, num);
  998. if (StrUtil.equals(loginReq.getLang(), Constant.EN_US)) {
  999. throw BusinessRuntimeException.getInstance("This account is no longer valid");
  1000. }
  1001. throw BusinessRuntimeException.getInstance("该账号已失效");
  1002. }
  1003. loginReq.setUserId(relation.getUserId());
  1004. loginReq.setRelationId(relation.getId());
  1005. loginReq.setGoodsId(goodsId);
  1006. }
  1007. try {
  1008. String aiVerifyCode = getAiVerifyCode(loginReq);
  1009. if (StrUtil.isEmpty(aiVerifyCode)) {
  1010. throw BusinessRuntimeException.getInstance("");
  1011. }
  1012. return aiVerifyCode;
  1013. } catch (Exception e) {
  1014. if (StrUtil.equals(loginReq.getLang(), Constant.EN_US)) {
  1015. throw BusinessRuntimeException.getInstance("Please verify that the link was sent");
  1016. }
  1017. throw BusinessRuntimeException.getInstance("请校验链接是否已发送");
  1018. }
  1019. }
  1020. @Override
  1021. public String getNfHouseholdDevice(long userId, Long relationId) throws Exception {
  1022. List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1023. RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder().field(RenewalView::getUserId, relationUserIdList).op(Operator.InList)
  1024. .field(RenewalView::getRelationId, relationId).build());
  1025. if (renewalView == null) {
  1026. throw BusinessRuntimeException.getInstance("您的车票不存在...");
  1027. }
  1028. if (StrUtil.isEmpty(renewalView.getAccount())) {
  1029. throw BusinessRuntimeException.getInstance("车票未配置账号");
  1030. }
  1031. String account = renewalView.getAccount();
  1032. String password = renewalView.getPassword();
  1033. if (StrUtil.hasEmpty(account, password)) {
  1034. throw BusinessRuntimeException.getInstance("您的车票账号密码异常,请联系客服...");
  1035. }
  1036. String code = commonMailService.getTicketMailCode(renewalView.getGoodsId(), account, renewalView.getRelateEmail(), renewalView.getGptEmailPwd(), renewalView.getCreatedTime(), null, 1, true);
  1037. return code;
  1038. }
  1039. @Override
  1040. public String getVerifyCode(String account) throws Exception {
  1041. Account at = accountMapper.selectOne(Wrappers.lambdaQuery(Account.class)
  1042. .eq(Account::getAccount, account)
  1043. .eq(Account::getGoodsId, 18));
  1044. if (at == null) {
  1045. return null;
  1046. }
  1047. String password = at.getPassword();
  1048. if (StrUtil.hasEmpty(account, password)) {
  1049. throw BusinessRuntimeException.getInstance("账号异常");
  1050. }
  1051. String code = commonMailService.getTicketMailCode(at.getGoodsId(), account, at.getRelateEmail(), at.getGptEmailPwd(), at.getCreatedTime(), null, null, false);
  1052. return code;
  1053. }
  1054. @Override
  1055. public void changeTicket(long userId, Long relationId) {
  1056. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1057. RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder()
  1058. .field(RenewalView::getUserId, userIdList).op(Operator.InList)
  1059. .field(RenewalView::getRelationId, relationId)
  1060. .field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
  1061. .build());
  1062. if (renewalView == null) {
  1063. throw BusinessRuntimeException.getInstance("车票不存在");
  1064. }
  1065. if (renewalView.getGoodsId() != 1) {
  1066. throw BusinessRuntimeException.getInstance("只针对奈飞车票");
  1067. }
  1068. AccountNetflixState accountNetflixState = accountNetflixStateMapper.selectOne(Wrappers.lambdaQuery(AccountNetflixState.class)
  1069. .eq(AccountNetflixState::getAccount, renewalView.getAccount())
  1070. .orderByDesc(AccountNetflixState::getId)
  1071. .last("limit 1"));
  1072. if (accountNetflixState == null || accountNetflixState.getState() != 3) {
  1073. throw BusinessRuntimeException.getInstance("只支持异常账号更换车票");
  1074. }
  1075. String key = RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getName() + relationId;
  1076. if (!redisService.setNx(key, relationId, RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getTimeout())) {
  1077. throw BusinessRuntimeException.getInstance("正在更换车票中..");
  1078. }
  1079. Long groupId = renewalView.getGroupId();
  1080. Long skuId = renewalView.getSkuId();
  1081. Date expiryTime = renewalView.getExpiryTime();
  1082. //随机选择同规格得车票
  1083. Long item_groupsId = groupsMapper.selectRandomGroupsTripsBySkuId(groupId, skuId, expiryTime);
  1084. GroupsRelation newRelation = null;
  1085. if (item_groupsId != null) {
  1086. //存在就随机分配一个,没有就不做处理
  1087. newRelation = changeTickerRelation.changeTicket(renewalView.getUserId(), relationId, item_groupsId, renewalView.getSkuId());
  1088. }
  1089. //若无移至空车队
  1090. if (newRelation == null) {
  1091. newRelation = changeTickerRelation.getEmptyGroupsRelation(renewalView.getUserId(), renewalView.getRelationId(), renewalView.getSkuId());
  1092. }
  1093. if (newRelation == null) {
  1094. throw BusinessRuntimeException.getInstance("更换异常,请重新提交");
  1095. }
  1096. NetflixUserAccountStatusRecord netflixUserAccountStatusRecord = netflixUserAccountStatusRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class)
  1097. .eq(NetflixUserAccountStatusRecord::getRelationId, relationId)
  1098. .last("limit 1"));
  1099. if (netflixUserAccountStatusRecord != null) {
  1100. netflixUserAccountStatusRecord.setDeleted(false);
  1101. netflixUserAccountStatusRecordMapper.updateById(netflixUserAccountStatusRecord);
  1102. }
  1103. redisService.del(key);
  1104. }
  1105. @Override
  1106. public AccountView getTempAccount(long userId, Long relationId) {
  1107. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1108. RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder()
  1109. .field(RenewalView::getRelationId, relationId)
  1110. .field(RenewalView::getUserId, userIdList).op(Operator.InList)
  1111. .field(RenewalView::getGroupsStatus, GroupsTrips.Status.waiting.name())
  1112. .field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
  1113. .build());
  1114. if (renewalView == null) {
  1115. throw BusinessRuntimeException.getInstance("车票不存在");
  1116. }
  1117. AccountView accountView = new AccountView();
  1118. //奈飞超过3帐车票不给看
  1119. Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder()
  1120. .field(RenewalView::getUserId, userIdList).op(Operator.InList)
  1121. .field(RenewalView::getGoodsId, 1)
  1122. .field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
  1123. .build());
  1124. if (number.intValue() > 2) {
  1125. return accountView;
  1126. }
  1127. NetflixTempAccountUser netflixTempAccountUser = netflixTempAccountUserMapper.selectOne(Wrappers.lambdaQuery(NetflixTempAccountUser.class)
  1128. .eq(NetflixTempAccountUser::getRelationId, relationId)
  1129. .in(NetflixTempAccountUser::getUserId, userIdList)
  1130. .last("limit 1"));
  1131. Account account;
  1132. if (netflixTempAccountUser == null) {
  1133. account = accountMapper.selectNetflixTempAccount();
  1134. if (account != null) {
  1135. netflixTempAccountUser = new NetflixTempAccountUser();
  1136. netflixTempAccountUser.setAccountId(account.getId());
  1137. netflixTempAccountUser.setRelationId(relationId);
  1138. netflixTempAccountUser.setUserId(renewalView.getUserId());
  1139. netflixTempAccountUserMapper.insert(netflixTempAccountUser);
  1140. }
  1141. } else {
  1142. account = accountMapper.selectById(netflixTempAccountUser.getAccountId());
  1143. }
  1144. if (account != null) {
  1145. accountView.setAccount(account.getAccount());
  1146. accountView.setPassword(account.getPassword());
  1147. }
  1148. return accountView;
  1149. }
  1150. @Override
  1151. public void nfErrorAccountSubmit(long userId, Long relationId) {
  1152. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1153. RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder()
  1154. .field(RenewalView::getUserId, userIdList).op(Operator.InList)
  1155. .field(RenewalView::getRelationId, relationId)
  1156. .field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan).build());
  1157. if (renewalView == null) {
  1158. throw BusinessRuntimeException.getInstance("车票不存在");
  1159. }
  1160. if (renewalView.getGoodsId() != 1) {
  1161. throw BusinessRuntimeException.getInstance("只支持奈飞车票");
  1162. }
  1163. String account = renewalView.getAccount();
  1164. String password = renewalView.getPassword();
  1165. Integer selectCount = netflixUserAccountStatusRecordMapper.selectCount(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class)
  1166. .eq(NetflixUserAccountStatusRecord::getRelationId, relationId)
  1167. .in(NetflixUserAccountStatusRecord::getUserId, userIdList)
  1168. .eq(NetflixUserAccountStatusRecord::getAccount, account)
  1169. .eq(NetflixUserAccountStatusRecord::getState, 0)
  1170. .eq(NetflixUserAccountStatusRecord::getDeleted, 1));
  1171. if (selectCount > 0) {
  1172. throw BusinessRuntimeException.getInstance("该账号正在检测中");
  1173. }
  1174. AccountNetflixState accountNetflixState = accountNetflixStateMapper.selectOne(Wrappers.lambdaQuery(AccountNetflixState.class)
  1175. .eq(AccountNetflixState::getAccount, account)
  1176. .last("limit 1"));
  1177. Integer state = 0;
  1178. if (accountNetflixState != null && accountNetflixState.getState() == 3) {
  1179. state = accountNetflixState.getState();
  1180. }
  1181. //非正常状态
  1182. if (state != 1) {
  1183. //20号之前得校验 直接失败
  1184. if (renewalView.getCreatedTime().compareTo(DateUtil.parse("2025-06-20")) < 0) {
  1185. state = 3;
  1186. }
  1187. //如果账号下架了 直接失败
  1188. if (StrUtil.equals(GroupsTrips.Status.down.name(), renewalView.getGroupsStatus()) && renewalView.getSkuNum() > 1) {
  1189. state = 3;
  1190. }
  1191. }
  1192. NetflixUserAccountStatusRecord netflixUserAccountStatusRecord = new NetflixUserAccountStatusRecord();
  1193. netflixUserAccountStatusRecord.setAccount(account);
  1194. netflixUserAccountStatusRecord.setRelationId(relationId);
  1195. netflixUserAccountStatusRecord.setPassword(password);
  1196. netflixUserAccountStatusRecord.setUserId(renewalView.getUserId());
  1197. netflixUserAccountStatusRecord.setState(state);
  1198. OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
  1199. .eq(OrderDon::getRelationId, renewalView.getRelationId())
  1200. .in(OrderDon::getUserId, userIdList)
  1201. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
  1202. .orderByDesc(OrderDon::getId)
  1203. .last("limit 1"));
  1204. if (orderDon != null) {
  1205. netflixUserAccountStatusRecord.setOrderId(orderDon.getId());
  1206. }
  1207. netflixUserAccountStatusRecordMapper.insert(netflixUserAccountStatusRecord);
  1208. }
  1209. @Override
  1210. public NetflixErrorAccountStatus getNetflixErrorAccountStatus(long userId, Long relationId) {
  1211. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1212. NetflixUserAccountStatusRecord netflixUseAccountStatusRecord = netflixUserAccountStatusRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class)
  1213. .eq(NetflixUserAccountStatusRecord::getRelationId, relationId)
  1214. .eq(NetflixUserAccountStatusRecord::getDeleted, 1)
  1215. .in(NetflixUserAccountStatusRecord::getUserId, userIdList)
  1216. .orderByDesc(NetflixUserAccountStatusRecord::getId)
  1217. .last("limit 1"));
  1218. NetflixErrorAccountStatus status = new NetflixErrorAccountStatus();
  1219. if (netflixUseAccountStatusRecord == null) {
  1220. //是否已经更换
  1221. NetflixUserAccountSubmitRecoverRecord replaceRecover = netflixUserAccountSubmitRecoverRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class)
  1222. .eq(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList)
  1223. .eq(NetflixUserAccountSubmitRecoverRecord::getReplaceRelationId, relationId)
  1224. .last("limit 1"));
  1225. if (replaceRecover != null) {
  1226. status.setRecoverStatus(replaceRecover.getStatus());
  1227. }
  1228. return status;
  1229. }
  1230. Integer state = netflixUseAccountStatusRecord.getState();
  1231. //2是登录失败 3是被封号
  1232. // if (state == 3) {
  1233. // if (netflixUseAccountStatusRecord.getCreatedTime().compareTo(DateUtil.offsetMinute(DateTime.now(), -10)) > 0) {
  1234. // state = 0;
  1235. // }
  1236. // }
  1237. //登录失败 可继续申请检测
  1238. if (state == 2) {
  1239. return status;
  1240. }
  1241. //未异常
  1242. if (state != 3) {
  1243. //车队是否已下架
  1244. GroupsRelation relation = groupsRelationMapper.selectById(relationId);
  1245. GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
  1246. if (groupsTrips != null && groupsTrips.getStatus() == GroupsTrips.Status.down) {
  1247. state = 3;
  1248. //下架 异常
  1249. if (netflixUseAccountStatusRecord != null) {
  1250. netflixUseAccountStatusRecord.setState(state);
  1251. netflixUserAccountStatusRecordMapper.updateById(netflixUseAccountStatusRecord);
  1252. }
  1253. }
  1254. }
  1255. //账号检测状态
  1256. status.setNfStatus(state);
  1257. NetflixUserAccountSubmitRecoverRecord recoverRecord = netflixUserAccountSubmitRecoverRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class)
  1258. .in(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList)
  1259. .eq(NetflixUserAccountSubmitRecoverRecord::getRelationId, relationId)
  1260. .last("limit 1"));
  1261. if (recoverRecord != null) {
  1262. //申请恢复状态
  1263. status.setRecoverStatus(recoverRecord.getStatus());
  1264. status.setSubmitTime(recoverRecord.getCreatedTime());
  1265. }
  1266. return status;
  1267. }
  1268. @Override
  1269. public List<NetflixUserAccountStatusRecord> getUserNetflixSubmitRecord(long userId) {
  1270. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1271. List<NetflixUserAccountStatusRecord> netflixUseAccountStatusRecords = netflixUserAccountStatusRecordMapper.selectList(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class)
  1272. .in(NetflixUserAccountStatusRecord::getUserId, userIdList)
  1273. .eq(NetflixUserAccountStatusRecord::getDeleted, 1)
  1274. .select(NetflixUserAccountStatusRecord::getOrderId, NetflixUserAccountStatusRecord::getRelationId, NetflixUserAccountStatusRecord::getState, NetflixUserAccountStatusRecord::getCreatedTime));
  1275. return netflixUseAccountStatusRecords;
  1276. }
  1277. @Override
  1278. public Long getTrialTicketByUserIdAndGoodsId(Long userId, Long trialSkuId, Integer ticketType) {
  1279. Retryer<Long> build = RetryerBuilder.<Long>newBuilder()
  1280. .retryIfException()
  1281. //运行时异常重试
  1282. .retryIfRuntimeException()
  1283. //false重试
  1284. .retryIfResult(res -> res == null)
  1285. //1s 间隔
  1286. .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
  1287. //停止策略 : 尝试请求3次
  1288. .withStopStrategy(StopStrategies.stopAfterAttempt(3)).build();
  1289. try {
  1290. return build.call(() -> {
  1291. //体验规格
  1292. GroupsTrips groups = groupsMapper.selectCollegeStudentUserGptTicket(trialSkuId);
  1293. GroupsRelation relation = null;
  1294. if (groups == null) {
  1295. groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
  1296. .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting)
  1297. .eq(GroupsTrips::getSkuId, trialSkuId)
  1298. .last("limit 1"));
  1299. }
  1300. if (groups != null) {
  1301. relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId());
  1302. }
  1303. if (relation == null) {
  1304. //生成空车队
  1305. GoodsDonSku sku = goodsDonSkuMapper.selectById(trialSkuId);
  1306. relation = groupsFuncService.createNewGroupsTrips(sku);
  1307. }
  1308. DateTime startTime = DateTime.now();
  1309. DateTime expiryTime = DateUtil.offsetDay(startTime, 1);
  1310. int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  1311. .set(GroupsRelation::getUserId, userId)
  1312. .set(GroupsRelation::getStartTime, startTime)
  1313. .set(GroupsRelation::getExpiryTime, expiryTime)
  1314. .set(GroupsRelation::getStatus, GroupsRelation.Status.validity)
  1315. .set(GroupsRelation::getAqType, ticketType)
  1316. .eq(GroupsRelation::getId, relation.getId())
  1317. .eq(GroupsRelation::getUserId, 0));
  1318. if (update > 0) {
  1319. groupsMapper.decrAvailableNum(relation.getGroupsId());
  1320. return relation.getId();
  1321. }
  1322. log.error("发送用户:{} GPT镜像车票体验失败,进行重试", userId);
  1323. return null;
  1324. });
  1325. } catch (ExecutionException | RetryException e) {
  1326. log.error("发送用户GPT镜像体验失败:{}", StringUtil.getErrorText(e));
  1327. return null;
  1328. }
  1329. }
  1330. @Override
  1331. public Boolean getMirrorPopups(long userId) {
  1332. //是否弹窗 默认否
  1333. Boolean flag = false;
  1334. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1335. Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder()
  1336. .field(RenewalView::getUserId, userIdList).op(Operator.InList)
  1337. .field(RenewalView::getStatus, GroupsRelation.Status.validity.name())
  1338. .field(RenewalView::getIsMirror, true)
  1339. .build());
  1340. if (number.intValue() == 0) {
  1341. flag = true;
  1342. }
  1343. if (!flag) {
  1344. String thisWeekBegin = DateUtil.beginOfWeek(DateTime.now()).toDateStr();
  1345. Integer selectCount = mirrorTicketPopupsRecordMapper.selectCount(Wrappers.lambdaQuery(MirrorTicketPopupsRecord.class)
  1346. .in(MirrorTicketPopupsRecord::getUserId, userIdList)
  1347. .eq(MirrorTicketPopupsRecord::getThisWeek, thisWeekBegin));
  1348. if (selectCount == 0) {
  1349. MirrorTicketPopupsRecord mirrorTicketPopupsRecord = new MirrorTicketPopupsRecord();
  1350. mirrorTicketPopupsRecord.setThisWeek(thisWeekBegin);
  1351. mirrorTicketPopupsRecord.setUserId(userId);
  1352. mirrorTicketPopupsRecordMapper.insert(mirrorTicketPopupsRecord);
  1353. } else {
  1354. flag = true;
  1355. }
  1356. }
  1357. return flag;
  1358. }
  1359. @Override
  1360. public Long getTicket(Long userId, Long skuId, Boolean isVip) {
  1361. Retryer<Long> build = RetryerBuilder.<Long>newBuilder()
  1362. .retryIfException()
  1363. //运行时异常重试
  1364. .retryIfRuntimeException()
  1365. //false重试
  1366. .retryIfResult(res -> res == null)
  1367. //1s 间隔
  1368. .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
  1369. //停止策略 : 尝试请求1次
  1370. .withStopStrategy(StopStrategies.stopAfterAttempt(1)).build();
  1371. try {
  1372. return build.call(() -> {
  1373. GroupsTrips groups = groupsMapper.selectCollegeStudentUserGptTicket(skuId);
  1374. GroupsRelation relation = null;
  1375. if (groups == null) {
  1376. groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
  1377. .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting)
  1378. .eq(GroupsTrips::getSkuId, skuId)
  1379. .last("limit 1"));
  1380. }
  1381. if (groups != null) {
  1382. relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId());
  1383. }
  1384. GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId);
  1385. //生成空车队
  1386. if (relation == null) {
  1387. relation = groupsFuncService.createNewGroupsTrips(sku);
  1388. }
  1389. DateTime startTime = DateTime.now();
  1390. DateTime expiryTime;
  1391. if (sku.getDays() != null) {
  1392. expiryTime = DateUtil.offsetDay(startTime, sku.getDays());
  1393. } else {
  1394. expiryTime = DateUtil.offsetMonth(startTime, sku.getMonths());
  1395. }
  1396. int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  1397. .set(GroupsRelation::getUserId, userId)
  1398. .set(GroupsRelation::getStartTime, startTime)
  1399. .set(GroupsRelation::getExpiryTime, expiryTime)
  1400. .set(GroupsRelation::getStatus, GroupsRelation.Status.validity)
  1401. .set(GroupsRelation::getIsVip, isVip)
  1402. .eq(GroupsRelation::getId, relation.getId())
  1403. .eq(GroupsRelation::getUserId, 0));
  1404. if (update > 0) {
  1405. groupsMapper.decrAvailableNum(relation.getGroupsId());
  1406. return relation.getId();
  1407. }
  1408. log.error("发送用户:{} GPT镜像车票失败,进行重试", userId);
  1409. return null;
  1410. });
  1411. } catch (ExecutionException | RetryException e) {
  1412. log.error("发送用户GPT镜像失败:{}", StringUtil.getErrorText(e));
  1413. return null;
  1414. }
  1415. }
  1416. @Override
  1417. public Boolean getVipMirrorTicketIfEmpty(long userId, Long skuId) {
  1418. Integer selectCount = vipGoodsSkuMapper.selectCount(Wrappers.lambdaQuery(VipGoodsSku.class)
  1419. .eq(VipGoodsSku::getSkuId, skuId));
  1420. if (selectCount == 0) {
  1421. return false;
  1422. }
  1423. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1424. VipUser vipUser = vipUserMapper.selectOne(Wrappers.lambdaQuery(VipUser.class)
  1425. .in(VipUser::getUserId, userIdList)
  1426. .gt(VipUser::getExpiryTime, DateTime.now())
  1427. .last("limit 1"));
  1428. //不是会员 或已到期
  1429. if (vipUser == null) {
  1430. return false;
  1431. }
  1432. Number number = beanSearcher.searchCount(GroupsRelationView.class, MapUtils.builder()
  1433. .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
  1434. .field(GroupsRelationView::getSkuId, skuId)
  1435. .field(GroupsRelationView::getIsVip, Boolean.TRUE)
  1436. .build());
  1437. if (number.intValue() == 0) {
  1438. Long relationId = getTicket(vipUser.getUserId(), skuId, Boolean.TRUE);
  1439. //同步时间
  1440. groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  1441. .set(GroupsRelation::getExpiryTime, vipUser.getExpiryTime())
  1442. .eq(GroupsRelation::getUserId, vipUser.getUserId())
  1443. .eq(GroupsRelation::getId, relationId));
  1444. return true;
  1445. }
  1446. return false;
  1447. }
  1448. @Override
  1449. @Transactional(rollbackFor = Throwable.class)
  1450. public NetflixRecoverResp netflixSubmitRecover(ErrorNetflixChangeReq req) {
  1451. NetflixRecoverResp recoverResp = new NetflixRecoverResp();
  1452. Long relationId = req.getRelationId();
  1453. Long userId = req.getUserId();
  1454. //校验奈飞账号状态
  1455. GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId);
  1456. if (netflixRelationView.getIsFrozen()) {
  1457. int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  1458. .set(GroupsRelation::getIsFrozen, Boolean.FALSE)
  1459. .eq(GroupsRelation::getId, netflixRelationView.getId())
  1460. .eq(GroupsRelation::getIsFrozen, Boolean.TRUE));
  1461. if (update == 0) {
  1462. throw BusinessRuntimeException.getInstance("申请恢复账号失败,请重试");
  1463. }
  1464. try {
  1465. //获取同规格的车票
  1466. Long skuId = netflixRelationView.getSkuId();
  1467. GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId);
  1468. GroupsRelation relation = getRelation(null, userId, sku, null);
  1469. if (relation != null) {
  1470. Long groupsId = relation.getGroupsId();
  1471. GroupsTrips groupsTrips = groupsMapper.selectById(groupsId);
  1472. //已发车
  1473. if (groupsTrips.getStatus() == GroupsTrips.Status.validity) {
  1474. resetUserTicket(netflixRelationView, relation);
  1475. recoverResp.setIsReset(Boolean.TRUE);
  1476. return recoverResp;
  1477. }
  1478. }
  1479. } catch (Exception e) {
  1480. throw BusinessRuntimeException.getInstance("申请恢复账号失败,请重试");
  1481. }
  1482. }
  1483. Date expiryTime = netflixRelationView.getExpiryTime();
  1484. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1485. NetflixUserAccountSubmitRecoverRecord recoverRecord = netflixUserAccountSubmitRecoverRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class)
  1486. .eq(NetflixUserAccountSubmitRecoverRecord::getRelationId, relationId)
  1487. .in(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList)
  1488. .eq(NetflixUserAccountSubmitRecoverRecord::getStatus, 0)
  1489. .last("limit 1"));
  1490. if (recoverRecord == null) {
  1491. recoverRecord = new NetflixUserAccountSubmitRecoverRecord();
  1492. recoverRecord.setRelationId(relationId);
  1493. recoverRecord.setUserId(netflixRelationView.getUserId());
  1494. recoverRecord.setSkuId(netflixRelationView.getSkuId());
  1495. recoverRecord.setAccount(netflixRelationView.getAccount());
  1496. Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1;
  1497. recoverRecord.setRemainDays(betweenDay);
  1498. recoverRecord.setAccount(netflixRelationView.getTripsAccount());
  1499. try {
  1500. netflixUserAccountSubmitRecoverRecordMapper.insert(recoverRecord);
  1501. } catch (DuplicateKeyException e) {
  1502. throw BusinessRuntimeException.getInstance("您已申请恢复");
  1503. }
  1504. }
  1505. //等待位数
  1506. Integer selectCount = netflixUserAccountSubmitRecoverRecordMapper.selectCount(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class)
  1507. .lt(NetflixUserAccountSubmitRecoverRecord::getCreatedTime, recoverRecord.getCreatedTime())
  1508. .eq(NetflixUserAccountSubmitRecoverRecord::getStatus, 0));
  1509. //往前加100位
  1510. recoverResp.setIndex(100 + selectCount + 1);
  1511. recoverResp.setRemainDays(recoverRecord.getRemainDays());
  1512. return recoverResp;
  1513. }
  1514. private void resetUserTicket(GroupsRelationView oldRelation, GroupsRelation newRelation) {
  1515. Long userId = oldRelation.getUserId();
  1516. Long oldRelationId = oldRelation.getId();
  1517. //清除车票
  1518. List<Long> userIdList;
  1519. try {
  1520. userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1521. } catch (Exception e) {
  1522. userIdList = List.of(userId);
  1523. }
  1524. GroupsRelation clearRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
  1525. .eq(GroupsRelation::getId, oldRelationId)
  1526. .in(GroupsRelation::getUserId, userIdList)
  1527. .last("limit 1"));
  1528. if (clearRelation != null) {
  1529. clearRelation.setNewRelationId(newRelation.getId());
  1530. clearService.clearTicket(clearRelation, UserTicketClearedRecord.Source.ticket_replace);
  1531. }
  1532. newRelation.setUserId(userId);
  1533. //校验座位
  1534. int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  1535. .set(GroupsRelation::getUserId, userId)
  1536. .eq(GroupsRelation::getUserId, 0)
  1537. .eq(GroupsRelation::getId, newRelation.getId()));
  1538. if (update == 0) {
  1539. throw BusinessRuntimeException.getInstance("申请恢复账号失败,请重试");
  1540. }
  1541. //恢复状态
  1542. newRelation.setStartTime(oldRelation.getStartTime());
  1543. newRelation.setExpiryTime(DateUtil.offsetDay(DateTime.now(), oldRelation.getReservedDays()));
  1544. newRelation.setStatus(GroupsRelation.Status.validity);
  1545. groupsRelationMapper.updateById(newRelation);
  1546. //原订单座位id更新
  1547. OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
  1548. .in(OrderDon::getUserId, userIdList)
  1549. .eq(OrderDon::getRelationId, oldRelationId)
  1550. .notIn(OrderDon::getStatus, Constant.noOrderStatus)
  1551. .orderByDesc(OrderDon::getId)
  1552. .last("limit 1"));
  1553. if (orderDon != null) {
  1554. orderDon.setRelationId(newRelation.getId());
  1555. orderDonMapper.updateById(orderDon);
  1556. }
  1557. }
  1558. @Override
  1559. @Transactional(rollbackFor = Throwable.class)
  1560. public void errorNetflixSubmitChangeOtherTicket(ErrorNetflixChangeReq req) throws Exception {
  1561. Long relationId = req.getRelationId();
  1562. Long userId = req.getUserId();
  1563. //校验奈飞账号状态
  1564. GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId);
  1565. Date expiryTime = netflixRelationView.getExpiryTime();
  1566. //小于15 不可替换其他车票
  1567. Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1;
  1568. if (betweenDay <= 30) {
  1569. throw BusinessRuntimeException.getInstance("您的车票有效期未超过30天");
  1570. }
  1571. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1572. NetflixUserAccountSubmitRecoverRecord recoverRecord = netflixUserAccountSubmitRecoverRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class)
  1573. .eq(NetflixUserAccountSubmitRecoverRecord::getRelationId, relationId)
  1574. .in(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList)
  1575. .orderByDesc(NetflixUserAccountSubmitRecoverRecord::getId).last("limit 1"));
  1576. if (recoverRecord != null) {
  1577. if (recoverRecord.getCreatedTime().after(DateUtil.offsetDay(DateTime.now(), -1))) {
  1578. throw BusinessRuntimeException.getInstance("您的车票申请恢复中...");
  1579. }
  1580. recoverRecord.setStatus(2);
  1581. int update = netflixUserAccountSubmitRecoverRecordMapper.update(recoverRecord, Wrappers.lambdaUpdate(NetflixUserAccountSubmitRecoverRecord.class)
  1582. .eq(NetflixUserAccountSubmitRecoverRecord::getStatus, 0)
  1583. .eq(NetflixUserAccountSubmitRecoverRecord::getId, recoverRecord.getId()));
  1584. if (update == 0) {
  1585. throw BusinessRuntimeException.getInstance("系统异常,请重试");
  1586. }
  1587. }
  1588. String key = RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getName() + relationId;
  1589. if (!redisService.setNx(key, relationId, RedisService.key.NETFLIX_CHANGE_TICKET_KEY.getTimeout())) {
  1590. throw BusinessRuntimeException.getInstance("正在更换其他车票中..");
  1591. }
  1592. try {
  1593. Long skuId = req.getSkuId();
  1594. SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
  1595. .eq(SysConfig::getSysKey, Constant.ERROR_NETFLIX_CHANGE_OTHER_SKU_KEY)
  1596. .last("limit 1"));
  1597. List<ErrorNetflixChangeOtherSkuTicketDto> errorNetflixChangeOtherSkuTicketDtos = Jsons.parseList(sysConfig.getSysValue(), ErrorNetflixChangeOtherSkuTicketDto.class);
  1598. ErrorNetflixChangeOtherSkuTicketDto errorNetflixChangeOtherSkuTicketDto;
  1599. //自定义顺序 直接获取
  1600. if (betweenDay <= 60) {
  1601. //检验规格
  1602. errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(0);
  1603. } else if (betweenDay <= 120) {
  1604. errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(1);
  1605. } else {
  1606. errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(2);
  1607. }
  1608. List<Long> availableSkuIds = errorNetflixChangeOtherSkuTicketDto.getSkuIds();
  1609. if (!availableSkuIds.contains(skuId)) {
  1610. throw BusinessRuntimeException.getInstance("不支持更换该类型车票");
  1611. }
  1612. //替换车票
  1613. TicketChangeDto changeDto = getTicketAndGenerateOrder(userId, skuId, null, null);
  1614. if (changeDto == null) {
  1615. throw BusinessRuntimeException.getInstance("系统繁忙,请重试");
  1616. }
  1617. //替换记录
  1618. NetflixUserChangeOtherTicketRecord changeOtherTicketRecord = new NetflixUserChangeOtherTicketRecord();
  1619. changeOtherTicketRecord.setUserId(userId);
  1620. changeOtherTicketRecord.setRelationId(relationId);
  1621. changeOtherTicketRecord.setOtherRelationId(changeDto.getOtherRelationId());
  1622. changeOtherTicketRecord.setRelateOrderId(changeDto.getOtherOrderId());
  1623. //该车票订单id
  1624. changeOtherTicketRecord.setOrderId(netflixRelationView.getNfOriOrderId());
  1625. changeOtherTicketRecord.setStartTime(netflixRelationView.getStartTime());
  1626. changeOtherTicketRecord.setExpiryTime(expiryTime);
  1627. netflixUserChangeOtherTicketRecordMapper.insert(changeOtherTicketRecord);
  1628. if (netflixRelationView.getNfCheckId() != null) {
  1629. netflixUserAccountStatusRecordMapper.update(null, Wrappers.lambdaUpdate(NetflixUserAccountStatusRecord.class)
  1630. .set(NetflixUserAccountStatusRecord::getDeleted, false)
  1631. .eq(NetflixUserAccountStatusRecord::getId, netflixRelationView.getNfCheckId()));
  1632. }
  1633. Long ticketUserId = null;
  1634. //清除车票
  1635. GroupsRelation clearRelation = groupsRelationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
  1636. .eq(GroupsRelation::getId, relationId)
  1637. .in(GroupsRelation::getUserId, userIdList)
  1638. .last("limit 1"));
  1639. if (clearRelation != null) {
  1640. ticketUserId = clearRelation.getUserId();
  1641. clearService.clearTicket(clearRelation, UserTicketClearedRecord.Source.ticket_replace);
  1642. }
  1643. OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
  1644. .eq(OrderDon::getRelationId, relationId)
  1645. .in(OrderDon::getUserId, userIdList)
  1646. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
  1647. .orderByDesc(OrderDon::getId)
  1648. .last("limit 1"));
  1649. if (orderDon != null) {
  1650. if (ticketUserId == null) {
  1651. ticketUserId = orderDon.getUserId();
  1652. }
  1653. //替换sku
  1654. GoodsDonSku replaceSku = goodsDonSkuMapper.selectById(skuId);
  1655. GoodsDonSku oriTicketSku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
  1656. //每天单价
  1657. BigDecimal dayPrice = oriTicketSku.getPrice().divide(BigDecimal.valueOf(oriTicketSku.getMonths() * 30), RoundingMode.DOWN);
  1658. //需要退款金额
  1659. BigDecimal refundMoney = dayPrice.multiply(BigDecimal.valueOf(betweenDay));
  1660. BigDecimal balance = Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO);
  1661. BigDecimal finalOrderMoney = orderDon.getMoney().add(balance);
  1662. if (refundMoney.compareTo(finalOrderMoney) > 0) {
  1663. refundMoney = finalOrderMoney;
  1664. }
  1665. //车票价格高于替换的规格价格 退余额
  1666. if (refundMoney.compareTo(replaceSku.getPrice()) > 0) {
  1667. BigDecimal refundBalance = refundMoney.subtract(replaceSku.getPrice());
  1668. if (refundBalance.compareTo(BigDecimal.ZERO) > 0) {
  1669. userBenefitsService.addUserBalance(ticketUserId, refundBalance, UserBalanceSourceRecord.Source.TICKET_REPLACE, 0L, orderDon.getId(), UserBalanceSourceRecord.Source.TICKET_REPLACE.getDesc(), true);
  1670. }
  1671. }
  1672. }
  1673. } finally {
  1674. redisService.del(key);
  1675. }
  1676. }
  1677. @Override
  1678. public List<GoodsCategorySkuView> getNetflixReplaceOtherSkus(long userId, Long relationId) throws Exception {
  1679. //校验奈飞账号状态
  1680. GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId);
  1681. Date expiryTime = netflixRelationView.getExpiryTime();
  1682. //小于15 不可替换其他车票
  1683. Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1;
  1684. SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
  1685. .eq(SysConfig::getSysKey, Constant.ERROR_NETFLIX_CHANGE_OTHER_SKU_KEY)
  1686. .last("limit 1"));
  1687. List<ErrorNetflixChangeOtherSkuTicketDto> errorNetflixChangeOtherSkuTicketDtos = Jsons.parseList(sysConfig.getSysValue(), ErrorNetflixChangeOtherSkuTicketDto.class);
  1688. ErrorNetflixChangeOtherSkuTicketDto errorNetflixChangeOtherSkuTicketDto;
  1689. if (betweenDay <= 30) {
  1690. return null;
  1691. }
  1692. //自定义顺序 直接获取
  1693. if (betweenDay <= 60) {
  1694. //检验规格
  1695. errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(0);
  1696. } else if (betweenDay <= 120) {
  1697. errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(1);
  1698. } else {
  1699. errorNetflixChangeOtherSkuTicketDto = errorNetflixChangeOtherSkuTicketDtos.get(2);
  1700. }
  1701. List<GoodsCategorySkuView> goodsCategorySkuViews = beanSearcher.searchAll(GoodsCategorySkuView.class, MapUtils.builder()
  1702. .field(GoodsCategorySkuView::getSkuId, errorNetflixChangeOtherSkuTicketDto.getSkuIds()).op(Operator.InList)
  1703. .orderBy(GoodsCategorySkuView::getPrice).desc()
  1704. .build());
  1705. return goodsCategorySkuViews;
  1706. }
  1707. @Override
  1708. public NetflixRefundInfoResp refundNetflixInfo(Long userId, Long relationId) {
  1709. //校验奈飞账号状态
  1710. GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId);
  1711. Date expiryTime = netflixRelationView.getExpiryTime();
  1712. //小于15
  1713. Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1;
  1714. NetflixRefundInfoResp refundInfoResp = new NetflixRefundInfoResp();
  1715. refundInfoResp.setIsRefund(true);
  1716. if (betweenDay > 30) {
  1717. refundInfoResp.setIsRefund(false);
  1718. }
  1719. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1720. OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
  1721. .eq(OrderDon::getRelationId, relationId)
  1722. .in(OrderDon::getUserId, userIdList)
  1723. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
  1724. .orderByDesc(OrderDon::getId)
  1725. .last("limit 1"));
  1726. if (orderDon == null) {
  1727. refundInfoResp.setIsRefund(false);
  1728. }
  1729. Long skuId = netflixRelationView.getSkuId();
  1730. GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId);
  1731. BigDecimal orderMoney = orderDon == null ? BigDecimal.ZERO : orderDon.getMoney();
  1732. if (orderMoney.compareTo(BigDecimal.ZERO) == 0) {
  1733. refundInfoResp.setIsRefund(false);
  1734. }
  1735. //每天单价
  1736. BigDecimal dayPrice = sku.getPrice().divide(BigDecimal.valueOf(sku.getMonths() * 30), RoundingMode.DOWN);
  1737. //需要退款金额
  1738. BigDecimal refundMoney = dayPrice.multiply(BigDecimal.valueOf(betweenDay));
  1739. refundInfoResp.setPrice(refundMoney);
  1740. BigDecimal balance = orderDon == null ? BigDecimal.ZERO : Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO);
  1741. //超过本身订单金额 不允许退款
  1742. if (refundMoney.compareTo(orderMoney) > 0) {
  1743. refundInfoResp.setIsRefund(false);
  1744. }
  1745. if (refundMoney.compareTo(orderMoney.add(balance)) > 0) {
  1746. refundInfoResp.setPrice(orderMoney.add(balance));
  1747. }
  1748. refundInfoResp.setRemainDays(betweenDay);
  1749. return refundInfoResp;
  1750. }
  1751. @Override
  1752. public Boolean refundNetflix(ErrorNetflixChangeReq req) throws Exception {
  1753. Long relationId = req.getRelationId();
  1754. Long userId = req.getUserId();
  1755. //校验奈飞账号状态
  1756. GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId);
  1757. Date expiryTime = netflixRelationView.getExpiryTime();
  1758. //小于15
  1759. Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1;
  1760. if (betweenDay > 30) {
  1761. throw BusinessRuntimeException.getInstance("车票有效期不超过30天可退款");
  1762. }
  1763. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1764. OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
  1765. .eq(OrderDon::getRelationId, relationId)
  1766. .in(OrderDon::getUserId, userIdList)
  1767. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
  1768. .orderByDesc(OrderDon::getId)
  1769. .last("limit 1"));
  1770. if (orderDon == null) {
  1771. throw BusinessRuntimeException.getInstance("对应车票订单不存在,请联系客服");
  1772. }
  1773. Long skuId = netflixRelationView.getSkuId();
  1774. GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId);
  1775. BigDecimal orderMoney = orderDon.getMoney();
  1776. if (orderMoney.compareTo(BigDecimal.ZERO) == 0) {
  1777. throw BusinessRuntimeException.getInstance("不符合退款条件");
  1778. }
  1779. //每天单价
  1780. BigDecimal dayPrice = sku.getPrice().divide(BigDecimal.valueOf(sku.getMonths() * 30), RoundingMode.DOWN);
  1781. //需要退款金额
  1782. BigDecimal refundMoney = dayPrice.multiply(BigDecimal.valueOf(betweenDay));
  1783. if (refundMoney.compareTo(orderMoney) > 0) {
  1784. throw BusinessRuntimeException.getInstance("不符合退款条件");
  1785. }
  1786. //调用第三方接口退款
  1787. OrderRefundReq refundReq = new OrderRefundReq();
  1788. refundReq.setRefundMoney(refundMoney);
  1789. refundReq.setRefundType("money");
  1790. String outNo = orderRefundService.centerRefund(refundReq, orderDon);
  1791. orderDon.setStatus(OrderDon.Status.refund);
  1792. orderDon.setRefundMoney(refundMoney);
  1793. GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
  1794. orderDonMapper.updateById(orderDon);
  1795. orderRefundService.refundRecord(orderDon, refundMoney, null, "系统", goodsDon, sku, outNo, orderDon.getType().name(), null);
  1796. //清除车票
  1797. GroupsRelation relation = groupsRelationMapper.selectById(relationId);
  1798. clearService.clearTicket(relation, UserTicketClearedRecord.Source.refund);
  1799. if (netflixRelationView.getNfCheckId() != null) {
  1800. netflixUserAccountStatusRecordMapper.update(null, Wrappers.lambdaUpdate(NetflixUserAccountStatusRecord.class)
  1801. .set(NetflixUserAccountStatusRecord::getDeleted, false)
  1802. .eq(NetflixUserAccountStatusRecord::getId, netflixRelationView.getNfCheckId()));
  1803. }
  1804. return true;
  1805. }
  1806. @Override
  1807. public List<UserMirrorTicketView> getMirrorTicket(long userId) {
  1808. User u = userMapper.selectById(userId);
  1809. if (u == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
  1810. if (u.getIsBlack()) {
  1811. return null;
  1812. }
  1813. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, u);
  1814. MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
  1815. DateTime now = DateTime.now();
  1816. String lang = request.getHeader("lang");
  1817. List<UserMirrorTicketView> list = beanSearcher.searchAll(UserMirrorTicketView.class, builder
  1818. .field(UserMirrorTicketView::getUserId, userIds).op(Operator.InList)
  1819. .field(UserMirrorTicketView::getIsMirror, Boolean.TRUE)
  1820. //过期7天内的镜像车票都展示
  1821. .field(UserMirrorTicketView::getExpiryTime, DateUtil.offsetDay(now, -7)).op(Operator.GreaterThan)
  1822. .orderBy(RenewalView::getExpiryTime).asc()
  1823. .build());
  1824. list.forEach(ticket -> {
  1825. if (ticket.getExpiryTime() != null) {
  1826. String remainDays = DateUtil.formatBetween(now, ticket.getExpiryTime(), BetweenFormater.Level.DAY);
  1827. if ("0天".equals(remainDays)) {
  1828. remainDays = "小于1天";
  1829. } else {
  1830. //当天也算
  1831. int days = Integer.parseInt(remainDays.substring(0, remainDays.indexOf("天")));
  1832. remainDays = days + 1 + "天";
  1833. }
  1834. ticket.setRemainDays(remainDays);
  1835. ticket.setTotal(DateUtil.betweenDay(ticket.getStartTime(), ticket.getExpiryTime(), false) + 1);
  1836. }
  1837. if (ticket.getExpiryTime() != null) {
  1838. ticket.setExpiryTimeStr(DateUtil.format(ticket.getExpiryTime(), "yyyy-MM-dd"));
  1839. }
  1840. //续费升级折扣
  1841. BigDecimal renewDiscount = getRenewDiscount(ticket.getGoodsId(), ticket.getSkuId(), ticket.getIsMirror(), ticket.getSkuNum());
  1842. ticket.setDiscount(renewDiscount);
  1843. setAIZoneMirrorTicketInfo(ticket);
  1844. if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
  1845. String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(ticket.getSkuId(), lang);
  1846. if (StrUtil.isNotBlank(languageSpecVal)) {
  1847. ticket.setSpecVal(languageSpecVal);
  1848. }
  1849. }
  1850. OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
  1851. .eq(OrderDon::getRelationId, ticket.getRelationId())
  1852. .eq(OrderDon::getUserId, ticket.getUserId())
  1853. .eq(OrderDon::getOrderType, 1)
  1854. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
  1855. .orderByDesc(OrderDon::getId)
  1856. .last("limit 1"));
  1857. if (orderDon != null) {
  1858. ticket.setOrderId(orderDon.getId());
  1859. }
  1860. });
  1861. userLoginRecordService.saveUserLoginDayRecord(userId);
  1862. return list;
  1863. }
  1864. @Override
  1865. public TicketRenewUpgradeView getRenewUpgradeInfo(long userId, Long relationId) {
  1866. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1867. GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
  1868. .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
  1869. .field(GroupsRelationView::getId, relationId)
  1870. .field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
  1871. .build());
  1872. TicketRenewUpgradeView ticketRenewUpgradeView = new TicketRenewUpgradeView();
  1873. if (groupsRelationView != null) {
  1874. String lang = request.getHeader("lang");
  1875. //clause pro
  1876. if (groupsRelationView.getGoodsId() == Constant.CLAUDE_PRO_GID) {
  1877. try {
  1878. ClaudeUserView userInfo = claudeService.getUserInfo(groupsRelationView.getUserId(), groupsRelationView.getId());
  1879. Long renewSkuId = userInfo.getRenewSkuId();
  1880. if (renewSkuId != null) {
  1881. GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build());
  1882. ticketRenewUpgradeView.setRenewSku(renewSku);
  1883. }
  1884. ticketRenewUpgradeView.setGptUserLimitNum(userInfo.getLimitNum());
  1885. ticketRenewUpgradeView.setGptUserLimitTime(userInfo.getLimitTime());
  1886. } catch (Exception e) {
  1887. }
  1888. }
  1889. if (groupsRelationView.getGoodsId() == Constant.GPT_PLUS_GID) {
  1890. try {
  1891. //gpt用户镜像
  1892. ChatGptUserView userInfo = chatGptAccountService.getUserInfo(groupsRelationView.getUserId(), groupsRelationView.getId());
  1893. Integer count = upgradePackageMapper.selectCount(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + groupsRelationView.getSkuId() + "\"')")
  1894. .gt(UpgradePackage::getNum, userInfo.getLimitNum())
  1895. .eq(UpgradePackage::getStatus, Boolean.TRUE)
  1896. .eq(UpgradePackage::getGptType, 0)
  1897. .eq(UpgradePackage::getDeleted, Boolean.TRUE));
  1898. ticketRenewUpgradeView.setUpgrade(count > 0 ? true : false);
  1899. ticketRenewUpgradeView.setPackageId(userInfo.getPackageId());
  1900. ticketRenewUpgradeView.setGptUserLimitNum(userInfo.getLimitNum());
  1901. ticketRenewUpgradeView.setGptUserLimitTime(userInfo.getLimitTime());
  1902. ticketRenewUpgradeView.setUserDsLimitNum(userInfo.getDsLimitNum());
  1903. ticketRenewUpgradeView.setUserDsLimitTime(userInfo.getDsLimitTime());
  1904. ticketRenewUpgradeView.setUserOtherLimitNum(userInfo.getOtherLimitNum());
  1905. ticketRenewUpgradeView.setUserOtherLimitTime(userInfo.getOtherLimitTime());
  1906. if (userInfo.getPackageId() != 0) {
  1907. UpgradePackage upgradePackage = upgradePackageMapper.selectById(userInfo.getPackageId());
  1908. ticketRenewUpgradeView.setPackagePrice(upgradePackage.getPrice());
  1909. Long upgradeOrderDonSkuId = upgradePackage.getUpgradeSkuId();
  1910. GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, upgradeOrderDonSkuId).build());
  1911. renewSku.setPackageId(userInfo.getPackageId());
  1912. ticketRenewUpgradeView.setRenewSku(renewSku);
  1913. }
  1914. ticketRenewUpgradeView.setIsRenewPackage(userInfo.getIsRenewPackage());
  1915. Long renewSkuId = userInfo.getRenewSkuId();
  1916. if (renewSkuId != null) {
  1917. GoodsDonSkuRenewView upgradeSkuRenewView = ticketRenewUpgradeView.getRenewSku();
  1918. GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build());
  1919. //续费升级是更高级规格
  1920. if (upgradeSkuRenewView == null || (renewSku.getGptUserLimitNum() >= upgradeSkuRenewView.getGptUserLimitNum() && renewSku.getMonths() >= userInfo.getMonths())) {
  1921. Optional.ofNullable(orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class)
  1922. .eq(OrderDonRenewRecord::getOrderId, userInfo.getRenewOrderId())
  1923. .last("limit 1"))).ifPresent(e -> renewSku.setOriginalOrderId(e.getOrderId()));
  1924. if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
  1925. String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(renewSku.getSkuId(), lang);
  1926. if (StrUtil.isNotBlank(languageSpecVal)) {
  1927. renewSku.setSpecVal(languageSpecVal);
  1928. }
  1929. }
  1930. ticketRenewUpgradeView.setRenewSku(renewSku);
  1931. }
  1932. }
  1933. } catch (Exception e) {
  1934. }
  1935. }
  1936. //claude code
  1937. if (groupsRelationView.getGoodsId() == Constant.CLAUDE_CODE_GOODS_ID) {
  1938. try {
  1939. //cc用户镜像
  1940. ClaudeCodeUserInfoView userInfo = claudeCodeService.getClaudeCodeUserSubsInfo(userId);
  1941. ticketRenewUpgradeView.setClaudeDailyLimit(userInfo.getClaudeDailyLimit());
  1942. ticketRenewUpgradeView.setClaudeQuota(userInfo.getClaudeQuota());
  1943. ticketRenewUpgradeView.setIsRenewPackage(userInfo.getRenewSkuId() != null ? true : false);
  1944. ticketRenewUpgradeView.setHighestUsage(userInfo.getHighestUsage());
  1945. Long renewSkuId = userInfo.getRenewSkuId();
  1946. if (renewSkuId != null) {
  1947. GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build());
  1948. Optional.ofNullable(claudeCodeUserRenewExpiryRecordMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUserRenewExpiryRecord.class)
  1949. .eq(ClaudeCodeUserRenewExpiryRecord::getOrderId, userInfo.getRenewOrderId())
  1950. .last("limit 1"))).ifPresent(e -> renewSku.setOriginalOrderId(e.getOrderId()));
  1951. if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
  1952. String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(renewSku.getSkuId(), lang);
  1953. if (StrUtil.isNotBlank(languageSpecVal)) {
  1954. renewSku.setSpecVal(languageSpecVal);
  1955. }
  1956. }
  1957. ticketRenewUpgradeView.setRenewSku(renewSku);
  1958. }
  1959. } catch (Exception e) {
  1960. }
  1961. }
  1962. //codex
  1963. if (groupsRelationView.getGoodsId() == Constant.CODEX_GOODS_ID) {
  1964. try {
  1965. //codex用户镜像
  1966. CodexUserInfoView userInfo = codexService.getUserSubsInfo(userId);
  1967. ticketRenewUpgradeView.setOpenaiDailyLimit(userInfo.getOpenaiDailyLimit());
  1968. ticketRenewUpgradeView.setOpenaiQuota(userInfo.getOpenaiQuota());
  1969. ticketRenewUpgradeView.setIsRenewPackage(userInfo.getRenewSkuId() != null ? true : false);
  1970. Long renewSkuId = userInfo.getRenewSkuId();
  1971. if (renewSkuId != null) {
  1972. GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build());
  1973. Optional.ofNullable(codexUserRenewExpiryRecordMapper.selectOne(Wrappers.lambdaQuery(CodexUserRenewExpiryRecord.class)
  1974. .eq(CodexUserRenewExpiryRecord::getOrderId, userInfo.getRenewOrderId())
  1975. .last("limit 1"))).ifPresent(e -> renewSku.setOriginalOrderId(e.getOrderId()));
  1976. if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
  1977. String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(renewSku.getSkuId(), lang);
  1978. if (StrUtil.isNotBlank(languageSpecVal)) {
  1979. renewSku.setSpecVal(languageSpecVal);
  1980. }
  1981. }
  1982. ticketRenewUpgradeView.setRenewSku(renewSku);
  1983. }
  1984. } catch (Exception e) {
  1985. }
  1986. }
  1987. }
  1988. return ticketRenewUpgradeView;
  1989. }
  1990. @Override
  1991. public void netflixSubmitFrozen(ErrorNetflixChangeReq req) {
  1992. Long relationId = req.getRelationId();
  1993. Long userId = req.getUserId();
  1994. //校验奈飞账号状态
  1995. GroupsRelationView netflixRelationView = checkNetflixErrorStatus(relationId, userId);
  1996. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1997. Integer recoverCount = netflixUserAccountSubmitRecoverRecordMapper.selectCount(Wrappers.lambdaQuery(NetflixUserAccountSubmitRecoverRecord.class)
  1998. .eq(NetflixUserAccountSubmitRecoverRecord::getRelationId, relationId)
  1999. .in(NetflixUserAccountSubmitRecoverRecord::getUserId, userIdList)
  2000. .eq(NetflixUserAccountSubmitRecoverRecord::getStatus, 0));
  2001. if (recoverCount > 0) {
  2002. throw BusinessRuntimeException.getInstance("你已申请恢复账号,无法再申请冻结");
  2003. }
  2004. if (netflixRelationView.getIsFrozen()) {
  2005. throw BusinessRuntimeException.getInstance("你已申请冻结,无法再申请冻结");
  2006. }
  2007. Date expiryTime = netflixRelationView.getExpiryTime();
  2008. //保留天数
  2009. Long betweenDay = DateUtil.betweenDay(DateTime.now(), expiryTime, false) + 1;
  2010. groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  2011. .set(GroupsRelation::getIsFrozen, Boolean.TRUE)
  2012. //冻结2个月
  2013. .set(GroupsRelation::getUnfrozenTime, DateUtil.offsetMonth(DateTime.now(), 2))
  2014. .set(GroupsRelation::getReservedDays, betweenDay)
  2015. .eq(GroupsRelation::getId, netflixRelationView.getId())
  2016. .eq(GroupsRelation::getUserId, netflixRelationView.getUserId()));
  2017. //送一个月GPT基础月付
  2018. Long sendRelationId = getTicket(userId, Constant.GPT_MIRROR_COMMON_SKU_ID, Boolean.FALSE);
  2019. if (sendRelationId != null) {
  2020. AccountNetflixFrozenTicketReceivedRecord receivedRecord = new AccountNetflixFrozenTicketReceivedRecord();
  2021. receivedRecord.setUserId(userId);
  2022. receivedRecord.setRelationId(relationId);
  2023. receivedRecord.setSendRelationId(sendRelationId);
  2024. accountNetflixFrozenTicketReceivedRecordMapper.insert(receivedRecord);
  2025. }
  2026. }
  2027. @Override
  2028. public String getSoraCode(Long userId, Long relationId) {
  2029. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  2030. GroupsRelation relation = groupsRelationMapper.selectById(relationId);
  2031. if (relation == null) {
  2032. throw BusinessRuntimeException.getInstance("车票不存在");
  2033. }
  2034. if (!userIdList.contains(relation.getUserId())) {
  2035. throw BusinessRuntimeException.getInstance("车票不存在");
  2036. }
  2037. if (relation.getStatus() != GroupsRelation.Status.validity) {
  2038. throw BusinessRuntimeException.getInstance("车票不存在");
  2039. }
  2040. if (relation.getExpiryTime() != null && relation.getExpiryTime().before(DateTime.now())) {
  2041. throw BusinessRuntimeException.getInstance("车票已过期");
  2042. }
  2043. GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
  2044. GoodsDonSku sku = goodsDonSkuMapper.selectById(groupsTrips.getSkuId());
  2045. //非GPT独立
  2046. if (sku.getGoodsId() != Constant.GPT_PLUS_GID || sku.getNum() != 1) {
  2047. throw BusinessRuntimeException.getInstance("非GPT独立会员车票");
  2048. }
  2049. 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"));
  2050. SoraCode soraCode = soraCodeMapper.selectOne(Wrappers.lambdaQuery(SoraCode.class).eq(SoraCode::getOrderId, orderDon.getId()).last("limit 1"));
  2051. if (soraCode == null) {
  2052. try {
  2053. if (orderDon.getCreatedTime().before(DateUtil.parse("2025-10-14 17:30:00"))) {
  2054. throw BusinessRuntimeException.getInstance("系统异常");
  2055. }
  2056. soraCodeFrontService.grantSoraCodeForGptMember(relation.getUserId(), orderDon.getId());
  2057. soraCode = soraCodeMapper.selectOne(Wrappers.lambdaQuery(SoraCode.class).eq(SoraCode::getOrderId, orderDon.getId()).last("limit 1"));
  2058. } catch (Exception e) {
  2059. }
  2060. }
  2061. if (soraCode == null) {
  2062. throw BusinessRuntimeException.getInstance("暂无可用sora邀请码,请联系客服");
  2063. }
  2064. return soraCode.getCode();
  2065. }
  2066. private DistributePosterGoodsDetailView setGoodsPoster(RenewalView ticket, User user, List<Long> userIds) {
  2067. DistributePosterGoodsDetailView distributePosterGoodsDetailView = beanSearcher.searchFirst(DistributePosterGoodsDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
  2068. .field(DistributePosterGoodsFrontView::getGoodsId, ticket.getGoodsId()).build());
  2069. if (distributePosterGoodsDetailView == null) {
  2070. return null;
  2071. }
  2072. distributePosterGoodsDetailView.setNickname(user.getNickname());
  2073. UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class)
  2074. .eq(UserDistribute::getUserId, user.getId())
  2075. .eq(UserDistribute::getDeleted, 1)
  2076. .last("limit 1"));
  2077. if (userDistribute != null) {
  2078. UserPlatDistributeRate userPlatDistributeRate = userPlatDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatDistributeRate.class)
  2079. .eq(UserPlatDistributeRate::getDistributeId, userDistribute.getId())
  2080. .eq(UserPlatDistributeRate::getGoodsId, ticket.getGoodsId())
  2081. .last("limit 1"));
  2082. if (userPlatDistributeRate != null) {
  2083. distributePosterGoodsDetailView.setRate(userPlatDistributeRate.getRate());
  2084. }
  2085. }
  2086. GoodsDon goodsDon = goodsDonMapper.selectById(ticket.getGoodsId());
  2087. if (goodsDon.getIsSkuDistribute()) {
  2088. if (userDistribute != null) {
  2089. UserPlatSkuDistributeRate userPlatSkuDistributeRate = userPlatSkuDistributeRateMapper.selectOne(Wrappers.lambdaQuery(UserPlatSkuDistributeRate.class)
  2090. .eq(UserPlatSkuDistributeRate::getDistributeId, userDistribute.getId())
  2091. .eq(UserPlatSkuDistributeRate::getSkuId, ticket.getSkuId())
  2092. .last("limit 1"));
  2093. if (userPlatSkuDistributeRate != null) {
  2094. distributePosterGoodsDetailView.setRate(userPlatSkuDistributeRate.getRate());
  2095. }
  2096. } else {
  2097. DistributeGeneralSkuRate distributeGeneralSkuRate = distributeGeneralSkuRateMapper.selectOne(Wrappers.lambdaQuery(DistributeGeneralSkuRate.class)
  2098. .eq(DistributeGeneralSkuRate::getSkuId, ticket.getSkuId())
  2099. .last("limit 1"));
  2100. if (distributeGeneralSkuRate != null) {
  2101. distributePosterGoodsDetailView.setRate(distributeGeneralSkuRate.getRate());
  2102. }
  2103. }
  2104. }
  2105. //用户推广海报记录id
  2106. Optional.ofNullable(userDistributePosterRecordMapper.selectOne(Wrappers.lambdaQuery(UserDistributePosterRecord.class)
  2107. .eq(UserDistributePosterRecord::getPosterId, distributePosterGoodsDetailView.getId())
  2108. .in(UserDistributePosterRecord::getUserId, userIds)
  2109. .last("limit 1"))).ifPresent(re -> distributePosterGoodsDetailView.setRid(re.getId()));
  2110. return distributePosterGoodsDetailView;
  2111. }
  2112. private BigDecimal getRenewDiscount(Long goodsId, Long skuId, Boolean isMirror, Integer skuNum) {
  2113. //镜像或者独立规格
  2114. if (goodsId == Constant.CODEX_GOODS_ID || goodsId == Constant.CLAUDE_CODE_GOODS_ID || isMirror || (skuNum != null && skuNum == 1)) {
  2115. RenewUpgradePackage renewUpgradePackage = renewUpgradePackageMapper.selectOne(Wrappers.lambdaQuery(RenewUpgradePackage.class)
  2116. .eq(RenewUpgradePackage::getGoodsId, goodsId)
  2117. .eq(RenewUpgradePackage::getStatus, 1)
  2118. .eq(RenewUpgradePackage::getDeleted, 1)
  2119. .eq(RenewUpgradePackage::getSkuId, skuId)
  2120. .orderByAsc(RenewUpgradePackage::getDiscount)
  2121. .last("limit 1")
  2122. .select(RenewUpgradePackage::getId, RenewUpgradePackage::getDiscount));
  2123. if (renewUpgradePackage != null) {
  2124. return renewUpgradePackage.getDiscount();
  2125. }
  2126. }
  2127. return null;
  2128. }
  2129. private void setMirrorTicketInfo(RenewalView ticket) {
  2130. //// //设置MJ镜像信息
  2131. // setMjMirrorInfo(ticket);
  2132. //设置GPT镜像信息
  2133. setGptMirrorInfo(ticket);
  2134. //// //clause pro
  2135. // setClaudeProInfo(ticket);
  2136. //// //luma
  2137. // setLumaInfo(ticket);
  2138. }
  2139. private void setMjMirrorInfo(RenewalView ticket) {
  2140. if (ticket.getGoodsId() == 26 && ticket.getIsMirror()) {
  2141. List<UpgradePackage> upgradePackages = upgradePackageMapper.selectList(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + ticket.getSkuId() + "\"')").eq(UpgradePackage::getStatus, Boolean.TRUE).eq(UpgradePackage::getDeleted, Boolean.TRUE));
  2142. if (CollectionUtil.isNotEmpty(upgradePackages)) {
  2143. upgradePackages.stream().map(e -> e.getPrice().divide(BigDecimal.valueOf(e.getNum()), 2, RoundingMode.HALF_UP)).min(BigDecimal::compareTo).ifPresent(ticket::setMjPackagePrice);
  2144. }
  2145. try {
  2146. MidjourneyUserView search = beanSearcher.searchFirst(MidjourneyUserView.class, MapUtils.flatBuilder(request.getParameterMap())
  2147. .field(MidjourneyUserView::getUserId, ticket.getUserId()).field(MidjourneyUserView::getRelationId, ticket.getRelationId())
  2148. .onlySelect(MidjourneyUserView::getMjUserRelaxNum, MidjourneyUserView::getMjUserFastNum,MidjourneyUserView::getMjUserUpgradeNum, MidjourneyUserView::getIsCar)
  2149. .build());
  2150. if (search == null) {
  2151. MidjourneyUser midjourneyUser = midjourneyAccountService.getMidjourneyUserToken(ticket.getUserId(), ticket.getRelationId());
  2152. ticket.setMjUserFastNum(midjourneyUser.getMjFastNum());
  2153. ticket.setMjUserUpgradeNum(midjourneyUser.getMjUpgradeNum());
  2154. ticket.setMjUserRelaxNum(midjourneyUser.getMjRelaxNum());
  2155. ticket.setIsCar(false);
  2156. } else {
  2157. ticket.setIsCar(search.getIsCar());
  2158. ticket.setMjUserFastNum(search.getMjUserFastNum());
  2159. ticket.setMjUserUpgradeNum(search.getMjUserUpgradeNum());
  2160. ticket.setMjUserRelaxNum(search.getMjUserRelaxNum());
  2161. }
  2162. midjourneyAccountService.updateUserExpiryTime(ticket.getRelationId(), ticket.getExpiryTime());
  2163. } catch (Exception e) {
  2164. }
  2165. }
  2166. }
  2167. public void setGptMirrorInfo(RenewalView ticket) {
  2168. if (ticket.getGoodsId() == 18 && ticket.getIsCar() && ticket.getExpiryTime() != null) {
  2169. try {
  2170. //gpt用户镜像
  2171. ChatGptUserView userInfo = chatGptAccountService.getUserInfo(ticket.getUserId(), ticket.getRelationId());
  2172. ticket.setGptUserLimitNum(userInfo.getLimitNum());
  2173. ticket.setGptUserLimitTime(userInfo.getLimitTime());
  2174. ticket.setUserDsLimitNum(userInfo.getDsLimitNum());
  2175. ticket.setUserDsLimitTime(userInfo.getDsLimitTime());
  2176. ticket.setUserOtherLimitNum(userInfo.getOtherLimitNum());
  2177. ticket.setUserOtherLimitTime(userInfo.getOtherLimitTime());
  2178. ticket.setUserToken(userInfo.getUserToken());
  2179. ticket.setUse(userInfo.getUse());
  2180. ticket.setModel(userInfo.getModel());
  2181. // Integer count = upgradePackageMapper.selectCount(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + ticket.getSkuId() + "\"')")
  2182. // .gt(UpgradePackage::getNum, userInfo.getLimitNum())
  2183. // .eq(UpgradePackage::getStatus, Boolean.TRUE)
  2184. // .eq(UpgradePackage::getGptType, 0)
  2185. // .eq(UpgradePackage::getDeleted, Boolean.TRUE));
  2186. // ticket.setUpgrade(count > 0 ? true : false);
  2187. // ticket.setPackageId(userInfo.getPackageId());
  2188. // if (userInfo.getPackageId() != 0) {
  2189. // UpgradePackage upgradePackage = upgradePackageMapper.selectById(userInfo.getPackageId());
  2190. // ticket.setPackagePrice(upgradePackage.getPrice());
  2191. // Long upgradeOrderDonSkuId = upgradePackage.getUpgradeSkuId();
  2192. // GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, upgradeOrderDonSkuId).build());
  2193. // renewSku.setPackageId(userInfo.getPackageId());
  2194. // ticket.setRenewSku(renewSku);
  2195. // }
  2196. // ticket.setIsRenewPackage(userInfo.getIsRenewPackage());
  2197. // Long renewSkuId = userInfo.getRenewSkuId();
  2198. // if (renewSkuId != null) {
  2199. // GoodsDonSkuRenewView upgradeSkuRenewView = ticket.getRenewSku();
  2200. // GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build());
  2201. // //续费升级是更高级规格
  2202. // if (upgradeSkuRenewView == null || (renewSku.getGptUserLimitNum() >= upgradeSkuRenewView.getGptUserLimitNum() && renewSku.getMonths() >= userInfo.getMonths())) {
  2203. // Optional.ofNullable(orderDonRenewRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonRenewRecord.class)
  2204. // .eq(OrderDonRenewRecord::getOrderId, userInfo.getRenewOrderId())
  2205. // .last("limit 1"))).ifPresent(e -> renewSku.setOriginalOrderId(e.getOrderId()));
  2206. // ticket.setRenewSku(renewSku);
  2207. // }
  2208. // }
  2209. } catch (Exception e) {
  2210. }
  2211. }
  2212. }
  2213. public void setClaudeProInfo(RenewalView ticket) {
  2214. //clause pro
  2215. if (ticket.getGoodsId() == 75l && ticket.getExpiryTime() != null) {
  2216. try {
  2217. ClaudeUserView userInfo = claudeService.getUserInfo(ticket.getUserId(), ticket.getRelationId());
  2218. ticket.setGptUserLimitNum(userInfo.getLimitNum());
  2219. ticket.setGptUserLimitTime(userInfo.getLimitTime());
  2220. ticket.setUse(userInfo.getUse());
  2221. Long renewSkuId = userInfo.getRenewSkuId();
  2222. if (renewSkuId != null) {
  2223. GoodsDonSkuRenewView renewSku = beanSearcher.searchFirst(GoodsDonSkuRenewView.class, MapUtils.builder().field(GoodsDonSkuRenewView::getSkuId, renewSkuId).build());
  2224. ticket.setRenewSku(renewSku);
  2225. }
  2226. } catch (Exception e) {
  2227. }
  2228. }
  2229. }
  2230. public void setLumaInfo(RenewalView ticket) {
  2231. if (ticket.getGoodsId() == Constant.LUMA_GOODS_ID && ticket.getExpiryTime() != null) {
  2232. try {
  2233. List<UpgradePackage> upgradePackages = upgradePackageMapper.selectList(Wrappers.lambdaQuery(UpgradePackage.class).apply("JSON_CONTAINS(sku_ids,'\"" + ticket.getSkuId() + "\"')").eq(UpgradePackage::getStatus, Boolean.TRUE).eq(UpgradePackage::getDeleted, Boolean.TRUE));
  2234. if (CollectionUtil.isNotEmpty(upgradePackages)){
  2235. upgradePackages.stream().map(e -> e.getPrice().divide(BigDecimal.valueOf(e.getNum()), 2, RoundingMode.HALF_UP)).min(BigDecimal::compareTo).ifPresent(ticket::setLumaPackagePrice);
  2236. }
  2237. LumaUser lumaUser = lumaService.getLumaUser(ticket.getUserId(), ticket.getRelationId());
  2238. ticket.setLumaUserNum(lumaUser.getNum());
  2239. } catch (Exception e) {
  2240. }
  2241. }
  2242. }
  2243. /**
  2244. * 获取gpt镜像天卡活动参与平台ids
  2245. * @return
  2246. */
  2247. private List<Long> getGptMirrorGiveawayBuyGids() {
  2248. GptMirrorDayCardGiveawayActivity gptMirrorDayCardGiveawayActivity = beanSearcher.searchFirst(GptMirrorDayCardGiveawayActivity.class, MapUtils.builder().build());
  2249. if (gptMirrorDayCardGiveawayActivity != null) {
  2250. String buyGoodsIds = gptMirrorDayCardGiveawayActivity.getBuyGoodsIds();
  2251. try {
  2252. return Jsons.parseList(buyGoodsIds, Long.class);
  2253. } catch (Exception e) {
  2254. }
  2255. }
  2256. return null;
  2257. }
  2258. /**
  2259. * 标记是否可抵扣会员车票
  2260. */
  2261. private void markVipDeductTicket(List<Long> userIds, RenewalView ticket, Set<Long> vipGoodsIds, Boolean isVip) {
  2262. if (CollUtil.isNotEmpty(vipGoodsIds) && ticket.getIsMirror() != null && ticket.getIsMirror() && !isVip) {
  2263. Long goodsId = ticket.getGoodsId();
  2264. //只购买
  2265. if (ticket.getAqType() != 1) {
  2266. return;
  2267. }
  2268. if (vipGoodsIds.contains(goodsId)) {
  2269. if (goodsId == Constant.NANO_GOODS_ID) {
  2270. NanoUserQuota nanoUserQuota = nanoUserQuotaMapper.selectOne(Wrappers.lambdaQuery(NanoUserQuota.class).in(NanoUserQuota::getUid, userIds).orderByDesc(NanoUserQuota::getRemainingQuota).last("limit 1"));
  2271. if (nanoUserQuota != null) {
  2272. if (ObjectUtil.equal(nanoUserQuota.getRelationId(), ticket.getRelationId())) {
  2273. ticket.setIsVipDeduct(true);
  2274. }
  2275. return;
  2276. }
  2277. RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder()
  2278. .field(RenewalView::getGoodsId, goodsId)
  2279. .field(RenewalView::getUserId, userIds).op(Operator.InList)
  2280. .orderBy(RenewalView::getSkuNanoQuota).desc()
  2281. .onlySelect(RenewalView::getRelationId)
  2282. .build());
  2283. if (renewalView != null && ObjectUtil.equal(renewalView.getRelationId(), ticket.getRelationId())) {
  2284. ticket.setIsVipDeduct(true);
  2285. }
  2286. return;
  2287. }
  2288. //是否时长最长
  2289. Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder()
  2290. .field(RenewalView::getRelationId, ticket.getRelationId()).op(Operator.NotEqual)
  2291. .field(RenewalView::getGoodsId, goodsId)
  2292. .field(RenewalView::getUserId, userIds).op(Operator.InList)
  2293. .field(RenewalView::getExpiryTime, ticket.getExpiryTime()).op(Operator.GreaterThan)
  2294. .build());
  2295. if (number.intValue() == 0) {
  2296. ticket.setIsVipDeduct(true);
  2297. }
  2298. }
  2299. }
  2300. }
  2301. /**
  2302. * 检验奈飞账号状态
  2303. */
  2304. public GroupsRelationView checkNetflixErrorStatus(Long relationId, Long userId) {
  2305. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  2306. NetflixUserAccountStatusRecord netflixUseAccountStatusRecord = netflixUserAccountStatusRecordMapper.selectOne(Wrappers.lambdaQuery(NetflixUserAccountStatusRecord.class)
  2307. .eq(NetflixUserAccountStatusRecord::getRelationId, relationId)
  2308. .eq(NetflixUserAccountStatusRecord::getDeleted, 1)
  2309. .in(NetflixUserAccountStatusRecord::getUserId, userIdList)
  2310. .orderByDesc(NetflixUserAccountStatusRecord::getId)
  2311. .last("limit 1"));
  2312. if (netflixUseAccountStatusRecord == null) {
  2313. throw BusinessRuntimeException.getInstance("请先提交账号检测");
  2314. }
  2315. Integer state = netflixUseAccountStatusRecord.getState();
  2316. if (state == 0) {
  2317. throw BusinessRuntimeException.getInstance("您的账号检测中");
  2318. }
  2319. //2是登录失败 3是被封号
  2320. if (state != 3) {
  2321. throw BusinessRuntimeException.getInstance("您的账号未封禁");
  2322. }
  2323. GroupsRelationView netflixRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
  2324. .field(GroupsRelationView::getId, relationId)
  2325. .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
  2326. .field(GroupsRelationView::getGoodsId, Constant.NETFLIX_GID)
  2327. .build());
  2328. if (netflixRelationView == null) {
  2329. throw BusinessRuntimeException.getInstance("奈飞车票已过期");
  2330. }
  2331. if (netflixRelationView != null) {
  2332. if (netflixRelationView.getIsFrozen() && netflixRelationView.getUnfrozenTime().after(DateTime.now())) {
  2333. throw BusinessRuntimeException.getInstance("冻结未结束");
  2334. }
  2335. if (netflixRelationView.getIsFrozen()) {
  2336. //重新设置车票时长
  2337. netflixRelationView.setExpiryTime(DateUtil.offsetDay(DateTime.now(), netflixRelationView.getReservedDays()));
  2338. }
  2339. if (netflixRelationView.getExpiryTime().before(DateTime.now())) {
  2340. throw BusinessRuntimeException.getInstance("奈飞车票已过期");
  2341. }
  2342. }
  2343. netflixRelationView.setNfCheckId(netflixUseAccountStatusRecord.getId());
  2344. netflixRelationView.setNfOriOrderId(netflixUseAccountStatusRecord.getOrderId());
  2345. return netflixRelationView;
  2346. }
  2347. /**
  2348. * 获取车票 并生成订单
  2349. */
  2350. public TicketChangeDto getTicketAndGenerateOrder(Long userId, Long skuId, Date startTime, Date expiryTime) {
  2351. Retryer<TicketChangeDto> build = RetryerBuilder.<TicketChangeDto>newBuilder()
  2352. .retryIfException()
  2353. //运行时异常重试
  2354. .retryIfRuntimeException()
  2355. //false重试
  2356. .retryIfResult(res -> res == null)
  2357. //1s 间隔
  2358. .withWaitStrategy(WaitStrategies.fixedWait(1, TimeUnit.SECONDS))
  2359. //停止策略 : 尝试请求1次
  2360. .withStopStrategy(StopStrategies.stopAfterAttempt(1)).build();
  2361. if (startTime == null) {
  2362. startTime = DateTime.now();
  2363. }
  2364. GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId);
  2365. if (expiryTime == null) {
  2366. if (sku.getDays() != null) {
  2367. expiryTime = DateUtil.offsetDay(startTime, sku.getDays());
  2368. } else {
  2369. expiryTime = DateUtil.offsetMonth(startTime, sku.getMonths());
  2370. }
  2371. }
  2372. Date finalStartTime = startTime;
  2373. Date finalExpiryTime = expiryTime;
  2374. try {
  2375. return build.call(() -> {
  2376. GroupsTrips groups = groupsMapper.selectCollegeStudentUserGptTicket(skuId);
  2377. if (groups == null) {
  2378. groups = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class)
  2379. .eq(GroupsTrips::getStatus, GroupsTrips.Status.waiting)
  2380. .eq(GroupsTrips::getSkuId, skuId)
  2381. .last("limit 1"));
  2382. }
  2383. GroupsRelation relation = null;
  2384. if (groups != null) {
  2385. relation = groupsRelationMapper.selectRandomOneRelationByGroupsId(groups.getId());
  2386. }
  2387. //生成空车队
  2388. if (relation == null) {
  2389. relation = groupsFuncService.createNewGroupsTrips(sku);
  2390. }
  2391. int update = groupsRelationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  2392. .set(GroupsRelation::getUserId, userId)
  2393. .set(GroupsRelation::getStartTime, finalStartTime)
  2394. .set(GroupsRelation::getExpiryTime, finalExpiryTime)
  2395. .set(GroupsRelation::getStatus, GroupsRelation.Status.validity)
  2396. .eq(GroupsRelation::getId, relation.getId())
  2397. .eq(GroupsRelation::getUserId, 0));
  2398. if (update > 0) {
  2399. groupsMapper.decrAvailableNum(relation.getGroupsId());
  2400. Long relationId = relation.getId();
  2401. //生成新的订单
  2402. OrderDon otherOrderDon = generateNewTicketOrder(relationId, userId, sku);
  2403. TicketChangeDto ticketChangeDto = new TicketChangeDto();
  2404. ticketChangeDto.setOtherRelationId(relationId);
  2405. ticketChangeDto.setOtherOrderId(otherOrderDon.getId());
  2406. return ticketChangeDto;
  2407. }
  2408. log.error("发送用户:{} GPT镜像车票失败,进行重试", userId);
  2409. return null;
  2410. });
  2411. } catch (ExecutionException | RetryException e) {
  2412. log.error("发送用户GPT镜像失败:{}", StringUtil.getErrorText(e));
  2413. return null;
  2414. }
  2415. }
  2416. private OrderDon generateNewTicketOrder(Long relationId, Long userId, GoodsDonSku sku) {
  2417. OrderDon orderDon = new OrderDon();
  2418. orderDon.setUserId(userId);
  2419. orderDon.setOrderNo(SEQUENCE.nextId().toString());
  2420. orderDon.setMoney(BigDecimal.ZERO);
  2421. orderDon.setRelationId(relationId);
  2422. orderDon.setGoodsId(sku.getGoodsId());
  2423. orderDon.setSkuId(sku.getId());
  2424. orderDon.setType(OrderDon.Type.TICKET_REPLACE);
  2425. orderDon.setStatus(OrderDon.Status.complete);
  2426. orderDonMapper.insert(orderDon);
  2427. return orderDon;
  2428. }
  2429. private void setAIZoneMirrorTicketInfo(UserMirrorTicketView ticket) {
  2430. setAIZoneGptMirrorInfo(ticket);
  2431. }
  2432. private void setAIZoneGptMirrorInfo(UserMirrorTicketView ticket) {
  2433. if (ticket.getGoodsId() != null && ticket.getGoodsId() == Constant.GPT_PLUS_GID) {
  2434. ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
  2435. .eq(ChatgptUser::getRelationId, ticket.getRelationId())
  2436. .last("limit 1"));
  2437. if (chatgptUser != null) {
  2438. ticket.setModel(chatgptUser.getModel());
  2439. }
  2440. }
  2441. }
  2442. }