浏览代码

代充自动充值

zoujiajian 1 年之前
父节点
当前提交
ca6d3cf59e

+ 7 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GroupsRelation.java

@@ -59,6 +59,11 @@ public class GroupsRelation extends BaseEntity {
      */
     private Integer rechargeRemainNum;
 
+    /**
+     * gpt自动充值任务id
+     */
+    private String gptTaskId;
+
     private Date submitTime;
 
     private Date sendTime;
@@ -170,6 +175,8 @@ public class GroupsRelation extends BaseEntity {
         waiting("待充值"),
         complete("已完成"),
         error("账号错误"),
+        auto_error("自动充值错误"),
+        auto_recharge("自动充值中"),
         ;
 
         private String desc;

+ 25 - 0
netflix-dao/src/main/java/com/cyksj/model/request/GroupsRelationRechargeReq.java

@@ -0,0 +1,25 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+import javax.validation.constraints.NotNull;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: GroupsRelationRechargeReq
+ * 创建者: JavaZou
+ * 创建时间:2025/7/31 15:45
+ */
+@Getter
+@Setter
+public class GroupsRelationRechargeReq {
+	@NotNull
+	private Long relationId;
+
+	private Long userId;
+
+	@NotEmpty
+	private String accessToken;
+}

+ 3 - 0
netflix-service/src/main/java/com/cyksj/server/recharge/GptProxyRechargeService.java

@@ -1,5 +1,6 @@
 package com.cyksj.server.recharge;
 
+import com.cyksj.model.request.GroupsRelationRechargeReq;
 import com.cyksj.server.recharge.dto.*;
 
 /**
@@ -27,4 +28,6 @@ public interface GptProxyRechargeService {
      * 获取任务结果
      */
     TaskResult getTaskResult(String taskId);
+
+    String confirmRecharge(GroupsRelationRechargeReq req);
 }

+ 128 - 3
netflix-service/src/main/java/com/cyksj/server/recharge/impl/GptProxyRechargeServiceImpl.java

@@ -4,15 +4,25 @@ import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.json.JSONObject;
 import cn.hutool.json.JSONUtil;
-import com.cyksj.mapper.GptRechargeCardKeyMapper;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.task.GlobalThreadPoolTaskExecutor;
+import com.cyksj.mapper.*;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.GroupsRelationRechargeReq;
 import com.cyksj.server.recharge.GptProxyRechargeService;
 import com.cyksj.server.recharge.dto.CardKeyValidationResult;
 import com.cyksj.server.recharge.dto.TaskResult;
 import com.cyksj.server.recharge.dto.TaskSubmitResult;
 import com.cyksj.server.recharge.dto.TokenParseResult;
+import com.cyksj.service.user.UserBindRelationService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
 
 /**
  * @author chan
@@ -27,7 +37,19 @@ public class GptProxyRechargeServiceImpl implements GptProxyRechargeService {
 
     private final GptRechargeCardKeyMapper gptRechargeCardKeyMapper;
 
-    private HttpRequest createBaseRequest(String uri) {
+    private final GroupsRelationMapper relationMapper;
+
+    private final UserBindRelationService userBindRelationService;
+
+    private GroupsMapper groupsMapper;
+
+    private final GoodsDonSkuMapper skuMapper;
+
+    private final OrderDonMapper orderDonMapper;
+
+	private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
+
+	private HttpRequest createBaseRequest(String uri) {
         return HttpRequest.get(BASE_URL + uri)
                 .header("accept", "application/json, text/plain, */*")
                 .header("accept-language", "zh-CN,zh;q=0.9,en;q=0.8")
@@ -138,10 +160,113 @@ public class GptProxyRechargeServiceImpl implements GptProxyRechargeService {
                 jsonResponse.getStr("result")
             );
             log.info("任务查询结果: {}", result);
-            return result;
+	        String status = result.getStatus();
+	        if ("success".equals(status)) {
+		        GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
+				        .eq(GroupsRelation::getGptTaskId, taskId)
+				        .last("limit 1"));
+		        if (relation != null) {
+			        relation.setRechargeStatus(GroupsRelation.RechargeStatus.complete);
+			        relationMapper.updateById(relation);
+		        }
+	        }
+	        return result;
         } catch (Exception e) {
             log.error("获取任务结果失败: {}", e.getMessage(), e);
             throw new RuntimeException("获取任务结果失败: " + e.getMessage(), e);
         }
     }
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public String confirmRecharge(GroupsRelationRechargeReq req) {
+		Long relationId = req.getRelationId();
+		Long userId = req.getUserId();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
+				.in(GroupsRelation::getUserId, userIdList)
+				.eq(GroupsRelation::getId, relationId)
+				.eq(GroupsRelation::getStatus, GroupsRelation.Status.validity));
+		if (relation == null) {
+			throw BusinessRuntimeException.getInstance("车票不存在");
+		}
+		GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
+		GoodsDonSku sku = skuMapper.selectById(groupsTrips.getSkuId());
+		//GPT 代充
+		if (sku.getGoodsId() != Constant.GPT_RECHARGE_GOODS_ID) {
+			throw BusinessRuntimeException.getInstance("车票类型错误");
+		}
+		Integer rechargeRemainNum = relation.getRechargeRemainNum();
+		if (rechargeRemainNum == null || rechargeRemainNum <= 0) {
+			throw BusinessRuntimeException.getInstance("剩余可代充次数为0");
+		}
+		int updateRemainNum = relationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+				.set(GroupsRelation::getRechargeRemainNum, rechargeRemainNum - 1)
+				.eq(GroupsRelation::getId, relationId)
+				.eq(GroupsRelation::getUserId, relation.getUserId())
+				.eq(GroupsRelation::getRechargeRemainNum, rechargeRemainNum));
+		if (updateRemainNum == 0) {
+			throw BusinessRuntimeException.getInstance("代充异常,请重试");
+		}
+		OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
+				.in(OrderDon::getUserId, userIdList)
+				.eq(OrderDon::getRelationId, relation)
+				.notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
+				.orderByDesc(OrderDon::getId)
+				.last("limit 1"));
+		if (orderDon == null) {
+			throw BusinessRuntimeException.getInstance("代充订单不存在或已退款");
+		}
+		String accessToken = req.getAccessToken();
+		//验证用户token是否正确
+		TokenParseResult tokenParseResult = parseToken(accessToken);
+		if (!tokenParseResult.getSuccess()) {
+			throw BusinessRuntimeException.getInstance("您输入的凭证有误,请重新输入");
+		}
+		String rechargeAccount = tokenParseResult.getMessage();
+		//获取GPT代充key
+		GptRechargeCardKey gptRechargeCardKey = gptRechargeCardKeyMapper.selectOne(Wrappers.lambdaQuery(GptRechargeCardKey.class)
+				.eq(GptRechargeCardKey::getStatus, Boolean.FALSE)
+				.last("order by rand() limit 1"));
+		if (gptRechargeCardKey != null) {
+			setRechargeRelationStatusAutoError(relation);
+			throw BusinessRuntimeException.getInstance("充值失败,请联系客服开通");
+		}
+		int update = gptRechargeCardKeyMapper.update(null, Wrappers.lambdaUpdate(GptRechargeCardKey.class)
+				.set(GptRechargeCardKey::getStatus, Boolean.TRUE)
+				.set(GptRechargeCardKey::getOrderId, orderDon.getId())
+				.set(GptRechargeCardKey::getOrderNo, orderDon.getOrderNo())
+				.eq(GptRechargeCardKey::getId, gptRechargeCardKey.getId())
+				.eq(GptRechargeCardKey::getStatus, Boolean.FALSE));
+		if (update == 0) {
+			setRechargeRelationStatusAutoError(relation);
+			throw BusinessRuntimeException.getInstance("充值失败,请联系客服开通");
+		}
+		String gptCardKey = gptRechargeCardKey.getCardKey();
+		//校验卡密是否可用
+		validateCardKey(gptCardKey);
+		//提交任务
+		TaskSubmitResult result = submitTask(gptCardKey, accessToken, "auth0");
+		if (!result.getSuccess()) {
+			setRechargeRelationStatusAutoError(relation);
+			throw BusinessRuntimeException.getInstance("充值失败,请联系客服开通");
+		}
+		relation.setAccount(rechargeAccount);
+		relation.setGptToken(accessToken);
+		relation.setRechargeStatus(GroupsRelation.RechargeStatus.auto_recharge);
+		String taskId = result.getTaskId();
+		relation.setGptTaskId(taskId);
+		relationMapper.updateById(relation);
+		return taskId;
+	}
+
+	/**
+	 * 设置代充自动充值异常
+	 */
+	public void setRechargeRelationStatusAutoError(GroupsRelation relation) {
+		TASK_EXECUTOR.execute(()->{
+			relation.setRechargeStatus(GroupsRelation.RechargeStatus.auto_error);
+			relationMapper.updateById(relation);
+		});
+	}
 }

+ 6 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -1744,6 +1744,12 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				if ((goodsDon.getSpecialType() != null && goodsDon.getSpecialType() == GoodsDon.SpecialType.recharge) || Constant.RECHARGE_INVITE_GOODS_IDS.contains(order.getGoodsId())) {
 					relation.setRechargeStatus(GroupsRelation.RechargeStatus.waiting);
 					relation.setSubmitTime(DateTime.now());
+					//GPT代充
+					if (goodsDon.getId() == Constant.GPT_RECHARGE_GOODS_ID) {
+						//代充次数
+						relation.setRechargeNum(sku.getMonths());
+						relation.setRechargeRemainNum(relation.getRechargeNum());
+					}
 				}
 				GroupsTrips.Status tripsStatus = groupsTrips.getStatus();
 				//邀请制 不给车票设置时间

+ 18 - 1
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -55,6 +55,7 @@ import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.dao.DuplicateKeyException;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
@@ -589,6 +590,7 @@ public class CmsOrderController {
 	 * 修改订单状态
 	 */
 	@PutMapping("/put/status/{orderId}")
+	@Transactional(rollbackFor = Throwable.class)
 	public Result<String> updateOrderStatus(@PathVariable Long orderId) {
 		long adminId = StpUtil.getLoginIdAsLong();
 		CmsUser cmsUser = cmsUserMapper.selectById(adminId);
@@ -610,7 +612,7 @@ public class CmsOrderController {
 				.eq(GroupsRelation::getUserId, orderDon.getUserId())
 				.last("limit 1"))).ifPresent(relation->{
 			GroupsRelation.RechargeStatus rechargeStatus = relation.getRechargeStatus();
-			if (rechargeStatus != null && rechargeStatus == GroupsRelation.RechargeStatus.waiting) {
+			if (rechargeStatus != null && (rechargeStatus == GroupsRelation.RechargeStatus.waiting || rechargeStatus == GroupsRelation.RechargeStatus.auto_error)) {
 				relation.setRechargeStatus(GroupsRelation.RechargeStatus.complete);
 				if (cmsUser != null) {
 					relation.setOperator(cmsUser.getNickname());
@@ -626,6 +628,21 @@ public class CmsOrderController {
 				}
 				relation.setExpiryTime(expiryTime);
 				relationMapper.updateById(relation);
+
+				//GPT代充
+				if (orderDon.getGoodsId() == Constant.GPT_RECHARGE_GOODS_ID) {
+					//扣除次数
+					Integer rechargeRemainNum = relation.getRechargeRemainNum();
+					if (rechargeRemainNum != null && rechargeRemainNum > 0) {
+						int update = relationMapper.update(null, Wrappers.lambdaUpdate(GroupsRelation.class)
+								.set(GroupsRelation::getRechargeRemainNum, rechargeRemainNum - 1)
+								.eq(GroupsRelation::getId, relationId)
+								.eq(GroupsRelation::getRechargeRemainNum, rechargeRemainNum));
+						if (update == 0) {
+							throw BusinessRuntimeException.getInstance("更新用户代充剩余次数失败,请重试");
+						}
+					}
+				}
 			}
 		});
 

+ 19 - 2
netflix-web/src/main/java/com/cyksj/web/controller/recharge/GptRechargeController.java

@@ -1,5 +1,8 @@
 package com.cyksj.web.controller.recharge;
 
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.request.GroupsRelationRechargeReq;
 import com.cyksj.server.recharge.GptProxyRechargeService;
 import com.cyksj.server.recharge.dto.CardKeyValidationResult;
 import com.cyksj.server.recharge.dto.TaskResult;
@@ -8,11 +11,13 @@ import com.cyksj.server.recharge.dto.TokenParseResult;
 import com.cyksj.web.controller.recharge.req.ParseTokenRequest;
 import com.cyksj.web.controller.recharge.req.SubmitTaskRequest;
 import com.cyksj.web.controller.recharge.req.ValidateCardRequest;
+import com.cyksj.web.util.StpUserUtil;
 import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 /**
- * GPT代理充值控制器
+ * server/GPT代理充值控制器
  */
 @RestController
 @RequestMapping("/api/gpt-recharge")
@@ -38,6 +43,18 @@ public class GptRechargeController {
         return gptProxyRechargeService.parseToken(request.getAccessToken());
     }
 
+    /**
+     * 用户确认充值
+     */
+    @PostMapping("/confirm")
+    public Result<String> confirmRecharge(@RequestBody @Validated GroupsRelationRechargeReq req) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        req.setUserId(userId);
+        String taskId = gptProxyRechargeService.confirmRecharge(req);
+        return GatewayResponse.SUCCESS.newBuilder().toResult(taskId);
+    }
+
+
     /**
      * 提交任务
      */
@@ -45,7 +62,7 @@ public class GptRechargeController {
     public TaskSubmitResult submitTask(@RequestBody SubmitTaskRequest request) {
         return gptProxyRechargeService.submitTask(
             request.getCardKey(), 
-            request.getAccessToken(), 
+            request.getAccessToken(),
             request.getIdp()
         );
     }