Sfoglia il codice sorgente

claude code 渠道推广优惠码

zoujiajian 1 anno fa
parent
commit
b5d3c2196d
19 ha cambiato i file con 283 aggiunte e 32 eliminazioni
  1. 20 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/claudecode/ClaudeCodeUserPopularizeTrialTicketRecordMapper.java
  3. 5 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponRecommendMapper.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/model/dto/UserWhoami.java
  5. 16 0
      netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeUserPopularizeTrialTicketRecord.java
  6. 3 0
      netflix-dao/src/main/java/com/cyksj/model/entity/User.java
  7. 6 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserDistributePopularize.java
  8. 19 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuView.java
  9. 8 1
      netflix-dao/src/main/java/com/cyksj/model/views/UserDistributePopularizeView.java
  10. 12 0
      netflix-dao/src/main/resources/mapper/CouponRecommendMapper.xml
  11. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  12. 7 1
      netflix-service/src/main/java/com/cyksj/service/claude/impl/ClaudeCodeServiceImpl.java
  13. 1 1
      netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java
  14. 5 6
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java
  15. 1 1
      netflix-service/src/main/java/com/cyksj/service/user/UserService.java
  16. 70 16
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  17. 73 3
      netflix-web/src/main/java/com/cyksj/web/controller/claude/ClaudeCodeController.java
  18. 8 1
      netflix-web/src/main/java/com/cyksj/web/controller/cps/CpsPopularizeController.java
  19. 2 2
      netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

+ 20 - 0
netflix-common/src/main/java/com/cyksj/common/constant/Constant.java

@@ -638,4 +638,24 @@ public interface Constant {
 	 * claude code平台id
 	 */
 	Long CLAUDE_CODE_GOODS_ID = 102L;
+
+	/**
+	 * 推广claude code分销链接
+	 */
+	String DISTRIBUTE_CLAUDE_CODE_CC_URL = "https://cc.yhlxj.com/%s";
+
+	/**
+	 * 推广claude code无优惠码的优惠券id
+	 */
+	Long DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID = 616L;
+
+	/**
+	 * 推广claude code关联优惠券的优惠券id
+	 */
+	Long DISTRIBUTE_CLAUDE_CODE_COUPON_ID = 630L;
+
+	/**
+	 * claude code日卡推广活动
+	 */
+	Long DISTRIBUTE_CLAUDE_CODE_TRIAL_SKU_ID = 732L;
 }

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/claudecode/ClaudeCodeUserPopularizeTrialTicketRecordMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.claudecode;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.ClaudeCodeUserPopularizeTrialTicketRecord;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeUserPopularizeTrialTicketRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/8/21 14:04
+ */
+public interface ClaudeCodeUserPopularizeTrialTicketRecordMapper extends BaseMapper<ClaudeCodeUserPopularizeTrialTicketRecord> {
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/coupon/CouponRecommendMapper.java

@@ -24,4 +24,9 @@ public interface CouponRecommendMapper extends BaseMapper<CouponRecommend> {
 	List<CouponAvailableRecommendView> getRecommendCouponList(@Param("userId") Long userId, @Param("isNewUser") Boolean isNewUser);
 
 	Page<CouponRecommendView> getRecommendCouponViewList(@Param("userId") Long userId, @Param("isNewUser") Boolean isNewUser, @Param("page") IPage<CouponRecommendView> page, @Param("couponId") Long couponId);
+
+	/**
+	 * 该优惠券是否处于推荐中
+	 */
+	int checkPresentRecommendByCouponId(Long couponId);
 }

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/UserWhoami.java

@@ -1,5 +1,6 @@
 package com.cyksj.model.dto;
 
+import com.ejlchina.searcher.bean.DbIgnore;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.experimental.Accessors;
@@ -51,4 +52,16 @@ public class UserWhoami implements Serializable {
      * 是否是未下单的用户
      */
     private Boolean isPay;
+
+    /**
+     * claude code是否渠道配置了优惠码
+     */
+    @DbIgnore
+    private Boolean ccCode;
+
+    /**
+     * claude code是否弹窗
+     */
+    @DbIgnore
+    private Boolean tc;
 }

+ 16 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeCodeUserPopularizeTrialTicketRecord.java

@@ -0,0 +1,16 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: ClaudeCodeUserPopularizeTrialTicketRecord
+ * 创建者: JavaZou
+ * 创建时间:2025/8/21 14:03
+ */
+@Getter
+@Setter
+public class ClaudeCodeUserPopularizeTrialTicketRecord extends BaseEntity{
+	private Long userId;
+}

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/User.java

@@ -1,6 +1,7 @@
 package com.cyksj.model.entity;
 
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.experimental.Accessors;
@@ -104,9 +105,11 @@ public class User extends BaseEntity implements Serializable{
     private Date lastTime;
 
     @TableField(exist = false)
+    @DbIgnore
     private Long emailUserId;
 
     @TableField(exist = false)
+    @DbIgnore
     private Long phoneUserId;
 
     /**

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserDistributePopularize.java

@@ -31,5 +31,11 @@ public class UserDistributePopularize extends BaseEntity{
 
 	private String remark;
 
+	/**
+	 * 其他网址标识
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String otherUrl;
+
 	private Boolean deleted;
 }

+ 19 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuView.java

@@ -1,6 +1,7 @@
 package com.cyksj.model.views;
 
 import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
 import com.ejlchina.searcher.bean.SearchBean;
 import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.Getter;
@@ -78,4 +79,22 @@ public class GoodsDonSkuView {
 	 */
 	@DbField("gdk.code_credit_recovery")
 	private Integer codeCreditRecovery;
+
+	/**
+	 * 优惠价格
+	 */
+	@DbIgnore
+	private BigDecimal discountPrice;
+
+	/**
+	 * 优惠折扣
+	 */
+	@DbIgnore
+	private BigDecimal discount;
+
+	/**
+	 * 满减金额
+	 */
+	@DbIgnore
+	private BigDecimal reduceMoney;
 }

+ 8 - 1
netflix-dao/src/main/java/com/cyksj/model/views/UserDistributePopularizeView.java

@@ -18,7 +18,7 @@ import java.util.Date;
  */
 @Getter
 @Setter
-@SearchBean(tables = "(select id,name,remark,code,created_time,goods_id,sku_id from user_distribute_popularize where deleted is true :userId:) dp left join order_don od on od.cps_popularize_id = dp.id" +
+@SearchBean(tables = "(select id,name,remark,code,created_time,goods_id,sku_id,other_url from user_distribute_popularize where deleted is true :userId:) dp left join order_don od on od.cps_popularize_id = dp.id" +
 		" and od.status not in ('close','noPayment') and od.relation_id != 0 and is_fixed_distribute is true :time:" +
 		" left join distribute_waiting_send_points dsp on dsp.order_id = od.id and dsp.send_status in ('success','waiting')",
 		groupBy = "dp.id,dp.name,dp.code,dp.remark,dp.created_time,dp.goods_id")
@@ -90,6 +90,13 @@ public class UserDistributePopularizeView {
 	@DbField("dp.created_time")
 	private Date createdTime;
 
+	/**
+	 * 其他网址标识
+	 * cc 独立网址
+	 */
+	@DbField("dp.other_url")
+	private String otherUrl;
+
 	/**
 	 * 优惠码
 	 */

+ 12 - 0
netflix-dao/src/main/resources/mapper/CouponRecommendMapper.xml

@@ -57,4 +57,16 @@
             and c.scope !='newUser'
         </if>)s where flag is true
     </select>
+
+    <select id="checkPresentRecommendByCouponId" resultType="java.lang.Integer">
+        select count(1)
+        from coupon_recommend cr
+                 inner join coupon c on c.id = cr.coupon_id
+        where cr.coupon_id = #{couponId}
+          and cr.deleted is true
+          and c.deleted is true
+          and cr.status = 1
+          and (cr.up_time is null or cr.up_time &lt;= now())
+          and (cr.down_time is null or cr.down_time > now())
+    </select>
 </mapper>

+ 1 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -859,6 +859,7 @@ public class RedisService {
         TG_MINI_USER_SAHRE_COUNT_KEY("mini_popualrize_user_sahre_count_key:", "推广小程序用户分享次数key", 60 * 60 * 24l),
         GPT_RECHARGE_KEY("gpt_recharge_key:", "gpt代充", 60),
         GPT_RECHARGE_RECOVER_KEY("gpt_recharge_recover_key:", "gpt代充恢复key", 60 * 5l),
+        CLAUDE_CODE_TY_DAY_CARD_KEY("claude_code_ty_day_card_key:", "claude_code体验天卡key", 30L),
         ;
 
         private String name;

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

@@ -119,7 +119,7 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 				return;
 			}
 			//清缓存
-			if (orderType == 2) {
+			if (orderType != null && orderType == 2) {
 				invalidateUserCache(relationUserId);
 			}
 		} catch (Exception e) {
@@ -306,6 +306,12 @@ public class ClaudeCodeServiceImpl implements ClaudeCodeService {
 				GoodsDonSku 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();
+				GoodsDonSku 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());

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/relation/GroupRelationFrontService.java

@@ -89,7 +89,7 @@ public interface GroupRelationFrontService {
 	 *
 	 * @param userId
 	 * @param trialSkuId
-	 * @return
+	 * @param ticketType 默认1购买,2.体验,3.镜像裂变
 	 */
 	Long getTrialTicketByUserIdAndGoodsId(Long userId, Long trialSkuId, Integer ticketType);
 

+ 5 - 6
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationClearServiceImpl.java

@@ -139,12 +139,11 @@ public class GroupRelationClearServiceImpl implements GroupRelationClearService
 					//用户失效 车票用户id
 					claudeCodeService.invalidateUserCache(groupsRelation.getUserId());
 					//删除用户套餐
-					if (claudeCodeService.delUserPackages(groupsRelation.getUserId())) {
-						//清除claude code user
-						claudeCodeUserMapper.delete(Wrappers.lambdaQuery(ClaudeCodeUser.class).eq(ClaudeCodeUser::getRelationId, relationId));
-						//清除claude code tokens
-						oAuthTokenMapper.delete(Wrappers.lambdaQuery(OAuthToken.class).eq(OAuthToken::getUserId, userId));
-					}
+					claudeCodeService.delUserPackages(groupsRelation.getUserId());
+					//清除claude code user
+					claudeCodeUserMapper.delete(Wrappers.lambdaQuery(ClaudeCodeUser.class).eq(ClaudeCodeUser::getRelationId, relationId));
+					//清除claude code tokens
+					oAuthTokenMapper.delete(Wrappers.lambdaQuery(OAuthToken.class).eq(OAuthToken::getUserId, userId));
 				}
 			}
 		}

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/user/UserService.java

@@ -22,7 +22,7 @@ public interface UserService extends IService<User> {
 
 	User saveAuth(GzhOAuth2UserInfo userinfo, AuthRedirect re, User.RegisterEnv registerEnv) throws Exception;
 
-    UserWhoami whoami(long userId);
+	UserWhoami whoami(long userId, Boolean ccCode);
 
     User getSyncUser(String openId, String unionId, WxSyncLog wxSyncLog);
 

+ 70 - 16
netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java

@@ -19,8 +19,12 @@ import com.cyksj.config.wxlogin.WxOpenPlatYHLXLoginConfig;
 import com.cyksj.dto.UserSharedDto;
 import com.cyksj.mapper.*;
 import com.cyksj.mapper.channel.ChannelPopularizeMapper;
+import com.cyksj.mapper.claudecode.ClaudeCodeUserPopularizeTrialTicketRecordMapper;
 import com.cyksj.mapper.corp.*;
+import com.cyksj.mapper.manage.coupon.CouponDistributePopularizeMapper;
+import com.cyksj.mapper.manage.coupon.CouponRecommendMapper;
 import com.cyksj.mapper.manage.cps.UserDistributePopularizeMapper;
+import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
 import com.cyksj.mapper.market.task.UserBindDetailMapper;
 import com.cyksj.mapper.mirrorshop.UserMirrorShopMapper;
@@ -28,9 +32,11 @@ import com.cyksj.mapper.station.CollegeStudentStationUserRelateMapper;
 import com.cyksj.mapper.vip.VipUserMapper;
 import com.cyksj.model.dto.*;
 import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.request.LoginReq;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.claude.ClaudeCodeService;
 import com.cyksj.service.distribute.DistributeService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.exchange.ExchangeCodeService;
@@ -137,6 +143,16 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
 	private final VipUserMapper vipUserMapper;
 
+	private final CouponDistributePopularizeMapper couponDistributePopularizeMapper;
+
+	private final UserDistributeMapper userDistributeMapper;
+
+	private final ClaudeCodeService claudeCodeService;
+
+	private final ClaudeCodeUserPopularizeTrialTicketRecordMapper claudeCodeUserPopularizeTrialTicketRecordMapper;
+
+	private final CouponRecommendMapper couponRecommendMapper;
+
 	private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
 	@Override
@@ -242,14 +258,14 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 	}
 
 	@Override
-    public UserWhoami whoami(long userId) {
-	    User user = this.getById(userId);
-	    Assert.notNull(user, "业务处理失败,请联系客服");
-	    UserWhoami userWhoami = new UserWhoami();
-	    if (StrUtil.isEmpty(user.getShowId())) {
-		    user.setShowId(userCommonService.getUserShowId(userId));
-	    }
-	    BeanUtil.copyProperties(user, userWhoami);
+	public UserWhoami whoami(long userId, Boolean ccCode) {
+		User user = this.getById(userId);
+		Assert.notNull(user, "业务处理失败,请联系客服");
+		UserWhoami userWhoami = new UserWhoami();
+		if (StrUtil.isEmpty(user.getShowId())) {
+			user.setShowId(userCommonService.getUserShowId(userId));
+		}
+		BeanUtil.copyProperties(user, userWhoami);
 
 		UserBindDetail bindPhone = userBindDetailMapper.selectOne(Wrappers.lambdaQuery(UserBindDetail.class)
 				.eq(StrUtil.isNotEmpty(user.getUnionid()), UserBindDetail::getUserId, userId)
@@ -260,13 +276,13 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 			userWhoami.setBindPhone(bindPhone.getPhone());
 			userWhoami.setBindEmail(bindPhone.getEmail());
 		}
-	    Integer type = 3;
-	    if (StrUtil.isNotBlank(user.getLoginPhone())) {
-		    type = 1;
-	    } else if (StrUtil.isNotBlank(user.getEmail())) {
-		    type = 2;
-	    }
-	    userWhoami.setType(type);
+		Integer type = 3;
+		if (StrUtil.isNotBlank(user.getLoginPhone())) {
+			type = 1;
+		} else if (StrUtil.isNotBlank(user.getEmail())) {
+			type = 2;
+		}
+		userWhoami.setType(type);
 		//是否加过企业微信
 		String unionId = user.getUnionid();
 		if (StrUtil.isEmpty(unionId)) {
@@ -295,8 +311,19 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 				.in(OrderDon::getUserId, userIdList)
 				.notIn(OrderDon::getStatus, Constant.noOrderStatus));
 		userWhoami.setIsPay(selectCount > 0);
+		if (ccCode != null) {
+			Number number = beanSearcher.searchCount(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getUserId, userIdList).op(Operator.InList).field(GroupsRelationView::getSkuId, Constant.DISTRIBUTE_CLAUDE_CODE_TRIAL_SKU_ID).field(GroupsRelationView::getGoodsId, Constant.CLAUDE_CODE_GOODS_ID).build());
+			userWhoami.setCcCode(number.intValue() > 0);
+			Integer selectCount1 = claudeCodeUserPopularizeTrialTicketRecordMapper.selectCount(Wrappers.lambdaQuery(ClaudeCodeUserPopularizeTrialTicketRecord.class).in(ClaudeCodeUserPopularizeTrialTicketRecord::getUserId, userIdList));
+			if (selectCount1 == 0) {
+				ClaudeCodeUserPopularizeTrialTicketRecord record = new ClaudeCodeUserPopularizeTrialTicketRecord();
+				record.setUserId(userId);
+				claudeCodeUserPopularizeTrialTicketRecordMapper.insert(record);
+			}
+			userWhoami.setTc(selectCount1 == 0);
+		}
 		return userWhoami;
-    }
+	}
 
     @Override
     public User getSyncUser(String openId, String unionId, WxSyncLog wxSyncLog) {
@@ -570,6 +597,33 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 		if (sharedId != null && dsType != null && dsType == 2) {
 			equipDistributeService.saveDistributionInvitation(sharedId, isNewUser, user.getId());
 		}
+		//查找渠道是否有设置了对应的claude code优惠码
+		if (sharedId != null) {
+			UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, sharedId).eq(UserDistribute::getDeleted, Boolean.TRUE).last("limit 1"));
+			if (userDistribute != null) {
+				Integer selectCount = couponDistributePopularizeMapper.selectCount(Wrappers.lambdaQuery(CouponDistributePopularize.class).eq(CouponDistributePopularize::getDistributeId, userDistribute.getId()).eq(CouponDistributePopularize::getDeleted, Boolean.TRUE).eq(CouponDistributePopularize::getCouponId, Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID));
+				//是否设置claude cod优惠券
+				if (selectCount > 0) {
+					//设置了 直接发送优惠券
+					couponCommonService.sendCouponToUser(user.getId(), Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID, 0l, 0l, dsPopularizeId, CouponUser.Channel.manual);
+					if (redisService.setNx(RedisService.key.CLAUDE_CODE_TY_DAY_CARD_KEY.getName() + user.getId(), user.getId(), RedisService.key.CLAUDE_CODE_TY_DAY_CARD_KEY.getTimeout())) {
+						//存在Claude code车票不发送体验卡
+						if (!claudeCodeService.checkClaudeCodeUser(user.getId())) {
+							//发送claude code 体验卡
+							groupRelationFrontService.getTrialTicketByUserIdAndGoodsId(user.getId(), Constant.DISTRIBUTE_CLAUDE_CODE_TRIAL_SKU_ID, 1);
+						}
+					}
+				} else {
+					//该优惠券是否处于推荐中
+					int isTj = couponRecommendMapper.checkPresentRecommendByCouponId(Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID);
+					if (isTj != 0) {
+						//发送无优惠码的 优惠券
+						couponCommonService.sendCouponToUser(user.getId(), Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID, 0l, 0l, dsPopularizeId, CouponUser.Channel.manual);
+					}
+				}
+			}
+		}
+
 		//每日活跃记录
 		userLoginRecordService.saveUserLoginDayRecord(user.getId());
 		return user;

+ 73 - 3
netflix-web/src/main/java/com/cyksj/web/controller/claude/ClaudeCodeController.java

@@ -1,16 +1,20 @@
 package com.cyksj.web.controller.claude;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateTime;
 import cn.hutool.core.util.StrUtil;
 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.dto.Result;
+import com.cyksj.dto.UserSharedDto;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.ClaudeCodeUserMapper;
 import com.cyksj.mapper.GroupsMapper;
 import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.manage.coupon.*;
+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;
@@ -39,6 +43,7 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * server/claude code
@@ -74,6 +79,19 @@ public class ClaudeCodeController {
 	private final GroupsMapper groupsMapper;
 
 	private final UserService userService;
+
+	private final UserDistributeMapper userDistributeMapper;
+
+	private final CouponDistributePopularizeMapper couponDistributePopularizeMapper;
+
+	private final CouponMapper couponMapper;
+
+	private final CouponSkuMapper couponSkuMapper;
+
+	private final CouponRecommendMapper couponRecommendMapper;
+
+	private final CouponUserMapper couponUserMapper;
+
 	/**
 	 * 用户创建API KEY
 	 */
@@ -190,7 +208,7 @@ public class ClaudeCodeController {
 	 * claude code可选套餐
 	 */
 	@GetMapping("/get/packages")
-	public Result<ClaudeCodePackageView> getClaudeCodePackages() {
+	public Result<ClaudeCodePackageView> getClaudeCodePackages(String dsCode) {
 		Long userId = StpUserUtil.getUserIdAfterLogin();
 		ClaudeCodePackageView claudeCodePackageView = new ClaudeCodePackageView();
 		if (userId != null) {
@@ -226,6 +244,8 @@ public class ClaudeCodeController {
 			}
 		}
 		List<GoodsDonSkuView> goodsDonSkuViews = beanSearcher.searchAll(GoodsDonSkuView.class, MapUtils.builder().field(GoodsDonSkuView::getGoodsId, Constant.CLAUDE_CODE_GOODS_ID).field(GoodsDonSkuView::getUserOwns).op(Operator.IsNull).build());
+		//渠道推广
+		setClaudeCodeSkuCouponInfo(dsCode, userId, goodsDonSkuViews);
 		claudeCodePackageView.setSkus(goodsDonSkuViews);
 		return GatewayResponse.SUCCESS.newBuilder().toResult(claudeCodePackageView);
 	}
@@ -258,7 +278,7 @@ public class ClaudeCodeController {
 	 */
 	@GetMapping("/authorize")
 	public Result<String> authorize(@RequestParam(name = "client_id") String clientId,
-									@RequestParam String state) throws Exception {
+	                                @RequestParam String state) throws Exception {
 		// 验证参数
 		if (clientId == null || clientId.isEmpty() ||
 				state == null || state.isEmpty()) {
@@ -295,7 +315,7 @@ public class ClaudeCodeController {
 			}
 
 			// 验证token
-			OAuthToken oauthToken = oAuthClaudeCodeService.validateToken(code,token);
+			OAuthToken oauthToken = oAuthClaudeCodeService.validateToken(code, token);
 			if (oauthToken == null) {
 				throw BusinessRuntimeException.getInstance("Invalid or expired token");
 			}
@@ -374,4 +394,54 @@ public class ClaudeCodeController {
 		}
 	}
 
+	public void setClaudeCodeSkuCouponInfo(String dsCode, Long userId, List<GoodsDonSkuView> goodsDonSkuViews) {
+		//渠道推广
+		if (dsCode != null) {
+			UserSharedDto popularizeDto = userService.getUserShredDtoByDsCode(dsCode);
+			if (popularizeDto != null) {
+				UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, popularizeDto.getSharedId()).eq(UserDistribute::getDeleted, Boolean.TRUE).last("limit 1"));
+				//渠道推广
+				if (userDistribute != null) {
+					Integer selectCount = couponDistributePopularizeMapper.selectCount(Wrappers.lambdaQuery(CouponDistributePopularize.class)
+							.eq(CouponDistributePopularize::getDistributeId, userDistribute.getId())
+							.eq(CouponDistributePopularize::getCouponId, Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID)
+							.eq(CouponDistributePopularize::getDeleted, Boolean.TRUE));
+					//已配置使用渠道优惠码 未配置使用推荐优惠券
+					Coupon coupon = couponMapper.selectById(selectCount > 0 ? Constant.DISTRIBUTE_CLAUDE_CODE_COUPON_ID : Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID);
+					if (coupon == null) {
+						return;
+					}
+					if (coupon.getId().intValue() == Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID.intValue()) {
+						int isTj = couponRecommendMapper.checkPresentRecommendByCouponId(Constant.DISTRIBUTE_CLAUDE_CODE_NO_CODE_COUPON_ID);
+						if (isTj == 0) {
+							return;
+						}
+					}
+					List<Long> couponSkuIds = couponSkuMapper.selectList(Wrappers.lambdaQuery(CouponSku.class).eq(CouponSku::getCouponId, coupon.getId()).eq(CouponSku::getDeleted, Boolean.TRUE)).stream().map(CouponSku::getSkuId).collect(Collectors.toList());
+					//该优惠券是否已经使用
+					if (userId != null) {
+						Integer isUsed = couponUserMapper.selectCount(Wrappers.lambdaQuery(CouponUser.class)
+								.eq(CouponUser::getCouponId, coupon.getId())
+								.eq(CouponUser::getStatus, CouponUser.Status.unused)
+								.eq(CouponUser::getUserId, userId)
+								.lt(CouponUser::getValidStartTime, DateTime.now())
+								.gt(CouponUser::getValidEndTime, DateTime.now()));
+						if (isUsed == 0) {
+							return;
+						}
+					}
+					goodsDonSkuViews.forEach(sku -> {
+						if (couponSkuIds.contains(sku.getSkuId())) {
+							if (coupon.getType() == Coupon.Type.discount) {
+								sku.setDiscount(coupon.getDiscount());
+								sku.setDiscountPrice(sku.getMoney().multiply(coupon.getDiscount()));
+							} else {
+								sku.setReduceMoney(coupon.getReduceMoney());
+							}
+						}
+					});
+				}
+			}
+		}
+	}
 }

+ 8 - 1
netflix-web/src/main/java/com/cyksj/web/controller/cps/CpsPopularizeController.java

@@ -117,7 +117,14 @@ public class CpsPopularizeController {
 				.last("limit 1"));
 		SearchResult<UserDistributePopularizeView> search = beanSearcher.search(UserDistributePopularizeView.class, builder.build());
 		search.getDataList().forEach(data -> {
-			data.setPopularizeLink(String.format(envCommonService.DISTRIBUTE_DEFAULT_URL_PREFIX, data.getCode()));
+			if (StrUtil.isNotBlank(data.getOtherUrl())) {
+				if ("cc".equals(data.getOtherUrl())) {
+					data.setPopularizeLink(String.format(Constant.DISTRIBUTE_CLAUDE_CODE_CC_URL, data.getCode()));
+				}
+			}
+			if (StrUtil.isEmpty(data.getPopularizeLink())) {
+				data.setPopularizeLink(String.format(envCommonService.DISTRIBUTE_DEFAULT_URL_PREFIX, data.getCode()));
+			}
 			Optional.ofNullable(goodsDonMapper.selectById(data.getGoodsId())).ifPresent(goods -> {
 				data.setTitle(goods.getTitle());
 				data.setLogo(goods.getLogo());

+ 2 - 2
netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java

@@ -106,10 +106,10 @@ public class UserController {
     private final UserGalaxyCoinRecordMapper userGalaxyCoinRecordMapper;
 
     @GetMapping(value = "/wx/whoami")
-    public Result<UserWhoami> whoami() {
+    public Result<UserWhoami> whoami(Boolean ccCode) {
         long userId = StpUserUtil.getLoginIdAsLong();
 
-        UserWhoami userWhoami = userService.whoami(userId);
+        UserWhoami userWhoami = userService.whoami(userId, ccCode);
 
         return GatewayResponse.SUCCESS.newBuilder().toResult(userWhoami);
     }