Explorar el Código

用户使用重置次数,使用积分卡API

zoujiajian hace 1 año
padre
commit
a4a4e52bd7

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/mapper/claudecode/ClaudeCodeCreditCardMapper.java

@@ -0,0 +1,16 @@
+package com.cyksj.mapper.claudecode;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.ClaudeCodeCreditCard;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeCreditCardMapper
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode积分卡Mapper
+ */
+@Mapper
+public interface ClaudeCodeCreditCardMapper extends BaseMapper<ClaudeCodeCreditCard> {
+}

+ 62 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeCreditCard.java

@@ -0,0 +1,62 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeCreditCard
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode积分卡定义表
+ */
+@Getter
+@Setter
+public class ClaudeCodeCreditCard extends BaseEntity {
+    
+    /**
+     * 积分卡编号
+     */
+    private String cardNumber;
+    
+    /**
+     * 积分额度
+     */
+    private Integer creditAmount;
+    
+    /**
+     * 积分卡状态 0:未使用 1:已使用 2:已过期
+     */
+    private Integer status;
+    
+    /**
+     * 使用用户ID
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private Long usedUserId;
+    
+    /**
+     * 使用时间
+     */
+    @TableField(updateStrategy = FieldStrategy.IGNORED)
+    private Date usedTime;
+    
+    /**
+     * 有效期
+     */
+    private Date expiryTime;
+    
+    /**
+     * 创建批次
+     */
+    private String batchNumber;
+    
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 0 - 5
netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeUserCreditCardRecord.java

@@ -34,11 +34,6 @@ public class ClaudeCodeUserCreditCardRecord extends BaseEntity {
      */
     private Integer afterCodePoints;
     
-    /**
-     * 积分卡类型 1:普通积分卡 2:高级积分卡
-     */
-    private Integer cardType;
-    
     /**
      * 积分卡编号/批次号
      */

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/request/ClaudeCodeCreditCardUseReq.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeCreditCardUseReq
+ * 创建者: Claude
+ * 创建时间:2025/8/26
+ * 描述: ClaudeCode积分卡使用请求
+ */
+@Getter
+@Setter
+public class ClaudeCodeCreditCardUseReq {
+    
+    /**
+     * 积分卡编号
+     */
+    private String cardNumber;
+    
+    /**
+     * 用户ID (由控制器自动设置)
+     */
+    private Long userId;
+}

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/response/claudecode/ClaudeCodeResp.java

@@ -17,4 +17,6 @@ public class ClaudeCodeResp {
 	private Integer code;
 
 	private String message;
+
+	private Boolean success;
 }

+ 7 - 1
netflix-service/src/main/java/com/cyksj/service/claude/ClaudeCodeService.java

@@ -4,6 +4,7 @@ import com.cyksj.model.entity.ClaudeCodeUser;
 import com.cyksj.model.entity.GoodsDonSku;
 import com.cyksj.model.entity.GroupsRelation;
 import com.cyksj.model.request.ClaudeCodeApiKeysReq;
+import com.cyksj.model.request.ClaudeCodeCreditCardUseReq;
 import com.cyksj.model.request.ClaudeCodeDelReq;
 import com.cyksj.model.request.CreditResetReq;
 import com.cyksj.model.request.TimeRateConfigReq;
@@ -107,10 +108,15 @@ public interface ClaudeCodeService {
 	/**
 	 * 使用积分卡增加用户codePoints并记录使用次数
 	 */
-	void useCreditCard(Long userId, Integer addCodePoints, Integer cardType, String cardNumber, Long operatorId, String operatorName, String useReason);
+	void useCreditCard(Long userId, Integer addCodePoints, String cardNumber, Long operatorId, String operatorName, String useReason);
 
 	/**
 	 * 用户使用重置次数 - 保持幂等性
 	 */
 	boolean useResetCount(Long userId);
+
+	/**
+	 * 用户使用积分卡
+	 */
+	ClaudeCodeResp useCreditCard(ClaudeCodeCreditCardUseReq req) throws Exception;
 }

+ 87 - 2
netflix-service/src/main/java/com/cyksj/service/claude/impl/ClaudeCodeServiceImpl.java

@@ -16,9 +16,11 @@ import com.cyksj.common.util.StringUtil;
 import com.cyksj.mapper.*;
 import com.cyksj.mapper.claudecode.ClaudeCodeUserResetRecordMapper;
 import com.cyksj.mapper.claudecode.ClaudeCodeUserCreditCardRecordMapper;
+import com.cyksj.mapper.claudecode.ClaudeCodeCreditCardMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.ClaudeCodeApiKeysReq;
+import com.cyksj.model.request.ClaudeCodeCreditCardUseReq;
 import com.cyksj.model.request.ClaudeCodeDelReq;
 import com.cyksj.model.request.CreditResetReq;
 import com.cyksj.model.request.TimeRateConfigReq;
@@ -74,6 +76,8 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 
 	private final ClaudeCodeUserCreditCardRecordMapper claudeCodeUserCreditCardRecordMapper;
 
+	private final ClaudeCodeCreditCardMapper claudeCodeCreditCardMapper;
+
 	private final static String CLAUDE_CODE_API_PREFIX = "https://relay01.yhlxj.com/";
 
 	public static final String CLAUDE_CODE_API_ADMIN_KEY = "claudecodeyhlxjclaude";
@@ -687,7 +691,7 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 	}
 
 	@Override
-	public void useCreditCard(Long userId, Integer addCodePoints, Integer cardType, String cardNumber, Long operatorId, String operatorName, String useReason) {
+	public void useCreditCard(Long userId, Integer addCodePoints, String cardNumber, Long operatorId, String operatorName, String useReason) {
 		ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
 			Wrappers.<ClaudeCodeUser>lambdaQuery().eq(ClaudeCodeUser::getUserId, userId)
 		);
@@ -707,7 +711,6 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 		creditCardRecord.setBeforeCodePoints(beforeCodePoints);
 		creditCardRecord.setAddCodePoints(addCodePoints);
 		creditCardRecord.setAfterCodePoints(afterCodePoints);
-		creditCardRecord.setCardType(cardType);
 		creditCardRecord.setCardNumber(cardNumber);
 		creditCardRecord.setOperatorId(operatorId);
 		creditCardRecord.setOperatorName(operatorName);
@@ -758,4 +761,86 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 		}
 	}
 
+	@Override
+	public ClaudeCodeResp useCreditCard(ClaudeCodeCreditCardUseReq req) throws Exception {
+		Long userId = req.getUserId();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		
+		ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
+			Wrappers.lambdaQuery(ClaudeCodeUser.class)
+				.in(ClaudeCodeUser::getUserId, userIdList)
+				.last("limit 1")
+		);
+		
+		if (claudeCodeUser == null) {
+			throw new BusinessRuntimeException("用户未开通Claude Code服务");
+		}
+		
+		ClaudeCodeCreditCard creditCard = claudeCodeCreditCardMapper.selectOne(
+			Wrappers.lambdaQuery(ClaudeCodeCreditCard.class)
+				.eq(ClaudeCodeCreditCard::getStatus, 0)
+					.last("limit 1")
+		);
+		
+		if (creditCard == null) {
+			throw new BusinessRuntimeException("积分卡不存在");
+		}
+		
+		if (creditCard.getStatus() != 0) {
+			if (creditCard.getStatus() == 1) {
+				throw new BusinessRuntimeException("积分卡已被使用");
+			} else if (creditCard.getStatus() == 2) {
+				throw new BusinessRuntimeException("积分卡已过期");
+			} else {
+				throw new BusinessRuntimeException("积分卡状态异常");
+			}
+		}
+		String cardNumber = creditCard.getCardNumber();
+		
+		if (creditCard.getExpiryTime() != null && creditCard.getExpiryTime().before(new Date())) {
+			creditCard.setStatus(2);
+			claudeCodeCreditCardMapper.updateById(creditCard);
+			throw new BusinessRuntimeException("积分卡已过期");
+		}
+		
+		Integer beforeCodePoints = claudeCodeUser.getCodePoints();
+		Integer addCodePoints = creditCard.getCreditAmount();
+		Integer afterCodePoints = beforeCodePoints + addCodePoints;
+		
+		try {
+			claudeCodeUser.setCodePoints(afterCodePoints);
+			int userUpdateResult = claudeCodeUserMapper.updateById(claudeCodeUser);
+			
+			creditCard.setStatus(1);
+			creditCard.setUsedUserId(userId);
+			creditCard.setUsedTime(new Date());
+			int cardUpdateResult = claudeCodeCreditCardMapper.update(creditCard,
+					Wrappers.lambdaUpdate(ClaudeCodeCreditCard.class)
+							.eq(ClaudeCodeCreditCard::getId, creditCard.getId())
+							.eq(ClaudeCodeCreditCard::getStatus, 0)
+			);
+			
+			if (userUpdateResult > 0 && cardUpdateResult > 0) {
+				useCreditCard(userId,addCodePoints,cardNumber,null,"用户自助","使用积分卡");
+				
+				log.info("用户{}成功使用积分卡{},增加{}积分", userId, cardNumber, addCodePoints);
+				
+				ClaudeCodeResp resp = new ClaudeCodeResp();
+				resp.setSuccess(true);
+				resp.setMessage("积分卡使用成功");
+				resp.setData(Map.of(
+					"beforeCodePoints", beforeCodePoints,
+					"addCodePoints", addCodePoints,
+					"afterCodePoints", afterCodePoints
+				));
+				return resp;
+			} else {
+				throw new BusinessRuntimeException("积分卡使用失败,请重试");
+			}
+		} catch (Exception e) {
+			log.error("用户{}使用积分卡{}异常", userId, cardNumber, e);
+			throw new BusinessRuntimeException("积分卡使用失败:" + e.getMessage());
+		}
+	}
+
 }

+ 13 - 0
netflix-web/src/main/java/com/cyksj/web/controller/claude/ClaudeCodeController.java

@@ -18,6 +18,7 @@ import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.OrderDonView;
 import com.cyksj.model.request.ClaudeCodeApiKeysReq;
+import com.cyksj.model.request.ClaudeCodeCreditCardUseReq;
 import com.cyksj.model.request.ClaudeCodeDelReq;
 import com.cyksj.model.request.CreditResetReq;
 import com.cyksj.model.request.TimeRateConfigReq;
@@ -548,4 +549,16 @@ public class ClaudeCodeController {
 		
 		return GatewayResponse.SUCCESS.newBuilder().toResult(result);
 	}
+
+	/**
+	 * 用户使用积分卡
+	 */
+	@PostMapping("/use/credit-card")
+	public ClaudeCodeResp useCreditCard() throws Exception {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		ClaudeCodeCreditCardUseReq req = new ClaudeCodeCreditCardUseReq();
+		req.setUserId(userId);
+		ClaudeCodeResp resp = claudeCodeService.useCreditCard(req);
+		return resp;
+	}
 }