Quellcode durchsuchen

银河会员需求

zoujiajian vor 1 Jahr
Ursprung
Commit
0194c2f892
36 geänderte Dateien mit 1367 neuen und 18 gelöschten Zeilen
  1. 5 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/vip/RefundVipOrderDonMapper.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/vip/VipGoodsSkuMapper.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/vip/VipOrderDonMapper.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/vip/VipUserMapper.java
  6. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/ChatgptUser.java
  7. 5 2
      netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeUser.java
  8. 4 1
      netflix-dao/src/main/java/com/cyksj/model/entity/GrokUser.java
  9. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GroupsRelation.java
  10. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/LumaUser.java
  11. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/MidjourneyUser.java
  12. 54 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RefundVipOrderDon.java
  13. 1 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserBalanceSourceRecord.java
  14. 18 0
      netflix-dao/src/main/java/com/cyksj/model/entity/VipGoodsSku.java
  15. 163 0
      netflix-dao/src/main/java/com/cyksj/model/entity/VipOrderDon.java
  16. 22 0
      netflix-dao/src/main/java/com/cyksj/model/entity/VipUser.java
  17. 6 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/GroupsRelationBackView.java
  18. 68 0
      netflix-dao/src/main/java/com/cyksj/model/request/VipOrderDonPayReq.java
  19. 27 0
      netflix-dao/src/main/java/com/cyksj/model/response/VipUserPageResp.java
  20. 96 0
      netflix-dao/src/main/java/com/cyksj/model/views/CmsVipOrderDonView.java
  21. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java
  22. 94 0
      netflix-dao/src/main/java/com/cyksj/model/views/VipGoodsSkuFrontView.java
  23. 30 0
      netflix-dao/src/main/java/com/cyksj/model/views/VipGoodsSkuView.java
  24. 13 0
      netflix-service/src/main/java/com/cyksj/service/mange/vip/CmsVipOrderService.java
  25. 15 0
      netflix-service/src/main/java/com/cyksj/service/mange/vip/VipCommonService.java
  26. 159 0
      netflix-service/src/main/java/com/cyksj/service/mange/vip/impl/CmsVipOrderServiceImpl.java
  27. 44 0
      netflix-service/src/main/java/com/cyksj/service/mange/vip/impl/VipCommonServiceImpl.java
  28. 2 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderRefundService.java
  29. 15 0
      netflix-service/src/main/java/com/cyksj/service/order/VipOrderDonService.java
  30. 85 15
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderRefundServiceImpl.java
  31. 149 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/VipOrderDonServiceImpl.java
  32. 1 0
      netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java
  33. 1 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupRelationController.java
  34. 92 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/vip/VipController.java
  35. 54 0
      netflix-web/src/main/java/com/cyksj/web/controller/vip/VipController.java
  36. 66 0
      netflix-web/src/main/java/com/cyksj/web/controller/vip/VipUserOrderController.java

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

@@ -584,4 +584,9 @@ public interface Constant {
 	 * openai file 域名
 	 */
 	String GPT_FILE_DOMAIN = "filesystem.site";
+
+	/**
+	 * VIP用户费用
+	 */
+	String VIP_FEE_KEY = "vip_fee_key";
 }

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/vip/RefundVipOrderDonMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.vip;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RefundVipOrderDon;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RefundVipOrderDonMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/5/14 15:34
+ */
+public interface RefundVipOrderDonMapper extends BaseMapper<RefundVipOrderDon> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/vip/VipGoodsSkuMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.vip;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.VipGoodsSku;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipGoodsSkuMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 11:06
+ */
+public interface VipGoodsSkuMapper extends BaseMapper<VipGoodsSku> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/vip/VipOrderDonMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.vip;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.VipOrderDon;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipOrderDonMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 11:05
+ */
+public interface VipOrderDonMapper extends BaseMapper<VipOrderDon> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/vip/VipUserMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.vip;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.VipUser;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipUserMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 11:04
+ */
+public interface VipUserMapper extends BaseMapper<VipUser> {
+}

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

@@ -136,4 +136,9 @@ public class ChatgptUser extends BaseEntity {
      * 用户目前模式 0旧版 1新版
      */
     private Integer model;
+
+    /**
+     * 是否是VIP
+     */
+    private Boolean isVip;
 }

+ 5 - 2
netflix-dao/src/main/java/com/cyksj/model/entity/ClaudeUser.java

@@ -13,8 +13,6 @@ import java.util.Date;
  */
 @Data
 public class ClaudeUser extends BaseEntity {
-
-
     private String name;
 
     @DbField("userToken")
@@ -73,4 +71,9 @@ public class ClaudeUser extends BaseEntity {
      */
     @TableField(updateStrategy = FieldStrategy.IGNORED)
     private Date renewExpiryTime;
+
+    /**
+     * 是否是VIP
+     */
+    private Boolean isVip;
 }

+ 4 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/GrokUser.java

@@ -1,6 +1,5 @@
 package com.cyksj.model.entity;
 
-import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
 import com.ejlchina.searcher.bean.DbField;
 import lombok.Data;
@@ -50,4 +49,8 @@ public class GrokUser extends BaseEntity {
      */
     private Boolean isBlock;
 
+    /**
+     * 是否是VIP
+     */
+    private Boolean isVip;
 }

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

@@ -129,6 +129,11 @@ public class GroupsRelation extends BaseEntity {
      */
     private String pinCode;
 
+    /**
+     * 是否是VIP
+     */
+    private Boolean isVip;
+
 
     @AllArgsConstructor
     @Getter

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

@@ -50,4 +50,9 @@ public class LumaUser extends BaseEntity{
     @DbIgnore
     @TableField(exist = false)
     private Integer aqType;
+
+    /**
+     * 是否是VIP
+     */
+    private Boolean isVip;
 }

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

@@ -64,4 +64,9 @@ public class MidjourneyUser extends BaseEntity{
     @DbIgnore
     @TableField(exist = false)
     private Integer aqType;
+
+    /**
+     * 是否是VIP
+     */
+    private Boolean isVip;
 }

+ 54 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/RefundVipOrderDon.java

@@ -0,0 +1,54 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: RefundOrderDon
+ *创建者: JavaZou
+ *创建时间:2022/11/8 18:16
+ */
+@Getter
+@Setter
+public class RefundVipOrderDon extends BaseEntity{
+	private Long userId;
+
+	private Long orderId;
+
+	/**
+	 * 退款订单号
+	 */
+	private String outRefundNo;
+
+	private String goodsTitle;
+
+	/**
+	 * 订单总金额
+	 */
+	private BigDecimal totalFee;
+
+	private BigDecimal refundFee;
+
+	private String refundDesc;
+
+	/**
+	 * 退款方式
+	 */
+	private String refundMethod;
+
+	/**
+	 * 是否清空余额退款
+	 * 默认false
+	 */
+	private Boolean isClearBalance;
+
+	private String operator;
+
+	/**
+	 * 聊天记录
+	 */
+	private String chatImg;
+}

+ 1 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserBalanceSourceRecord.java

@@ -44,6 +44,7 @@ public class UserBalanceSourceRecord extends BaseEntity {
 		distribute_rank("分销排行"),
 		wholesale_differ("返批发差价"),
 		wholesale_order("批发订单"),
+		vip_order("会员下单"),
 		;
 		String desc;
 

+ 18 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/VipGoodsSku.java

@@ -0,0 +1,18 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipGoodsSku
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 9:52
+ */
+@Getter
+@Setter
+public class VipGoodsSku extends BaseEntity{
+	private Long goodsId;
+
+	private Long skuId;
+}

+ 163 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/VipOrderDon.java

@@ -0,0 +1,163 @@
+package com.cyksj.model.entity;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipOrderDon
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 10:38
+ */
+@Getter
+@Setter
+public class VipOrderDon extends BaseEntity{
+
+	/** 订单号 */
+	private String orderNo ;
+
+	/**
+	 * 买家支付id
+	 */
+	private String buyerId;
+
+	/**
+	 * 微信订单号
+	 */
+	private String transactionId;
+
+
+	/** 用户id */
+	private Long userId ;
+
+	/**
+	 * openId
+	 */
+	private String openId;
+
+	/** 金额 */
+	private BigDecimal money;
+
+	/**
+	 * 海外支付金额
+	 */
+	private BigDecimal abroadMoney;
+
+	/**
+	 * 手续费
+	 */
+	private BigDecimal abroadTransactionFee;
+
+	/**
+	 * 退款金额
+	 */
+	private BigDecimal refundMoney;
+
+	/**
+	 * 退款余额
+	 */
+	private BigDecimal refundBalance;
+
+	/**
+	 * 退款原因
+	 */
+	private String refundDesc;
+
+	/** 支付状态 */
+	private Status status ;
+
+	/**
+	 * 支付类型
+	 */
+	private Type type;
+
+	/**
+	 * 订单类型 1普通订单、2续费订单
+	 * 默认值为1
+	 */
+	private Integer orderType;
+
+	/**
+	 * 支付时间
+	 */
+	private Date payTime;
+
+	/**
+	 * 商户id
+	 */
+	private String shopId;
+
+	/**
+	 * 渠道链接id
+	 */
+	private Long popularizeId;
+
+	/**
+	 * 是否是网页端支付 默认0移动端支付
+	 */
+	private Boolean isWebPay;
+
+	/**
+	 * 余额支付
+	 */
+	private BigDecimal balance;
+
+	private String payTitle;
+
+	/**
+	 * 付款说明
+	 */
+	@TableField(exist = false)
+	@DbIgnore
+	private String payDesc;
+
+	public enum Status {
+		/**
+		 * 订单状态
+		 */
+		close("已关闭"),
+		noPayment("待付款"),
+		hasPayment("已付款"),
+		complete("已完成"),
+		refund("已退款"),
+		;
+
+		private String desc;
+
+		Status(String desc) {
+			this.desc = desc;
+		}
+
+		public String getDesc() {
+			return desc;
+		}
+	}
+
+	@Getter
+	@AllArgsConstructor
+	public enum Type{
+		WeChat("wechat","微信"),
+		ALI_PAY("zfb","支付宝"),
+		BALANCE("balance", "余额支付"),
+		PAYPAL("paypal","paypal支付"),
+		STRIPE("stripe","stripe支付")
+		;
+		String type;
+		String desc;
+
+		public static VipOrderDon.Type getType(String type) {
+			if (StrUtil.isEmpty(type)) {
+				return ALI_PAY;
+			}
+			return Arrays.stream(VipOrderDon.Type.values()).filter(tp -> tp.getType().equals(type)).findFirst().orElse(ALI_PAY);
+		}
+	}
+}

+ 22 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/VipUser.java

@@ -0,0 +1,22 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipUser
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 9:51
+ */
+@Getter
+@Setter
+public class VipUser extends BaseEntity{
+	private Long userId;
+
+	private Date startTime;
+
+	private Date expiryTime;
+}

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/GroupsRelationBackView.java

@@ -119,6 +119,12 @@ public class GroupsRelationBackView {
 	@DbField("gr.account")
 	private String account;
 
+	/**
+	 * 是否是VIP
+	 */
+	@DbField("gr.is_vip")
+	private Boolean isVip;
+
 	@DbIgnore
 	private Date updateExpiryTime;
 

+ 68 - 0
netflix-dao/src/main/java/com/cyksj/model/request/VipOrderDonPayReq.java

@@ -0,0 +1,68 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipOrderDonPayReq
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 11:15
+ */
+@Getter
+@Setter
+public class VipOrderDonPayReq {
+	private Long userId;
+
+	/**
+	 * 金额
+	 */
+	@NotNull(message = "请输入金额")
+	private BigDecimal donMoney;
+
+	/**
+	 * 渠道链接id
+	 */
+	private Long popularizeId;
+
+	/**
+	 * 是否是网页端支付 默认0移动端支付
+	 */
+	private Boolean isWebPay;
+
+	/**
+	 * 余额支付
+	 */
+	private BigDecimal balance;
+
+	private String callback;
+
+	private String callbackType;
+
+	private Long goodsId;
+
+	/**
+	 * 礼品卡现金支付
+	 */
+	private BigDecimal gcCash;
+
+	/**
+	 * 礼品卡现金支付所拥有id
+	 */
+	private List<Long> gcpIds;
+
+	private String ip;
+
+	private String location;
+
+	private String type;
+
+	/**
+	 * 是否抵扣
+	 */
+	private Boolean isDeduct = false;
+}

+ 27 - 0
netflix-dao/src/main/java/com/cyksj/model/response/VipUserPageResp.java

@@ -0,0 +1,27 @@
+package com.cyksj.model.response;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipUserPageResp
+ * 创建者: JavaZou
+ * 创建时间:2025/5/14 18:06
+ */
+@Getter
+@Setter
+public class VipUserPageResp {
+	/**
+	 * 可抵扣金额
+	 */
+	private Date deductMoney;
+
+	/**
+	 * vip 费用
+	 */
+	private BigDecimal vipFee;
+}

+ 96 - 0
netflix-dao/src/main/java/com/cyksj/model/views/CmsVipOrderDonView.java

@@ -0,0 +1,96 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.VipOrderDon;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CmsVipOrderDonView
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 15:49
+ */
+@Getter
+@Setter
+@SearchBean(tables = "vip_order_don o left join user u on u.id = o.user_id",
+		where = ":condition:"
+)
+public class CmsVipOrderDonView {
+	@DbField("o.id")
+	private Long id;
+
+	@DbIgnore
+	private String channel;
+
+	@DbField("o.order_no")
+	private String orderNo;
+
+	@DbField("o.transaction_id")
+	private String transactionId;
+
+	/**
+	 * 平台id
+	 */
+	@DbField("o.goods_id")
+	private Long goodsId;
+
+	@DbField("o.user_id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("case when u.login_phone != '' then 'phone' when u.email != '' then 'email' when u.open_id != '' then 'wechat' else 'wechat' end")
+	private String register;
+
+	/**
+	 * 登录注册手机号
+	 */
+	@DbField("u.login_phone")
+	private String loginPhone;
+
+	/**
+	 * 登录注册邮箱
+	 */
+	@DbField("u.email")
+	private String email;
+
+	@DbField("o.money")
+	private BigDecimal money;
+
+	@DbField("o.balance")
+	private BigDecimal balance;
+
+	@DbField("o.refund_money")
+	private BigDecimal refundMoney;
+
+	@DbField("o.refund_balance")
+	private BigDecimal refundBalance;
+
+	@DbField("o.refund_desc")
+	private String refundDesc;
+
+	@DbField("o.status")
+	private VipOrderDon.Status status;
+
+	@DbField("o.type")
+	private VipOrderDon.Type type;
+
+	@DbField("o.popularize_id")
+	private Long popularizeId;
+
+	@DbField("o.pay_time")
+	private Date payTime;
+
+	@DbField("o.pay_title")
+	private String payTitle;
+
+	@DbField("o.created_time")
+	private Date createdTime;
+}

+ 6 - 0
netflix-dao/src/main/java/com/cyksj/model/views/RenewalView.java

@@ -210,6 +210,12 @@ public class RenewalView {
     @DbField("gr.aq_type")
     private Integer aqType;
 
+    /**
+     * 是否是VIP
+     */
+    @DbField("gr.is_vip")
+    private Boolean isVip;
+
     @DbIgnore
     private Date payTime;
 

+ 94 - 0
netflix-dao/src/main/java/com/cyksj/model/views/VipGoodsSkuFrontView.java

@@ -0,0 +1,94 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipGoodsSkuFrontView
+ * 创建者: JavaZou
+ * 创建时间:2025/5/14 17:54
+ */
+@Getter
+@Setter
+@SearchBean(tables = "vip_goods_sku vgs left join goods_don g on g.id = vgs.goods_id" +
+		" left join goods_don_sku sku on sku.id = vgs.sku_id")
+public class VipGoodsSkuFrontView {
+
+	@DbField("vgs.goods_id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("vgs.sku_id")
+	private Long skuId;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	/**
+	 * 价格
+	 */
+	@DbField("sku.price")
+	private BigDecimal price;
+
+
+	@DbField("sku.num")
+	private Integer skuNum;
+
+	/**
+	 * 限制次数
+	 */
+	@DbField("sku.gpt_limit_num")
+	private Integer gptLimitNum;
+
+	/**
+	 * 限制时间
+	 */
+	@DbField("sku.gpt_limit_time")
+	private Long gptLimitTime;
+
+	/**
+	 * mj fast次数
+	 */
+	@DbField("sku.mj_fast_num")
+	private Integer mjFastNum;
+
+	/**
+	 * mj relax次数
+	 */
+	@DbField("sku.mj_relax_num")
+	private Integer mjRelaxNum;
+
+	@DbField("sku.luma_num")
+	private Integer lumaNum;
+
+	/**
+	 * deepseek限制次数
+	 */
+	@DbField("sku.ds_limit_num")
+	private Integer dsLimitNum;
+
+	/**
+	 * deepseek限制时间
+	 */
+	@DbField("sku.ds_limit_time")
+	private Long dsLimitTime;
+
+	/**
+	 * 其他模型限制次数
+	 */
+	@DbField("sku.other_limit_num")
+	private Integer otherLimitNum;
+
+	/**
+	 * 其他模型限制时间
+	 */
+	@DbField("sku.other_limit_time")
+	private Long otherLimitTime;
+}

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/model/views/VipGoodsSkuView.java

@@ -0,0 +1,30 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipGoodsSkuView
+ * 创建者: JavaZou
+ * 创建时间:2025/5/14 16:57
+ */
+@Getter
+@Setter
+@SearchBean(tables = "vip_goods_sku vgs left join goods_don g on g.id = vgs.goods_id" +
+		" left join goods_don_sku sku on sku.id = vgs.sku_id")
+public class VipGoodsSkuView {
+	@DbField("vgs.goods_id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("vgs.sku_id")
+	private Long skuId;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+}

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/mange/vip/CmsVipOrderService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.mange.vip;
+
+import com.cyksj.model.request.OrderRefundReq;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CmsVipOrderService
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 16:40
+ */
+public interface CmsVipOrderService {
+	void refundOrders(OrderRefundReq refundReq) throws Exception;
+}

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/mange/vip/VipCommonService.java

@@ -0,0 +1,15 @@
+package com.cyksj.service.mange.vip;
+
+import com.cyksj.model.entity.VipGoodsSku;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipCommonService
+ * 创建者: JavaZou
+ * 创建时间:2025/5/14 17:01
+ */
+public interface VipCommonService {
+	void setVipGoodsSku(List<VipGoodsSku> vipGoodsSkus);
+}

+ 159 - 0
netflix-service/src/main/java/com/cyksj/service/mange/vip/impl/CmsVipOrderServiceImpl.java

@@ -0,0 +1,159 @@
+package com.cyksj.service.mange.vip.impl;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.*;
+import com.cyksj.mapper.vip.RefundVipOrderDonMapper;
+import com.cyksj.mapper.vip.VipOrderDonMapper;
+import com.cyksj.mapper.vip.VipUserMapper;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.OrderRefundReq;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.mange.MirrorUserCleatService;
+import com.cyksj.service.mange.vip.CmsVipOrderService;
+import com.cyksj.service.order.OrderRefundService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CmsVipOrderServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 16:40
+ */
+@Service
+@RequiredArgsConstructor
+public class CmsVipOrderServiceImpl implements CmsVipOrderService {
+	private final RefundVipOrderDonMapper refundVipOrderDonMapper;
+
+	private final OrderRefundService orderRefundService;
+
+	private final VipOrderDonMapper vipOrderDonMapper;
+
+	private final VipUserMapper vipUserMapper;
+
+	private final LumaUserMapper lumaUserMapper;
+
+	private final GrokUserMapper grokUserMapper;
+
+	private final MidjourneyUserMapper midjourneyUserMapper;
+
+	private final ChatgptUserMapper chatgptUserMapper;
+
+	private final ClaudeUserMapper claudeUserMapper;
+
+	private final RedisService redisService;
+
+	private final GroupsRelationMapper relationMapper;
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final GoodsDonSkuMapper skuMapper;
+
+	private final GroupsMapper groupsMapper;
+
+	private final MirrorUserCleatService mirrorUserCleatService;
+
+	@Override
+	public void refundOrders(OrderRefundReq refundReq) throws Exception {
+		VipOrderDon orderDon = vipOrderDonMapper.selectById(refundReq.getOrderId());
+		if (StrUtil.isEmpty(refundReq.getRefundType())) {
+			refundReq.setRefundType("money");
+		}
+		String refundType = refundReq.getRefundType();
+		//校验订单是否符合退款
+		checkOrderRefund(orderDon, refundReq);
+		//调用第三方接口退款
+		String outNo = StrUtil.EMPTY;
+		if (refundReq.getRefundMoney() != null && refundReq.getRefundMoney().compareTo(BigDecimal.ZERO) > 0) {
+			outNo = orderRefundService.vipCenterRefund(refundReq, orderDon);
+		}
+		orderDon.setRefundDesc(refundReq.getRefundDesc());
+		//记录退款信息
+		commonRefund(orderDon, refundReq.getRefundMoney(), refundReq.getOperator(), outNo, refundType, refundReq.getRefundBalance(), refundReq.getChatImg());
+		//修改订单状态
+		orderDon.setStatus(VipOrderDon.Status.refund);
+		vipOrderDonMapper.updateById(orderDon);
+	}
+
+	private void commonRefund(VipOrderDon orderDon, BigDecimal refundMoney, String operator, String outNo, String refundType, BigDecimal refundBalance, String chatImg) {
+		//记录退款
+		recordRefundOrder(orderDon, outNo, refundMoney, operator, chatImg, refundType);
+		//扣除会员时长
+		VipUser vipUser = vipUserMapper.selectById(orderDon.getUserId());
+		Date expiryTime = vipUser.getExpiryTime();
+		DateTime subExpiryTime = DateUtil.offsetMonth(expiryTime, -1);
+		vipUser.setExpiryTime(subExpiryTime);
+		//若会员过期清除镜像user
+		clearVipMirrorUser(vipUser.getUserId(), subExpiryTime);
+		vipUserMapper.updateById(vipUser);
+	}
+
+	private void recordRefundOrder(VipOrderDon orderDon, String outRefundNo, BigDecimal refundMoney, String operator, String chatImg, String refundType) {
+		RefundVipOrderDon refund = new RefundVipOrderDon();
+		refund.setOrderId(orderDon.getId());
+		refund.setOutRefundNo(outRefundNo);
+		refund.setTotalFee(orderDon.getMoney());
+		refund.setRefundDesc(orderDon.getRefundDesc());
+		//退款金额
+		refund.setRefundFee(refundMoney);
+		refund.setUserId(orderDon.getUserId());
+		refund.setGoodsTitle(orderDon.getPayTitle());
+		refund.setRefundMethod(orderDon.getType().name());
+		refund.setOperator(operator);
+		refund.setChatImg(chatImg);
+		//退款方式
+		if (StrUtil.isNotBlank(refundType) && refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
+			refund.setRefundMethod(refundType);
+			refund.setRefundFee(orderDon.getRefundBalance());
+		}
+		refundVipOrderDonMapper.insert(refund);
+	}
+
+	private void checkOrderRefund(VipOrderDon orderDon, OrderRefundReq refundReq) {
+		if (orderDon.getStatus()!= VipOrderDon.Status.complete) {
+			throw BusinessRuntimeException.getInstance("订单状态异常");
+		}
+		Long userId = orderDon.getUserId();
+		//会员是否已过期
+		VipUser vipUser = vipUserMapper.selectOne(Wrappers.lambdaQuery(VipUser.class)
+				.eq(VipUser::getUserId, userId)
+				.gt(VipUser::getExpiryTime, DateTime.now())
+				.last("limit 1"));
+		if (vipUser == null) {
+			throw BusinessRuntimeException.getInstance("用户会员已过期,无法退款");
+		}
+	}
+
+	/**
+	 * 整理会员车票时长
+	 * 过期清除镜像user
+	 */
+	private void clearVipMirrorUser(Long userId, Date expiryTimeAfterSub) {
+		Boolean overdue = expiryTimeAfterSub.before(DateTime.now());
+		List<GroupsRelation> groupsRelations = relationMapper.selectList(Wrappers.lambdaQuery(GroupsRelation.class)
+				.eq(GroupsRelation::getUserId, userId)
+				.eq(GroupsRelation::getIsVip, Boolean.TRUE));
+		groupsRelations.forEach(ticket -> {
+			if (overdue) {
+				GroupsTrips groupsTrips = groupsMapper.selectById(ticket.getGroupsId());
+				if (groupsTrips != null) {
+					GoodsDonSku sku = skuMapper.selectById(groupsTrips.getSkuId());
+					if (sku != null) {
+						mirrorUserCleatService.delMirrorUser(sku.getGoodsId(), ticket.getId());
+					}
+				}
+				return;
+			}
+			ticket.setExpiryTime(expiryTimeAfterSub);
+			relationMapper.updateById(ticket);
+		});
+	}
+}

+ 44 - 0
netflix-service/src/main/java/com/cyksj/service/mange/vip/impl/VipCommonServiceImpl.java

@@ -0,0 +1,44 @@
+package com.cyksj.service.mange.vip.impl;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.mapper.vip.VipGoodsSkuMapper;
+import com.cyksj.model.entity.VipGoodsSku;
+import com.cyksj.service.mange.vip.VipCommonService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipCommonServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2025/5/14 17:01
+ */
+@Service
+@RequiredArgsConstructor
+public class VipCommonServiceImpl implements VipCommonService {
+	private final VipGoodsSkuMapper vipGoodsSkuMapper;
+
+	@Override
+	public void setVipGoodsSku(List<VipGoodsSku> vipGoodsSkus) {
+		List<Long> collect = vipGoodsSkus.stream().map(VipGoodsSku::getSkuId).collect(Collectors.toList());
+		//清除
+		vipGoodsSkuMapper.delete(Wrappers.lambdaUpdate(VipGoodsSku.class)
+				.notIn(VipGoodsSku::getSkuId, collect));
+
+		vipGoodsSkus.forEach(ygs->{
+			Long id = ygs.getId();
+			if (id == null) {
+				try {
+					vipGoodsSkuMapper.insert(ygs);
+				} catch (DuplicateKeyException e) {
+				}
+				return;
+			}
+			vipGoodsSkuMapper.updateById(ygs);
+		});
+	}
+}

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/order/OrderRefundService.java

@@ -32,4 +32,6 @@ public interface OrderRefundService {
 	String refundUserMirrorShopFee(UserMirrorShopFeeOrderDon orderDon) throws Exception;
 
 	void refundSpotifyUpgrade(Long orderId) throws Exception;
+
+	String vipCenterRefund(OrderRefundReq refundReq, VipOrderDon orderDon) throws Exception;
 }

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/order/VipOrderDonService.java

@@ -0,0 +1,15 @@
+package com.cyksj.service.order;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.VipOrderDon;
+import com.cyksj.model.request.VipOrderDonPayReq;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipOrderDonService
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 11:14
+ */
+public interface VipOrderDonService extends IService<VipOrderDon> {
+	VipOrderDon submit(VipOrderDonPayReq payRequest);
+}

+ 85 - 15
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderRefundServiceImpl.java

@@ -12,6 +12,7 @@ import com.cyksj.config.WeChatConfig;
 import com.cyksj.config.zfb.AliPayClientFactory;
 import com.cyksj.mapper.*;
 import com.cyksj.mapper.channel.ShopConfigMapper;
+import com.cyksj.mapper.vip.VipOrderDonMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.OrderRefundReq;
 import com.cyksj.service.order.OrderRefundService;
@@ -65,15 +66,17 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 
 	private final SpotifyUserUpgradeOrderMapper spotifyUserUpgradeOrderMapper;
 
+	private final VipOrderDonMapper vipOrderDonMapper;
+
 	@Override
 	public String centerRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
 		OrderDon.Type type = orderDon.getType();
 		String refundType = refundReq.getRefundType();
 		if (type == OrderDon.Type.WeChat && !refundType.equals(OrderDon.Type.BALANCE.getType())) {
-			return wxRefund(refundReq, orderDon);
+			return wxRefund(refundReq, orderDon.getId(), orderDon.getShopId(), orderDon.getTransactionId(), orderDon.getMoney());
 		}
 		if (type == OrderDon.Type.ALI_PAY && !refundType.equals(OrderDon.Type.BALANCE.getType())) {
-			return zfbRefund(refundReq, orderDon);
+			return zfbRefund(refundReq, orderDon.getId(), orderDon.getShopId(), orderDon.getTransactionId(), orderDon.getMoney());
 		}
 		if (type == OrderDon.Type.PAYPAL && !refundType.equals(OrderDon.Type.BALANCE.getType())) {
 			if (!paypalRefund(refundReq, orderDon)) {
@@ -239,51 +242,50 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 		return outRefundNo;
 	}
 
-	public String wxRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
-		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) <=0){
+	public String wxRefund(OrderRefundReq refundReq, Long orderId, String shopId, String transactionId, BigDecimal orderMoney) throws Exception {
+		if (orderMoney.compareTo(BigDecimal.ZERO) <= 0) {
 			return StrUtil.EMPTY;
 		}
 		long time = System.currentTimeMillis();
 		//退款订单号
 		String outRefundNo = Codec.DoDigest.custom()
 				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
-				.setStringData(time + String.valueOf(orderDon.getId()))
+				.setStringData(time + String.valueOf(orderId))
 				.toHexString();
 		weChatService.refundWxOrder(weChatConfig.getAppid(),
-				Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.WX_DEFAULT_APP_ID),
-				orderDon.getTransactionId(),
+				Optional.ofNullable(shopId).orElse(ShopConfig.WX_DEFAULT_APP_ID),
+				transactionId,
 				outRefundNo,
-				orderDon.getMoney(),
+				orderMoney,
 				refundReq.getRefundMoney(),
 				weChatConfig.getNotifyDomain() + "manage/order/wx/refund/notify");
 		//记录退款信息
 		return outRefundNo;
 	}
 
-	public String zfbRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
-		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) <=0){
+	public String zfbRefund(OrderRefundReq refundReq,  Long orderId, String shopId, String transactionId, BigDecimal orderMoney) throws Exception {
+		if (orderMoney.compareTo(BigDecimal.ZERO) <=0){
 			return StrUtil.EMPTY;
 		}
 		AlipayTradeRefundResponse response;
 		//支付宝退款
-		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
+		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(shopId).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
 		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
 		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
 		//支付宝交易号
-		model.setTradeNo(orderDon.getTransactionId());
+		model.setTradeNo(transactionId);
 		model.setRefundAmount(refundReq.getRefundMoney().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_EVEN).toString());
 		model.setQueryOptions(List.of("gmt_refund_pay"));
 		long time = System.currentTimeMillis();
 		//退款订单号
 		String outRefundNo = Codec.DoDigest.custom()
 				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
-				.setStringData(time + String.valueOf(orderDon.getId()))
+				.setStringData(time + String.valueOf(orderId))
 				.toHexString();
 		//退款请求号
 		model.setOutRequestNo(outRefundNo);
 		request.setBizModel(model);
-		String shopId = orderDon.getShopId();
-		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, orderDon.getShopId()));
+		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, shopId));
 		if (shopId != null && shopConfig != null && shopConfig.getIsCert()) {
 			response = alipayClient.certificateExecute(request);
 		} else {
@@ -478,6 +480,29 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 		spotifyUserUpgradeOrderMapper.updateById(order);
 	}
 
+	@Override
+	public String vipCenterRefund(OrderRefundReq refundReq, VipOrderDon orderDon) throws Exception {
+		VipOrderDon.Type type = orderDon.getType();
+		String refundType = refundReq.getRefundType();
+		if (type == VipOrderDon.Type.WeChat && !refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
+			return wxRefund(refundReq, orderDon.getId(), orderDon.getShopId(), orderDon.getTransactionId(), orderDon.getMoney());
+		}
+		if (type == VipOrderDon.Type.ALI_PAY && !refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
+			return zfbRefund(refundReq, orderDon.getId(), orderDon.getShopId(), orderDon.getTransactionId(), orderDon.getMoney());
+		}
+		if (type == VipOrderDon.Type.PAYPAL && !refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
+			if (!paypalRefundVipOrder(refundReq, orderDon)) {
+				throw BusinessRuntimeException.getInstance("paypal退款失败");
+			}
+		}
+		if (type == VipOrderDon.Type.STRIPE && !refundType.equals(VipOrderDon.Type.BALANCE.getType())) {
+			if (!stripeRefundVipOrder(refundReq, orderDon)) {
+				throw BusinessRuntimeException.getInstance("stripe退款失败");
+			}
+		}
+		return StrUtil.EMPTY;
+	}
+
 	private String zfbRefundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception {
 		BigDecimal money = orderDon.getRefundMoney();
 		if (money.compareTo(BigDecimal.ZERO) <=0){
@@ -511,4 +536,49 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 		if (!response.isSuccess()) throw BusinessRuntimeException.getInstance("退款失败,e:{0}", response.getSubMsg());
 		return outRefundNo;
 	}
+
+	private boolean stripeRefundVipOrder(OrderRefundReq refundReq, VipOrderDon orderDon) throws StripeException {
+		BigDecimal net = refundReq.getRefundMoney().divide(new BigDecimal(7), 2, RoundingMode.HALF_DOWN);
+		if (!refundReq.getIsDiffer()) {
+			net = net.subtract(orderDon.getAbroadTransactionFee());
+		}
+		log.info("stripe return order:{},money:{}",orderDon.getId(),net);
+		StripePayConfig stripePayConfig = stripePayConfigMapper.selectById(1);
+		Stripe.apiKey = stripePayConfig.getApiKey();
+		RefundCreateParams params =
+				RefundCreateParams.builder()
+						.setCharge(orderDon.getTransactionId())
+						.setAmount(net.longValue())
+						.build();
+		com.stripe.model.Refund refund = com.stripe.model.Refund.create(params);
+		log.info("stripe return refund:{}",refund);
+		if ("succeeded".equals(refund.getStatus())){
+			orderDon.setStatus(VipOrderDon.Status.refund);
+			vipOrderDonMapper.updateById(orderDon);
+			return true;
+		}
+		return false;
+	}
+
+	private boolean paypalRefundVipOrder(OrderRefundReq refundReq, VipOrderDon orderDon) throws PayPalRESTException {
+		BigDecimal net = refundReq.getRefundMoney().divide(new BigDecimal(7), 2, RoundingMode.HALF_DOWN);
+		//非补差价 需要扣除手续费
+		if (!refundReq.getIsDiffer()) {
+			net = net.subtract(orderDon.getAbroadTransactionFee());
+		}
+		log.info("paypal return order:{},money:{}",orderDon.getId(),net);
+		PaypalPayConfig paypalPayConfig = paypalPayConfigMapper.selectById(1);
+		APIContext apiContext = getAPIContext(paypalPayConfig.getClientId(), paypalPayConfig.getClientSecret(),paypalPayConfig.getMode());
+		Sale sale = Sale.get(apiContext, orderDon.getTransactionId());
+		Refund refund = new Refund();
+		refund.setAmount(new Amount("USD", net.divide(new BigDecimal(100),2,RoundingMode.HALF_DOWN).toString()));
+		refund = sale.refund(apiContext, refund);
+		log.info("paypal return refund:{}",refund);
+		if ("completed".equals(refund.getState())){
+			orderDon.setStatus(VipOrderDon.Status.refund);
+			vipOrderDonMapper.updateById(orderDon);
+			return true;
+		}
+		return false;
+	}
 }

+ 149 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/VipOrderDonServiceImpl.java

@@ -0,0 +1,149 @@
+package com.cyksj.service.order.impl;
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.snowflake.Sequence;
+import com.cyksj.enums.GatewayApiCode;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.mapper.sys.SysConfigMapper;
+import com.cyksj.mapper.vip.VipGoodsSkuMapper;
+import com.cyksj.mapper.vip.VipOrderDonMapper;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.manage.views.GroupsRelationView;
+import com.cyksj.model.request.VipOrderDonPayReq;
+import com.cyksj.service.order.VipOrderDonService;
+import com.cyksj.service.user.UserBenefitsService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipOrderDonServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 11:14
+ */
+@Service
+@RequiredArgsConstructor
+public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOrderDon> implements VipOrderDonService {
+	private static final Sequence SEQUENCE = new Sequence(0);
+
+	private final UserMapper userMapper;
+
+	private final UserBenefitsService userBenefitsService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final VipGoodsSkuMapper vipGoodsSkuMapper;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final SysConfigMapper sysConfigMapper;
+
+	@Override
+	public VipOrderDon submit(VipOrderDonPayReq payRequest) {
+		Long userId = payRequest.getUserId();
+		User user = userMapper.selectById(userId);
+		if (user == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
+		if (user.getIsBlack()) throw BusinessRuntimeException.getInstance("系统检测操作异常,请稍后再试");
+		/* 生成订单 */
+		String donNo = SEQUENCE.nextId().toString();
+		VipOrderDon orderDon = new VipOrderDon();
+		orderDon.setOrderNo(donNo);
+		orderDon.setOpenId(user.getOpenId());
+		//获取会员价格
+		payRequest.setDonMoney(getVipMoney(user, payRequest.getIsDeduct()));
+		orderDon.setMoney(payRequest.getDonMoney());
+		//渠道链接id
+		if (payRequest.getPopularizeId() != null) {
+			orderDon.setPopularizeId(payRequest.getPopularizeId());
+		}
+		orderDon.setStatus(VipOrderDon.Status.noPayment);
+		orderDon.setUserId(user.getId());
+		orderDon.setType(VipOrderDon.Type.getType(payRequest.getType()));
+		orderDon.setIsWebPay(payRequest.getIsWebPay());
+		//扣除使用优惠券、余额的订单金额
+		deductOrderMoney(orderDon, user, payRequest);
+		//设置订单支付商品信息
+		orderDon.setPayTitle("银河超级AI会员");
+		this.saveOrUpdate(orderDon);
+
+		Long orderId = orderDon.getId();
+		//余额支付订单
+		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
+			orderDon = getById(orderId);
+			unifiedHandlerOrderNotify(orderDon);
+		}
+		return orderDon;
+	}
+
+	private void unifiedHandlerOrderNotify(VipOrderDon orderDon) {
+		orderDon.setStatus(VipOrderDon.Status.complete);
+		this.updateById(orderDon);
+		//余额使用记录
+		if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
+			userBenefitsService.recordBalanceBySource(orderDon.getUserId(), orderDon.getBalance().negate(), UserBalanceSourceRecord.Source.vip_order, orderDon.getId(), UserBalanceSourceRecord.Source.vip_order.getDesc(), null, null);
+		}
+		//发放
+	}
+
+	private void deductOrderMoney(VipOrderDon orderDon, User user, VipOrderDonPayReq payRequest) {
+		BigDecimal balance = payRequest.getBalance();
+		//存在余额
+		deductBalancePayOrderMoney(orderDon, balance, user);
+	}
+
+	private BigDecimal getVipMoney(User user, Boolean isDeduct) {
+		List<VipGoodsSku> skus = vipGoodsSkuMapper.selectList(null);
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(user.getId(), user);
+		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.VIP_FEE_KEY)
+				.last("limit 1"));
+		if (sysConfig == null || StrUtil.isEmpty(sysConfig.getSysValue())) {
+			throw BusinessRuntimeException.getInstance("系统异常");
+		}
+		BigDecimal vipFee = BigDecimal.valueOf(Long.valueOf(sysConfig.getSysValue()));
+		//是否使用抵扣
+		if (isDeduct) {
+			for (VipGoodsSku vipGoodsSku : skus) {
+				Long skuId = vipGoodsSku.getSkuId();
+				beanSearcher.searchFirst(GroupsRelationView.class, MapUtils.builder().field(GroupsRelationView::getSkuId, skuId)
+						.field(GroupsRelationView::getUserId, userIdList).op(Operator.InList)
+						.field(GroupsRelationView::getExpiryTime, DateTime.now()).op(Operator.GreaterThan)
+						.orderBy(GroupsRelationView::getExpiryTime).desc());
+			}
+		}
+		return vipFee;
+	}
+
+	public void deductBalancePayOrderMoney(VipOrderDon orderDon, BigDecimal balance, User user) {
+		//存在余额
+		if (balance != null && balance.compareTo(BigDecimal.ZERO) > 0) {
+			BigDecimal money = orderDon.getMoney();
+			//去掉余额 多出的部分
+			BigDecimal subBalance = balance;
+			orderDon.setMoney(money.subtract(subBalance));
+			if (balance.compareTo(money) >= 0) {
+				orderDon.setMoney(BigDecimal.ZERO);
+				orderDon.setBalance(money);
+				subBalance = money;
+				orderDon.setType(VipOrderDon.Type.BALANCE);
+			}
+			BigDecimal userBalance = user.getBalance();
+			//扣除余额 是否成功
+			Integer success = userMapper.deductBalance(user.getId(), subBalance, userBalance);
+			if (success != 1) throw BusinessRuntimeException.getInstance("您的余额不足!");
+			orderDon.setBalance(subBalance);
+		}
+	}
+}

+ 1 - 0
netflix-service/src/main/java/com/cyksj/service/relation/impl/GroupRelationFrontServiceImpl.java

@@ -812,6 +812,7 @@ public class GroupRelationFrontServiceImpl implements GroupRelationFrontService
 				.field(RenewalView::getExpiryTime, now).op(Operator.GreaterThan)
 				.field(RenewalView::getStatus, List.of("validity", "overdue", "outside")).op(Operator.InList)
 				.field(RenewalView::getAqType, 1)
+				.field(RenewalView::getIsVip, Boolean.TRUE)
 				.orderBy(RenewalView::getExpiryTime).asc()
 				.build());
 		if (list.size() > 5) {

+ 1 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/group/CmsGroupRelationController.java

@@ -72,6 +72,7 @@ public class CmsGroupRelationController {
     @GetMapping("/get")
     public Result<List<GroupsRelationBackView>> get(){
         List<GroupsRelationBackView> search = beanSearcher.searchAll(GroupsRelationBackView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .field(GroupsRelationBackView::getIsVip, Boolean.TRUE)
                 .field(GroupsRelationBackView::getStatus, List.of(GroupsRelation.Status.none.name(), GroupsRelation.Status.locking.name())).op(Operator.NotIn).build()
         );
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);

+ 92 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/vip/VipController.java

@@ -0,0 +1,92 @@
+package com.cyksj.web.controller.manage.vip;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.channel.ChannelPopularizeMapper;
+import com.cyksj.model.entity.VipGoodsSku;
+import com.cyksj.model.request.OrderRefundReq;
+import com.cyksj.model.views.CmsVipOrderDonView;
+import com.cyksj.model.views.VipGoodsSkuView;
+import com.cyksj.service.mange.vip.CmsVipOrderService;
+import com.cyksj.service.mange.vip.VipCommonService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipController
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 15:31
+ */
+@RestController
+@RequestMapping("/manage/vip")
+@RequiredArgsConstructor
+@Slf4j
+public class VipController {
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final ChannelPopularizeMapper channelPopularizeMapper;
+
+	private final CmsVipOrderService cmsVipOrderService;
+
+	private final VipCommonService vipCommonService;
+
+	/**
+	 * 会员订单列表
+	 */
+	@GetMapping("/get/orders")
+	public Result<SearchResult<CmsVipOrderDonView>> getOrders() {
+		SearchResult<CmsVipOrderDonView> search = beanSearcher.search(CmsVipOrderDonView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		search.getDataList().forEach(data->{
+			if (data.getPopularizeId() != null) {
+				Optional.ofNullable(channelPopularizeMapper.selectChannelByPid(data.getPopularizeId()))
+						.ifPresent(channelName -> data.setChannel(channelName));
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 会员订单退款
+	 */
+	@PostMapping("/refund/order")
+	public Result<String> refundOrders(@RequestBody @Validated OrderRefundReq refundReq) throws Exception {
+		long adminId = StpUtil.getLoginIdAsLong();
+		refundReq.setAdminId(adminId);
+		cmsVipOrderService.refundOrders(refundReq);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+
+	//==================================================会员配置======================================================================
+
+	/**
+	 * 会员规格配置列表
+	 */
+	@GetMapping("/get/skus")
+	public Result<List<VipGoodsSkuView>> getVipGoodsSku() {
+		List<VipGoodsSkuView> vipGoodsSkuViews = beanSearcher.searchAll(VipGoodsSkuView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(vipGoodsSkuViews);
+	}
+
+	/**
+	 * 设置会员规格
+	 */
+	@PostMapping("/post/skus")
+	public Result<String> setVipGoodsSku(@RequestBody List<VipGoodsSku> vipGoodsSkus) {
+		vipCommonService.setVipGoodsSku(vipGoodsSkus);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+}

+ 54 - 0
netflix-web/src/main/java/com/cyksj/web/controller/vip/VipController.java

@@ -0,0 +1,54 @@
+package com.cyksj.web.controller.vip;
+
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.response.VipUserPageResp;
+import com.cyksj.model.views.VipGoodsSkuFrontView;
+import com.cyksj.web.util.StpUserUtil;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipController
+ * 创建者: JavaZou
+ * 创建时间:2025/5/14 17:52
+ */
+@RestController
+@RequestMapping("/applet/vip")
+@RequiredArgsConstructor
+@Slf4j
+public class VipController {
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	/**
+	 * 会员关联规格列表
+	 */
+	@GetMapping("/get/skus")
+	public Result<List<VipGoodsSkuFrontView>> getVipSkus() {
+		List<VipGoodsSkuFrontView> vipGoodsSkuFrontViews = beanSearcher.searchAll(VipGoodsSkuFrontView.class, MapUtils.flatBuilder(request.getParameterMap()).orderBy(VipGoodsSkuFrontView::getGoodsId).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(vipGoodsSkuFrontViews);
+	}
+
+	/**
+	 * 会员可抵扣金额
+	 */
+	@GetMapping("/get/deduct/money")
+	public Result<VipUserPageResp> getDeductMoney() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		BigDecimal deductMoney = BigDecimal.ZERO;
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+}

+ 66 - 0
netflix-web/src/main/java/com/cyksj/web/controller/vip/VipUserOrderController.java

@@ -0,0 +1,66 @@
+package com.cyksj.web.controller.vip;
+
+import cn.hutool.extra.servlet.ServletUtil;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.StringUtil;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.VipOrderDon;
+import com.cyksj.model.request.VipOrderDonPayReq;
+import com.cyksj.service.order.VipOrderDonService;
+import com.cyksj.web.util.StpUserUtil;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.http.HttpServletRequest;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: VipUserOrderController
+ * 创建者: JavaZou
+ * 创建时间:2025/5/13 11:08
+ */
+@RestController
+@RequestMapping("/applet/vip/orders")
+@RequiredArgsConstructor
+@Slf4j
+public class VipUserOrderController {
+	private final HttpServletRequest request;
+
+	private final VipOrderDonService vipOrderDonService;
+
+	/**
+	 * 会员预下单
+	 */
+	/**
+	 * 支付
+	 * @author chan
+	 * @date 2021-10-11 下午4:56
+	 */
+	@PostMapping("/post/submit")
+	public Result<VipOrderDon> submit(@Validated @RequestBody VipOrderDonPayReq payRequest) throws Exception {
+		final String methodName = "吊起会员预支付";
+		Long userId = StpUserUtil.getUserIdAfterLogin();
+		payRequest.setUserId(userId);
+		log.info("{}[start] params:{}", methodName, payRequest);
+
+		String ip = ServletUtil.getClientIP(request);
+		String address = StringUtil.getNewInternalAddressByIp(ip);
+		//address.contains("柬埔寨") ||
+		if (address != null && address.contains("缅甸")) {
+			throw BusinessRuntimeException.getInstance("用户异常");
+		}
+		VipOrderDon orderDon = vipOrderDonService.submit(payRequest);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon);
+	}
+
+
+	/**
+	 * 会员支付宝支付
+	 */
+}