| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046 |
- package com.cyksj.service.claude.impl;
- import cn.hutool.core.date.DateTime;
- import cn.hutool.core.date.DateUtil;
- import cn.hutool.core.lang.Assert;
- import cn.hutool.core.util.ObjectUtil;
- import cn.hutool.http.HttpException;
- import cn.hutool.http.HttpResponse;
- import cn.hutool.http.HttpUtil;
- import cn.hutool.http.Method;
- import cn.hutool.json.JSONObject;
- import com.baomidou.mybatisplus.core.toolkit.Wrappers;
- import com.cyksj.common.constant.Constant;
- import com.cyksj.common.exception.BusinessRuntimeException;
- import com.cyksj.common.util.Jsons;
- import com.cyksj.common.util.StringUtil;
- import com.cyksj.mapper.*;
- import com.cyksj.mapper.claudecode.ClaudeCodeCreditCardMapper;
- import com.cyksj.mapper.claudecode.ClaudeCodeDayResetRecordMapper;
- import com.cyksj.mapper.claudecode.ClaudeCodeUserCreditCardRecordMapper;
- import com.cyksj.mapper.claudecode.ClaudeCodeUserResetRecordMapper;
- import com.cyksj.mapper.manage.distribute.DistributePointsExchangeMoneyMapper;
- import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
- 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.response.ClaudeCodePointsHistoryResp;
- import com.cyksj.model.response.ClaudeCodeRewardDetailsResp;
- import com.cyksj.model.response.CreditResetResp;
- import com.cyksj.model.response.TimeRateConfigsResp;
- import com.cyksj.model.response.claudecode.ClaudeCodeResp;
- import com.cyksj.model.views.ClaudeCodeUserApiKeysView;
- import com.cyksj.model.views.ClaudeCodeUserCreditCardRecordView;
- import com.cyksj.model.views.ClaudeCodeUserInfoView;
- import com.cyksj.model.views.ClaudeCodeUserResetRecordView;
- import com.cyksj.redis.RedisService;
- import com.cyksj.service.claude.ClaudeCodeService;
- import com.cyksj.service.user.UserBindRelationService;
- import com.ejlchina.searcher.BeanSearcher;
- import com.ejlchina.searcher.SearchResult;
- import com.ejlchina.searcher.param.Operator;
- import com.ejlchina.searcher.util.MapUtils;
- import com.github.rholder.retry.*;
- import lombok.RequiredArgsConstructor;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.dao.DuplicateKeyException;
- import org.springframework.stereotype.Service;
- import org.springframework.transaction.annotation.Transactional;
- import java.math.BigDecimal;
- import java.math.RoundingMode;
- import java.util.*;
- import java.util.concurrent.ExecutionException;
- import java.util.concurrent.TimeUnit;
- /**
- * 项目名: yhlxj11111111
- * 文件名: ClaudeCodeServiceImpl
- * 创建者: JavaZou
- * 创建时间:2025/8/8 10:55
- */
- @Service
- @RequiredArgsConstructor
- @Slf4j
- public class ClaudeCodeServiceImpl implements ClaudeCodeService {
- private final UserBindRelationService userBindRelationService;
- private final GroupsRelationMapper relationMapper;
- private final BeanSearcher beanSearcher;
- private final ClaudeCodeUserRenewExpiryRecordMapper claudeCodeUserRenewExpiryRecordMapper;
- private final ClaudeCodeUserMapper claudeCodeUserMapper;
- private final GoodsDonSkuMapper skuMapper;
- private final GroupsMapper groupsMapper;
- private final OrderDonMapper orderDonMapper;
- private final ClaudeCodeUserResetRecordMapper claudeCodeUserResetRecordMapper;
- private final ClaudeCodeUserCreditCardRecordMapper claudeCodeUserCreditCardRecordMapper;
- private final ClaudeCodeCreditCardMapper claudeCodeCreditCardMapper;
- private final UserMapper userMapper;
- private final DistributeWaitingSendPointsMapper distributeWaitingSendPointsMapper;
- private final DistributePointsExchangeMoneyMapper distributePointsExchangeMoneyMapper;
- private final GoodsDonMapper goodsDonMapper;
- private final ClaudeCodeDayResetRecordMapper claudeCodeDayResetRecordMapper;
- private final RedisService redisService;
- private final static String CLAUDE_CODE_API_PREFIX = "https://relay01.yhlxj.com/";
- public static final String CLAUDE_CODE_HEARD_KEY = "X-Admin-Key";
- public static final String CLAUDE_CODE_API_ADMIN_KEY = "claudecodeyhlxjclaude";
- //连接超时时间 毫秒
- public static final int CONNECT_MILLISECONDS = 10000;
- @Override
- public void generateOrUpdateClaudeCodeUserInfo(Long orderId, Long relationId, Long userId, GoodsDonSku sku, Integer orderType) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class).eq(GroupsRelation::getId, relationId).in(GroupsRelation::getUserId, userIdList));
- GroupsTrips groupsTrips = groupsMapper.selectById(relation.getGroupsId());
- GoodsDonSku relationSku = skuMapper.selectById(groupsTrips.getSkuId());
- Long thisCodeOriSkuId = relationSku.getId();
- Long relationUserId = relation.getUserId();
- //此时车票的套餐规格积分
- Integer thisRelationCodePoints = null;
- ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUser.class).eq(ClaudeCodeUser::getRelationId, relationId).last("limit 1"));
- if (claudeCodeUser != null) {
- thisRelationCodePoints = claudeCodeUser.getCodePoints();
- }
- Date expiryTime = relation.getExpiryTime();
- Integer codePoints = sku.getCodePoints();
- Integer codeCreditRecovery = sku.getCodeCreditRecovery();
- Long skuId = sku.getId();
- Boolean isUpgrade = false;
- Date renewExpiryTime = null;
- //若是续费升级 记录此时续费升级的过期时间
- if (!ObjectUtil.equal(thisCodeOriSkuId, skuId)) {
- //非车票原规格id 续费升级记录
- saveClaudeCodeRenewExpiryRecord(orderId, relationUserId, relationId, skuId);
- //是否需要修改当前claude code user 套餐等级
- if (thisRelationCodePoints != null && thisRelationCodePoints <= codePoints) {
- if (sku.getDays() != null) {
- renewExpiryTime = DateUtil.offsetDay(DateTime.now(), sku.getDays());
- } else {
- renewExpiryTime = DateUtil.offsetMonth(DateTime.now(), sku.getMonths());
- }
- isUpgrade = true;
- }
- }
- generateOrUpdateClaudeCodeUser(relationUserId, relationId, codePoints, codeCreditRecovery, expiryTime, isUpgrade, orderId, skuId, renewExpiryTime, sku.getSpecVal(), userIdList);
- try {
- //获取最新的claude code user
- claudeCodeUser = claudeCodeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUser.class).eq(ClaudeCodeUser::getRelationId, relationId).last("limit 1"));
- //生成claude code或更新用户套餐
- ClaudeCodeResp codeUserPackage = createOrUpdateClaudeCodeUserPackage(relation.getUserId(), claudeCodeUser.getPlanName(), claudeCodeUser.getCodePoints(), claudeCodeUser.getCodeCreditRecovery(), claudeCodeUser.getExpiryTime());
- if (!Constant.SUCCESS.equals(codeUserPackage.getMessage())) {
- //重试更新code userInfo数据
- setClaudeCodeUserRetryUpdateInfo(relationId);
- return;
- }
- //清缓存
- if (orderType != null && orderType == 2) {
- invalidateUserCache(relationUserId);
- }
- } catch (Exception e) {
- log.error("生成或更新claude code用户:{}套餐skuId:{} 失败,error_info:{}", userId, skuId, StringUtil.getErrorText(e));
- //重试更新code userInfo数据
- setClaudeCodeUserRetryUpdateInfo(relationId);
- }
- }
- private void generateOrUpdateClaudeCodeUser(Long relationUserId, Long relationId, Integer codePoints, Integer codeCreditRecovery, Date expiryTime, Boolean isUpgrade, Long orderId, Long renewSkuId, Date renewExpiryTime, String planName, List<Long> userIdList) {
- ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUser.class).eq(ClaudeCodeUser::getRelationId, relationId).last("limit 1"));
- if (claudeCodeUser == null) {
- claudeCodeUser = new ClaudeCodeUser();
- }
- if (isUpgrade) {
- claudeCodeUser.setRenewOrderId(orderId);
- claudeCodeUser.setRenewSkuId(renewSkuId);
- claudeCodeUser.setRenewExpiryTime(renewExpiryTime);
- claudeCodeUser.setPlanName(planName);
- claudeCodeUser.setCodePoints(codePoints);
- claudeCodeUser.setCodeCreditRecovery(codeCreditRecovery);
- }
- claudeCodeUser.setUserId(relationUserId);
- claudeCodeUser.setRelationId(relationId);
- claudeCodeUser.setExpiryTime(expiryTime);
- if (claudeCodeUser.getId() == null) {
- claudeCodeUser.setPlanName(planName);
- claudeCodeUser.setCodePoints(codePoints);
- claudeCodeUser.setCodeCreditRecovery(codeCreditRecovery);
- //可重置次数
- Integer resetCount = claudeCodeUserResetRecordMapper.getUserResetCountByUserIds(userIdList);
- if (resetCount != null && resetCount > 0) {
- claudeCodeUser.setResetCount(resetCount);
- }
- }
- if (claudeCodeUser.getId() == null) {
- try {
- claudeCodeUserMapper.insert(claudeCodeUser);
- } catch (DuplicateKeyException e) {
- log.info("插入claude code user 重复");
- }
- } else claudeCodeUserMapper.updateById(claudeCodeUser);
- }
- @Override
- public ClaudeCodeResp createApiKeys(ClaudeCodeApiKeysReq req) throws Exception {
- Long userId = req.getUserId();
- if (checkClaudeCodeUser(userId)) {
- Long claudeCodeUserId = getClaudeCodeUserId(userId);
- Assert.notNull(claudeCodeUserId, "您的claude code账号已过期");
- String apiKeyUrl = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/keys", claudeCodeUserId);
- Map<String, Object> parmas = new HashMap<>();
- parmas.put("name", req.getName());
- Integer expiresDays = req.getExpiresDays();
- if (expiresDays != null) {
- parmas.put("expires_days", expiresDays);
- }
- ClaudeCodeResp claudeCodeResp = executeClaudeCodePostApi(apiKeyUrl, Jsons.toJson(parmas));
- if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
- throw BusinessRuntimeException.getInstance("创建失败");
- }
- return claudeCodeResp;
- }
- throw new BusinessRuntimeException("您还没有claudecode账号");
- }
- @Override
- public void deleteApiKeysById(ClaudeCodeDelReq delReq) throws Exception {
- Long userId = delReq.getUserId();
- Long keyId = delReq.getKeyId();
- if (checkClaudeCodeUser(userId)) {
- Long claudeCodeUserId = getClaudeCodeUserId(userId);
- String url = String.format(CLAUDE_CODE_API_PREFIX + "api/keys/%s/%s", claudeCodeUserId, keyId);
- HttpResponse execute = HttpUtil.createRequest(Method.DELETE, url).header(CLAUDE_CODE_HEARD_KEY, CLAUDE_CODE_API_ADMIN_KEY).setConnectionTimeout(CONNECT_MILLISECONDS).execute();
- String responseBody = execute.body();
- ClaudeCodeResp claudeCodeResp = Jsons.parseObject(responseBody, ClaudeCodeResp.class);
- if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
- log.error("删除key失败:{}", claudeCodeResp.getMessage());
- throw BusinessRuntimeException.getInstance("删除失败");
- }
- }
- }
- @Override
- public List<ClaudeCodeUserApiKeysView> getUserApiKeys(long userId) throws Exception {
- Long claudeCodeUserId = getClaudeCodeUserId(userId);
- if (claudeCodeUserId != null) {
- String url = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/keys", claudeCodeUserId);
- ClaudeCodeResp claudeCodeResp = executeClaudeCodeGetApi(url);
- return Jsons.parseList(claudeCodeResp.getData(), ClaudeCodeUserApiKeysView.class);
- }
- return null;
- }
- @Override
- public ClaudeCodePointsHistoryResp getUserPointsDetail(Long userId, String type, Integer page, Integer limit) throws Exception {
- Long claudeCodeUserId = getClaudeCodeUserId(userId);
- if (claudeCodeUserId != null) {
- String url = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/credits/history?page=%s&limit=%s&type=%s", claudeCodeUserId, page, limit, type);
- ClaudeCodeResp claudeCodeResp = executeClaudeCodeGetApi(url);
- ClaudeCodePointsHistoryResp historyResp = Jsons.parseObject(claudeCodeResp.getData(), ClaudeCodePointsHistoryResp.class);
- return historyResp;
- }
- return null;
- }
- @Override
- public ClaudeCodeResp getUserDashboard(Long userId) throws Exception {
- Long claudeCodeUserId = getClaudeCodeUserId(userId);
- if (claudeCodeUserId != null) {
- String url = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/dashboard", claudeCodeUserId);
- ClaudeCodeResp claudeCodeResp = executeClaudeCodeGetApi(url);
- return claudeCodeResp;
- }
- return null;
- }
- @Override
- public ClaudeCodeResp getUserBalance(Long userId) throws Exception {
- Long claudeCodeUserId = getClaudeCodeUserId(userId);
- if (claudeCodeUserId != null) {
- String url = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/balance", claudeCodeUserId);
- ClaudeCodeResp claudeCodeResp = executeClaudeCodeGetApi(url);
- return claudeCodeResp;
- }
- return null;
- }
- @Override
- public ClaudeCodeResp getCreditsAnalytics(Long userId, String start, String end, String tz, Integer page, Integer limit, String order, String type) throws Exception {
- Long claudeCodeUserId = getClaudeCodeUserId(userId);
- if (start == null) {
- DateTime now = DateTime.now();
- start = DateUtil.offsetDay(now, -1).toString();
- end = now.toString();
- }
- if (claudeCodeUserId != null) {
- String url = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/credits/analytics?start=%s&end=%s&tz=%s&page=%s&limit=%s&order=%s&type=%s", claudeCodeUserId, start, end, tz, page, limit, order, type);
- ClaudeCodeResp claudeCodeResp = executeClaudeCodeGetApi(url);
- return claudeCodeResp;
- }
- return null;
- }
- /**
- * 用户缓存失效
- */
- @Override
- public void invalidateUserCache(Long userId) {
- String url = String.format(CLAUDE_CODE_API_PREFIX + "api/cache/invalidate/user/%s", userId);
- try {
- executeClaudeCodePostApi(url, null);
- } catch (Exception e) {
- }
- }
- @Override
- public ClaudeCodeUserInfoView getClaudeCodeUserSubsInfo(Long userId) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- //是否有该车票
- GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
- .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
- .field(GroupsRelationView::getGoodsId, Constant.CLAUDE_CODE_GOODS_ID)
- .field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
- .build());
- ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUser.class).in(ClaudeCodeUser::getUserId, userIdList).last("limit 1"));
- //车票不存在
- if (groupsRelationView == null) {
- //套餐是否存在
- if (claudeCodeUser != null) {
- //清除用户套餐
- if (delUserPackages(claudeCodeUser.getUserId())) {
- claudeCodeUserMapper.deleteById(claudeCodeUser.getId());
- }
- }
- return null;
- }
- GoodsDonSku sku = null;
- if (claudeCodeUser == null) {
- OrderDon orderDon = orderDonMapper.selectOne(Wrappers.lambdaQuery(OrderDon.class)
- .eq(OrderDon::getGoodsId, Constant.CLAUDE_CODE_GOODS_ID)
- .eq(OrderDon::getRelationId, groupsRelationView.getId())
- .in(OrderDon::getUserId, userIdList)
- .notIn(OrderDon::getStatus, Constant.noOrderAllStatus)
- .orderByDesc(OrderDon::getId)
- .last("limit 1"));
- if (orderDon != null) {
- sku = skuMapper.selectById(orderDon.getSkuId());
- generateOrUpdateClaudeCodeUserInfo(orderDon.getId(), orderDon.getRelationId(), orderDon.getUserId(), sku, orderDon.getOrderType());
- claudeCodeUser = claudeCodeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUser.class).in(ClaudeCodeUser::getUserId, userIdList).last("limit 1"));
- } else {
- //试用车票
- Long skuId = groupsRelationView.getSkuId();
- sku = skuMapper.selectById(skuId);
- generateOrUpdateClaudeCodeUserInfo(null, groupsRelationView.getId(), groupsRelationView.getUserId(), sku, null);
- claudeCodeUser = claudeCodeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUser.class).in(ClaudeCodeUser::getUserId, userIdList).last("limit 1"));
- }
- } else {
- claudeCodeUser.setExpiryTime(groupsRelationView.getExpiryTime());
- claudeCodeUserMapper.updateById(claudeCodeUser);
- }
- if (sku == null) {
- sku = skuMapper.selectById(groupsRelationView.getSkuId());
- }
- //是否需要重试更新 cladueCode userInfo信息
- if (claudeCodeUser.getIsRetry()) {
- try {
- ClaudeCodeResp codeUserPackage = createOrUpdateClaudeCodeUserPackage(claudeCodeUser.getUserId(), claudeCodeUser.getPlanName(), claudeCodeUser.getCodePoints(), claudeCodeUser.getCodeCreditRecovery(), claudeCodeUser.getExpiryTime());
- if (!Constant.SUCCESS.equals(codeUserPackage.getMessage())) {
- claudeCodeUser.setIsRetry(Boolean.TRUE);
- claudeCodeUserMapper.updateById(claudeCodeUser);
- } else {
- claudeCodeUser.setIsRetry(Boolean.FALSE);
- claudeCodeUserMapper.updateById(claudeCodeUser);
- }
- } catch (Exception e) {
- }
- }
- return ClaudeCodeUserInfoView.builder()
- .planName(claudeCodeUser.getPlanName())
- .relationId(claudeCodeUser.getRelationId())
- .codePoints(claudeCodeUser.getCodePoints())
- .codeCreditRecovery(claudeCodeUser.getCodeCreditRecovery())
- .expiryTime(claudeCodeUser.getExpiryTime())
- .renewSkuId(claudeCodeUser.getRenewSkuId())
- .renewOrderId(claudeCodeUser.getRenewOrderId())
- .renewExpiryTime(claudeCodeUser.getRenewExpiryTime())
- .highestUsage(sku.getHighestUsage())
- .build();
- }
- public ClaudeCodeResp createOrUpdateClaudeCodeUserPackage(Long userId, String planName, Integer codePoints, Integer codeCreditRecovery, Date expiryTime) throws Exception {
- Map<String, Object> parmas = new HashMap<>();
- parmas.put("plan_name", planName.replaceAll(";", ""));
- parmas.put("credit_limit", codePoints);
- parmas.put("credit_recovery", codeCreditRecovery);
- parmas.put("expire_time", DateUtil.format(expiryTime,"yyyy-MM-dd HH:mm:ss"));
- String planUrl = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/plan", userId);
- ClaudeCodeResp claudeCodeResp = executeClaudeCodePostApi(planUrl, Jsons.toJson(parmas));
- if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
- log.info("用户claude code用户:{}套餐:{}创建或更新失败,info:{}", userId, planName, claudeCodeResp.getMessage());
- }
- return claudeCodeResp;
- }
- /**
- * 校验是否是claude code用户
- * @param userId
- * @return
- */
- @Override
- public Boolean checkClaudeCodeUser(Long userId) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- Integer count = relationMapper.selectCountByGoodsId(userIdList, Constant.CLAUDE_CODE_GOODS_ID, DateTime.now());
- return count > 0;
- }
- @Override
- public void updateClaudeCodeUserPackageInfo(ClaudeCodeUser claudeCodeUser, Date expiryTime) {
- try {
- ClaudeCodeResp codeUserPackage = createOrUpdateClaudeCodeUserPackage(claudeCodeUser.getUserId(), claudeCodeUser.getPlanName(), claudeCodeUser.getCodePoints(), claudeCodeUser.getCodeCreditRecovery(), expiryTime);
- if (!Constant.SUCCESS.equals(codeUserPackage.getMessage())) {
- //重试标记
- claudeCodeUser.setIsRetry(Boolean.TRUE);
- claudeCodeUserMapper.updateById(claudeCodeUser);
- return;
- }
- //刷新缓存
- invalidateUserCache(claudeCodeUser.getUserId());
- } catch (Exception e) {
- claudeCodeUser.setIsRetry(Boolean.TRUE);
- claudeCodeUserMapper.updateById(claudeCodeUser);
- }
- }
- @Override
- public Boolean delUserPackages(Long userId) {
- String url = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/plan", userId);
- try {
- ClaudeCodeResp claudeCodeResp = executeClaudeCodeDeletedApi(url);
- if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
- log.error("删除用户:{} claude code套餐失败:{}", userId, claudeCodeResp.getMessage());
- return Boolean.FALSE;
- }
- return Boolean.TRUE;
- } catch (Exception e) {
- log.error("删除用户:{} claude code套餐报错:{}", userId, StringUtil.getErrorText(e));
- }
- return Boolean.FALSE;
- }
- @Override
- public void handleClaudeCodeUserPackageSku(GroupsRelation relation, GoodsDonSku sku, Long orderId) {
- generateOrUpdateClaudeCodeUserInfo(orderId, relation.getId(), relation.getUserId(), sku, 2);
- }
- @Override
- public TimeRateConfigsResp getAllConfigs() {
- try {
- String url = CLAUDE_CODE_API_PREFIX + "api/time-multiplier/configs";
- ClaudeCodeResp claudeCodeResp = executeClaudeCodeGetApi(url);
- return Jsons.parseObject(claudeCodeResp.getData(), TimeRateConfigsResp.class);
- } catch (Exception e) {
- log.error("获取时间倍率配置列表失败", e);
- throw BusinessRuntimeException.getInstance("获取时间倍率配置列表失败");
- }
- }
- @Override
- public CreditResetResp resetUserCredits(Long userId, CreditResetReq req) throws Exception {
- if (userId <= 0) {
- throw BusinessRuntimeException.getInstance("用户ID无效");
- }
- String url = CLAUDE_CODE_API_PREFIX + "api/users/" + userId + "/credits/reset";
- String body = req != null ? Jsons.toJson(req) : "{}";
- ClaudeCodeResp claudeCodeResp = executeClaudeCodePostApi(url, body);
- if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
- throw BusinessRuntimeException.getInstance("重置次数失败");
- }
- return Jsons.parseObject(claudeCodeResp.getData(), CreditResetResp.class);
- }
- /**
- * 验证时间范围
- */
- private void validateTimeRange(Integer startHour, Integer endHour) {
- if (startHour == null || endHour == null) {
- throw BusinessRuntimeException.getInstance("开始和结束小时不能为空");
- }
- if (startHour < 0 || startHour > 23) {
- throw BusinessRuntimeException.getInstance("开始小时必须在0-23之间");
- }
- if (endHour < 0 || endHour > 23) {
- throw BusinessRuntimeException.getInstance("结束小时必须在0-23之间");
- }
- }
- /**
- * 获取claude code用户id
- */
- public Long getClaudeCodeUserId(Long userId) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
- .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
- .field(GroupsRelationView::getGoodsId, Constant.CLAUDE_CODE_GOODS_ID)
- .field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
- .build());
- if (groupsRelationView != null) {
- return groupsRelationView.getUserId();
- }
- return null;
- }
- /**
- * claude code GET请求
- */
- public ClaudeCodeResp executeClaudeCodeGetApi(String url) {
- Retryer<ClaudeCodeResp> build = getApiRetryer(1, 3);
- try {
- return build.call(() -> {
- try {
- HttpResponse execute = HttpUtil.createGet(url)
- .header(CLAUDE_CODE_HEARD_KEY, CLAUDE_CODE_API_ADMIN_KEY)
- .setConnectionTimeout(CONNECT_MILLISECONDS)
- .execute();
- ClaudeCodeResp resp = Jsons.parseObject(execute.body(), ClaudeCodeResp.class);
- if (!Constant.SUCCESS.equals(resp.getMessage())) {
- log.error("claude code GET URL:{}接口返回msg:{}", url, resp.getMessage());
- }
- return resp;
- } catch (HttpException e) {
- return null;
- }
- });
- } catch (ExecutionException | RetryException e) {
- log.error("重试调用claude code GET请求url->{}失败,msg->{}", url, StringUtil.getErrorText(e));
- throw BusinessRuntimeException.getInstance("接口请求失败");
- }
- }
- /**
- * claude code Post请求
- */
- public ClaudeCodeResp executeClaudeCodePostApi(String url, String body) {
- Retryer<ClaudeCodeResp> build = getApiRetryer(1, 3);
- try {
- return build.call(() -> {
- try {
- HttpResponse execute = HttpUtil.createPost(url)
- .header(CLAUDE_CODE_HEARD_KEY, CLAUDE_CODE_API_ADMIN_KEY)
- .setConnectionTimeout(CONNECT_MILLISECONDS)
- .body(body)
- .execute();
- ClaudeCodeResp resp = Jsons.parseObject(execute.body(), ClaudeCodeResp.class);
- if (!Constant.SUCCESS.equals(resp.getMessage())) {
- log.error("claude code POST URL:{}接口返回msg:{}", url, resp.getMessage());
- }
- return resp;
- } catch (Exception e) {
- return null;
- }
- });
- } catch (ExecutionException | RetryException e) {
- log.info("重试调用claude code POST请求 url->{}失败,msg->{}", url, StringUtil.getErrorText(e));
- throw BusinessRuntimeException.getInstance("接口请求失败");
- }
- }
- /**
- * claude code DELETE请求
- */
- public ClaudeCodeResp executeClaudeCodeDeletedApi(String url) {
- Retryer<ClaudeCodeResp> build = getApiRetryer(1, 3);
- try {
- return build.call(() -> {
- try {
- HttpResponse execute = HttpUtil.createRequest(Method.DELETE, url).header(CLAUDE_CODE_HEARD_KEY, CLAUDE_CODE_API_ADMIN_KEY).setConnectionTimeout(CONNECT_MILLISECONDS).execute();
- ClaudeCodeResp resp = Jsons.parseObject(execute.body(), ClaudeCodeResp.class);
- if (!Constant.SUCCESS.equals(resp.getMessage())) {
- log.error("claude code DELETE URL:{}接口返回msg:{}", url, resp.getMessage());
- }
- return resp;
- } catch (HttpException e) {
- return null;
- }
- });
- } catch (ExecutionException | RetryException e) {
- log.error("重试调用claude code DELETE请求url->{}失败,msg->{}", url, StringUtil.getErrorText(e));
- throw BusinessRuntimeException.getInstance("接口请求失败");
- }
- }
- /**
- * 记录claude code 续费升级的过期时间
- */
- private void saveClaudeCodeRenewExpiryRecord(Long orderId, Long relationUserId, Long relationId, Long skuId) {
- ClaudeCodeUserRenewExpiryRecord renewExpiryRecord = new ClaudeCodeUserRenewExpiryRecord();
- renewExpiryRecord.setOrderId(orderId);
- renewExpiryRecord.setUserId(relationUserId);
- renewExpiryRecord.setRelationId(relationId);
- renewExpiryRecord.setRenewSkuId(skuId);
- claudeCodeUserRenewExpiryRecordMapper.insert(renewExpiryRecord);
- }
- /**
- * claude code用户信息重试更新信息
- */
- public void setClaudeCodeUserRetryUpdateInfo(Long relationId) {
- ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUser.class).eq(ClaudeCodeUser::getRelationId, relationId).last("limit 1"));
- if (claudeCodeUser != null) {
- claudeCodeUser.setIsRetry(Boolean.TRUE);
- claudeCodeUserMapper.updateById(claudeCodeUser);
- }
- }
- public Retryer getApiRetryer(Integer sleepSecond, Integer attemptNum) {
- Retryer build = RetryerBuilder.newBuilder()
- .retryIfException()
- //运行时异常重试
- .retryIfRuntimeException()
- //false重试
- .retryIfResult(res -> res == null)
- //1s 间隔
- .withWaitStrategy(WaitStrategies.fixedWait(sleepSecond, TimeUnit.SECONDS))
- //停止策略 : 尝试请求3次
- .withStopStrategy(StopStrategies.stopAfterAttempt(attemptNum)).build();
- return build;
- }
- @Override
- public void resetUserCodePoints(Long userId, Integer resetType, String resetReason) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
- Wrappers.<ClaudeCodeUser>lambdaQuery().in(ClaudeCodeUser::getUserId, userIdList)
- );
- if (claudeCodeUser == null) {
- throw new BusinessRuntimeException("用户不存在或未开通Claude Code服务");
- }
- Integer beforeCodePoints = claudeCodeUser.getCodePoints();
- Integer afterCodePoints = claudeCodeUser.getOriCodePoints();
- claudeCodeUser.setCodePoints(afterCodePoints);
- claudeCodeUserMapper.updateById(claudeCodeUser);
- ClaudeCodeUserResetRecord resetRecord = new ClaudeCodeUserResetRecord();
- resetRecord.setUserId(userId);
- resetRecord.setBeforeCodePoints(beforeCodePoints);
- resetRecord.setAfterCodePoints(afterCodePoints);
- resetRecord.setResetType(resetType);
- resetRecord.setResetReason(resetReason);
- claudeCodeUserResetRecordMapper.insert(resetRecord);
- log.info("用户{}的积分已重置", userId);
- }
- @Override
- @Transactional(rollbackFor = Throwable.class)
- public void useResetCount(Long userId) throws Exception {
- 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服务");
- }
- Integer currentResetCount = claudeCodeUser.getResetCount();
- if (currentResetCount == null || currentResetCount <= 0) {
- throw BusinessRuntimeException.getInstance("可用重置次数为0");
- }
- claudeCodeUser.setResetCount(currentResetCount - 1);
- int updateResult = claudeCodeUserMapper.update(claudeCodeUser,
- Wrappers.lambdaUpdate(ClaudeCodeUser.class)
- .eq(ClaudeCodeUser::getId, claudeCodeUser.getId())
- .eq(ClaudeCodeUser::getResetCount, currentResetCount)
- );
- if (updateResult > 0) {
- log.info("用户{}成功使用重置次数,剩余次数:{}", userId, currentResetCount - 1);
- //重置用户次数
- CreditResetReq creditResetReq = new CreditResetReq();
- creditResetReq.setDescription("用户使用重置次数");
- //调用API重置用户次数
- resetUserCredits(claudeCodeUser.getUserId(), creditResetReq);
- ClaudeCodeUserResetRecord resetRecord = new ClaudeCodeUserResetRecord();
- resetRecord.setUserId(userId);
- resetRecord.setNum(-1);
- resetRecord.setResetReason("使用重置次数");
- claudeCodeUserResetRecordMapper.insert(resetRecord);
- } else {
- throw BusinessRuntimeException.getInstance("使用重置次数失败");
- }
- }
- @Override
- @Transactional(rollbackFor = Throwable.class)
- public void 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)
- .in(ClaudeCodeCreditCard::getUserId, userIdList)
- .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("积分卡已过期");
- }
- ClaudeCodeResp userBalance = getUserBalance(userId);
- JSONObject data = Jsons.parseObject(userBalance.getData(), JSONObject.class);
- Integer availableCredits = data.getInt("available_credits");
- Integer creditLimit = data.getInt("credit_limit");
- //超出积分 异常
- if (availableCredits + creditCard.getCreditAmount() > creditLimit) {
- throw BusinessRuntimeException.getInstance("目前使用只能补充到{0},建议您消耗更多积分后再兑换使用", creditLimit);
- }
- Integer beforeCodePoints = availableCredits;
- Integer addCodePoints = creditCard.getCreditAmount();
- Integer afterCodePoints = beforeCodePoints + addCodePoints;
- 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 (cardUpdateResult > 0) {
- ClaudeCodeUserCreditCardRecord creditCardRecord = new ClaudeCodeUserCreditCardRecord();
- creditCardRecord.setUserId(userId);
- creditCardRecord.setBeforeCodePoints(beforeCodePoints);
- creditCardRecord.setAddCodePoints(addCodePoints);
- creditCardRecord.setAfterCodePoints(afterCodePoints);
- creditCardRecord.setCardNumber(cardNumber);
- //使用一次
- creditCardRecord.setNum(-1);
- creditCardRecord.setUseReason("使用积分卡");
- claudeCodeUserCreditCardRecordMapper.insert(creditCardRecord);
- log.info("用户{}成功使用积分卡{},增加{}积分", userId, cardNumber, addCodePoints);
- //调用API调整用户积分
- adjClaudeCodeUserPoints(claudeCodeUser.getUserId(), creditCard.getCreditAmount(), "adjustment", "用户使用积分卡");
- } else {
- throw new BusinessRuntimeException("积分卡使用失败,请重试");
- }
- }
- @Override
- public SearchResult<ClaudeCodeUserResetRecordView> getUserResetRecords(Long userId, Integer page, Integer limit) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- return beanSearcher.search(ClaudeCodeUserResetRecordView.class, MapUtils.builder()
- .field(ClaudeCodeUserResetRecordView::getUserId, userIdList).op(Operator.InList)
- .page(page, limit)
- .orderBy(ClaudeCodeUserResetRecordView::getCreatedTime).desc()
- .build());
- }
- @Override
- public SearchResult<ClaudeCodeUserCreditCardRecordView> getUserCreditCardRecords(Long userId, Integer page, Integer limit) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- return beanSearcher.search(ClaudeCodeUserCreditCardRecordView.class, MapUtils.builder()
- .field(ClaudeCodeUserCreditCardRecordView::getUserId, userIdList).op(Operator.InList)
- .page(page, limit)
- .orderBy(ClaudeCodeUserCreditCardRecordView::getCreatedTime).desc()
- .build());
- }
- @Override
- public ClaudeCodeRewardDetailsResp getUserRewardDetails(Long userId, Boolean general) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- ClaudeCodeRewardDetailsResp response = new ClaudeCodeRewardDetailsResp();
- // 获取用户Claude Code信息
- ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
- Wrappers.lambdaQuery(ClaudeCodeUser.class)
- .in(ClaudeCodeUser::getUserId, userIdList)
- .last("limit 1")
- );
- // 设置可重置次数
- if (claudeCodeUser != null) {
- Integer resetCount = claudeCodeUser.getResetCount();
- response.setResetCount(resetCount != null ? resetCount : 0);
- } else {
- response.setResetCount(0);
- }
- // 获取可用积分卡数量
- Integer availableCreditCards = claudeCodeCreditCardMapper.selectCount(
- Wrappers.lambdaQuery(ClaudeCodeCreditCard.class)
- .eq(ClaudeCodeCreditCard::getStatus, 0)
- .in(ClaudeCodeCreditCard::getUserId, userIdList)
- .isNull(ClaudeCodeCreditCard::getUsedUserId)
- );
- response.setAvailableCreditCards(availableCreditCards != null ? availableCreditCards : 0);
- if (claudeCodeUser.getCodePoints() > 5000) {
- Integer selectCount = claudeCodeDayResetRecordMapper.selectCount(Wrappers.lambdaQuery(ClaudeCodeDayResetRecord.class).in(ClaudeCodeDayResetRecord::getUserId, userIdList).gt(ClaudeCodeDayResetRecord::getCreatedTime, DateUtil.beginOfDay(DateTime.now())));
- //每日可用重置次数
- response.setDayRestNum(selectCount > 0 ? 0 : 1);
- }
- //是否是普通推广
- if (general != null && general) {
- //提现门槛
- DistributePointsExchangeMoney distributePointsExchangeMoney = distributePointsExchangeMoneyMapper.selectOne(Wrappers.lambdaQuery(DistributePointsExchangeMoney.class).last("limit 1"));
- response.setThresholdMoney(BigDecimal.valueOf(distributePointsExchangeMoney.getMinPoints()).divide(BigDecimal.valueOf(distributePointsExchangeMoney.getPoints())).multiply(distributePointsExchangeMoney.getMoney()));
- // 获取分销相关数据
- try {
- User user = userMapper.selectById(userId);
- List<DistributeWaitingSendPoints> distributeWaitingSendPoints = distributeWaitingSendPointsMapper.selectList(Wrappers.lambdaQuery(DistributeWaitingSendPoints.class).eq(DistributeWaitingSendPoints::getSendStatus, DistributeWaitingSendPoints.Status.waiting).eq(DistributeWaitingSendPoints::getSharedId, userId).select(DistributeWaitingSendPoints::getPoints));
- BigDecimal waitingPoints = BigDecimal.ZERO;
- if (!distributeWaitingSendPoints.isEmpty()) {
- Optional<BigDecimal> points = distributeWaitingSendPoints.stream().map(DistributeWaitingSendPoints::getPoints).reduce(BigDecimal::add);
- if (points.isPresent()) {
- waitingPoints = points.get();
- }
- }
- GoodsDon goodsDon = goodsDonMapper.selectById(Constant.CLAUDE_CODE_GOODS_ID);
- //cc 分销平台比例
- if (goodsDon != null) {
- response.setRate(goodsDon.getRate());
- }
- if (user.getPoints().compareTo(BigDecimal.ZERO) <= 0 && waitingPoints.compareTo(BigDecimal.ZERO) <= 0) {
- response.setGotMoney(BigDecimal.ZERO);
- response.setWaitingMoney(BigDecimal.ZERO);
- } else {
- BigDecimal points = BigDecimal.valueOf(distributePointsExchangeMoney.getPoints());
- BigDecimal money = distributePointsExchangeMoney.getMoney();
- BigDecimal oneHundred = BigDecimal.valueOf(100);
- if (user.getPoints().compareTo(BigDecimal.ZERO) >= 0) {
- response.setGotMoney(user.getPoints().divide(points).multiply(money).divide(oneHundred, 2, RoundingMode.HALF_DOWN));
- }
- if (user.getPoints().compareTo(BigDecimal.ZERO) >= 0) {
- response.setWaitingMoney(waitingPoints.divide(points).multiply(money).divide(oneHundred, 2, RoundingMode.DOWN));
- }
- }
- } catch (Exception e) {
- log.warn("获取用户{}分销数据异常", userId, e);
- // 设置默认值
- response.setGotMoney(BigDecimal.ZERO);
- response.setWaitingMoney(BigDecimal.ZERO);
- }
- }
- return response;
- }
- @Override
- public void sendCreditCard(Long orderId, Long userId, Integer points, String cardNumber, String remark) {
- ClaudeCodeCreditCard creditCard = new ClaudeCodeCreditCard();
- creditCard.setUserId(userId);
- creditCard.setOrderId(orderId);
- creditCard.setCardNumber(cardNumber);
- creditCard.setCreditAmount(points);
- creditCard.setRemark(remark);
- claudeCodeCreditCardMapper.insert(creditCard);
- //积分卡明细
- ClaudeCodeUserCreditCardRecord creditCardRecord = new ClaudeCodeUserCreditCardRecord();
- creditCardRecord.setUserId(userId);
- creditCardRecord.setCardNumber(cardNumber);
- creditCardRecord.setUseReason(remark);
- creditCardRecord.setNum(1);
- creditCardRecord.setAddCodePoints(points);
- claudeCodeUserCreditCardRecordMapper.insert(creditCardRecord);
- }
- @Override
- public void adjUserRestNum(Long orderId, Long userId, Integer num, String remark) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- // 获取用户Claude Code信息
- ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
- Wrappers.lambdaQuery(ClaudeCodeUser.class)
- .in(ClaudeCodeUser::getUserId, userIdList)
- .last("limit 1")
- );
- if (claudeCodeUser == null) {
- log.info("claude code user不存在");
- return;
- }
- Integer resetCount = claudeCodeUser.getResetCount();
- claudeCodeUser.setResetCount(resetCount + num);
- if (claudeCodeUser.getResetCount() < 0) {
- return;
- }
- int update = 0;
- while (update == 0) {
- update = claudeCodeUserMapper.update(claudeCodeUser, Wrappers.lambdaUpdate(ClaudeCodeUser.class).eq(ClaudeCodeUser::getUserId, claudeCodeUser.getUserId()).eq(ClaudeCodeUser::getResetCount, resetCount));
- if (update == 0) {
- claudeCodeUser = claudeCodeUserMapper.selectOne(
- Wrappers.lambdaQuery(ClaudeCodeUser.class)
- .in(ClaudeCodeUser::getUserId, userIdList)
- .last("limit 1")
- );
- if (claudeCodeUser == null) {
- break;
- }
- resetCount = claudeCodeUser.getResetCount();
- claudeCodeUser.setResetCount(resetCount + num);
- if (claudeCodeUser.getResetCount() < 0) {
- break;
- }
- }
- //记录获取重置次数记录
- ClaudeCodeUserResetRecord resetRecord = new ClaudeCodeUserResetRecord();
- resetRecord.setOrderId(orderId);
- resetRecord.setUserId(userId);
- resetRecord.setResetReason(remark);
- resetRecord.setNum(num);
- claudeCodeUserResetRecordMapper.insert(resetRecord);
- }
- }
- @Override
- @Transactional(rollbackFor = Throwable.class)
- public void useDayResetCount(Long userId) throws Exception {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- // 获取用户Claude Code信息
- ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(
- Wrappers.lambdaQuery(ClaudeCodeUser.class)
- .in(ClaudeCodeUser::getUserId, userIdList)
- .last("limit 1")
- );
- if (claudeCodeUser == null) {
- log.info("claude code user不存在");
- return;
- }
- //非标准版、专业版 不给使用
- if (claudeCodeUser.getCodePoints() < 5000) {
- return;
- }
- Integer selectCount = claudeCodeDayResetRecordMapper.selectCount(Wrappers.lambdaQuery(ClaudeCodeDayResetRecord.class).in(ClaudeCodeDayResetRecord::getUserId, userIdList).gt(ClaudeCodeDayResetRecord::getCreatedTime, DateUtil.beginOfDay(DateTime.now())));
- //今日使用为0
- if (selectCount == 0) {
- String idxKey = "cc:uid:" + userId;
- try {
- if (redisService.setNx(idxKey, userId, 5l)) {
- //重置用户次数
- CreditResetReq creditResetReq = new CreditResetReq();
- creditResetReq.setDescription("用户使用每日重置");
- //调用API重置用户次数
- resetUserCredits(claudeCodeUser.getUserId(), creditResetReq);
- ClaudeCodeDayResetRecord claudeCodeDayResetRecord = new ClaudeCodeDayResetRecord();
- claudeCodeDayResetRecord.setUserId(userId);
- claudeCodeDayResetRecord.setRelationId(claudeCodeUser.getRelationId());
- claudeCodeDayResetRecordMapper.insert(claudeCodeDayResetRecord);
- }
- } finally {
- if (redisService.hasKey(idxKey)) {
- redisService.del(idxKey);
- }
- }
- }
- }
- @Override
- public Boolean getUserSubs(long userId) {
- List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
- //是否有该车票
- GroupsRelationView groupsRelationView = beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder()
- .field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
- .field(GroupsRelationView::getGoodsId, Constant.CLAUDE_CODE_GOODS_ID)
- .field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
- .build());
- ClaudeCodeUser claudeCodeUser = claudeCodeUserMapper.selectOne(Wrappers.lambdaQuery(ClaudeCodeUser.class).in(ClaudeCodeUser::getUserId, userIdList).last("limit 1"));
- //车票不存在
- if (groupsRelationView == null) {
- //套餐是否存在
- if (claudeCodeUser != null) {
- //清除用户套餐
- if (delUserPackages(claudeCodeUser.getUserId())) {
- claudeCodeUserMapper.deleteById(claudeCodeUser.getId());
- }
- }
- return false;
- }
- return true;
- }
- private void adjClaudeCodeUserPoints(Long userId, Integer points, String type, String description) throws Exception {
- String apiKeyUrl = String.format(CLAUDE_CODE_API_PREFIX + "api/users/%s/credits/adjust", userId);
- Map<String, Object> parmas = new HashMap<>();
- parmas.put("amount", points);
- parmas.put("type", type);
- parmas.put("description", description);
- ClaudeCodeResp claudeCodeResp = executeClaudeCodePostApi(apiKeyUrl, Jsons.toJson(parmas));
- if (!Constant.SUCCESS.equals(claudeCodeResp.getMessage())) {
- throw BusinessRuntimeException.getInstance("使用积分卡失败");
- }
- }
- }
|