RedeemCloudRechargeServiceImpl.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296
  1. package com.cyksj.service.recharge.impl;
  2. import cn.hutool.core.date.DateTime;
  3. import cn.hutool.core.date.DateUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import cn.hutool.http.HttpRequest;
  6. import cn.hutool.http.HttpResponse;
  7. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  8. import com.cyksj.common.exception.BusinessRuntimeException;
  9. import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
  10. import com.cyksj.common.util.Jsons;
  11. import com.cyksj.mapper.*;
  12. import com.cyksj.model.entity.*;
  13. import com.cyksj.model.response.recharge.RedeemCloudCdkQueryResponse;
  14. import com.cyksj.model.response.recharge.RedeemCloudExchangeResponse;
  15. import com.cyksj.model.response.recharge.RedeemCloudTaskResultResponse;
  16. import com.cyksj.redis.RedisService;
  17. import com.cyksj.server.recharge.dto.TaskResult;
  18. import com.cyksj.service.chatgpt.GptUserRechargeRecordService;
  19. import com.cyksj.service.recharge.GptRechargeCardKeyChannelService;
  20. import com.cyksj.service.recharge.RedeemCloudRechargeService;
  21. import lombok.RequiredArgsConstructor;
  22. import lombok.extern.slf4j.Slf4j;
  23. import org.springframework.stereotype.Service;
  24. import java.util.Date;
  25. @Service
  26. @RequiredArgsConstructor
  27. @Slf4j
  28. public class RedeemCloudRechargeServiceImpl implements RedeemCloudRechargeService {
  29. private final GptRechargeCardKeyChannelService gptRechargeCardKeyChannelService;
  30. private final GroupsRelationMapper relationMapper;
  31. private final GroupsMapper groupsMapper;
  32. private final GoodsDonSkuMapper skuMapper;
  33. private final RedisService redisService;
  34. private final OrderDonMapper orderDonMapper;
  35. private final GptRechargeCardKeyMapper gptRechargeCardKeyMapper;
  36. private final GptUserRechargeRecordService gptUserRechargeRecordService;
  37. private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
  38. private static final int SUCCESS_CODE = 200;
  39. private static final int UNUSED_STATUS = 0;
  40. @Override
  41. public RedeemCloudCdkQueryResponse validateCardKey(String cardKey) throws Exception {
  42. String baseUrl = gptRechargeCardKeyChannelService.getCardKeyDomain(cardKey);
  43. String url = baseUrl + "/sys-cdk/query?cdkCode=" + cardKey;
  44. HttpResponse response = HttpRequest.get(url)
  45. .setConnectionTimeout(10000)
  46. .execute();
  47. String body = response.body();
  48. log.info("redeemcloud验证卡密结果: {}", body);
  49. return Jsons.parseObject(body, RedeemCloudCdkQueryResponse.class);
  50. }
  51. @Override
  52. public String confirmRecharge(GroupsRelation relation, String gptCardKey, CmsUser cmsUser) {
  53. Long relationId = relation.getId();
  54. RedeemCloudCdkQueryResponse validateResponse;
  55. try {
  56. validateResponse = validateCardKey(gptCardKey);
  57. } catch (Exception e) {
  58. if (cmsUser == null) {
  59. throw BusinessRuntimeException.getInstance("系统繁忙,请重试");
  60. }
  61. throw BusinessRuntimeException.getInstance("卡密:{0}错误", gptCardKey);
  62. }
  63. if (!isCardKeyAvailable(validateResponse)) {
  64. if (cmsUser == null) {
  65. throw BusinessRuntimeException.getInstance("系统繁忙,请重试");
  66. }
  67. throw BusinessRuntimeException.getInstance(getValidateErrorMessage(validateResponse, gptCardKey));
  68. }
  69. String accessToken = relation.getGptToken();
  70. String rechargeAccount = relation.getAccount();
  71. String taskId;
  72. try {
  73. taskId = submitTask(gptCardKey, accessToken);
  74. } catch (Exception e) {
  75. setRechargeRelationStatusAutoError(relation);
  76. if (cmsUser == null) {
  77. throw BusinessRuntimeException.getInstance("充值失败,请联系客服开通");
  78. }
  79. throw BusinessRuntimeException.getInstance("充值失败,{0}", e.getMessage());
  80. }
  81. String operator = cmsUser != null ? cmsUser.getNickname() : null;
  82. String password = relation.getPassword();
  83. relationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  84. .set(GroupsRelation::getAccount, rechargeAccount)
  85. .set(GroupsRelation::getOperator, operator)
  86. .set(StrUtil.isNotBlank(password), GroupsRelation::getPassword, password)
  87. .set(GroupsRelation::getRechargeStatus, GroupsRelation.RechargeStatus.recharging)
  88. .set(GroupsRelation::getCardKey, gptCardKey)
  89. .set(GroupsRelation::getGptToken, accessToken)
  90. .set(GroupsRelation::getGptTaskId, taskId)
  91. .eq(GroupsRelation::getId, relationId));
  92. relation.setRechargeStatus(GroupsRelation.RechargeStatus.recharging);
  93. relation.setCardKey(gptCardKey);
  94. relation.setOperator(operator);
  95. return taskId;
  96. }
  97. private boolean isCardKeyAvailable(RedeemCloudCdkQueryResponse validateResponse) {
  98. return validateResponse != null
  99. && validateResponse.getCode() != null
  100. && validateResponse.getCode() == SUCCESS_CODE
  101. && validateResponse.getData() != null
  102. && validateResponse.getData().getUseStatus() != null
  103. && validateResponse.getData().getUseStatus() == UNUSED_STATUS
  104. && Boolean.TRUE.equals(validateResponse.getData().getChannelEnabled());
  105. }
  106. private String getValidateErrorMessage(RedeemCloudCdkQueryResponse validateResponse, String cardKey) {
  107. if (validateResponse == null) {
  108. return "卡密错误:" + cardKey;
  109. }
  110. if (StrUtil.isNotBlank(validateResponse.getMessage())) {
  111. return validateResponse.getMessage();
  112. }
  113. return "卡密错误:" + cardKey;
  114. }
  115. private String submitTask(String cardKey, String accessToken) {
  116. log.info("开始提交redeemcloud任务 - 卡密: {}", cardKey);
  117. try {
  118. String baseUrl = gptRechargeCardKeyChannelService.getCardKeyDomain(cardKey);
  119. String url = baseUrl + "/sys-cdk/exchange?cdkCode=" + cardKey;
  120. HttpResponse response = HttpRequest.post(url)
  121. .setConnectionTimeout(60000)
  122. .header("content-type", "application/json")
  123. .body(accessToken)
  124. .execute();
  125. String body = response.body();
  126. log.info("redeemcloud任务提交响应: {}", body);
  127. RedeemCloudExchangeResponse exchangeResponse = Jsons.parseObject(body, RedeemCloudExchangeResponse.class);
  128. if (exchangeResponse != null && exchangeResponse.getCode() != null && exchangeResponse.getCode() == SUCCESS_CODE && StrUtil.isNotBlank(exchangeResponse.getData())) {
  129. return exchangeResponse.getData();
  130. }
  131. String errorMessage = exchangeResponse != null && StrUtil.isNotBlank(exchangeResponse.getMessage()) ? exchangeResponse.getMessage() : "提交任务失败";
  132. throw BusinessRuntimeException.getInstance(errorMessage);
  133. } catch (Exception e) {
  134. log.error("提交redeemcloud任务失败: {}", e.getMessage(), e);
  135. throw new RuntimeException("提交任务失败: " + e.getMessage(), e);
  136. }
  137. }
  138. @Override
  139. public TaskResult getTaskResult(GroupsRelation relation) {
  140. String cardKey = relation.getCardKey();
  141. String taskId = relation.getGptTaskId();
  142. try {
  143. RedeemCloudTaskResultResponse taskResultResponse = queryTaskResult(cardKey, taskId);
  144. TaskResult taskResult = convertTaskResult(taskResultResponse);
  145. resetGroupsRelationRechargeStatus(relation, taskResult.getStatus(), taskResult.getError());
  146. return taskResult;
  147. } catch (Exception e) {
  148. log.error("查询redeemcloud任务结果失败: {}", e.getMessage(), e);
  149. throw new RuntimeException("获取任务结果失败: " + e.getMessage(), e);
  150. }
  151. }
  152. private RedeemCloudTaskResultResponse queryTaskResult(String cardKey, String taskId) throws Exception {
  153. String baseUrl = gptRechargeCardKeyChannelService.getCardKeyDomain(cardKey);
  154. String url = baseUrl + "/sys-cdk/exchange/result?taskId=" + taskId;
  155. HttpResponse response = HttpRequest.get(url)
  156. .setConnectionTimeout(10000)
  157. .execute();
  158. String body = response.body();
  159. log.info("redeemcloud任务查询响应: {}", body);
  160. return Jsons.parseObject(body, RedeemCloudTaskResultResponse.class);
  161. }
  162. private TaskResult convertTaskResult(RedeemCloudTaskResultResponse taskResultResponse) {
  163. TaskResult result = new TaskResult();
  164. if (taskResultResponse == null || taskResultResponse.getCode() == null || taskResultResponse.getCode() != SUCCESS_CODE) {
  165. result.setStatus("failed");
  166. result.setError(taskResultResponse != null ? taskResultResponse.getMessage() : "任务查询失败");
  167. return result;
  168. }
  169. if (taskResultResponse.getData() == null) {
  170. result.setStatus("recharging");
  171. result.setResult(taskResultResponse.getMessage());
  172. return result;
  173. }
  174. String status = taskResultResponse.getData().getStatus();
  175. if ("COMPLETED".equalsIgnoreCase(status)) {
  176. result.setStatus("completed");
  177. } else if ("FAILED".equalsIgnoreCase(status) || "ERROR".equalsIgnoreCase(status)) {
  178. result.setStatus("failed");
  179. } else if (taskResultResponse.getData().getUseStatus() != null && taskResultResponse.getData().getUseStatus() != UNUSED_STATUS) {
  180. result.setStatus("completed");
  181. } else if (StrUtil.isNotBlank(taskResultResponse.getData().getEmail()) || StrUtil.isNotBlank(taskResultResponse.getData().getAccountId())) {
  182. result.setStatus("completed");
  183. } else {
  184. result.setStatus("recharging");
  185. }
  186. result.setResult(status);
  187. result.setError(taskResultResponse.getData().getErrorMessage());
  188. return result;
  189. }
  190. public void setRechargeRelationStatusAutoError(GroupsRelation relation) {
  191. TASK_EXECUTOR.execute(() -> relationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  192. .set(GroupsRelation::getAccount, relation.getAccount())
  193. .set(GroupsRelation::getGptToken, relation.getGptToken())
  194. .set(GroupsRelation::getRechargeStatus, GroupsRelation.RechargeStatus.recharge_error)
  195. .eq(GroupsRelation::getId, relation.getId())));
  196. }
  197. private void resetGroupsRelationRechargeStatus(GroupsRelation relation, String status, String result) {
  198. if (!"completed".equals(status) && !"failed".equals(status) && !"unknown".equals(status)) {
  199. return;
  200. }
  201. relation = relationMapper.selectById(relation.getId());
  202. if (relation == null || relation.getRechargeStatus() != GroupsRelation.RechargeStatus.recharging) {
  203. return;
  204. }
  205. String taskId = relation.getGptTaskId();
  206. Integer rechargeRemainNum = relation.getRechargeRemainNum();
  207. GroupsRelation.RechargeStatus rechargeStatus = "completed".equals(status) ? GroupsRelation.RechargeStatus.complete : GroupsRelation.RechargeStatus.recharge_error;
  208. String cardKey = relation.getCardKey();
  209. GptRechargeCardKey gptRechargeCardKey = gptRechargeCardKeyMapper.selectOne(Wrappers.lambdaQuery(GptRechargeCardKey.class)
  210. .eq(GptRechargeCardKey::getCardKey, cardKey)
  211. .last("limit 1"));
  212. if (rechargeStatus == GroupsRelation.RechargeStatus.recharge_error && gptRechargeCardKey != null) {
  213. gptRechargeCardKeyMapper.update(null, Wrappers.lambdaUpdate(GptRechargeCardKey.class)
  214. .set(GptRechargeCardKey::getStatus, Boolean.FALSE)
  215. .set(GptRechargeCardKey::getOrderId, null)
  216. .set(GptRechargeCardKey::getOrderNo, null)
  217. .eq(GptRechargeCardKey::getId, gptRechargeCardKey.getId())
  218. .eq(GptRechargeCardKey::getStatus, Boolean.TRUE));
  219. }
  220. if (rechargeStatus == GroupsRelation.RechargeStatus.recharge_error
  221. && !redisService.setNx(RedisService.key.GPT_RECHARGE_RECOVER_KEY.getName() + taskId, taskId, RedisService.key.GPT_RECHARGE_RECOVER_KEY.getTimeout())) {
  222. return;
  223. }
  224. Date startTime = relation.getStartTime();
  225. DateTime expiryTime = null;
  226. if (rechargeStatus == GroupsRelation.RechargeStatus.complete && startTime == null) {
  227. GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
  228. if (groupsTrips != null) {
  229. startTime = DateTime.now();
  230. GoodsDonSku sku = skuMapper.selectById(groupsTrips.getSkuId());
  231. if (sku.getDays() != null && sku.getDays() > 0) {
  232. expiryTime = DateUtil.offsetDay(startTime, sku.getDays());
  233. } else {
  234. expiryTime = DateUtil.offsetMonth(startTime, sku.getMonths());
  235. }
  236. }
  237. }
  238. String rechargeErrorInfo = rechargeStatus == GroupsRelation.RechargeStatus.recharge_error ? result : null;
  239. int update = relationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
  240. .set(rechargeStatus == GroupsRelation.RechargeStatus.recharge_error, GroupsRelation::getRechargeRemainNum, rechargeRemainNum + 1)
  241. .set(GroupsRelation::getRechargeStatus, rechargeStatus)
  242. .set(expiryTime != null, GroupsRelation::getStartTime, startTime)
  243. .set(expiryTime != null, GroupsRelation::getExpiryTime, expiryTime)
  244. .set(StrUtil.isNotEmpty(rechargeErrorInfo), GroupsRelation::getRechargeErrorInfo, rechargeErrorInfo)
  245. .eq(GroupsRelation::getId, relation.getId())
  246. .le(GroupsRelation::getRechargeRemainNum, relation.getRechargeNum())
  247. .eq(GroupsRelation::getRechargeStatus, GroupsRelation.RechargeStatus.recharging));
  248. if (update == 0) {
  249. return;
  250. }
  251. if (rechargeStatus == GroupsRelation.RechargeStatus.complete) {
  252. String remark = StrUtil.isNotBlank(relation.getOperator()) ? "后台自动代充" : "自动代充";
  253. gptUserRechargeRecordService.recordGptUserRechargeNum(relation.getCardKey(), relation.getUserId(), relation.getId(), relation.getAccount(), -1, relation.getOperator(), remark);
  254. if (gptRechargeCardKey != null) {
  255. Long orderId = gptRechargeCardKey.getOrderId();
  256. OrderDon orderDon = orderDonMapper.selectById(orderId);
  257. if (orderDon != null && orderDon.getStatus() == OrderDon.Status.hasPayment) {
  258. orderDon.setStatus(OrderDon.Status.complete);
  259. orderDonMapper.updateById(orderDon);
  260. }
  261. }
  262. }
  263. }
  264. }