feat(chat): 新增免费额度与VIP校验逻辑
在聊天接口中增加用户免费次数及VIP身份校验,未通过时返回新错误码50022; 调用成功后若使用免费额度则自动扣减,保障额度体系闭环。
This commit is contained in:
@@ -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");
|
||||
|
||||
/**
|
||||
* 状态码
|
||||
|
||||
@@ -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<Boolean> 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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user