package com.cyksj.web.controller.group; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.date.DateTime; import cn.hutool.core.date.DateUtil; import cn.hutool.core.thread.ThreadUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.servlet.ServletUtil; import cn.hutool.json.JSONObject; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.cyksj.common.annotation.NoSubmit; import com.cyksj.common.exception.BusinessRuntimeException; import com.cyksj.common.snowflake.Sequence; import com.cyksj.common.task.GlobalThreadPoolTaskExecutor; import com.cyksj.common.util.GoogleGenerator; import com.cyksj.common.util.Jsons; import com.cyksj.common.util.StringUtil; import com.cyksj.dto.Result; import com.cyksj.enums.GatewayResponse; import com.cyksj.mapper.*; import com.cyksj.mapper.manage.form.FormFieldsDataMapper; import com.cyksj.mapper.manage.form.QuestionnairePromotionMapper; import com.cyksj.model.dto.DoubleVerifyDto; import com.cyksj.model.dto.QuestionnaireView; import com.cyksj.model.entity.*; import com.cyksj.model.manage.views.GroupsRelationView; import com.cyksj.model.request.OrderPayRequest; import com.cyksj.model.views.DoubleVerifyCodeView; import com.cyksj.model.views.QuestionnairePromotionFieldsListView; import com.cyksj.model.views.RenewalView; import com.cyksj.model.views.UserTicketView; import com.cyksj.redis.RedisService; import com.cyksj.service.mange.coupon.CouponCommonService; import com.cyksj.service.order.OrderDonService; import com.cyksj.service.relation.GroupRelationFrontService; import com.cyksj.service.user.UserService; import com.cyksj.web.util.StpUserUtil; import com.ejlchina.searcher.BeanSearcher; import com.ejlchina.searcher.param.Operator; import com.ejlchina.searcher.util.MapUtils; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import javax.servlet.http.HttpServletRequest; import java.util.List; import java.util.concurrent.TimeUnit; /** * @author chan * @date 2022/9/27 11:48 AM */ @Slf4j @RequiredArgsConstructor @RestController @RequestMapping("/applets/group/relation") public class GroupRelationController { private final BeanSearcher beanSearcher; private final OrderDonService orderDonService; private final GroupsRelationMapper relationMapper; private final GroupRelationFrontService groupRelationFrontService; private final UserService userService; private final ChatGptPwdViewRecordMapper chatGptPwdViewRecordMapper; private final HttpServletRequest request; private final AccountDoubleVerifyRecordMapper accountDoubleVerifyRecordMapper; private final DoubleVerifyClickRecordMapper doubleVerifyRecordMapper; private final RedisService redisService; private final UserFuncPropertyMapper userFuncPropertyMapper; private final DoubleVerifyClickRefreshRecordMapper refreshRecordMapper; private final QuestionResponseRecordMapper questionResponseRecordMapper; private final CouponCommonService couponCommonService; private final FormFieldsDataMapper formFieldsDataMapper; private final QuestionnairePromotionMapper questionnairePromotionMapper; private final QuestionnairePromotionMapper promotionMapper; private final GlobalThreadPoolTaskExecutor THREAD_POOL; private final static Sequence SEQUENCE = new Sequence(0); @RequestMapping("/get/renewal") public Result> get(Boolean isLoginPopularize) { long userId = StpUserUtil.getLoginIdAsLong(); List list = groupRelationFrontService.getMyTicket(userId, isLoginPopularize); return GatewayResponse.SUCCESS.newBuilder().toResult(list); } @PostMapping("/post/renewal") public Result renewal(@RequestBody OrderPayRequest request) throws Exception { long userId = StpUserUtil.getLoginIdAsLong(); request.setUserId(userId); OrderDon orderDon = orderDonService.renewal(request); return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon); } @PutMapping("/update/set/account") public Result setAccount(@RequestBody GroupsRelation relation) { long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userService.getRelationUserIdList(userId, null); GroupsRelation re = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class) .eq(GroupsRelation::getId, relation.getId()) .in(GroupsRelation::getUserId, userIds) .last(" limit 1")); if (re == null) { throw new BusinessRuntimeException("该车票不存在,请联系客服."); } relationMapper.update(relation, Wrappers.lambdaUpdate(GroupsRelation.class).set(GroupsRelation::getAccount, relation.getAccount()).eq(GroupsRelation::getId, relation.getId())); return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 查询是否加入了企业微信 */ @GetMapping("/check/joinCorpWx") public Result isJoinCorpWx() { long userId = StpUserUtil.getLoginIdAsLong(); Boolean flag = groupRelationFrontService.isJoinCorpWx(userId, false, false); return GatewayResponse.SUCCESS.newBuilder().toResult(flag); } /** * 获取全部车票 */ @GetMapping("/get") public Result> getUserTicketView() { long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userService.getRelationUserIdList(userId, null); List ticketViews = beanSearcher.searchAll(UserTicketView.class, MapUtils.builder() .field(UserTicketView::getUserId, userIds).op(Operator.InList) .orderBy(UserTicketView::getRelationId).asc() .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(ticketViews); } /** * 记录查看ChatGPT车票密码 */ @GetMapping("/recordView/{relationId}") public Result recordGPTPwdView(@PathVariable Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userService.getRelationUserIdList(userId, null); GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder() .field(GroupsRelationView::getUserId, userIds).op(Operator.InList) .field(GroupsRelationView::getId, relationId).build()); if (groupsRelationView == null) { log.info("userId:{}查看relationId:{}车票不存在", userId, relationId); throw BusinessRuntimeException.getInstance("该车票已不存在"); } if (groupsRelationView.getAccountId() == null) throw BusinessRuntimeException.getInstance("该车队未配置账号"); if (groupRelationFrontService == null) throw BusinessRuntimeException.getInstance("车票已不存在"); ChatGptPwdViewRecord viewRecord = new ChatGptPwdViewRecord(); viewRecord.setUserId(userId); viewRecord.setRelationId(relationId); viewRecord.setSkuId(groupsRelationView.getSkuId()); viewRecord.setOperateLocation(StringUtil.getRealAddressByIP(ServletUtil.getClientIP(request))); chatGptPwdViewRecordMapper.insert(viewRecord); if (StrUtil.isEmpty(groupsRelationView.getApiSecret())) { THREAD_POOL.execute(() -> { //车队所有人查看密码 Integer num = groupsRelationView.getGtNum(); Integer viewNum = relationMapper.selectViewPwdCount(groupsRelationView.getGroupsId()); if (num <= viewNum) { AccountDoubleVerifyRecord exist = accountDoubleVerifyRecordMapper.selectOne(Wrappers.lambdaQuery(AccountDoubleVerifyRecord.class) .eq(AccountDoubleVerifyRecord::getAccountId, groupsRelationView.getAccountId()) .eq(AccountDoubleVerifyRecord::getDeleted, true).last("limit 1")); if (exist == null) { if (redisService.setNx(String.format("%s-%s", groupsRelationView.getAccountId(), groupsRelationView.getId()), groupsRelationView.getId(), 60l)) { //记录 AccountDoubleVerifyRecord accountDoubleVerifyRecord = new AccountDoubleVerifyRecord(); accountDoubleVerifyRecord.setAccountId(groupsRelationView.getAccountId()); accountDoubleVerifyRecord.setAccount(groupsRelationView.getTripsAccount()); accountDoubleVerifyRecord.setGroupsId(groupsRelationView.getGroupsId()); accountDoubleVerifyRecord.setSkuId(groupsRelationView.getSkuId()); accountDoubleVerifyRecord.setRemark("车队所有人看过密码"); accountDoubleVerifyRecordMapper.insert(accountDoubleVerifyRecord); } } } }); } return GatewayResponse.SUCCESS.newBuilder().toResult(groupsRelationView.getTripsPassword()); } /** * 获取AI类 ChatGPT产品谷歌验证码 */ @GetMapping("/get/authCode") public Result getAuthCode(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List userIds = userService.getRelationUserIdList(userId, null); //每个人 每月只能获取3次 if (relationId == null) throw BusinessRuntimeException.getInstance("车票不存在"); GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder() .field(GroupsRelationView::getId, relationId) .field(GroupsRelationView::getUserId, userIds).op(Operator.InList).build()); if (groupsRelationView == null) throw BusinessRuntimeException.getInstance("车票不存在"); if (StrUtil.isEmpty(groupsRelationView.getApiSecret())) throw BusinessRuntimeException.getInstance("未开启验证"); DateTime now = DateTime.now(); Integer count = doubleVerifyRecordMapper.selectCount(Wrappers.lambdaQuery(DoubleVerifyClickRecord.class) .in(DoubleVerifyClickRecord::getUserId, userIds) .eq(DoubleVerifyClickRecord::getRelationId, relationId) .eq(DoubleVerifyClickRecord::getAccountId, groupsRelationView.getAccountId()) .between(DoubleVerifyClickRecord::getCreatedTime, DateUtil.beginOfMonth(now), DateUtil.endOfMonth(now))); UserFuncProperty userFuncProperty = userFuncPropertyMapper.selectOne(Wrappers.lambdaQuery(UserFuncProperty.class) .eq(UserFuncProperty::getUserId, userId).last("limit 1")); //默认3次 int num = 3; if (userFuncProperty != null) num = userFuncProperty.getVerifyCheckNum(); if (count >= num) throw BusinessRuntimeException.getInstance("获取双重验证码次数上限"); int second = now.second(); if (second < 30 && 30 - second < 3) { ThreadUtil.sleep(30 - second + 1, TimeUnit.SECONDS); } else if (second > 30 && 60 - second < 3) { ThreadUtil.sleep(60 - second + 1, TimeUnit.SECONDS); } StringBuilder sb = new StringBuilder(); JSONObject re = new JSONObject(); try { long code = GoogleGenerator.getCode(groupsRelationView.getApiSecret(), now.getTime()); sb.append(code); while (sb.length() < 6) { sb.insert(0, 0); } re.putOpt("code", sb.toString()); int nowSecond = DateTime.now().second(); int time = 0; if (nowSecond < 30) { time = 30 - nowSecond; } else { time = 60 - nowSecond; } re.putOpt("time", time); DoubleVerifyClickRecord doubleVerifyClickRecord = new DoubleVerifyClickRecord(); doubleVerifyClickRecord.setRelationId(relationId); doubleVerifyClickRecord.setUserId(userId); doubleVerifyClickRecord.setAccountId(groupsRelationView.getAccountId()); doubleVerifyClickRecord.setAccount(groupsRelationView.getTripsAccount()); doubleVerifyClickRecord.setSkuId(groupsRelationView.getSkuId()); doubleVerifyClickRecord.setCode(sb.toString()); doubleVerifyClickRecord.setRemainTime(time); doubleVerifyRecordMapper.insert(doubleVerifyClickRecord); DoubleVerifyDto doubleVerifyDto = new DoubleVerifyDto(); doubleVerifyDto.setClickId(doubleVerifyClickRecord.getId()); doubleVerifyDto.setApiSecret(groupsRelationView.getApiSecret()); redisService.set(String.format("%s-%s", userId, sb.toString()), 0, 60 * 10l); redisService.set(String.format("%s/%s", userId, sb.toString()), Jsons.toJson(doubleVerifyDto), 60 * 10l); } catch (Exception e) { throw BusinessRuntimeException.getInstance("获取双重验证码错误,请联系客服"); } return GatewayResponse.SUCCESS.newBuilder().toResult(re.toString()); } /** * 刷新验证码 */ @GetMapping("/refresh/code") public Result refreshCode(String code) { long userId = StpUserUtil.getLoginIdAsLong(); String numKey = String.format("%s-%s", userId, code); Object num = redisService.get(numKey); String objKey = String.format("%s/%s", userId, code); Object objValue = redisService.get(objKey); if (objValue == null || num == null) { throw BusinessRuntimeException.getInstance("请重新获取双重验证码"); } Integer refreshNum = Integer.parseInt(num.toString()); String apiSecret = null; Long clickId = 0l; try { DoubleVerifyDto dto = Jsons.parseObject(objValue.toString(), DoubleVerifyDto.class); apiSecret = dto.getApiSecret(); clickId = dto.getClickId(); } catch (Exception e) { apiSecret = objValue.toString(); } if (refreshNum >= 3) { redisService.del(numKey); redisService.del(objKey); throw BusinessRuntimeException.getInstance("刷新次数已达到3次,请重新获取验证码"); } if (apiSecret == null) { throw BusinessRuntimeException.getInstance("请重新获取双重验证码"); } StringBuilder sb = new StringBuilder(); try { long c = GoogleGenerator.getCode(apiSecret, DateTime.now().getTime()); sb.append(c); while (sb.length() < 6) { sb.insert(0, 0); } redisService.incr(numKey, 1l); } catch (Exception e) { throw BusinessRuntimeException.getInstance("刷新双重验证码错误,请联系客服"); } if (clickId != 0) { int nowSecond = DateTime.now().second(); int time = 0; if (nowSecond < 30) { time = 30 - nowSecond; } else { time = 60 - nowSecond; } //刷新双重验证码记录 DoubleVerifyClickRefreshRecord refreshRecord = new DoubleVerifyClickRefreshRecord(); refreshRecord.setClickId(clickId); refreshRecord.setUserId(userId); refreshRecord.setCode(sb.toString()); refreshRecord.setRemainTime(time); refreshRecordMapper.insert(refreshRecord); } return GatewayResponse.SUCCESS.newBuilder().toResult(sb.toString()); } /** * 获取双重验证码记录 */ @GetMapping("/get/doubleVerify/codeList") public Result> getDoubleVerifyCodeList(Long relationId) { long userId = StpUserUtil.getLoginIdAsLong(); List views = doubleVerifyRecordMapper.getDoubleVerifyCodeList(userId, relationId); return GatewayResponse.SUCCESS.newBuilder().toResult(views); } /** * 用户是不是自然流量渠道 * 且未回答答题 */ @GetMapping("/natural/channel") public Result isNaturalChannel() { long userId = StpUserUtil.getLoginIdAsLong(); String question_key = RedisService.key.QUESTION_RESPONSE_KEY.getNameFormat(userId); if (redisService.get(question_key) != null) { return GatewayResponse.SUCCESS.newBuilder().toResult(false); } User user = userService.getById(userId); if (user.getPopularizeId() != 0) { redisService.set(question_key, userId, RedisService.key.QUESTION_RESPONSE_KEY.getTimeout()); return GatewayResponse.SUCCESS.newBuilder().toResult(false); } if (user.getPopularizeId() == 0) { QuestionResponseRecord record = questionResponseRecordMapper.selectOne(Wrappers.lambdaQuery(QuestionResponseRecord.class) .eq(QuestionResponseRecord::getUserId, userId).select(QuestionResponseRecord::getId).last("limit 1")); if (record != null) { redisService.set(question_key, userId, RedisService.key.QUESTION_RESPONSE_KEY.getTimeout()); return GatewayResponse.SUCCESS.newBuilder().toResult(false); } return GatewayResponse.SUCCESS.newBuilder().toResult(true); } return GatewayResponse.SUCCESS.newBuilder().toResult(false); } /** * 问卷记录 */ @PostMapping("/record/replyQuestion") public Result recordReplyQuestion(@RequestBody @Validated QuestionResponseRecord record) { long userId = StpUserUtil.getLoginIdAsLong(); User user = userService.getById(userId); String nickname = user.getNickname(); String question_key = RedisService.key.QUESTION_RESPONSE_KEY.getNameFormat(userId); QuestionResponseRecord dbRecord = questionResponseRecordMapper.selectOne(Wrappers.lambdaQuery(QuestionResponseRecord.class) .eq(QuestionResponseRecord::getUserId, userId).select(QuestionResponseRecord::getId).last("limit 1")); if (dbRecord == null) { if (redisService.setNx(String.format("%s-%s", userId, nickname), userId, 10l)) { record.setUserId(userId); record.setNickname(nickname); questionResponseRecordMapper.insert(record); //发放优惠券 couponCommonService.sendCouponToUser(userId, 100l, 0l, 0l, 0l, CouponUser.Channel.ques_response); redisService.set(question_key, userId, RedisService.key.QUESTION_RESPONSE_KEY.getTimeout()); } } return GatewayResponse.SUCCESS.newBuilder().toResult(); } /** * 获取对应的动态问卷 */ @GetMapping("/get/questionnaire") public Result> getQuestionnaireView(Long promotionId) { QuestionnairePromotion promotion = questionnairePromotionMapper.selectById(promotionId); if (promotion == null || !promotion.getDeleted()) throw BusinessRuntimeException.getInstance("问卷不存在"); Long templateId = promotion.getTemplateId(); List questionnaireViews = beanSearcher.searchAll(QuestionnaireView.class, MapUtils.builder() .field(QuestionnaireView::getPromotionId, promotionId) .orderBy(QuestionnaireView::getSorted).asc() .orderBy(QuestionnaireView::getFieldsId).asc() .build()); return GatewayResponse.SUCCESS.newBuilder().toResult(questionnaireViews); } /** * 记录问卷 */ @PostMapping("/record/questionnaire/{promotionId}") @Transactional(rollbackFor = Exception.class) @NoSubmit public Result recordQuestionnaire(@PathVariable Long promotionId, @RequestBody List answers) { Long groupsId = SEQUENCE.nextId(); List promotionFieldsListViews = beanSearcher.searchAll(QuestionnairePromotionFieldsListView.class, MapUtils.builder().field(QuestionnairePromotionFieldsListView::getPromotionId, promotionId).build()); if (CollUtil.isEmpty(promotionFieldsListViews)) throw BusinessRuntimeException.getInstance("问卷已结束"); if (promotionFieldsListViews.size() != answers.size()) throw BusinessRuntimeException.getInstance("请完成所有问题"); answers.forEach(answer -> { Long fieldsId = answer.getFieldsId(); String content = answer.getContent(); if (fieldsId == null || StrUtil.isBlank(content)) { throw BusinessRuntimeException.getInstance("必填项为空"); } answer.setPromotionId(promotionId); answer.setGroupsId(groupsId); formFieldsDataMapper.insert(answer); }); return GatewayResponse.SUCCESS.newBuilder().toResult(); } }