diff --git a/src/main/java/com/yolo/keyborad/common/ErrorCode.java b/src/main/java/com/yolo/keyborad/common/ErrorCode.java index 237e8ec..39129c1 100644 --- a/src/main/java/com/yolo/keyborad/common/ErrorCode.java +++ b/src/main/java/com/yolo/keyborad/common/ErrorCode.java @@ -56,7 +56,8 @@ public enum ErrorCode { PRODUCT_QUOTA_NOT_SET(50018, "商品额度未配置"), LACK_ORIGIN_TRANSACTION_ID_ERROR(50019, "缺少原始交易id"), UNKNOWN_PRODUCT_TYPE(50020, "未知商品类型"), - PRODUCT_NOT_FOUND(50021, "商品不存在"); + PRODUCT_NOT_FOUND(50021, "商品不存在"), + NO_QUOTA_AND_NOT_VIP(50022, "免费次数已用完,请开通VIP"); /** * 状态码 diff --git a/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java b/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java index 00a4812..ddcb0ef 100644 --- a/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java +++ b/src/main/java/com/yolo/keyborad/service/impl/ChatServiceImpl.java @@ -11,10 +11,10 @@ import com.yolo.keyborad.exception.BusinessException; import com.yolo.keyborad.model.dto.chat.ChatReq; import com.yolo.keyborad.model.dto.chat.ChatStreamMessage; import com.yolo.keyborad.model.entity.KeyboardCharacter; +import com.yolo.keyborad.model.entity.KeyboardUser; import com.yolo.keyborad.model.entity.KeyboardUserCallLog; -import com.yolo.keyborad.service.ChatService; -import com.yolo.keyborad.service.KeyboardCharacterService; -import com.yolo.keyborad.service.KeyboardUserCallLogService; +import com.yolo.keyborad.model.entity.KeyboardUserQuotaTotal; +import com.yolo.keyborad.service.*; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.client.ChatClient; @@ -55,6 +55,12 @@ public class ChatServiceImpl implements ChatService { @Resource private KeyboardUserCallLogService callLogService; + @Resource + private KeyboardUserQuotaTotalService quotaTotalService; + + @Resource + private UserService userService; + private final NacosAppConfigCenter.DynamicAppConfig cfgHolder; public ChatServiceImpl(NacosAppConfigCenter.DynamicAppConfig cfgHolder) { @@ -105,6 +111,22 @@ public class ChatServiceImpl implements ChatService { throw new BusinessException(ErrorCode.CHAT_CHARACTER_NOT_FOUND); } + // ============ 3. 校验用户免费次数和VIP ============ + Long userId = StpUtil.getLoginIdAsLong(); + KeyboardUserQuotaTotal quota = quotaTotalService.getById(userId); + boolean hasFreeQuota = quota != null && quota.getUsedQuota() < quota.getTotalQuota(); + AtomicReference usedFreeQuota = new AtomicReference<>(hasFreeQuota); + + if (!hasFreeQuota) { + KeyboardUser user = userService.getById(userId); + boolean isValidVip = user != null && user.getIsVip() != null && user.getIsVip() + && (user.getVipExpiry() == null || user.getVipExpiry().after(new Date())); + if (!isValidVip) { + log.error("用户无免费次数且非VIP,用户ID: {}", userId); + throw new BusinessException(ErrorCode.NO_QUOTA_AND_NOT_VIP); + } + } + // 获取应用配置 // ============ 初始化调用日志相关变量 ============ @@ -260,6 +282,14 @@ public class ChatServiceImpl implements ChatService { callLog.setCreatedAt(new Date()); // 保存日志到数据库 callLogService.save(callLog); + + // 如果使用了免费次数且调用成功,扣减免费次数 + if (usedFreeQuota.get() && callLog.getSuccess()) { + KeyboardUserQuotaTotal updateQuota = new KeyboardUserQuotaTotal(); + updateQuota.setUserId(callLog.getUserId()); + updateQuota.setUsedQuota(quota.getUsedQuota() + 1); + quotaTotalService.updateById(updateQuota); + } } catch (Exception e) { log.error("保存调用日志失败", e); }