GroupRelationController.java 76 KB

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