GroupRelationController.java 81 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658
  1. package com.cyksj.web.controller.group;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.date.BetweenFormater;
  4. import cn.hutool.core.date.DateTime;
  5. import cn.hutool.core.date.DateUnit;
  6. import cn.hutool.core.date.DateUtil;
  7. import cn.hutool.core.lang.Assert;
  8. import cn.hutool.core.thread.ThreadUtil;
  9. import cn.hutool.core.util.StrUtil;
  10. import cn.hutool.extra.servlet.ServletUtil;
  11. import cn.hutool.json.JSONObject;
  12. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  13. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  14. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  15. import com.cyksj.common.annotation.NoSubmit;
  16. import com.cyksj.common.constant.Constant;
  17. import com.cyksj.common.exception.BusinessRuntimeException;
  18. import com.cyksj.common.snowflake.Sequence;
  19. import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
  20. import com.cyksj.common.util.GoogleGenerator;
  21. import com.cyksj.common.util.Jsons;
  22. import com.cyksj.common.util.StringUtil;
  23. import com.cyksj.dto.Result;
  24. import com.cyksj.enums.GatewayResponse;
  25. import com.cyksj.mapper.*;
  26. import com.cyksj.mapper.manage.form.FormFieldsDataMapper;
  27. import com.cyksj.mapper.manage.form.QuestionnairePromotionMapper;
  28. import com.cyksj.mapper.shop.YhShopMapper;
  29. import com.cyksj.model.dto.*;
  30. import com.cyksj.model.dto.QuestionnaireView;
  31. import com.cyksj.model.entity.*;
  32. import com.cyksj.model.manage.views.AccountView;
  33. import com.cyksj.model.manage.views.GroupsRelationView;
  34. import com.cyksj.model.request.*;
  35. import com.cyksj.model.response.GptStandbyResp;
  36. import com.cyksj.model.response.NetflixErrorAccountStatus;
  37. import com.cyksj.model.response.NetflixRecoverResp;
  38. import com.cyksj.model.response.NetflixRefundInfoResp;
  39. import com.cyksj.model.views.*;
  40. import com.cyksj.redis.RedisService;
  41. import com.cyksj.service.chatgpt.ChatGptAuthService;
  42. import com.cyksj.service.mange.CmsOrderDonService;
  43. import com.cyksj.service.mange.coupon.CouponCommonService;
  44. import com.cyksj.service.mange.ticket.TicketAdvertiseConfigClickRecordService;
  45. import com.cyksj.service.order.OrderDonService;
  46. import com.cyksj.service.relation.GroupRelationFrontService;
  47. import com.cyksj.service.relation.GroupsRelationNetflixService;
  48. import com.cyksj.service.sys.SysConfigService;
  49. import com.cyksj.service.translations.BackInfoTranslationsFrontService;
  50. import com.cyksj.service.user.UserBindRelationService;
  51. import com.cyksj.service.user.UserService;
  52. import com.cyksj.web.util.StpUserUtil;
  53. import com.ejlchina.searcher.BeanSearcher;
  54. import com.ejlchina.searcher.SearchResult;
  55. import com.ejlchina.searcher.operator.LessEqual;
  56. import com.ejlchina.searcher.param.Operator;
  57. import com.ejlchina.searcher.util.MapBuilder;
  58. import com.ejlchina.searcher.util.MapUtils;
  59. import lombok.RequiredArgsConstructor;
  60. import lombok.extern.slf4j.Slf4j;
  61. import org.springframework.transaction.annotation.Transactional;
  62. import org.springframework.validation.annotation.Validated;
  63. import org.springframework.web.bind.annotation.*;
  64. import javax.servlet.http.HttpServletRequest;
  65. import javax.validation.constraints.NotEmpty;
  66. import javax.validation.constraints.NotNull;
  67. import java.math.BigDecimal;
  68. import java.math.RoundingMode;
  69. import java.util.*;
  70. import java.util.concurrent.TimeUnit;
  71. import java.util.concurrent.atomic.AtomicInteger;
  72. import java.util.concurrent.atomic.AtomicLong;
  73. import java.util.stream.Collectors;
  74. /**
  75. * @author chan
  76. * @date 2022/9/27 11:48 AM
  77. */
  78. @Slf4j
  79. @RequiredArgsConstructor
  80. @RestController
  81. @RequestMapping("/applets/group/relation")
  82. public class GroupRelationController {
  83. private final BeanSearcher beanSearcher;
  84. private final OrderDonService orderDonService;
  85. private final GroupsRelationMapper relationMapper;
  86. private final TicketRedemptionCodeRecordMapper ticketRedemptionCodeRecordMapper;
  87. private final GroupRelationFrontService groupRelationFrontService;
  88. private final UserService userService;
  89. private final UserBindRelationService userBindRelationService;
  90. private final TicketPwdViewRecordMapper ticketPwdViewRecordMapper;
  91. private final HttpServletRequest request;
  92. private final AccountDoubleVerifyRecordMapper accountDoubleVerifyRecordMapper;
  93. private final DoubleVerifyClickRecordMapper doubleVerifyRecordMapper;
  94. private final RedisService redisService;
  95. private final DoubleVerifyClickRefreshRecordMapper refreshRecordMapper;
  96. private final QuestionResponseRecordMapper questionResponseRecordMapper;
  97. private final CouponCommonService couponCommonService;
  98. private final FormFieldsDataMapper formFieldsDataMapper;
  99. private final QuestionnairePromotionMapper questionnairePromotionMapper;
  100. private final TicketAdvertiseConfigClickRecordService ticketAdvertiseConfigClickRecordService;
  101. private final GlobalThreadPoolTaskExecutor THREAD_POOL;
  102. private final ChatGptAuthService chatGptAuthService;
  103. private final GoodsCoursewareFileMapper goodsCoursewareFileMapper;
  104. private final GptTicketStandbyMapper gptTicketStandbyMapper;
  105. private final CmsOrderDonService cmsOrderDonService;
  106. private final GoodsDonSkuMapper goodsDonSkuMapper;
  107. private final AccountBlockedReplaceRecordMapper accountBlockedReplaceRecordMapper;
  108. private final OrderDonMapper orderDonMapper;
  109. private final UserGoodsNewbieGuideRecordMapper userGoodsNewbieGuideRecordMapper;
  110. private final GroupsRelationNetflixService groupsRelationNetflixService;
  111. private final ChatgptUserMapper chatgptUserMapper;
  112. private final UpgradeOrderDonMapper upgradeOrderDonMapper;
  113. private final UserBenefitsOrderRecordMapper userBenefitsOrderRecordMapper;
  114. private final ClaudeUserMapper claudeUserMapper;
  115. private final UserMapper userMapper;
  116. private final SysConfigService sysConfigService;
  117. private final BackInfoTranslationsFrontService backInfoTranslationsFrontService;
  118. private final YhShopMapper yhShopMapper;
  119. private final GroupsMapper groupsMapper;
  120. private final static Sequence SEQUENCE = new Sequence(0);
  121. @RequestMapping("/get/renewal")
  122. public Result<SearchResult<RenewalView>> get(Boolean isLoginPopularize, String customId, String account, String orderNo, Integer cmt) {
  123. long userId = StpUserUtil.getLoginIdAsLong();
  124. SearchResult<RenewalView> list = groupRelationFrontService.getMyTicket(userId, isLoginPopularize, customId, account, orderNo, cmt);
  125. return GatewayResponse.SUCCESS.newBuilder().toResult(list);
  126. }
  127. @GetMapping("/get/pay/goods")
  128. public Result<List<RenewalView>> getHasPayGoods() {
  129. long userId = StpUserUtil.getLoginIdAsLong();
  130. List<RenewalView> hasPayGoods = groupRelationFrontService.getHasPayGoods(userId);
  131. return GatewayResponse.SUCCESS.newBuilder().toResult(hasPayGoods);
  132. }
  133. @PostMapping("/post/renewal")
  134. public Result<OrderDon> renewal(@RequestBody OrderPayRequest payRequest) throws Exception {
  135. long userId = StpUserUtil.getLoginIdAsLong();
  136. payRequest.setUserId(userId);
  137. String ip = ServletUtil.getClientIP(request);
  138. payRequest.setIp(ip);
  139. OrderDon orderDon = orderDonService.renewal(payRequest);
  140. return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon);
  141. }
  142. /**
  143. * 邀请制绑定账号
  144. */
  145. @PutMapping("/update/set/account")
  146. public Result<String> setAccount(@RequestBody @Validated InviteBindAccountReq req) {
  147. long userId = StpUserUtil.getLoginIdAsLong();
  148. Long relationId = req.getId();
  149. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
  150. GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
  151. .eq(GroupsRelation::getId, relationId)
  152. .in(GroupsRelation::getUserId, userIds)
  153. .last(" limit 1"));
  154. if (relation == null) {
  155. throw new BusinessRuntimeException("该车票不存在,请联系客服.");
  156. }
  157. String account = req.getAccount();
  158. String password = req.getPassword();
  159. String contact = req.getContact();
  160. String bpVerifyCode = req.getBpVerifyCode();
  161. LambdaUpdateWrapper<GroupsRelation> updateWrapper = Wrappers.lambdaUpdate(GroupsRelation.class)
  162. .set(GroupsRelation::getAccount, account)
  163. .set(GroupsRelation::getPassword, password)
  164. .set(GroupsRelation::getContact, contact)
  165. .set(GroupsRelation::getBpVerifyCode, bpVerifyCode)
  166. .eq(GroupsRelation::getId, relationId);
  167. if (relation.getRechargeStatus() != null) {
  168. if (relation.getRechargeStatus() == GroupsRelation.RechargeStatus.complete) {
  169. throw BusinessRuntimeException.getInstance("代充账号已充值");
  170. }
  171. if (StrUtil.isEmpty(account)) {
  172. throw BusinessRuntimeException.getInstance("请输入正确的账号信息");
  173. }
  174. if (relation.getRechargeStatus() == GroupsRelation.RechargeStatus.error) {
  175. updateWrapper.set(GroupsRelation::getRechargeStatus, GroupsRelation.RechargeStatus.waiting);
  176. }
  177. relationMapper.update(relation, updateWrapper);
  178. }
  179. return GatewayResponse.SUCCESS.newBuilder().toResult();
  180. }
  181. /**
  182. * 查询是否加入了企业微信 并是否买了奈飞
  183. */
  184. @GetMapping("/check/joinCorpWx")
  185. public Result<Boolean> isJoinCorpWx() {
  186. long userId = StpUserUtil.getLoginIdAsLong();
  187. Boolean flag = groupRelationFrontService.isJoinCorpWx(userId, false, false);
  188. return GatewayResponse.SUCCESS.newBuilder().toResult(flag);
  189. }
  190. /**
  191. * 获取全部车票
  192. */
  193. @GetMapping("/get")
  194. public Result<List<UserTicketView>> getUserTicketView(Long goodsId, Long skuId) {
  195. long userId = StpUserUtil.getLoginIdAsLong();
  196. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
  197. List<UserTicketView> tickets = relationMapper.selectUserTickets(userIds, goodsId, skuId);
  198. return GatewayResponse.SUCCESS.newBuilder().toResult(tickets);
  199. }
  200. /**
  201. * 获取车票api额度兑换码
  202. */
  203. @GetMapping("/get/redemption/code/{relationId}")
  204. public Result<String> getRedemptionCode(@PathVariable Long relationId) {
  205. long userId = StpUserUtil.getLoginIdAsLong();
  206. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
  207. TicketRedemptionCodeRecord record = ticketRedemptionCodeRecordMapper.selectOne(Wrappers.lambdaQuery(TicketRedemptionCodeRecord.class)
  208. .eq(TicketRedemptionCodeRecord::getRelationId, relationId)
  209. .in(TicketRedemptionCodeRecord::getUserId, userIds)
  210. .eq(TicketRedemptionCodeRecord::getStatus, "success")
  211. .last("limit 1"));
  212. if (record == null || StrUtil.isBlank(record.getRedeemCode())) {
  213. throw BusinessRuntimeException.getInstance("兑换码不存在");
  214. }
  215. return GatewayResponse.SUCCESS.newBuilder().toResult(record.getRedeemCode());
  216. }
  217. /**
  218. * 记录查看ChatGPT车票密码
  219. */
  220. @GetMapping("/recordView/{relationId}")
  221. public Result<String> recordGPTPwdView(@PathVariable Long relationId) {
  222. long userId = StpUserUtil.getLoginIdAsLong();
  223. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
  224. GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
  225. .field(GroupsRelationView::getUserId, userIds).op(Operator.InList)
  226. .field(GroupsRelationView::getId, relationId).build());
  227. if (groupsRelationView == null) {
  228. log.info("userId:{}查看relationId:{}车票不存在", userId, relationId);
  229. throw BusinessRuntimeException.getInstance("该车票已不存在");
  230. }
  231. if (groupsRelationView.getAccountId() == null) throw BusinessRuntimeException.getInstance("该车队未配置账号");
  232. if (groupRelationFrontService == null) throw BusinessRuntimeException.getInstance("车票已不存在");
  233. TicketPwdViewRecord viewRecord = new TicketPwdViewRecord();
  234. viewRecord.setUserId(userId);
  235. viewRecord.setRelationId(relationId);
  236. viewRecord.setSkuId(groupsRelationView.getSkuId());
  237. viewRecord.setOperateLocation(ServletUtil.getClientIP(request));
  238. viewRecord.setAccount(groupsRelationView.getTripsAccount());
  239. viewRecord.setPassword(groupsRelationView.getTripsPassword());
  240. ticketPwdViewRecordMapper.insert(viewRecord);
  241. if (groupsRelationView.getGoodsId() == 18 && StrUtil.isEmpty(groupsRelationView.getApiSecret())) {
  242. THREAD_POOL.execute(() -> {
  243. //车队所有人查看密码
  244. Integer num = groupsRelationView.getGtNum();
  245. Integer viewNum = relationMapper.selectViewPwdCount(groupsRelationView.getGroupsId());
  246. if (num <= viewNum) {
  247. AccountDoubleVerifyRecord exist = accountDoubleVerifyRecordMapper.selectOne(Wrappers.lambdaQuery(AccountDoubleVerifyRecord.class)
  248. .eq(AccountDoubleVerifyRecord::getAccountId, groupsRelationView.getAccountId())
  249. .eq(AccountDoubleVerifyRecord::getDeleted, true).last("limit 1"));
  250. if (exist == null) {
  251. if (redisService.setNx(String.format("%s-%s", groupsRelationView.getAccountId(), groupsRelationView.getId()), groupsRelationView.getId(), 60l)) {
  252. //记录
  253. AccountDoubleVerifyRecord accountDoubleVerifyRecord = new AccountDoubleVerifyRecord();
  254. accountDoubleVerifyRecord.setAccountId(groupsRelationView.getAccountId());
  255. accountDoubleVerifyRecord.setAccount(groupsRelationView.getTripsAccount());
  256. accountDoubleVerifyRecord.setGroupsId(groupsRelationView.getGroupsId());
  257. accountDoubleVerifyRecord.setSkuId(groupsRelationView.getSkuId());
  258. accountDoubleVerifyRecord.setRemark("车队所有人看过密码");
  259. accountDoubleVerifyRecordMapper.insert(accountDoubleVerifyRecord);
  260. }
  261. }
  262. }
  263. });
  264. }
  265. return GatewayResponse.SUCCESS.newBuilder().toResult(groupsRelationView.getTripsPassword());
  266. }
  267. /**
  268. * 是否有查看过密码记录
  269. */
  270. @GetMapping("/get/pwd/view/record")
  271. public Result<Boolean> getPwdViewRecord(Long relationId) {
  272. long userId = StpUserUtil.getLoginIdAsLong();
  273. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
  274. Integer selectCount = ticketPwdViewRecordMapper.selectCount(Wrappers.lambdaQuery(TicketPwdViewRecord.class).eq(TicketPwdViewRecord::getRelationId, relationId).in(TicketPwdViewRecord::getUserId, userIds));
  275. return GatewayResponse.SUCCESS.newBuilder().toResult(selectCount > 0);
  276. }
  277. /**
  278. * 获取AI类 ChatGPT产品谷歌验证码
  279. */
  280. @GetMapping("/get/authCode")
  281. public Result<String> getAuthCode(Long relationId) {
  282. long userId = StpUserUtil.getLoginIdAsLong();
  283. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
  284. if (relationId == null) throw BusinessRuntimeException.getInstance("车票不存在");
  285. GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
  286. .field(GroupsRelationView::getId, relationId)
  287. .field(GroupsRelationView::getUserId, userIds).op(Operator.InList).build());
  288. if (groupsRelationView == null) throw BusinessRuntimeException.getInstance("车票不存在");
  289. if (StrUtil.isEmpty(groupsRelationView.getApiSecret())) throw BusinessRuntimeException.getInstance("未开启验证");
  290. DateTime now = DateTime.now();
  291. Integer count = doubleVerifyRecordMapper.selectCount(Wrappers.lambdaQuery(DoubleVerifyClickRecord.class)
  292. .in(DoubleVerifyClickRecord::getUserId, userIds)
  293. .eq(DoubleVerifyClickRecord::getRelationId, relationId)
  294. .eq(DoubleVerifyClickRecord::getAccountId, groupsRelationView.getAccountId())
  295. .between(DoubleVerifyClickRecord::getCreatedTime, DateUtil.beginOfMonth(now), DateUtil.endOfMonth(now)));
  296. //获取双重验证码
  297. Boolean isHasVerifyCode = StrUtil.isNotBlank(groupsRelationView.getVerifyCode()) ? true : false;
  298. //是否开启认证限制
  299. if (groupsRelationView.getIsVerifyLimit()) {
  300. Integer num = groupRelationFrontService.getUserCodeNumBySkuId(userId, groupsRelationView.getSkuId(), isHasVerifyCode);
  301. if (count >= num) throw BusinessRuntimeException.getInstance("获取双重验证码次数上限");
  302. }
  303. //一分钟内 只能一人获取
  304. boolean b = redisService.setNx(RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getName() + groupsRelationView.getTripsAccount(), relationId, RedisService.key.DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY.getTimeout());
  305. if (!b) {
  306. throw BusinessRuntimeException.getInstance("一分钟内已有人获取该账号验证码,请稍后获取..");
  307. }
  308. int second = now.second();
  309. if (second < 30 && 30 - second < 3) {
  310. ThreadUtil.sleep(30 - second + 1, TimeUnit.SECONDS);
  311. } else if (second > 30 && 60 - second < 3) {
  312. ThreadUtil.sleep(60 - second + 1, TimeUnit.SECONDS);
  313. }
  314. StringBuilder sb = new StringBuilder();
  315. JSONObject re = new JSONObject();
  316. try {
  317. long code = GoogleGenerator.getCode(groupsRelationView.getApiSecret(), now.getTime());
  318. sb.append(code);
  319. while (sb.length() < 6) {
  320. sb.insert(0, 0);
  321. }
  322. re.putOpt("code", sb.toString());
  323. int nowSecond = DateTime.now().second();
  324. int time = 0;
  325. if (nowSecond < 30) {
  326. time = 30 - nowSecond;
  327. } else {
  328. time = 60 - nowSecond;
  329. }
  330. re.putOpt("time", time);
  331. DoubleVerifyClickRecord doubleVerifyClickRecord = new DoubleVerifyClickRecord();
  332. doubleVerifyClickRecord.setRelationId(relationId);
  333. doubleVerifyClickRecord.setUserId(userId);
  334. doubleVerifyClickRecord.setAccountId(groupsRelationView.getAccountId());
  335. doubleVerifyClickRecord.setAccount(groupsRelationView.getTripsAccount());
  336. doubleVerifyClickRecord.setSkuId(groupsRelationView.getSkuId());
  337. doubleVerifyClickRecord.setCode(sb.toString());
  338. doubleVerifyClickRecord.setRemainTime(time);
  339. doubleVerifyRecordMapper.insert(doubleVerifyClickRecord);
  340. DoubleVerifyDto doubleVerifyDto = new DoubleVerifyDto();
  341. doubleVerifyDto.setClickId(doubleVerifyClickRecord.getId());
  342. doubleVerifyDto.setApiSecret(groupsRelationView.getApiSecret());
  343. redisService.set(String.format("%s-%s", userId, sb.toString()), 0, 60 * 10l);
  344. redisService.set(String.format("%s/%s", userId, sb.toString()), Jsons.toJson(doubleVerifyDto), 60 * 10l);
  345. } catch (Exception e) {
  346. throw BusinessRuntimeException.getInstance("获取双重验证码错误,请联系客服");
  347. }
  348. return GatewayResponse.SUCCESS.newBuilder().toResult(re.toString());
  349. }
  350. /**
  351. * 刷新验证码
  352. */
  353. @GetMapping("/refresh/code")
  354. public Result<String> refreshCode(String code) {
  355. long userId = StpUserUtil.getLoginIdAsLong();
  356. String numKey = String.format("%s-%s", userId, code);
  357. Object num = redisService.get(numKey);
  358. String objKey = String.format("%s/%s", userId, code);
  359. Object objValue = redisService.get(objKey);
  360. if (objValue == null || num == null) {
  361. throw BusinessRuntimeException.getInstance("请重新获取双重验证码");
  362. }
  363. Integer refreshNum = Integer.parseInt(num.toString());
  364. String apiSecret = null;
  365. Long clickId = 0l;
  366. try {
  367. DoubleVerifyDto dto = Jsons.parseObject(objValue.toString(), DoubleVerifyDto.class);
  368. apiSecret = dto.getApiSecret();
  369. clickId = dto.getClickId();
  370. } catch (Exception e) {
  371. apiSecret = objValue.toString();
  372. }
  373. if (refreshNum >= 3) {
  374. redisService.del(numKey);
  375. redisService.del(objKey);
  376. throw BusinessRuntimeException.getInstance("刷新次数已达到3次,请重新获取验证码");
  377. }
  378. if (apiSecret == null) {
  379. throw BusinessRuntimeException.getInstance("请重新获取双重验证码");
  380. }
  381. StringBuilder sb = new StringBuilder();
  382. try {
  383. long c = GoogleGenerator.getCode(apiSecret, DateTime.now().getTime());
  384. sb.append(c);
  385. while (sb.length() < 6) {
  386. sb.insert(0, 0);
  387. }
  388. redisService.incr(numKey, 1l);
  389. } catch (Exception e) {
  390. throw BusinessRuntimeException.getInstance("刷新双重验证码错误,请联系客服");
  391. }
  392. if (clickId != 0) {
  393. int nowSecond = DateTime.now().second();
  394. int time = 0;
  395. if (nowSecond < 30) {
  396. time = 30 - nowSecond;
  397. } else {
  398. time = 60 - nowSecond;
  399. }
  400. //刷新双重验证码记录
  401. DoubleVerifyClickRefreshRecord refreshRecord = new DoubleVerifyClickRefreshRecord();
  402. refreshRecord.setClickId(clickId);
  403. refreshRecord.setUserId(userId);
  404. refreshRecord.setCode(sb.toString());
  405. refreshRecord.setRemainTime(time);
  406. refreshRecordMapper.insert(refreshRecord);
  407. }
  408. return GatewayResponse.SUCCESS.newBuilder().toResult(sb.toString());
  409. }
  410. /**
  411. * 获取双重验证码记录
  412. */
  413. @GetMapping("/get/doubleVerify/codeList")
  414. public Result<List<DoubleVerifyCodeView>> getDoubleVerifyCodeList(Long relationId) {
  415. long userId = StpUserUtil.getLoginIdAsLong();
  416. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  417. List<DoubleVerifyCodeView> views = doubleVerifyRecordMapper.getDoubleVerifyCodeList(userIdList, relationId);
  418. return GatewayResponse.SUCCESS.newBuilder().toResult(views);
  419. }
  420. /**
  421. * 用户是不是自然流量渠道
  422. * 且未回答答题
  423. */
  424. @GetMapping("/natural/channel")
  425. public Result<Boolean> isNaturalChannel() {
  426. long userId = StpUserUtil.getLoginIdAsLong();
  427. String question_key = RedisService.key.QUESTION_RESPONSE_KEY.getNameFormat(userId);
  428. if (redisService.get(question_key) != null) {
  429. return GatewayResponse.SUCCESS.newBuilder().toResult(false);
  430. }
  431. User user = userService.getById(userId);
  432. if (user.getPopularizeId() != 0) {
  433. redisService.set(question_key, userId, RedisService.key.QUESTION_RESPONSE_KEY.getTimeout());
  434. return GatewayResponse.SUCCESS.newBuilder().toResult(false);
  435. }
  436. if (user.getPopularizeId() == 0) {
  437. QuestionResponseRecord record = questionResponseRecordMapper.selectOne(Wrappers.lambdaQuery(QuestionResponseRecord.class)
  438. .eq(QuestionResponseRecord::getUserId, userId).select(QuestionResponseRecord::getId).last("limit 1"));
  439. if (record != null) {
  440. redisService.set(question_key, userId, RedisService.key.QUESTION_RESPONSE_KEY.getTimeout());
  441. return GatewayResponse.SUCCESS.newBuilder().toResult(false);
  442. }
  443. return GatewayResponse.SUCCESS.newBuilder().toResult(true);
  444. }
  445. return GatewayResponse.SUCCESS.newBuilder().toResult(false);
  446. }
  447. /**
  448. * 问卷记录
  449. */
  450. @PostMapping("/record/replyQuestion")
  451. public Result<String> recordReplyQuestion(@RequestBody @Validated QuestionResponseRecord record) {
  452. long userId = StpUserUtil.getLoginIdAsLong();
  453. User user = userService.getById(userId);
  454. String nickname = user.getNickname();
  455. String question_key = RedisService.key.QUESTION_RESPONSE_KEY.getNameFormat(userId);
  456. QuestionResponseRecord dbRecord = questionResponseRecordMapper.selectOne(Wrappers.lambdaQuery(QuestionResponseRecord.class)
  457. .eq(QuestionResponseRecord::getUserId, userId).select(QuestionResponseRecord::getId).last("limit 1"));
  458. if (dbRecord == null) {
  459. if (redisService.setNx(String.format("%s-%s", userId, nickname), userId, 10l)) {
  460. record.setUserId(userId);
  461. record.setNickname(nickname);
  462. questionResponseRecordMapper.insert(record);
  463. //发放优惠券
  464. couponCommonService.sendCouponToUser(userId, 100l, 0l, 0l, 0l, CouponUser.Channel.ques_response);
  465. redisService.set(question_key, userId, RedisService.key.QUESTION_RESPONSE_KEY.getTimeout());
  466. }
  467. }
  468. return GatewayResponse.SUCCESS.newBuilder().toResult();
  469. }
  470. /**
  471. * 获取对应的动态问卷
  472. */
  473. @GetMapping("/get/questionnaire")
  474. public Result<List<QuestionnaireView>> getQuestionnaireView(Long promotionId) {
  475. QuestionnairePromotion promotion = questionnairePromotionMapper.selectById(promotionId);
  476. if (promotion == null || !promotion.getDeleted()) throw BusinessRuntimeException.getInstance("问卷不存在");
  477. Long templateId = promotion.getTemplateId();
  478. List<QuestionnaireView> questionnaireViews = beanSearcher.searchAll(QuestionnaireView.class, MapUtils.builder()
  479. .field(QuestionnaireView::getPromotionId, promotionId)
  480. .orderBy(QuestionnaireView::getSorted).asc()
  481. .orderBy(QuestionnaireView::getFieldsId).asc()
  482. .build());
  483. return GatewayResponse.SUCCESS.newBuilder().toResult(questionnaireViews);
  484. }
  485. /**
  486. * 记录问卷
  487. */
  488. @PostMapping("/record/questionnaire/{promotionId}")
  489. @Transactional(rollbackFor = Exception.class)
  490. @NoSubmit
  491. public Result<String> recordQuestionnaire(@PathVariable Long promotionId, String showId, @RequestBody List<FormFieldsData> answers) {
  492. Long userId = StpUserUtil.getUserIdAfterLogin();
  493. Long groupsId = SEQUENCE.nextId();
  494. List<QuestionnairePromotionFieldsListView> promotionFieldsListViews = beanSearcher.searchAll(QuestionnairePromotionFieldsListView.class, MapUtils.builder().field(QuestionnairePromotionFieldsListView::getPromotionId, promotionId).build());
  495. if (CollUtil.isEmpty(promotionFieldsListViews)) throw BusinessRuntimeException.getInstance("问卷已结束");
  496. if (promotionFieldsListViews.size() != answers.size()) throw BusinessRuntimeException.getInstance("请完成所有问题");
  497. log.info("开始记录问卷:{}", promotionId);
  498. answers.forEach(answer -> {
  499. // if (StringUtil.isNotBlank(showId)) {
  500. // answer.setUserId(userService.getUserIdByShowId(showId));
  501. // }
  502. answer.setUserId(userId);
  503. Long fieldsId = answer.getFieldsId();
  504. String content = answer.getContent();
  505. if (fieldsId == null || StrUtil.isBlank(content)) {
  506. throw BusinessRuntimeException.getInstance("必填项为空");
  507. }
  508. answer.setPromotionId(promotionId);
  509. answer.setGroupsId(groupsId);
  510. formFieldsDataMapper.insert(answer);
  511. });
  512. return GatewayResponse.SUCCESS.newBuilder().toResult();
  513. }
  514. /**
  515. * 查询用户是否填写问卷
  516. */
  517. @GetMapping("/check/questionnaire/{promotionId}")
  518. public Result<Boolean> checkQuestionnaire(@PathVariable Long promotionId) {
  519. long userId = StpUserUtil.getLoginIdAsLong();
  520. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  521. Integer count = formFieldsDataMapper.selectCount(Wrappers.lambdaQuery(FormFieldsData.class).in(FormFieldsData::getUserId, userIdList).eq(FormFieldsData::getPromotionId, promotionId));
  522. return GatewayResponse.SUCCESS.newBuilder().toResult(count > 0);
  523. }
  524. /**
  525. * 对应平台车票 广告配置列表
  526. */
  527. @GetMapping("/get/advertise")
  528. public Result<List<TicketAdvertiseConfigFrontView>> getTicketAdvertiseConfig() {
  529. long userId = StpUserUtil.getLoginIdAsLong();
  530. List<RenewalView> hasPayGoods = groupRelationFrontService.getHasPayGoods(userId);
  531. if (CollUtil.isEmpty(hasPayGoods)) {
  532. return GatewayResponse.SUCCESS.newBuilder().toResult();
  533. }
  534. List<Long> goodsIds = hasPayGoods.stream().map(RenewalView::getGoodsId).collect(Collectors.toList());
  535. log.info("userId:{}获取广告位配置", userId);
  536. List<TicketAdvertiseConfigFrontView> views = beanSearcher.searchAll(TicketAdvertiseConfigFrontView.class, MapUtils.flatBuilder(request.getParameterMap())
  537. .field(TicketAdvertiseConfigFrontView::getGoodsId, goodsIds).op(Operator.InList)
  538. .orderBy(TicketAdvertiseConfigFrontView::getSorted).desc()
  539. .orderBy(TicketAdvertiseConfigFrontView::getGoodsId).asc()
  540. .orderBy(TicketAdvertiseConfigFrontView::getConfigId).desc()
  541. .build());
  542. return GatewayResponse.SUCCESS.newBuilder().toResult(views);
  543. }
  544. /**
  545. * 记录用户点击车票广告
  546. */
  547. @PostMapping("/click/ticket/advertise/record/{configId}")
  548. public Result<String> recordClickTicketAdvertise(@PathVariable Long configId) {
  549. long userId = StpUserUtil.getLoginIdAsLong();
  550. ticketAdvertiseConfigClickRecordService.recordUserClickTicketAdvertise(userId, configId);
  551. return GatewayResponse.SUCCESS.newBuilder().toResult();
  552. }
  553. /**
  554. * 推荐平台
  555. */
  556. @GetMapping("/get/recommend/goods")
  557. public Result<Page<UserRecommendGoodsFrontView>> getRecommendGoodsViews(@RequestParam(defaultValue = "0") Integer start, @RequestParam(defaultValue = "5") Integer limit, String customId) {
  558. //推荐用户未购买的车票平台 优先展示ai类平台 然后是影视流媒体
  559. long userId = StpUserUtil.getLoginIdAsLong();
  560. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
  561. List<Long> filter_goods_id = relationMapper.getTicketGoodsId(userIds, List.of("validity", "overdue", "outside"));
  562. //用户是否购买过奈飞产品
  563. Boolean isPayNf = false;
  564. if (filter_goods_id.contains(1l)) {
  565. isPayNf = true;
  566. } else {
  567. int count = orderDonService.count(Wrappers.lambdaQuery(OrderDon.class)
  568. .eq(OrderDon::getGoodsId, 1)
  569. .eq(OrderDon::getUserId, userId)
  570. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus));
  571. if (count > 0) {
  572. //优先展示路由器、ai、流媒体
  573. isPayNf = true;
  574. }
  575. }
  576. Boolean filterCourseGoods = false;
  577. //GPT Plus基础2月 课程不展示
  578. Integer orders = orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
  579. .in(OrderDon::getUserId, userIds)
  580. .eq(OrderDon::getSkuId, 444)
  581. .notIn(OrderDon::getStatus, Constant.noOrderStatus));
  582. if (orders > 0) {
  583. filterCourseGoods = true;
  584. }
  585. List<Long> yhShopGoodsIds = null;
  586. if (StrUtil.isNotBlank(customId)) {
  587. YhShop yhShop = yhShopMapper.selectOne(Wrappers.lambdaQuery(YhShop.class)
  588. .eq(YhShop::getCustomId, customId)
  589. .last("limit 1"));
  590. if (yhShop != null) {
  591. //获取可用的平台
  592. yhShopGoodsIds = yhShopMapper.getGoodsIdsByShop(yhShop.getId());
  593. }
  594. }
  595. Page<UserRecommendGoodsFrontView> page = groupRelationFrontService.getRecommendGoodsViews(yhShopGoodsIds, isPayNf, filter_goods_id, filterCourseGoods, start, limit);
  596. return GatewayResponse.SUCCESS.newBuilder().toResult(page);
  597. }
  598. /**
  599. * 查看GPT token
  600. */
  601. @GetMapping("/get/gptAccessToken")
  602. public Result<String> getGptAccessToken(Long relationId) throws Exception {
  603. long userId = StpUserUtil.getLoginIdAsLong();
  604. List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
  605. //存在该车票
  606. RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder()
  607. .field(RenewalView::getRelationId, relationId)
  608. .field(RenewalView::getUserId, userIds).op(Operator.InList).build());
  609. Assert.notNull(renewalView, "您的车票不存在");
  610. if (renewalView.getGoodsId() != 42) {
  611. throw BusinessRuntimeException.getInstance("该平台类型车票无法获取GPT直连token");
  612. }
  613. String account = renewalView.getAccount();
  614. String accessToken = chatGptAuthService.getAccessToken(account);
  615. return GatewayResponse.SUCCESS.newBuilder().toResult(accessToken);
  616. }
  617. /**
  618. * 获取特殊类型课程 通过邮件发送课程
  619. * 领取课件
  620. */
  621. @PostMapping("/courseware")
  622. public Result<String> getCourseWare(@RequestBody SpecialGoodsTicketReq request) throws Exception {
  623. long userId = StpUserUtil.getLoginIdAsLong();
  624. request.setUserId(userId);
  625. groupRelationFrontService.sendCourseWare(request);
  626. return GatewayResponse.SUCCESS.newBuilder().toResult();
  627. }
  628. //获取课程云盘链接
  629. @GetMapping("/get/courseware")
  630. public Result<GoodsCoursewareFile> getGoodsCourseware(Long relationId) {
  631. long userId = StpUserUtil.getLoginIdAsLong();
  632. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  633. RenewalView relationView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder()
  634. .field(RenewalView::getUserId, userIdList).op(Operator.InList)
  635. .field(RenewalView::getRelationId, relationId).build());
  636. if (relationView == null) {
  637. throw BusinessRuntimeException.getInstance("您的车票不存在");
  638. }
  639. GoodsCoursewareFile goodsCoursewareFile = goodsCoursewareFileMapper.selectOne(Wrappers.lambdaQuery(GoodsCoursewareFile.class)
  640. .eq(GoodsCoursewareFile::getGoodsId, relationView.getGoodsId())
  641. .eq(GoodsCoursewareFile::getStatus, true)
  642. .select(GoodsCoursewareFile::getLink, GoodsCoursewareFile::getCode)
  643. .last("limit 1"));
  644. if (goodsCoursewareFile == null) {
  645. throw BusinessRuntimeException.getInstance("暂未配置课件链接地址,请联系客服");
  646. }
  647. return GatewayResponse.SUCCESS.newBuilder().toResult(goodsCoursewareFile);
  648. }
  649. /**
  650. * 读取车票账号登录验证码
  651. */
  652. @PostMapping("/get/verifyCode")
  653. public Result<String> getAiVerifyCode(@RequestBody TicketLoginReq loginReq) throws Exception {
  654. long userId = StpUserUtil.getLoginIdAsLong();
  655. loginReq.setUserId(userId);
  656. return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.getAiVerifyCode(loginReq));
  657. }
  658. /**
  659. * 车票后台登录
  660. */
  661. @PostMapping("/ticket/login")
  662. public Result<GroupsRelation> ticketLogin(@RequestBody TicketLoginReq loginReq) {
  663. GroupsRelation relation = groupRelationFrontService.ticketLogin(loginReq);
  664. return GatewayResponse.SUCCESS.newBuilder().toResult(relation);
  665. }
  666. /**
  667. * 奈飞验证校验
  668. */
  669. @PostMapping("/ticket/verify")
  670. public Result<String> outsideTicketVerify(@RequestBody TicketLoginReq loginReq) {
  671. return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.outsideTicketVerify(loginReq));
  672. }
  673. /**
  674. * 是否有mid车票可候补
  675. */
  676. @GetMapping("/get/standby")
  677. public Result<GptStandbyResp> getGptStandby() {
  678. long userId = StpUserUtil.getLoginIdAsLong();
  679. List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
  680. String condition = "(a.account like '%@yinhe.ac.cn%' or exists (select id from account_blocked_replace_record abrr where abrr.account = a.account and abrr.goods_id = g.id limit 1))";
  681. List<RenewalView> renewalViewList = beanSearcher.searchAll(RenewalView.class, MapUtils.builder()
  682. .field(RenewalView::getUserId, relationUserIdList).op(Operator.InList)
  683. .field(RenewalView::getGoodsId, 26)
  684. .put("condition", condition)
  685. .field(RenewalView::getExpiryTime).op(Operator.NotNull)
  686. .onlySelect(RenewalView::getAccount, RenewalView::getExpiryTime)
  687. .build());
  688. GptStandbyResp gptStandbyResp = new GptStandbyResp();
  689. if (renewalViewList.isEmpty()) {
  690. gptStandbyResp.setIsHasAccount(false);
  691. return GatewayResponse.SUCCESS.newBuilder().toResult(gptStandbyResp);
  692. }
  693. List<RenewalView> overTen = new ArrayList<>();
  694. List<RenewalView> underTen = new ArrayList<>();
  695. DateTime now = DateTime.now();
  696. renewalViewList.forEach(e -> {
  697. if (e.getExpiryTime().compareTo(DateUtil.offsetDay(now, 10)) > 0) {
  698. overTen.add(e);
  699. } else underTen.add(e);
  700. });
  701. Integer accountBlockedCount = 1;
  702. if (overTen.size() > 1) {
  703. List<String> accountList = overTen.stream().map(RenewalView::getAccount).distinct().collect(Collectors.toList());
  704. accountBlockedCount = accountBlockedReplaceRecordMapper.selectCount(Wrappers.lambdaQuery(AccountBlockedReplaceRecord.class)
  705. .eq(AccountBlockedReplaceRecord::getGoodsId, 26)
  706. .in(AccountBlockedReplaceRecord::getAccount, accountList));
  707. }
  708. if (accountBlockedCount > 1) {
  709. gptStandbyResp.setIsHasAccount(false);
  710. return GatewayResponse.SUCCESS.newBuilder().toResult(gptStandbyResp);
  711. }
  712. gptStandbyResp.setIsHasAccount(true);
  713. gptStandbyResp.setOverTen(overTen);
  714. gptStandbyResp.setUnderTen(underTen);
  715. Integer count = gptTicketStandbyMapper.selectCount(Wrappers.lambdaQuery(GptTicketStandby.class)
  716. .in(GptTicketStandby::getUserId, relationUserIdList));
  717. gptStandbyResp.setIsApply(count > 0 ? true : false);
  718. return GatewayResponse.SUCCESS.newBuilder().toResult(gptStandbyResp);
  719. }
  720. /**
  721. * 申请候补
  722. */
  723. @PostMapping("/apply/standby")
  724. @NoSubmit
  725. public Result<Boolean> applyGptStandby() {
  726. long userId = StpUserUtil.getLoginIdAsLong();
  727. List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
  728. String condition = "(a.account like '%@yinhe.ac.cn%' or exists (select id from account_blocked_replace_record abrr where abrr.account = a.account and abrr.goods_id = g.id limit 1))";
  729. List<RenewalView> renewalViewList = beanSearcher.searchAll(RenewalView.class, MapUtils.builder()
  730. .field(RenewalView::getUserId, relationUserIdList).op(Operator.InList)
  731. .field(RenewalView::getGoodsId, 26)
  732. .put("condition", condition)
  733. .field(RenewalView::getExpiryTime, DateUtil.offsetDay(DateTime.now(), 10)).op(Operator.GreaterThan)
  734. .onlySelect(RenewalView::getAccount)
  735. .build());
  736. if (renewalViewList.isEmpty()) {
  737. throw BusinessRuntimeException.getInstance("你未有车票账号");
  738. }
  739. Integer count = gptTicketStandbyMapper.selectCount(Wrappers.lambdaQuery(GptTicketStandby.class)
  740. .in(GptTicketStandby::getUserId, relationUserIdList));
  741. if (count > 0) {
  742. throw BusinessRuntimeException.getInstance("你已申请车票账号候补");
  743. }
  744. if (renewalViewList.size() > 1) {
  745. Set<String> accountSet = renewalViewList.stream().map(RenewalView::getAccount).collect(Collectors.toSet());
  746. Integer accountBlockedCount = accountBlockedReplaceRecordMapper.selectCount(Wrappers.lambdaQuery(AccountBlockedReplaceRecord.class)
  747. .eq(AccountBlockedReplaceRecord::getGoodsId, 26)
  748. .in(AccountBlockedReplaceRecord::getAccount, accountSet));
  749. if (accountBlockedCount > 1) {
  750. return GatewayResponse.SUCCESS.newBuilder().toResult(true);
  751. }
  752. }
  753. GptTicketStandby gptTicketStandby = new GptTicketStandby();
  754. gptTicketStandby.setUserId(userId);
  755. gptTicketStandbyMapper.insert(gptTicketStandby);
  756. return GatewayResponse.SUCCESS.newBuilder().toResult(true);
  757. }
  758. /**
  759. * midjourney车票退款
  760. */
  761. @PutMapping("/refund/ticketOrder/{relationId}")
  762. @NoSubmit
  763. public Result<String> ticketRefundOrders(@PathVariable Long relationId) throws Exception {
  764. long userId = StpUserUtil.getLoginIdAsLong();
  765. List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
  766. String condition = "(a.account like '%@yinhe.ac.cn%' or exists (select id from account_blocked_replace_record abrr where abrr.account = a.account and abrr.goods_id = g.id limit 1))";
  767. RenewalView renewalView = beanSearcher.searchFirst(RenewalView.class, MapUtils.builder()
  768. .field(RenewalView::getRelationId, relationId)
  769. .field(RenewalView::getUserId, relationUserIdList).op(Operator.InList)
  770. .put("condition", condition)
  771. .field(RenewalView::getGoodsId, 26)
  772. .field(RenewalView::getExpiryTime, DateUtil.offsetDay(DateTime.now(), 10)).op(Operator.LessEqual)
  773. .build());
  774. if (renewalView == null) {
  775. throw BusinessRuntimeException.getInstance("你车票不存在或不符合退款要求");
  776. }
  777. OrderDon orderDon = orderDonService.getOne(Wrappers.lambdaQuery(OrderDon.class)
  778. .in(OrderDon::getUserId, relationUserIdList)
  779. .eq(OrderDon::getRelationId, relationId)
  780. .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
  781. .orderByDesc(OrderDon::getId)
  782. .last("limit 1"));
  783. if (orderDon == null) {
  784. throw BusinessRuntimeException.getInstance("你对应车票的订单不存在");
  785. }
  786. GoodsDonSku sku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
  787. if (sku == null) {
  788. throw BusinessRuntimeException.getInstance("该车票规格不存在,请联系客服进行人工退款..");
  789. }
  790. Date expiryTime = renewalView.getExpiryTime();
  791. long remainDay = DateUtil.between(DateTime.now(), expiryTime, DateUnit.DAY) + 1;
  792. BigDecimal money = orderDon.getMoney();
  793. BigDecimal refundMoney = null;
  794. BigDecimal refundBalance= null;
  795. String refundType = null;
  796. if (money.compareTo(BigDecimal.ZERO) > 0) {
  797. BigDecimal dayMoney = money.divide(BigDecimal.valueOf(sku.getMonths()).multiply(BigDecimal.valueOf(30)), 2, RoundingMode.HALF_DOWN);
  798. refundMoney = BigDecimal.valueOf(remainDay).multiply(dayMoney);
  799. refundType = "money";
  800. }
  801. OrderRefundReq refundReq = new OrderRefundReq();
  802. if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
  803. BigDecimal dayMoney = orderDon.getBalance().divide(BigDecimal.valueOf(sku.getMonths()).multiply(BigDecimal.valueOf(30)), 2, RoundingMode.HALF_DOWN);
  804. refundBalance = BigDecimal.valueOf(remainDay).multiply(dayMoney);
  805. refundReq.setIsOnly(true);
  806. }
  807. refundReq.setOrderId(orderDon.getId());
  808. refundReq.setRefundDesc("失效车票退款");
  809. refundReq.setRefundMoney(Optional.ofNullable(refundMoney).orElse(BigDecimal.ZERO));
  810. refundReq.setRefundBalance(Optional.ofNullable(refundBalance).orElse(BigDecimal.ZERO));
  811. refundReq.setRefundType(Optional.ofNullable(refundType).orElse("balance"));
  812. cmsOrderDonService.unifiedRefund(refundReq);
  813. return GatewayResponse.SUCCESS.newBuilder().toResult();
  814. }
  815. /**
  816. * 每日车票到期弹窗
  817. */
  818. @GetMapping("/get/expiry/notify")
  819. public Result<List<RenewalView>> getExpiryRenewalNotify() {
  820. Long userId = StpUserUtil.getLoginIdAsLong();
  821. List<RenewalView> expiryRenewals = groupRelationFrontService.getExpiryRenewalNotify(userId);
  822. return GatewayResponse.SUCCESS.newBuilder().toResult(expiryRenewals);
  823. }
  824. /**
  825. * 车票详情
  826. */
  827. @GetMapping("/get/detail")
  828. public Result<RenewalView> getTicketDetail(Long relationId) {
  829. if (relationId == null) {
  830. return GatewayResponse.SUCCESS.newBuilder().toResult();
  831. }
  832. long userId = StpUserUtil.getLoginIdAsLong();
  833. RenewalView ticketDetail = groupRelationFrontService.getTicketDetail(userId, relationId);
  834. return GatewayResponse.SUCCESS.newBuilder().toResult(ticketDetail);
  835. }
  836. /**
  837. * 车票售后常见问题
  838. */
  839. @GetMapping("/get/questions/{goodsId}")
  840. public Result<List<GoodsDonQaFrontView>> getTicketQuestions(@PathVariable Long goodsId, @RequestParam(defaultValue = "1") Integer type) {
  841. long userId = StpUserUtil.getLoginIdAsLong();
  842. log.info("userId:{}查看车票:{}售后问题", userId, goodsId);
  843. if (type < 1 || type > 2) {
  844. return GatewayResponse.SUCCESS.newBuilder().toResult();
  845. }
  846. String key = RedisService.key.YH_GOODS_QUESTIONS_DETAIL.getNameFormat(type, goodsId);
  847. Object o = redisService.get(key);
  848. if (o == null) {
  849. List<GoodsDonQaFrontView> donQaFrontViews = beanSearcher.searchAll(GoodsDonQaFrontView.class, MapUtils.builder().field(GoodsDonQaFrontView::getGoodsId, goodsId).field(GoodsDonQaFrontView::getType, type).build());
  850. if (CollUtil.isEmpty(donQaFrontViews)) {
  851. return GatewayResponse.SUCCESS.newBuilder().toResult();
  852. }
  853. redisService.setNx(key, donQaFrontViews, RedisService.key.YH_GOODS_QUESTIONS_DETAIL.getTimeout());
  854. o = redisService.get(key);
  855. }
  856. List<GoodsDonQaFrontView> donQaFrontViews = Jsons.parseList(o, GoodsDonQaFrontView.class);
  857. return GatewayResponse.SUCCESS.newBuilder().toResult(donQaFrontViews);
  858. }
  859. /**
  860. * 车票所有常见问题
  861. */
  862. @GetMapping("/get/questions")
  863. public Result<List<GoodsDonQaFrontView>> getAllTicketQuestions(String participle) {
  864. MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
  865. if (StrUtil.isNotBlank(participle)) {
  866. char[] charArray = participle.toCharArray();
  867. StringBuilder p = new StringBuilder();
  868. p.append("and (");
  869. for (int i = 0; i < charArray.length; i++) {
  870. char c = charArray[i];
  871. p.append(String.format(" ga.problem like '%%%s%%'", c));
  872. if (i != charArray.length - 1) {
  873. p.append(" or ");
  874. }
  875. }
  876. p.append(")");
  877. builder.put("p", p);
  878. }
  879. List<GoodsDonQaFrontView> donQaFrontViews = beanSearcher.searchAll(GoodsDonQaFrontView.class, builder.build());
  880. return GatewayResponse.SUCCESS.newBuilder().toResult(donQaFrontViews);
  881. }
  882. /**
  883. * 车票常见问题 分页
  884. */
  885. @GetMapping("/get/questions/page")
  886. public Result<SearchResult<GoodsDonQaFrontView>> getTicketQuestionsPage(String participle) {
  887. MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
  888. if (StrUtil.isNotBlank(participle)) {
  889. char[] charArray = participle.toCharArray();
  890. StringBuilder p = new StringBuilder();
  891. p.append("and (");
  892. for (int i = 0; i < charArray.length; i++) {
  893. char c = charArray[i];
  894. p.append(String.format(" ga.problem like '%%%s%%'", c));
  895. if (i != charArray.length - 1) {
  896. p.append(" or ");
  897. }
  898. }
  899. p.append(")");
  900. builder.put("p", p);
  901. }
  902. SearchResult<GoodsDonQaFrontView> donQaFrontViews = beanSearcher.search(GoodsDonQaFrontView.class, builder.build());
  903. return GatewayResponse.SUCCESS.newBuilder().toResult(donQaFrontViews);
  904. }
  905. /**
  906. * 是否首次购买车票
  907. */
  908. @GetMapping("/get/first/pay/{goodsId}")
  909. public Result<Boolean> getFirstPay(@PathVariable Long goodsId) {
  910. long userId = StpUserUtil.getLoginIdAsLong();
  911. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  912. Number number = beanSearcher.searchCount(OrderDon.class, MapUtils.builder()
  913. .field(OrderDon::getGoodsId, goodsId)
  914. .field(OrderDon::getCreatedTime, new DateTime().toDateStr()).op(Operator.LessEqual)
  915. .field(OrderDon::getUserId, userIdList).op(Operator.InList)
  916. .field(OrderDon::getStatus, Constant.noOrderStatus).op(Operator.NotIn)
  917. .build());
  918. if (number.intValue() == 0) {
  919. UserGoodsNewbieGuideRecord userGoodsNewbieGuideRecord = new UserGoodsNewbieGuideRecord();
  920. userGoodsNewbieGuideRecord.setGoodsId(goodsId);
  921. userGoodsNewbieGuideRecord.setUserId(userId);
  922. userGoodsNewbieGuideRecordMapper.insert(userGoodsNewbieGuideRecord);
  923. return GatewayResponse.SUCCESS.newBuilder().toResult(true);
  924. }
  925. return GatewayResponse.SUCCESS.newBuilder().toResult(false);
  926. }
  927. /**
  928. * 设置pin码
  929. */
  930. @PutMapping("/set/pin/{relationId}")
  931. public Result<String> setPin(@PathVariable Long relationId, String code) {
  932. long userId = StpUserUtil.getLoginIdAsLong();
  933. JSONObject data = groupsRelationNetflixService.setNetflixPin(relationId, userId, code);
  934. return GatewayResponse.SUCCESS.newBuilder().toResult(data.toString());
  935. }
  936. /**
  937. * 查询是否设置成功
  938. */
  939. @GetMapping("/get/pin/status/{taskId}")
  940. public Result<Integer> getPinStatus(@PathVariable String taskId) throws Exception {
  941. long userId = StpUserUtil.getLoginIdAsLong();
  942. log.info("userId:{}查看设置pin码状态", userId);
  943. return GatewayResponse.SUCCESS.newBuilder().toResult(groupsRelationNetflixService.getPinStatus(taskId));
  944. }
  945. /**
  946. * 踢出奈飞设备
  947. */
  948. @PostMapping("/kickOut/nf/{relationId}")
  949. public Result<String> nfKickOut(@PathVariable Long relationId) {
  950. long userId = StpUserUtil.getLoginIdAsLong();
  951. JSONObject data = groupsRelationNetflixService.nfKickOut(userId, relationId);
  952. return GatewayResponse.SUCCESS.newBuilder().toResult(data.toString());
  953. }
  954. /**
  955. * 奈飞同户装置链接
  956. */
  957. @GetMapping("/get/nf/household/device")
  958. public Result<String> getNfHouseholdDevice(@NotNull Long relationId) throws Exception {
  959. long userId = StpUserUtil.getLoginIdAsLong();
  960. String url = groupRelationFrontService.getNfHouseholdDevice(userId, relationId);
  961. return GatewayResponse.SUCCESS.newBuilder().toResult(url);
  962. }
  963. /**
  964. * 代点奈飞同户装置
  965. */
  966. @PostMapping("/click/nf/household/device")
  967. public void clickNfHouseholdDevice(@RequestBody NfDeviceReq nfDeviceReq) {
  968. groupsRelationNetflixService.clickNfHouseholdDevice(nfDeviceReq);
  969. }
  970. /**
  971. * 可选 续费升级车票
  972. */
  973. @GetMapping("/get/renew/skus/{relationId}/{skuId}")
  974. public Result<List<RenewUpgradePackageFrontView>> getRenewSkus(@PathVariable Long relationId, @PathVariable Long skuId) {
  975. long userId = StpUserUtil.getLoginIdAsLong();
  976. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  977. ChatgptUser chatgptUser = chatgptUserMapper.selectOne(Wrappers.lambdaQuery(ChatgptUser.class)
  978. .eq(ChatgptUser::getRelationId, relationId)
  979. .last("limit 1"));
  980. if (chatgptUser == null) return GatewayResponse.SUCCESS.newBuilder().toResult();
  981. //目前续费升级的规格
  982. Long renewSkuId = chatgptUser.getRenewSkuId();
  983. GoodsDonSku sku = goodsDonSkuMapper.selectById(skuId);
  984. AtomicInteger minMonths = new AtomicInteger(sku.getMonths());
  985. AtomicInteger minNum = new AtomicInteger(chatgptUser.getLimitNum());
  986. AtomicLong minTime = new AtomicLong(chatgptUser.getLimitTime());
  987. if (renewSkuId != null) {
  988. GoodsDonSku presentRenew = goodsDonSkuMapper.selectById(renewSkuId);
  989. minMonths.set(presentRenew.getMonths());
  990. }
  991. if (chatgptUser.getPackageId() != 0) {
  992. Long packageId = chatgptUser.getPackageId();
  993. UpgradeOrderDon upgradeOrderDon = upgradeOrderDonMapper.selectOne(Wrappers.lambdaQuery(UpgradeOrderDon.class)
  994. .eq(UpgradeOrderDon::getPackageId, packageId)
  995. .eq(UpgradeOrderDon::getRelationId, relationId)
  996. .in(UpgradeOrderDon::getUserId, userIdList)
  997. .last("limit 1"));
  998. Long upgradeOrderDonSkuId = upgradeOrderDon.getSkuId();
  999. GoodsDonSku upgradeSku = goodsDonSkuMapper.selectById(upgradeOrderDonSkuId);
  1000. if (upgradeSku != null) {
  1001. if (upgradeSku.getMonths() > minMonths.get()) {
  1002. minMonths.set(upgradeSku.getMonths());
  1003. }
  1004. }
  1005. }
  1006. String lang = request.getHeader("lang");
  1007. List<RenewUpgradePackageFrontView> renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build());
  1008. renewUpgradePackageFrontViews.forEach(renew -> {
  1009. try {
  1010. List<Long> upgradeSkuIds = Jsons.parseList(renew.getUpgradeSkuIds(), Long.class);
  1011. //年付展示
  1012. MapBuilder builder = MapUtils.builder();
  1013. // if (minMonths.get() == 12) {
  1014. // builder.field(RenewUpgradePackageFrontView.RenewSkuView::getMonths, minMonths.get()).op(Operator.GreaterEqual);
  1015. // if (renewSkuId != null) {
  1016. // upgradeSkuIds.remove(renewSkuId);
  1017. // }
  1018. // } else {
  1019. // builder.field(RenewUpgradePackageFrontView.RenewSkuView::getMonths, minMonths.get()).op(Operator.GreaterEqual);
  1020. // }
  1021. //GPT镜像2月规格 特殊处理
  1022. if (sku.getGoodsId() == 18 && sku.getMonths() == 2) {
  1023. } else {
  1024. //同续费时间规格
  1025. builder.field(RenewUpgradePackageFrontView.RenewSkuView::getMonths, minMonths.get()).op(Operator.GreaterEqual);
  1026. }
  1027. if (renewSkuId != null) {
  1028. upgradeSkuIds.remove(renewSkuId);
  1029. }
  1030. List<RenewUpgradePackageFrontView.RenewSkuView> renewSkuViews = new ArrayList<>();
  1031. if (CollUtil.isNotEmpty(upgradeSkuIds)) {
  1032. renewSkuViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.RenewSkuView.class, builder
  1033. .field(RenewUpgradePackageFrontView.RenewSkuView::getGptLimitNum, minNum.get()).op(Operator.GreaterEqual)
  1034. .field(RenewUpgradePackageFrontView.RenewSkuView::getGptLimitTime, minTime.get()).op(LessEqual.class)
  1035. .field(RenewUpgradePackageFrontView.RenewSkuView::getSkuId, upgradeSkuIds).op(Operator.InList)
  1036. .build());
  1037. if (lang != null && !StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
  1038. renewSkuViews.forEach(renewSku->{
  1039. String languageSpecVal = backInfoTranslationsFrontService.getLanguageSpecVal(renewSku.getSkuId(), lang);
  1040. if (StrUtil.isNotBlank(languageSpecVal)) {
  1041. renewSku.setSpecVal(languageSpecVal);
  1042. }
  1043. });
  1044. }
  1045. }
  1046. renew.setRenewSkus(renewSkuViews);
  1047. } catch (Exception e) {
  1048. }
  1049. });
  1050. return GatewayResponse.SUCCESS.newBuilder().toResult(renewUpgradePackageFrontViews);
  1051. }
  1052. /**
  1053. * 独立规格续费套餐列表
  1054. */
  1055. @GetMapping("/get/independent/renew/skus/{skuId}")
  1056. public Result<List<RenewUpgradePackageFrontView>> getRenewSkus(@PathVariable Long skuId) {
  1057. long userId = StpUserUtil.getLoginIdAsLong();
  1058. List<RenewUpgradePackageFrontView> renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build());
  1059. renewUpgradePackageFrontViews.forEach(renew -> {
  1060. try {
  1061. List<Long> upgradeSkuIds = Jsons.parseList(renew.getUpgradeSkuIds(), Long.class);
  1062. MapBuilder builder = MapUtils.builder();
  1063. List<RenewUpgradePackageFrontView.RenewSkuView> renewSkuViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.RenewSkuView.class, builder
  1064. .field(RenewUpgradePackageFrontView.RenewSkuView::getSkuId, upgradeSkuIds).op(Operator.InList)
  1065. .build());
  1066. renew.setRenewSkus(renewSkuViews);
  1067. } catch (Exception e) {
  1068. }
  1069. });
  1070. return GatewayResponse.SUCCESS.newBuilder().toResult(renewUpgradePackageFrontViews);
  1071. }
  1072. /**
  1073. * claude pro续费升级
  1074. */
  1075. @GetMapping("/get/claude/renew/skus/{relationId}/{skuId}")
  1076. public Result<List<RenewUpgradePackageFrontView> > getClaudeRenewSkus(@PathVariable Long relationId, @PathVariable Long skuId) {
  1077. long userId = StpUserUtil.getLoginIdAsLong();
  1078. ClaudeUser claudeUser = claudeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeUser.class)
  1079. .eq(ClaudeUser::getRelationId, relationId)
  1080. .last("limit 1"));
  1081. if (claudeUser == null) return GatewayResponse.SUCCESS.newBuilder().toResult();
  1082. List<RenewUpgradePackageFrontView> renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build());
  1083. renewUpgradePackageFrontViews.forEach(renew -> {
  1084. try {
  1085. List<Long> upgradeSkuIds = Jsons.parseList(renew.getUpgradeSkuIds(), Long.class);
  1086. MapBuilder builder = MapUtils.builder();
  1087. List<RenewUpgradePackageFrontView.RenewSkuView> renewSkuViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.RenewSkuView.class, builder
  1088. .field(RenewUpgradePackageFrontView.RenewSkuView::getSkuId, upgradeSkuIds).op(Operator.InList)
  1089. .field(RenewUpgradePackageFrontView.RenewSkuView::getGptLimitNum, claudeUser.getLimitNum()).op(Operator.GreaterEqual)
  1090. .build());
  1091. renew.setRenewSkus(renewSkuViews);
  1092. } catch (Exception e) {
  1093. }
  1094. });
  1095. return GatewayResponse.SUCCESS.newBuilder().toResult(renewUpgradePackageFrontViews);
  1096. }
  1097. /**
  1098. * 已配置的续费升级规格ids
  1099. */
  1100. @GetMapping("/get/renew/skus/configured")
  1101. public Result<List<Long> > getClaudeRenewSkus() {
  1102. long userId = StpUserUtil.getLoginIdAsLong();
  1103. List<RenewUpgradePackageFrontView> renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().onlySelect(RenewUpgradePackageFrontView::getSkuId).build());
  1104. List<Long> collect = renewUpgradePackageFrontViews.stream().map(RenewUpgradePackageFrontView::getSkuId).collect(Collectors.toList());
  1105. return GatewayResponse.SUCCESS.newBuilder().toResult(collect);
  1106. }
  1107. /**
  1108. * 获取邮箱验证码
  1109. */
  1110. @GetMapping("/get/email/code")
  1111. public Result<String> getEmailCode(Long relationId) throws Exception {
  1112. long userId = StpUserUtil.getLoginIdAsLong();
  1113. return GatewayResponse.SUCCESS.newBuilder().toResult(groupRelationFrontService.getEmailCode(userId, relationId));
  1114. }
  1115. /**
  1116. * 获取GPT PLUS登录验证码
  1117. */
  1118. @GetMapping("/get/verify/code")
  1119. public Result<String> getVerifyCode(@NotEmpty String account) throws Exception {
  1120. String code = groupRelationFrontService.getVerifyCode(account);
  1121. if (StrUtil.isEmpty(code)) {
  1122. throw BusinessRuntimeException.getInstance("请重新发送验证码");
  1123. }
  1124. return GatewayResponse.SUCCESS.newBuilder().toResult(code);
  1125. }
  1126. /**
  1127. * 独立规格续费减免
  1128. */
  1129. @GetMapping("/get/renew/reduce")
  1130. public Result<UserBenefitsFrontView> getRenewReduce(Long skuId, Long relationId) {
  1131. long userId = StpUserUtil.getLoginIdAsLong();
  1132. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1133. UserBenefitsFrontView data = beanSearcher.searchFirst(UserBenefitsFrontView.class, MapUtils.builder().field(UserBenefitsFrontView::getSkuId, skuId).field(UserBenefitsFrontView::getType, UserBenefits.Type.RENEW.name()).build());
  1134. if (data == null) {
  1135. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1136. }
  1137. Date startTime = null;
  1138. if (relationId != null) {
  1139. GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
  1140. .eq(GroupsRelation::getId, relationId)
  1141. .in(GroupsRelation::getUserId, userIdList));
  1142. if (relation == null) {
  1143. throw BusinessRuntimeException.getInstance("车票不存在");
  1144. }
  1145. startTime = relation.getStartTime();
  1146. }
  1147. Integer renewCount = userBenefitsOrderRecordMapper.selectUseComboRecordByUid(userIdList, data.getType(), data.getGoodsId(), data.getSkuId(), Constant.noOrderAllStatus, null, startTime, relationId);
  1148. data.setRenewCount(renewCount);
  1149. return GatewayResponse.SUCCESS.newBuilder().toResult(data);
  1150. }
  1151. /**
  1152. * 申请更换车票
  1153. */
  1154. @PostMapping("/change/ticket")
  1155. @Deprecated
  1156. public Result<String> changeTicket(@RequestBody ChangeTicketReq changeTicketReq) {
  1157. long userId = StpUserUtil.getLoginIdAsLong();
  1158. List<Long> relationIds = changeTicketReq.getRelationIds();
  1159. if (CollUtil.isEmpty(relationIds)) {
  1160. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1161. }
  1162. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1163. //奈飞超过3帐车票不给看
  1164. Number number = beanSearcher.searchCount(RenewalView.class, MapUtils.builder()
  1165. .field(RenewalView::getUserId, userIdList).op(Operator.InList)
  1166. .field(RenewalView::getGoodsId, 1)
  1167. .field(RenewalView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
  1168. .build());
  1169. if (number.intValue() > 2) {
  1170. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1171. }
  1172. relationIds.forEach(relationId -> {
  1173. try {
  1174. groupRelationFrontService.changeTicket(userId, relationId);
  1175. } catch (Exception e) {
  1176. log.error("更换车票失败:{}", StringUtil.getErrorText(e));
  1177. if (relationIds.size() == 1) {
  1178. throw BusinessRuntimeException.getInstance(e.getMessage());
  1179. }
  1180. }
  1181. });
  1182. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1183. }
  1184. /**
  1185. * 查看临时账号
  1186. */
  1187. @GetMapping("/get/temp/account/{relationId}")
  1188. public Result<AccountView> getTempAccount(@PathVariable Long relationId) {
  1189. long userId = StpUserUtil.getLoginIdAsLong();
  1190. AccountView accountView = groupRelationFrontService.getTempAccount(userId, relationId);
  1191. return GatewayResponse.SUCCESS.newBuilder().toResult(accountView);
  1192. }
  1193. /**
  1194. * 申请提交记录
  1195. */
  1196. @GetMapping("/get/netflix/get/error/submit/record")
  1197. public Result<List<NetflixUserAccountStatusRecord>> getUserNetflixSubmitRecord() {
  1198. long userId = StpUserUtil.getLoginIdAsLong();
  1199. List<NetflixUserAccountStatusRecord> netflixUserAccountStatusRecords = groupRelationFrontService.getUserNetflixSubmitRecord(userId);
  1200. return GatewayResponse.SUCCESS.newBuilder().toResult(netflixUserAccountStatusRecords);
  1201. }
  1202. /**
  1203. * 奈飞账号异常检测提交
  1204. */
  1205. @PostMapping("/netflix/error/account/submit/{relationId}")
  1206. public Result<String> nfErrorAccountSubmit(@PathVariable Long relationId) {
  1207. long userId = StpUserUtil.getLoginIdAsLong();
  1208. groupRelationFrontService.nfErrorAccountSubmit(userId, relationId);
  1209. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1210. }
  1211. /**
  1212. * 奈飞账号检测结果
  1213. */
  1214. @GetMapping("/get/netflix/error/account/status/{relationId}")
  1215. public Result<NetflixErrorAccountStatus> getNetflixErrorAccountStatus(@PathVariable Long relationId) {
  1216. long userId = StpUserUtil.getLoginIdAsLong();
  1217. NetflixErrorAccountStatus status = groupRelationFrontService.getNetflixErrorAccountStatus(userId, relationId);
  1218. return GatewayResponse.SUCCESS.newBuilder().toResult(status);
  1219. }
  1220. /**
  1221. * 奈飞可替换其他规格车票列表
  1222. */
  1223. @GetMapping("/get/netflix/replace/other/skus/{relationId}")
  1224. public Result<List<GoodsCategorySkuView>> getNetflixReplaceOtherSkus(@PathVariable Long relationId) throws Exception {
  1225. long userId = StpUserUtil.getLoginIdAsLong();
  1226. List<GoodsCategorySkuView> goodsCategorySkuViews = groupRelationFrontService.getNetflixReplaceOtherSkus(userId, relationId);
  1227. return GatewayResponse.SUCCESS.newBuilder().toResult(goodsCategorySkuViews);
  1228. }
  1229. /**
  1230. * 奈飞账号申请恢复
  1231. */
  1232. @PostMapping("/netflix/submit/recover")
  1233. public Result<NetflixRecoverResp> netflixSubmitRecover(@RequestBody ErrorNetflixChangeReq req) {
  1234. long userId = StpUserUtil.getLoginIdAsLong();
  1235. req.setUserId(userId);
  1236. NetflixRecoverResp recoverResp = groupRelationFrontService.netflixSubmitRecover(req);
  1237. return GatewayResponse.SUCCESS.newBuilder().toResult(recoverResp);
  1238. }
  1239. /**
  1240. * 奈飞申请冻结
  1241. */
  1242. @PostMapping("/netflix/submit/frozen")
  1243. public Result<String> netflixSubmitFrozen(@RequestBody ErrorNetflixChangeReq req) {
  1244. long userId = StpUserUtil.getLoginIdAsLong();
  1245. req.setUserId(userId);
  1246. groupRelationFrontService.netflixSubmitFrozen(req);
  1247. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1248. }
  1249. /**
  1250. * 奈飞更换其他车票
  1251. */
  1252. @PostMapping("/netflix/submit/change/otherTicket")
  1253. public Result<Integer> errorNetflixSubmitChangeOtherTicket(@RequestBody ErrorNetflixChangeReq req) throws Exception {
  1254. long userId = StpUserUtil.getLoginIdAsLong();
  1255. req.setUserId(userId);
  1256. groupRelationFrontService.errorNetflixSubmitChangeOtherTicket(req);
  1257. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1258. }
  1259. /**
  1260. * 不超过30天 奈飞退款info
  1261. */
  1262. @GetMapping("/netflix/refund/info/{relationId}")
  1263. public Result<NetflixRefundInfoResp> refundNetflixInfo(@PathVariable Long relationId) {
  1264. long userId = StpUserUtil.getLoginIdAsLong();
  1265. //是否可进行退款 true可 false否 走恢复账号流程
  1266. NetflixRefundInfoResp refundInfoResp = groupRelationFrontService.refundNetflixInfo(userId, relationId);
  1267. return GatewayResponse.SUCCESS.newBuilder().toResult(refundInfoResp);
  1268. }
  1269. /**
  1270. * 奈飞不超过30天有效期进行退款
  1271. * 是否可进行退款 true可 false否 走恢复账号流程
  1272. */
  1273. @PostMapping("/netflix/refund")
  1274. public Result<Boolean> refundNetflix(@RequestBody ErrorNetflixChangeReq req) throws Exception {
  1275. long userId = StpUserUtil.getLoginIdAsLong();
  1276. req.setUserId(userId);
  1277. //是否可进行退款 true可 false否 走恢复账号流程
  1278. Boolean availableRefund = groupRelationFrontService.refundNetflix(req);
  1279. return GatewayResponse.SUCCESS.newBuilder().toResult(availableRefund);
  1280. }
  1281. /**
  1282. * AI镜像车票 每周弹窗
  1283. */
  1284. @GetMapping("/get/mirror/popups")
  1285. public Result<Boolean> getMirrorPopups() {
  1286. long userId = StpUserUtil.getLoginIdAsLong();
  1287. Boolean flag = groupRelationFrontService.getMirrorPopups(userId);
  1288. return GatewayResponse.SUCCESS.newBuilder().toResult(flag);
  1289. }
  1290. /**
  1291. * 银河币续费车票列表
  1292. */
  1293. @GetMapping("/get/galaxyCoin/tickets")
  1294. public Result<SearchResult<GalaxyCoinRenewTicketsView>> getGalaxyCoinTickets() throws Exception {
  1295. long userId = StpUserUtil.getLoginIdAsLong();
  1296. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1297. DateTime now = DateTime.now();
  1298. //非独立账号
  1299. String conditionSql = String.format("(gr.expiry_time is null or gr.expiry_time > '%s' or (sku.is_mirror and gr.expiry_time > '%s')) and (sku.months is null or sku.months != 300)", now, DateUtil.offsetDay(now, -7));
  1300. SearchResult<GalaxyCoinRenewTicketsView> search = beanSearcher.search(GalaxyCoinRenewTicketsView.class, MapUtils.flatBuilder(request.getParameterMap())
  1301. .field(GalaxyCoinRenewTicketsView::getUserId, userIdList).op(Operator.InList)
  1302. .put("condition", conditionSql)
  1303. .field(GalaxyCoinRenewTicketsView::getIsVip, Boolean.FALSE)
  1304. //购买
  1305. .field(GalaxyCoinRenewTicketsView::getAqType, 1)
  1306. //非代充
  1307. .field(GalaxyCoinRenewTicketsView::getRechargeStatus).op(Operator.IsNull)
  1308. //车队状态
  1309. .field(GalaxyCoinRenewTicketsView::getGroupsStatus, GroupsTrips.Status.waiting.name()).op(Operator.NotEqual)
  1310. .field(GalaxyCoinRenewTicketsView::getStatus, List.of(GroupsRelation.Status.validity.name(), GroupsRelation.Status.outside.name())).op(Operator.InList)
  1311. .field(GalaxyCoinRenewTicketsView::getSecondType, 2)
  1312. .orderBy(GalaxyCoinRenewTicketsView::getExpiryTime).asc()
  1313. .build());
  1314. User user = userMapper.selectById(userId);
  1315. if (user.getGalaxyCoin().compareTo(BigDecimal.ZERO) == 0) {
  1316. return GatewayResponse.SUCCESS.newBuilder().toResult(search);
  1317. }
  1318. BigDecimal userGalaxyCoin = user.getGalaxyCoin();
  1319. SysConfig payDeductConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
  1320. .eq(SysConfig::getSysKey, Constant.GALAXY_COIN_PAY_DEDUCT_KEY)
  1321. .last("limit 1"));
  1322. GalaxyCoinPayConfigDto galaxyCoinPayConfigDto = Jsons.parseObject(payDeductConfig.getSysValue(), GalaxyCoinPayConfigDto.class);
  1323. BigDecimal maxRate = galaxyCoinPayConfigDto.getMaxRate();
  1324. BigDecimal payGalaxyCoin = galaxyCoinPayConfigDto.getGalaxyCoin();
  1325. BigDecimal payMoney = galaxyCoinPayConfigDto.getMoney();
  1326. for (GalaxyCoinRenewTicketsView galaxyCoinRenewTicketsView : search.getDataList()) {
  1327. Long skuId = galaxyCoinRenewTicketsView.getSkuId();
  1328. BigDecimal maxSkuPrice = BigDecimal.ZERO;
  1329. if (galaxyCoinRenewTicketsView.getIsMirror() != null && galaxyCoinRenewTicketsView.getIsMirror()) {
  1330. List<RenewUpgradePackageFrontView> renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build());
  1331. for (RenewUpgradePackageFrontView renew : renewUpgradePackageFrontViews) {
  1332. try {
  1333. List<Long> upgradeSkuIds = Jsons.parseList(renew.getUpgradeSkuIds(), Long.class);
  1334. GoodsDonSku maxPriceSku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
  1335. .eq(GoodsDonSku::getStatus, Boolean.TRUE)
  1336. .in(GoodsDonSku::getId, upgradeSkuIds)
  1337. .orderByDesc(GoodsDonSku::getPrice)
  1338. .last("limit 1"));
  1339. BigDecimal discountMoney = maxPriceSku.getPrice().multiply(renew.getDiscount());
  1340. if (discountMoney.compareTo(maxSkuPrice) > 0) {
  1341. maxSkuPrice = discountMoney;
  1342. }
  1343. } catch (Exception e) {
  1344. }
  1345. }
  1346. }
  1347. if (maxSkuPrice.compareTo(BigDecimal.ZERO) == 0) {
  1348. if (galaxyCoinRenewTicketsView.getGoodsId() == Constant.NETFLIX_GID) {
  1349. GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
  1350. .eq(GoodsDonSku::getStatus, Boolean.TRUE)
  1351. .orderByDesc(GoodsDonSku::getPrice)
  1352. .last("limit 1"));
  1353. if (sku != null) {
  1354. maxSkuPrice = sku.getPrice();
  1355. }
  1356. } else {
  1357. maxSkuPrice = goodsDonSkuMapper.selectById(skuId).getPrice();
  1358. }
  1359. }
  1360. //此次最大可抵扣银河币数量
  1361. BigDecimal maxDeductGalaxyCoin = maxSkuPrice.multiply(maxRate).divide(payMoney).multiply(payGalaxyCoin);
  1362. galaxyCoinRenewTicketsView.setMaxGalaxyCoinDeduct(userGalaxyCoin.compareTo(maxDeductGalaxyCoin) > 0 ? maxDeductGalaxyCoin : userGalaxyCoin);
  1363. if (galaxyCoinRenewTicketsView.getExpiryTime() != null && galaxyCoinRenewTicketsView.getGoodsType() == 1) {
  1364. String remainDays = DateUtil.formatBetween(now, galaxyCoinRenewTicketsView.getExpiryTime(), BetweenFormater.Level.DAY);
  1365. if ("0天".equals(remainDays)) {
  1366. remainDays = "小于1天";
  1367. } else {
  1368. //当天也算
  1369. int days = Integer.parseInt(remainDays.substring(0, remainDays.indexOf("天")));
  1370. remainDays = days + 1 + "天";
  1371. }
  1372. galaxyCoinRenewTicketsView.setRemainDays(remainDays);
  1373. }
  1374. }
  1375. return GatewayResponse.SUCCESS.newBuilder().toResult(search);
  1376. }
  1377. /**
  1378. * 镜像车票列表
  1379. */
  1380. @GetMapping("/get/mirror/ticket")
  1381. public Result<List<UserMirrorTicketView>> getMirrorTicket() {
  1382. long userId = StpUserUtil.getLoginIdAsLong();
  1383. List<UserMirrorTicketView> list = groupRelationFrontService.getMirrorTicket(userId);
  1384. return GatewayResponse.SUCCESS.newBuilder().toResult(list);
  1385. }
  1386. /**
  1387. * 镜像车票续费升级信息
  1388. */
  1389. @GetMapping("/get/renewInfo")
  1390. public Result<TicketRenewUpgradeView> getRenewUpgradeInfo(Long relationId) {
  1391. long userId = StpUserUtil.getLoginIdAsLong();
  1392. TicketRenewUpgradeView renewView = groupRelationFrontService.getRenewUpgradeInfo(userId, relationId);
  1393. return GatewayResponse.SUCCESS.newBuilder().toResult(renewView);
  1394. }
  1395. /**
  1396. * 代充记录
  1397. */
  1398. @GetMapping("/get/recharge/record")
  1399. public Result<List<GptUserRechargeNumRecordView>> getRechargeRecord(Long relationId) {
  1400. long userId = StpUserUtil.getLoginIdAsLong();
  1401. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1402. GroupsRelation relation = relationMapper.selectById(relationId);
  1403. if (relation == null || !userIdList.contains(relation.getUserId())) {
  1404. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1405. }
  1406. Date filterDate = relation.getSubmitTime();
  1407. if (filterDate == null) {
  1408. filterDate = relation.getStartTime();
  1409. }
  1410. List<GptUserRechargeNumRecordView> search = beanSearcher.searchAll(GptUserRechargeNumRecordView.class, MapUtils.flatBuilder(request.getParameterMap())
  1411. .field(GptUserRechargeNumRecordView::getUserId, userIdList).op(Operator.InList)
  1412. .field(GptUserRechargeNumRecordView::getRelationId, relationId)
  1413. .field(GptUserRechargeNumRecordView::getCreatedTime, filterDate).op(Operator.GreaterEqual)
  1414. .orderBy(GptUserRechargeNumRecordView::getCreatedTime).desc()
  1415. .build());
  1416. return GatewayResponse.SUCCESS.newBuilder().toResult(search);
  1417. }
  1418. /**
  1419. * claude code+codex 套餐情况
  1420. */
  1421. @GetMapping("/get/cc/codex/info")
  1422. public Result<CcCodexInfoView> getCcCodexInfo() {
  1423. long userId = StpUserUtil.getLoginIdAsLong();
  1424. List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
  1425. ClaudeCodeUser claudeCodeUser = beanSearcher.searchFirst(ClaudeCodeUser.class, MapUtils.builder().field(ClaudeCodeUser::getUserId, userIdList).op(Operator.InList).build());
  1426. CodexUser codexUser = beanSearcher.searchFirst(CodexUser.class, MapUtils.builder().field(CodexUser::getUserId, userIdList).op(Operator.InList).build());
  1427. //cc codex
  1428. CcCodexInfoView ccCodexInfoView = new CcCodexInfoView();
  1429. ccCodexInfoView.setClaudeCodeUser(claudeCodeUser);
  1430. ccCodexInfoView.setCodexUser(codexUser);
  1431. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1432. }
  1433. /**
  1434. * 账号下架操作记录
  1435. */
  1436. @GetMapping("/get/account/down/logs/{accountId}")
  1437. public Result<List<SysLog>> getAccountDownLogs(@PathVariable Long accountId) {
  1438. GroupsTrips groupsTrips = groupsMapper.selectOne(Wrappers.lambdaQuery(GroupsTrips.class).eq(GroupsTrips::getAccountId, accountId).select(GroupsTrips::getId).last("limit 1"));
  1439. List<SysLog> sysLogs = null;
  1440. if (groupsTrips != null) {
  1441. sysLogs = beanSearcher.searchAll(SysLog.class, MapUtils.flatBuilder(request.getParameterMap())
  1442. .field(SysLog::getModule, "过期账号/上下架过期车队")
  1443. .field(SysLog::getOperateParams, groupsTrips.getId())
  1444. .onlySelect(SysLog::getOperator, SysLog::getOperateIp, SysLog::getOperateLocation, SysLog::getCreatedTime)
  1445. .build());
  1446. }
  1447. return GatewayResponse.SUCCESS.newBuilder().toResult(sysLogs);
  1448. }
  1449. /**
  1450. * 查看sora邀请码
  1451. */
  1452. @GetMapping("/get/sora/code/{relationId}")
  1453. public Result<String> getSoraCode(@PathVariable Long relationId) {
  1454. long userId = StpUserUtil.getLoginIdAsLong();
  1455. String soraCode = groupRelationFrontService.getSoraCode(userId, relationId);
  1456. return GatewayResponse.SUCCESS.newBuilder().toResult(soraCode);
  1457. }
  1458. /**
  1459. * 奈飞补偿
  1460. * 用户可领取GPT镜像标准月付情况
  1461. */
  1462. @GetMapping("/netflix/gptMirror/condition")
  1463. public Result<Boolean> netflixGptMirrorCondition() {
  1464. long userId = StpUserUtil.getLoginIdAsLong();
  1465. NetflixRecoverReceivedGptConditionDto conditionDto = groupRelationFrontService.netflixGptMirrorCondition(userId);
  1466. return GatewayResponse.SUCCESS.newBuilder().toResult(conditionDto.getStatus());
  1467. }
  1468. /**
  1469. * 奈飞申请恢复过的用户 领取GPT镜像标准月付
  1470. */
  1471. @GetMapping("/netflix/recover/get/gptMirror")
  1472. public Result<String> netflixRecoverGetGptMirror() {
  1473. long userId = StpUserUtil.getLoginIdAsLong();
  1474. groupRelationFrontService.netflixRecoverGetGptMirror(userId);
  1475. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1476. }
  1477. //=====================================================youtube===================================================================
  1478. /**
  1479. * youtube可替换其他规格车票列表
  1480. */
  1481. @GetMapping("/get/youtube/replace/other/skus")
  1482. public Result<List<GoodsCategorySkuView>> getYoutubeReplaceOtherSkus() throws Exception {
  1483. long userId = StpUserUtil.getLoginIdAsLong();
  1484. List<GoodsCategorySkuView> goodsCategorySkuViews = groupRelationFrontService.getYoutubeReplaceOtherSkus();
  1485. return GatewayResponse.SUCCESS.newBuilder().toResult(goodsCategorySkuViews);
  1486. }
  1487. /**
  1488. * 油管申请冻结
  1489. */
  1490. @PostMapping("/youtube/submit/frozen")
  1491. public Result<String> youtubeSubmitFrozen(@RequestBody ErrorNetflixChangeReq req) {
  1492. long userId = StpUserUtil.getLoginIdAsLong();
  1493. req.setUserId(userId);
  1494. groupRelationFrontService.youtubeSubmitFrozen(req);
  1495. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1496. }
  1497. /**
  1498. * youtube更换其他车票
  1499. */
  1500. @PostMapping("/youtube/change/otherTicket")
  1501. public Result<Integer> errorYoutubeChangeOtherTicket(@RequestBody ErrorNetflixChangeReq req) throws Exception {
  1502. long userId = StpUserUtil.getLoginIdAsLong();
  1503. req.setUserId(userId);
  1504. groupRelationFrontService.errorYoutubeChangeOtherTicket(req);
  1505. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1506. }
  1507. /**
  1508. * youtube 退款
  1509. */
  1510. @PostMapping("/youtube/refund")
  1511. public Result<Integer> errorYoutubeRefund(@RequestBody ErrorNetflixChangeReq req) throws Exception {
  1512. long userId = StpUserUtil.getLoginIdAsLong();
  1513. req.setUserId(userId);
  1514. groupRelationFrontService.errorYoutubeRefund(req);
  1515. return GatewayResponse.SUCCESS.newBuilder().toResult();
  1516. }
  1517. /**
  1518. * youtube 退款详情
  1519. */
  1520. @GetMapping("/youtube/refund/info")
  1521. public Result<OrderRefundDto> getYoutubeRefundInfo(Long relationId) throws Exception {
  1522. long userId = StpUserUtil.getLoginIdAsLong();
  1523. OrderRefundDto orderRefundDto = groupRelationFrontService.getYoutubeRefundInfo(userId, relationId);
  1524. return GatewayResponse.SUCCESS.newBuilder().toResult(orderRefundDto);
  1525. }
  1526. }