Kaynağa Gözat

商品礼品卡购买;订单回调优化

zoujiajian 3 yıl önce
ebeveyn
işleme
450bcbca56
36 değiştirilmiş dosya ile 1321 ekleme ve 282 silme
  1. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/GiftCardGoodsSkuMapper.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/GiftCardOrderUseRecordMapper.java
  3. 19 0
      netflix-dao/src/main/java/com/cyksj/mapper/GiftCardUserRecordMapper.java
  4. 44 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GiftCardGoodsSku.java
  5. 35 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GiftCardOrderUseRecord.java
  6. 62 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GiftCardUserRecord.java
  7. 2 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java
  8. 16 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDon.java
  9. 24 0
      netflix-dao/src/main/java/com/cyksj/model/request/GiftCardPayReq.java
  10. 17 1
      netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java
  11. 1 1
      netflix-dao/src/main/java/com/cyksj/model/views/DistributePopularizeOrdersView.java
  12. 40 0
      netflix-dao/src/main/java/com/cyksj/model/views/GiftCardDetailFrontView.java
  13. 52 0
      netflix-dao/src/main/java/com/cyksj/model/views/GiftCardGoodsSkuFrontView.java
  14. 59 0
      netflix-dao/src/main/java/com/cyksj/model/views/GiftCardGoodsSkuView.java
  15. 67 0
      netflix-dao/src/main/java/com/cyksj/model/views/GiftCardUserPayFrontView.java
  16. 63 0
      netflix-dao/src/main/java/com/cyksj/model/views/GiftCardUserPayView.java
  17. 2 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuFrontView.java
  18. 7 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonViews.java
  19. 30 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsSkuGiftCardView.java
  20. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  21. 14 0
      netflix-service/src/main/java/com/cyksj/service/giftcard/GiftCardGoodsSkuService.java
  22. 14 0
      netflix-service/src/main/java/com/cyksj/service/giftcard/GiftCardOrderUseRecordService.java
  23. 13 0
      netflix-service/src/main/java/com/cyksj/service/giftcard/GiftCardUserRecordService.java
  24. 77 0
      netflix-service/src/main/java/com/cyksj/service/giftcard/impl/GiftCardGoodsSkuServiceImpl.java
  25. 51 0
      netflix-service/src/main/java/com/cyksj/service/giftcard/impl/GiftCardOrderUseRecordServiceImpl.java
  26. 17 0
      netflix-service/src/main/java/com/cyksj/service/giftcard/impl/GiftCardUserRecordServiceImpl.java
  27. 9 0
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  28. 342 263
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  29. 5 0
      netflix-service/src/main/java/com/cyksj/service/user/UserService.java
  30. 56 0
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  31. 31 8
      netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java
  32. 72 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/GiftCardController.java
  33. 1 7
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java
  34. 6 2
      netflix-web/src/main/java/com/cyksj/web/controller/user/DistributePopularizeController.java
  35. 39 0
      netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java
  36. 7 0
      netflix-web/src/main/java/com/cyksj/web/util/StpUserUtil.java

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GiftCardGoodsSku;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardGoodsSkuMapper
+ *创建者: JavaZou
+ *创建时间:2023/8/28 16:35
+ */
+public interface GiftCardGoodsSkuMapper extends BaseMapper<GiftCardGoodsSku> {
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GiftCardOrderUseRecord;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardOrderUseRecordMapper
+ *创建者: JavaZou
+ *创建时间:2023/8/29 16:13
+ */
+public interface GiftCardOrderUseRecordMapper extends BaseMapper<GiftCardOrderUseRecord> {
+}

+ 19 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GiftCardUserRecordMapper.java

@@ -0,0 +1,19 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GiftCardUserRecord;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Update;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardUserRecordMapper
+ *创建者: JavaZou
+ *创建时间:2023/8/28 12:01
+ */
+public interface GiftCardUserRecordMapper extends BaseMapper<GiftCardUserRecord> {
+	@Update("update gift_card_user_record set remain_crash = remain_crash + #{addCash} where id = #{gcId} and remain_crash = #{remainCash}")
+	Integer updateGiftCardRemainCash(@Param("gcId") Long gcId, @Param("addCash") BigDecimal addCash, @Param("remainCash") BigDecimal remainCash);
+}

+ 44 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GiftCardGoodsSku.java

@@ -0,0 +1,44 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardGoodsSku
+ *创建者: JavaZou
+ *创建时间:2023/8/28 16:34
+ */
+@Getter
+@Setter
+public class GiftCardGoodsSku extends BaseEntity{
+	private Long goodsId;
+
+	/**
+	 * 礼品卡类型 1现金卡、2虚拟卡
+	 */
+	private Integer gcType;
+
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private Long gcGoodsId;
+
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private Long gcSkuId;
+
+	/**
+	 * 现金
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private BigDecimal cash;
+
+	/**
+	 * 对应价格
+	 */
+	private BigDecimal price;
+
+	private String logo;
+}

+ 35 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GiftCardOrderUseRecord.java

@@ -0,0 +1,35 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardOrderUseRecord
+ *创建者: JavaZou
+ *创建时间:2023/8/29 16:12
+ */
+@Getter
+@Setter
+public class GiftCardOrderUseRecord extends BaseEntity{
+	private Long orderId;
+
+	private Long userId;
+
+	/**
+	 * 礼品卡id
+	 */
+	private Long gcId;
+
+	/**
+	 * 使用礼品卡现金数量
+	 */
+	private BigDecimal cash;
+
+	/**
+	 * 默认已使用
+	 */
+	private Boolean isUsed;
+}

+ 62 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GiftCardUserRecord.java

@@ -0,0 +1,62 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardUserRecord
+ *创建者: JavaZou
+ *创建时间:2023/8/25 18:16
+ */
+@Getter
+@Setter
+public class GiftCardUserRecord extends BaseEntity{
+	private Long userId;
+
+	private Long orderId;
+
+	/**
+	 * 礼品卡类型
+	 */
+	private Integer gcType;
+
+	/**
+	 * 礼品卡明细
+	 */
+	private String gcDetail;
+
+	private Long gcGoodsId;
+
+	private Long gcSkuId;
+
+	private BigDecimal cash;
+
+	private BigDecimal remainCash;
+
+	private Long toUserId;
+
+	private Boolean isSend;
+
+	/**
+	 * 领取时间
+	 */
+	private Date receivedTime;
+
+	private Date payTime;
+
+	/**
+	 * 是否已购买
+	 */
+	private Boolean isPay;
+
+	/**
+	 * 礼品卡兑换随机码
+	 */
+	private String rc;
+
+	private Boolean isUsed;
+}

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsDon.java

@@ -182,6 +182,8 @@ public class GoodsDon extends BaseEntity {
     @Getter
     public enum SpecialType {
         recharge("代充"),
+        courseware("课程"),
+        giftCard("礼品卡")
         ;
 
         private String desc;

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

@@ -2,6 +2,8 @@ package com.cyksj.model.entity;
 
 import com.baomidou.mybatisplus.annotation.FieldStrategy;
 import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnore;
 import lombok.AllArgsConstructor;
 import lombok.Getter;
 import lombok.Setter;
@@ -10,6 +12,7 @@ import java.io.Serializable;
 import java.math.BigDecimal;
 import java.util.Arrays;
 import java.util.Date;
+import java.util.List;
 
 /**
  * @author chan
@@ -71,6 +74,11 @@ public class OrderDon extends BaseEntity implements Serializable {
      */
     private BigDecimal refundBalance;
 
+    /**
+     * 礼品卡现金支付金额
+     */
+    private BigDecimal gcCash;
+
     /**
      * 退款原因
      */
@@ -226,6 +234,14 @@ public class OrderDon extends BaseEntity implements Serializable {
 
     private String payTitle;
 
+    /**
+     * 礼品卡现金使用记录
+     */
+    @DbIgnore
+    @TableField(exist = false)
+    @JsonIgnore
+    private List<GiftCardOrderUseRecord> gcUseRecords;
+
     public enum Status {
         /**
          * 订单状态

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/request/GiftCardPayReq.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardPayReq
+ *创建者: JavaZou
+ *创建时间:2023/8/30 11:02
+ */
+@Getter
+@Setter
+public class GiftCardPayReq {
+	/**
+	 * 礼品卡id
+	 */
+	private Long gcId;
+
+	/**
+	 * 礼品卡购买数量
+	 */
+	private Integer num;
+}

+ 17 - 1
netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java

@@ -22,7 +22,6 @@ public class OrderPayRequest {
     /**
      * 商品id
      */
-    @NotNull(message = "缺少必填参数")
     private Long skuId;
 
     /**
@@ -104,4 +103,21 @@ public class OrderPayRequest {
     private String callback;
 
     private String callbackType;
+
+    /**
+     * 购买 礼品卡
+     */
+    private List<GiftCardPayReq> giftCards;
+
+    private Long goodsId;
+
+    /**
+     * 礼品卡现金支付
+     */
+    private BigDecimal gcCash;
+
+    /**
+     * 礼品卡现金支付所拥有id
+     */
+    private List<Long> gcpIds;
 }

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

@@ -59,7 +59,7 @@ public class DistributePopularizeOrdersView {
 	@DbField("od.status")
 	private OrderDon.Status orderStatus;
 
-	@DbIgnore
+	@DbField("od.pay_title")
 	private String specVal;
 
 	@DbField("od.created_time")

+ 40 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GiftCardDetailFrontView.java

@@ -0,0 +1,40 @@
+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;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardDetailFrontView
+ *创建者: JavaZou
+ *创建时间:2023/8/29 17:58
+ */
+@Getter
+@Setter
+@SearchBean(tables = "gift_card_user_record gr left join user u on u.id = gr.user_id")
+public class GiftCardDetailFrontView {
+	@DbField("gr.id")
+	private Long id;
+
+	@DbField("u.headimgurl")
+	private String headimgurl;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("gr.gc_detail")
+	private String gcDetail;
+
+	@DbField("gr.cash")
+	private BigDecimal cash;
+
+	@DbField("gr.remain_cash")
+	private BigDecimal remainCash;
+
+	@DbField("gr.rc")
+	private String code;
+}

+ 52 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GiftCardGoodsSkuFrontView.java

@@ -0,0 +1,52 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonInclude;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardGoodsSkuFrontView
+ *创建者: JavaZou
+ *创建时间:2023/8/28 16:36
+ */
+@Getter
+@Setter
+@SearchBean(tables = "gift_card_goods_sku gc left join goods_don g on g.id = gc.gc_goods_id" +
+		" left join goods_don_sku sku on sku.id = gc.gc_sku_id")
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class GiftCardGoodsSkuFrontView {
+	@DbField("gc.id")
+	private Long id;
+
+	@DbField("gc.goods_id")
+	private Long goodsId;
+
+	@DbField("gc.gc_type")
+	private Integer gcType;
+
+	@DbField("gc.price")
+	private BigDecimal price;
+
+	@DbField("gc.gc_goods_id")
+	private Long gcGoodsId;
+
+	@DbField("gc.gc_sku_id")
+	private Long gcSkuId;
+
+	@DbField("g.title")
+	private String gcGoodsTitle;
+
+	@DbField("sku.spec_val")
+	private String gcSpecVal;
+
+	@DbField("gc.cash")
+	private BigDecimal cash;
+
+	@DbField("gc.logo")
+	private String logo;
+}

+ 59 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GiftCardGoodsSkuView.java

@@ -0,0 +1,59 @@
+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;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardGoodsSkuView
+ *创建者: JavaZou
+ *创建时间:2023/8/30 10:28
+ */
+@Getter
+@Setter
+@SearchBean(tables = "gift_card_goods_sku gc left join goods_don g on g.id = gc.gc_goods_id" +
+		" left join goods_don_sku sku on sku.id = gc.gc_sku_id")
+public class GiftCardGoodsSkuView {
+	@DbField("gc.id")
+	private Long id;
+
+	@DbField("gc.goods_id")
+	private Long goodsId;
+
+	/**
+	 * 礼品卡类型 1现金卡、2虚拟卡
+	 */
+	@DbField("gc.gc_type")
+	private Integer gcType;
+
+	@DbField("gc.gc_goods_id")
+	private Long gcGoodsId;
+
+	@DbField("g.title")
+	private String gcGoodsTitle;
+
+	@DbField("gc.gc_sku_id")
+	private Long gcSkuId;
+
+	@DbField("sku.spec_val")
+	private String gcSpecVal;
+
+	/**
+	 * 现金
+	 */
+	@DbField("gc.cash")
+	private BigDecimal cash;
+
+	/**
+	 * 对应价格
+	 */
+	@DbField("gc.price")
+	private BigDecimal price;
+
+	@DbField("gc.logo")
+	private String logo;
+}

+ 67 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GiftCardUserPayFrontView.java

@@ -0,0 +1,67 @@
+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;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardUserPayFrontView
+ *创建者: JavaZou
+ *创建时间:2023/8/29 17:33
+ * 购买的礼品卡
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select * from gift_card_user_record where is_pay is true :condition:) gr left join user u on u.id = gr.user_id")
+public class GiftCardUserPayFrontView {
+	@DbField("gr.id")
+	private Long id;
+
+	@DbField("gr.gc_type")
+	private Integer gcType;
+
+	@DbField("gr.gc_detail")
+	private String gcDetail;
+
+	/**
+	 * 赠送人
+	 */
+	@DbField("u.nickname")
+	private String donor;
+
+	@DbField("gr.cash")
+	private BigDecimal cash;
+
+	@DbField("gr.remain_cash")
+	private BigDecimal remainCash;
+
+	@DbField("gr.is_send")
+	private Boolean isSend;
+
+	@DbField("gr.rc")
+	private String code;
+
+	@DbField("gr.pay_time")
+	private Date payTime;
+
+	@DbField("gr.received_time")
+	private Date receivedTime;
+
+	/**
+	 * 默认未使用
+	 */
+	@DbField("gr.is_used")
+	private Boolean isUsed;
+
+	public Boolean getUsed() {
+		if (gcType == 1 && remainCash != null && remainCash.compareTo(BigDecimal.ZERO) == 0) {
+			return true;
+		}
+		return isUsed;
+	}
+}

+ 63 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GiftCardUserPayView.java

@@ -0,0 +1,63 @@
+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;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardUserPayView
+ *创建者: JavaZou
+ *创建时间:2023/8/29 18:24
+ */
+@Getter
+@Setter
+@SearchBean(tables = "gift_card_user_record gr left join user u on u.id = gr.user_id" +
+		" left join user u2 on u2.id = gr.to_user_id")
+public class GiftCardUserPayView {
+	@DbField("gr.id")
+	private Long id;
+
+	@DbField("gr.gc_type")
+	private Integer gcType;
+
+	@DbField("gr.gc_detail")
+	private String gcDetail;
+
+	@DbField("gr.user_id")
+	private Long userId;
+
+	/**
+	 * 赠送人
+	 */
+	@DbField("u.nickname")
+	private String donor;
+
+	@DbField("gr.cash")
+	private BigDecimal cash;
+
+	@DbField("gr.remain_cash")
+	private BigDecimal remainCash;
+
+	@DbField("gr.is_send")
+	private Boolean isSend;
+
+	@DbField("gr.to_user_id")
+	private Long toUserId;
+
+	@DbField("gr.to_nickname")
+	private String toNickname;
+
+	@DbField("gr.rc")
+	private String code;
+
+	@DbField("gr.pay_time")
+	private Date payTime;
+
+	@DbField("gr.received_time")
+	private Date receivedTime;
+}

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonSkuFrontView.java

@@ -3,6 +3,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.JsonInclude;
 import lombok.Getter;
 import lombok.Setter;
 
@@ -18,6 +19,7 @@ import java.util.List;
 @Getter
 @Setter
 @SearchBean(tables = "goods_don_sku")
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class GoodsDonSkuFrontView {
 
 	private Long id;

+ 7 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsDonViews.java

@@ -127,4 +127,11 @@ public class GoodsDonViews {
 
     @DbIgnore
     private GoodsDonSpecFrontView specs;
+
+    private String giftCards;
+
+    @DbIgnore
+    private List<GoodsSkuGiftCardView> giftCardsView;
+
+    private BigDecimal giftCardCash;
 }

+ 30 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsSkuGiftCardView.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;
+
+/*
+ *项目名: netflix
+ *文件名: GoodsSkuGiftCardView
+ *创建者: JavaZou
+ *创建时间:2023/8/28 14:23
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_don g left join goods_don_sku sku on sku.id = g.goods_id",
+		where = "g.deleted is true and g.status is true and sku.true is true")
+public class GoodsSkuGiftCardView {
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.sku_id")
+	private Long skuId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+}

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

@@ -633,6 +633,7 @@ public class RedisService {
         ORDER_COMMENT_KEY("order_comment_key:", "订单评价", 10l),
         USER_BIND_ACCOUNT_INFO_KEY("user_bind_account_info_key:", "用户绑定其他账号key", 10l),
         TASK_RECEIVED_KEY("task_received_key:%s:%s", "领取任务奖励key", 10l),
+        GIFT_CARD_USER_PAY_SUCCESS_RECORD_KEY("gift_card_user_pay_success_record_key:", "礼品卡购买成功记录key", 10 * 60l),
         ;
 
         private String name;

+ 14 - 0
netflix-service/src/main/java/com/cyksj/service/giftcard/GiftCardGoodsSkuService.java

@@ -0,0 +1,14 @@
+package com.cyksj.service.giftcard;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.GiftCardGoodsSku;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardGoodsSkuService
+ *创建者: JavaZou
+ *创建时间:2023/8/29 18:19
+ */
+public interface GiftCardGoodsSkuService extends IService<GiftCardGoodsSku> {
+	void setOrUpdateGiftCardSku(GiftCardGoodsSku giftCardSku);
+}

+ 14 - 0
netflix-service/src/main/java/com/cyksj/service/giftcard/GiftCardOrderUseRecordService.java

@@ -0,0 +1,14 @@
+package com.cyksj.service.giftcard;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.GiftCardOrderUseRecord;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardOrderUseRecordService
+ *创建者: JavaZou
+ *创建时间:2023/8/29 16:44
+ */
+public interface GiftCardOrderUseRecordService extends IService<GiftCardOrderUseRecord> {
+	void returnGiftCardCash(Long orderId);
+}

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/giftcard/GiftCardUserRecordService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.giftcard;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.GiftCardUserRecord;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardUserRecordService
+ *创建者: JavaZou
+ *创建时间:2023/8/30 10:54
+ */
+public interface GiftCardUserRecordService extends IService<GiftCardUserRecord> {
+}

+ 77 - 0
netflix-service/src/main/java/com/cyksj/service/giftcard/impl/GiftCardGoodsSkuServiceImpl.java

@@ -0,0 +1,77 @@
+package com.cyksj.service.giftcard.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.mapper.GiftCardGoodsSkuMapper;
+import com.cyksj.mapper.GoodsDonMapper;
+import com.cyksj.mapper.GoodsDonSkuMapper;
+import com.cyksj.model.entity.GiftCardGoodsSku;
+import com.cyksj.model.entity.GoodsDon;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.service.giftcard.GiftCardGoodsSkuService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardGoodsSkuServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/8/29 18:19
+ */
+@Service
+@RequiredArgsConstructor
+public class GiftCardGoodsSkuServiceImpl extends ServiceImpl<GiftCardGoodsSkuMapper, GiftCardGoodsSku> implements GiftCardGoodsSkuService {
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	@Override
+	public void setOrUpdateGiftCardSku(GiftCardGoodsSku data) {
+		if (data.getGoodsId() == null) {
+			throw BusinessRuntimeException.getInstance("请选择对应的礼品卡平台");
+		}
+		GoodsDon goodsDon = goodsDonMapper.selectById(data.getGoodsId());
+		if (goodsDon == null) {
+			throw BusinessRuntimeException.getInstance("请选择对应的礼品卡平台");
+		}
+		if (goodsDon.getSpecialType() == null || goodsDon.getSpecialType() != GoodsDon.SpecialType.giftCard) {
+			throw BusinessRuntimeException.getInstance("该{0}平台不是礼品卡特殊类型", goodsDon.getTitle());
+		}
+		BigDecimal cash = data.getCash();
+		Integer gcType = data.getGcType();
+		BigDecimal price = data.getPrice();
+		if (price == null || price.compareTo(BigDecimal.ZERO) == 0) {
+			throw BusinessRuntimeException.getInstance("请输入正确的礼品卡配置价格");
+		}
+		Long gcSkuId = data.getGcSkuId();
+		if (gcSkuId != null && cash != null) {
+			throw BusinessRuntimeException.getInstance("请选择对应的礼品卡类型");
+		}
+		//虚拟卡
+		if (cash != null) {
+			if (cash.compareTo(BigDecimal.ZERO) == 0) {
+				throw BusinessRuntimeException.getInstance("请输入正确的礼品卡现金类型金额");
+			}
+			gcType = 1;
+		}
+		if (gcSkuId != null) {
+			GoodsDonSku sku = goodsDonSkuMapper.selectById(gcSkuId);
+			if (sku == null) {
+				throw BusinessRuntimeException.getInstance("存在未有的虚拟卡规格,请重新选择");
+			}
+			if (!sku.getStatus()) {
+				throw BusinessRuntimeException.getInstance("存在下架的虚拟卡规格,请重新选择");
+			}
+			gcType = 2;
+			data.setGcGoodsId(sku.getGoodsId());
+		}
+		data.setGcType(gcType);
+		try {
+			this.saveOrUpdate(data);
+		} catch (DuplicateKeyException e) {
+		}
+	}
+}

+ 51 - 0
netflix-service/src/main/java/com/cyksj/service/giftcard/impl/GiftCardOrderUseRecordServiceImpl.java

@@ -0,0 +1,51 @@
+package com.cyksj.service.giftcard.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.GiftCardOrderUseRecordMapper;
+import com.cyksj.mapper.GiftCardUserRecordMapper;
+import com.cyksj.model.entity.GiftCardOrderUseRecord;
+import com.cyksj.model.entity.GiftCardUserRecord;
+import com.cyksj.service.giftcard.GiftCardOrderUseRecordService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardOrderUseRecordServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/8/29 16:44
+ */
+@Service
+@RequiredArgsConstructor
+public class GiftCardOrderUseRecordServiceImpl extends ServiceImpl<GiftCardOrderUseRecordMapper, GiftCardOrderUseRecord> implements GiftCardOrderUseRecordService {
+	private final GiftCardUserRecordMapper giftCardUserRecordMapper;
+
+	@Override
+	public void returnGiftCardCash(Long orderId) {
+		List<GiftCardOrderUseRecord> useRecords = this.list(Wrappers.lambdaQuery(GiftCardOrderUseRecord.class)
+				.eq(GiftCardOrderUseRecord::getOrderId, orderId));
+		if (CollUtil.isNotEmpty(useRecords)) {
+			useRecords.forEach(data -> {
+				while (true) {
+					Long gcId = data.getGcId();
+					BigDecimal addCash = data.getCash();
+					GiftCardUserRecord giftCardUserRecord = giftCardUserRecordMapper.selectById(gcId);
+					BigDecimal remainCash = giftCardUserRecord.getRemainCash();
+					Integer update = giftCardUserRecordMapper.updateGiftCardRemainCash(gcId, addCash, remainCash);
+					if (update > 0) {
+						this.update(null, Wrappers.lambdaUpdate(GiftCardOrderUseRecord.class)
+								.set(GiftCardOrderUseRecord::getIsUsed, false)
+								.eq(GiftCardOrderUseRecord::getId, data.getId())
+								.eq(GiftCardOrderUseRecord::getIsUsed, true));
+						break;
+					}
+				}
+			});
+		}
+	}
+}

+ 17 - 0
netflix-service/src/main/java/com/cyksj/service/giftcard/impl/GiftCardUserRecordServiceImpl.java

@@ -0,0 +1,17 @@
+package com.cyksj.service.giftcard.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.GiftCardUserRecordMapper;
+import com.cyksj.model.entity.GiftCardUserRecord;
+import com.cyksj.service.giftcard.GiftCardUserRecordService;
+import org.springframework.stereotype.Service;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardUserRecordServiceImpl
+ *创建者: JavaZou
+ *创建时间:2023/8/30 10:55
+ */
+@Service
+public class GiftCardUserRecordServiceImpl extends ServiceImpl<GiftCardUserRecordMapper, GiftCardUserRecord> implements GiftCardUserRecordService {
+}

+ 9 - 0
netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java

@@ -41,6 +41,7 @@ import com.cyksj.model.request.OrderRefundReq;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.coupon.CouponFontService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
+import com.cyksj.service.giftcard.GiftCardOrderUseRecordService;
 import com.cyksj.service.mange.CmsOrderDonService;
 import com.cyksj.service.mange.stock.GoodsDonStockService;
 import com.cyksj.service.market.MarketFrontService;
@@ -141,6 +142,8 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
     private final BeanSearcher beanSearcher;
 
+    private final GiftCardOrderUseRecordService giftCardOrderUseRecordService;
+
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
     @Override
@@ -677,6 +680,12 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
                     }
                 }
             }
+
+            //是否是礼品卡 现金支付订单
+            BigDecimal gcCash = orderDon.getGcCash();
+            if (gcCash != null && gcCash.compareTo(BigDecimal.ZERO) > 0) {
+                giftCardOrderUseRecordService.returnGiftCardCash(orderDon.getId());
+            }
         });
     }
 

+ 342 - 263
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollUtil;
 import cn.hutool.core.date.DateField;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.RandomUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.json.JSONObject;
 import com.alipay.api.AlipayApiException;
@@ -12,7 +14,10 @@ import com.alipay.api.AlipayRequest;
 import com.alipay.api.AlipayResponse;
 import com.alipay.api.domain.*;
 import com.alipay.api.internal.util.AlipaySignature;
-import com.alipay.api.request.*;
+import com.alipay.api.request.AlipayFundTransCommonQueryRequest;
+import com.alipay.api.request.AlipayFundTransUniTransferRequest;
+import com.alipay.api.request.AlipayTradeFastpayRefundQueryRequest;
+import com.alipay.api.request.AlipayTradeQueryRequest;
 import com.alipay.api.response.AlipayFundTransCommonQueryResponse;
 import com.alipay.api.response.AlipayTradeFastpayRefundQueryResponse;
 import com.alipay.api.response.AlipayTradeQueryResponse;
@@ -50,17 +55,21 @@ import com.cyksj.model.entity.Address;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.manage.views.OrderDonView;
+import com.cyksj.model.request.GiftCardPayReq;
 import com.cyksj.model.request.OrderAttach;
 import com.cyksj.model.request.OrderPayRequest;
 import com.cyksj.model.request.TransferAccountsReq;
 import com.cyksj.model.views.CouponNewUserView;
 import com.cyksj.model.views.CouponUserView;
+import com.cyksj.model.views.GiftCardGoodsSkuFrontView;
 import com.cyksj.model.views.GoodsDonSkuView;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.coupon.CouponFontService;
 import com.cyksj.service.distribute.UserBusinessFrontService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.exchange.ExchangeCodeService;
+import com.cyksj.service.giftcard.GiftCardOrderUseRecordService;
+import com.cyksj.service.giftcard.GiftCardUserRecordService;
 import com.cyksj.service.groups.GroupsFuncService;
 import com.cyksj.service.market.MarketFrontService;
 import com.cyksj.service.market.task.TaskService;
@@ -90,6 +99,9 @@ import org.springframework.transaction.annotation.Transactional;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_ALREADY_BE_USER;
 import static com.cyksj.enums.GatewayApiCode.GROUP_INDEX_NOT_FIND;
@@ -209,38 +221,69 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final ChannelPopularizeMapper channelPopularizeMapper;
 
+	private final GiftCardUserRecordService giftCardUserRecordService;
+
+	private final GiftCardOrderUseRecordService giftCardOrderUseRecordService;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
 	@Override
 	public OrderDon submit(OrderPayRequest payRequest) throws Exception {
+		GoodsDonSku sku = null;
+		Long goodsId;
+		List<GiftCardPayReq> giftCards = payRequest.getGiftCards();
+		AtomicBoolean isGiftCardPay = new AtomicBoolean(false);
+		if (CollUtil.isNotEmpty(giftCards)) {
+			goodsId = payRequest.getGoodsId();
+			isGiftCardPay.set(true);
+		} else {
+			if (payRequest.getSkuId() == null) {
+				throw BusinessRuntimeException.getInstance("请指定对应平台规格下单");
+			}
+			sku = goodsDonSkuMapper.selectById(payRequest.getSkuId());
+			Assert.notNull(sku, "规格不存在");
+			goodsId = sku.getGoodsId();
+		}
+		GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
+		if (goodsDon == null || !goodsDon.getStatus()) {
+			throw new BusinessRuntimeException("商品已下架");
+		}
+		if (isGiftCardPay.get() && (goodsDon.getSpecialType() == null || goodsDon.getSpecialType() != GoodsDon.SpecialType.giftCard)) {
+			throw BusinessRuntimeException.getInstance("非礼品卡类型商品");
+		}
 		CouponUser couponUser = null;
 		if (StrUtil.isNotBlank(payRequest.getCouponExCode()) || payRequest.getCouponId() != null) {
 			CouponPopularizeDto couponPopularizeDto = checkCouponStatus(payRequest.getSkuId(), payRequest.getCouponExCode(), payRequest.getCouponId(), payRequest.getUserId(), false);
 			//记录优惠券使用状态
 			couponUser = couponStatusRecord(payRequest.getCouponExCode(), payRequest.getCouponId(), payRequest.getUserId(), couponPopularizeDto);
 		}
-		GoodsDonSku sku = goodsDonSkuMapper.selectById(payRequest.getSkuId());
-		GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
-		if (goodsDon == null || !goodsDon.getStatus()) {
-			throw new BusinessRuntimeException("商品已下架");
-		}
 		Boolean isNoLogin = payRequest.getIsNoLogin();
 		User user;
 		String payOpenId = null;
 		Long relationId = 0L;
 
-		if (isNoLogin != null && isNoLogin) {
+		Boolean isNeedTicket = checkIsNeedGroupsRelation(goodsDon);
+		Long userId = payRequest.getUserId();
+		if (userId != null) {
+			int noPayCount = count(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, userId).eq(OrderDon::getGoodsId, goodsId).eq(OrderDon::getStatus, OrderDon.Status.noPayment.toString()));
+			if (noPayCount > 0) {
+				throw new BusinessRuntimeException("您有未支付订单.");
+			}
+		}
+		if (userId == null) {
 			user = new User();
 			user.setId(0l);
 		} else {
-			user = userMapper.selectById(payRequest.getUserId());
+			user = userMapper.selectById(userId);
 			if (user == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
 			if (user.getIsBlack()) throw BusinessRuntimeException.getInstance("系统检测操作异常,请稍后再试");
-			//ChatGPT Plus账号限购校验
-			checkChatGPTPlusPurchaseLimit(user.getId(), goodsDon.getId(), goodsDon.getTitle(), sku.getId(), sku.getSpecVal());
 			payOpenId = user.getOpenId();
-			if (goodsDon.getType() == 1) {
+			if (sku != null) {
+				//ChatGPT Plus账号限购校验
+				checkChatGPTPlusPurchaseLimit(user.getId(), goodsDon.getId(), goodsDon.getTitle(), sku.getId(), sku.getSpecVal());
+			}
+			if (goodsDon.getType() == 1 && isNeedTicket) {
 				//获取座位
 				relationId = getRelation(payRequest, sku);
 			} else {
@@ -257,12 +300,14 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		orderDon.setOrderNo(donNo);
 		orderDon.setOpenId(payOpenId);
-		if (sku.getPrice() == null || sku.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
-			throw BusinessRuntimeException.getInstance("下单商品价格异常");
-		}
-		if (payRequest.getDonMoney().compareTo(sku.getPrice()) < 0) {
-			log.info("规格:{}支付金额:{}异常,调整用户userId:{}支付金额为:{}", sku.getSpecVal(), payRequest.getDonMoney(), user.getId(), sku.getPrice());
-			payRequest.setDonMoney(sku.getPrice());
+		if (sku != null) {
+			if (sku.getPrice() == null || sku.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
+				throw BusinessRuntimeException.getInstance("下单商品价格异常");
+			}
+			if (payRequest.getDonMoney().compareTo(sku.getPrice()) < 0) {
+				log.info("规格:{}支付金额:{}异常,调整用户userId:{}支付金额为:{}", sku.getSpecVal(), payRequest.getDonMoney(), user.getId(), sku.getPrice());
+				payRequest.setDonMoney(sku.getPrice());
+			}
 		}
 
 		orderDon.setMoney(payRequest.getDonMoney());
@@ -298,8 +343,10 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		if (payRequest.getPopularizeId() != null) {
 			orderDon.setPopularizeId(payRequest.getPopularizeId());
 		}
-		//扣除使用优惠券、余额的订单金额
-		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon.getType());
+		if (sku != null) {
+			//扣除使用优惠券、余额的订单金额
+			deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon.getType(), payRequest.getGcCash(), payRequest.getGcpIds());
+		}
 
 		orderDon.setSkuId(payRequest.getSkuId());
 		orderDon.setRelationId(relationId);
@@ -311,24 +358,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		orderDon.setIsWebPay(payRequest.getIsWebPay());
 		orderDon.setSource(payRequest.getSource());
 		orderDon.setCouponExCode(payRequest.getCouponExCode());
-		if (isNoLogin == null || !isNoLogin) {
-			//虚拟商品订单,是否是分销订单
-			if (goodsDon.getType() == 1 || goodsDon.getType() == 2) {
-				//若该订单使用了规定推广者的兑换码 增加上下级关系
-				if (StrUtil.isNotBlank(orderDon.getCouponExCode()) && orderDon.getUserId() != 0) {
-					addDistributeCouponCode(orderDon.getUserId(), orderDon.getCouponExCode());
-				}
-				UserDistributeShared userDistributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class).eq(UserDistributeShared::getUserId, user.getId()).last("limit 1"));
-				if (userDistributeShared != null) {
-					orderDon.setIsDistribute(true);
-					UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, userDistributeShared.getSharedId()));
-					if (userDistribute != null) {
-						orderDon.setIsFixedDistribute(true);
-						orderDon.setCpsPopularizeId(userDistributeShared.getDsPopularizeId());
-					}
-				}
-			}
-		}
+		//设置分销订单
+		setDistributeOrderMark(orderDon, goodsDon.getType(), user.getId());
 		if (relationId != 0) {
 			Long gtSkuId = groupsRelationMapper.getGroupTripsSkuIdByRelationId(relationId);
 			if (!gtSkuId.equals(orderDon.getSkuId())) {
@@ -338,7 +369,46 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		orderDon.setPayDesc(goodsDon.getPayDesc());
 		StringBuilder payTitle = new StringBuilder();
 		payTitle.append(goodsDon.getTitle());
-		payTitle.append(sku.getSpecVal());
+		if (sku != null) {
+			payTitle.append(sku.getSpecVal());
+		}
+		if (isGiftCardPay.get()) {
+			//礼品卡规格
+			Map<Long, Integer> giftCardPayNumMap = new ConcurrentHashMap<>();
+			giftCards.stream().forEach(data->{
+				giftCardPayNumMap.putIfAbsent(data.getGcId(), data.getNum());
+			});
+			List<GiftCardGoodsSkuFrontView> giftCardViews = beanSearcher.searchAll(GiftCardGoodsSkuFrontView.class, MapUtils.builder().field(GiftCardGoodsSkuFrontView::getId, giftCardPayNumMap.keySet()).build());
+			if (giftCardViews.size() != giftCards.size()) {
+				throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重试");
+			}
+			payTitle.append("礼品卡:");
+			BigDecimal gift_card_pay_money = BigDecimal.ZERO;
+			for (GiftCardGoodsSkuFrontView data : giftCardViews) {
+				//礼品卡数量
+				Integer num = giftCardPayNumMap.get(data.getId());
+				gift_card_pay_money = gift_card_pay_money.add(data.getPrice().multiply(BigDecimal.valueOf(num)));
+
+				//礼品卡关系
+				if (!payTitle.toString().endsWith("礼品卡:")) {
+					payTitle.append(" + ");
+				}
+				String gcDetail;
+				if (data.getGcType() == 1) {
+					gcDetail = String.format("%s张现金卡%s", num, data.getCash().divide(BigDecimal.valueOf(100)));
+					payTitle.append(gcDetail);
+				} else {
+					gcDetail = String.format("%s张虚拟卡%s%s", num, data.getGcGoodsTitle(), data.getGcSpecVal());
+					payTitle.append(gcDetail);
+				}
+			}
+
+			//调整礼品卡金额
+			if (gift_card_pay_money.compareTo(orderDon.getMoney()) > 0) {
+				orderDon.setMoney(gift_card_pay_money);
+				orderDon.setRealMoney(gift_card_pay_money);
+			}
+		}
 		if (orderDon.getIsDp()) {
 			List<GoodsDonSkuView> dp_skuViewList = beanSearcher.searchAll(GoodsDonSkuView.class, MapUtils.builder().field(GoodsDonSkuView::getSkuId, dpSkuIds).op(Operator.InList).build());
 			if (dp_skuViewList.size() != dpSkuIds.size()) {
@@ -391,9 +461,31 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			}
 		}
 		orderDon.setSpecialType(goodsDon.getSpecialType());
+		//礼品卡购买记录
+		if (CollUtil.isNotEmpty(payRequest.getGiftCards())) {
+			redisService.set(RedisService.key.GIFT_CARD_USER_PAY_SUCCESS_RECORD_KEY.getName() + orderDon.getId(), payRequest.getGiftCards(), RedisService.key.GIFT_CARD_USER_PAY_SUCCESS_RECORD_KEY.getTimeout());
+		}
+		//礼品卡现金使用记录
+		if (CollUtil.isNotEmpty(orderDon.getGcUseRecords())) {
+			orderDon.getGcUseRecords().forEach(data -> {
+				data.setOrderId(orderDon.getId());
+			});
+			giftCardOrderUseRecordService.saveBatch(orderDon.getGcUseRecords());
+		}
 		return orderDon;
 	}
 
+	private Boolean checkIsNeedGroupsRelation(GoodsDon goodsDon) {
+		if (goodsDon.getType() == 1) {
+			//礼品卡特殊类型不需要车票
+			if (goodsDon.getSpecialType() != null && goodsDon.getSpecialType() == GoodsDon.SpecialType.giftCard) {
+				return false;
+			}
+			return true;
+		}
+		return false;
+	}
+
 	@Override
 	public H5JsPayParams pay(Long orderId, String tradeType) throws Exception {
 		log.info("调起微信支付[start] orderId:{}", orderId);
@@ -516,7 +608,6 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 		// 更改订单状态
 		order.setTransactionId(transactionId);
-		order.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
 
 		order.setPayTime(DateUtil.parse(map.get("time_end"), "yyyyMMddHHmmss"));
 		order.setShopId(appId);
@@ -528,63 +619,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			order.setOpenId(map.get("openid"));
 		}
 		order.setType(OrderDon.Type.WeChat);
-		if (order.getIsNoLogin()) {
-			order.setStatus(OrderDon.Status.hasPayment);
-		}
-
-		boolean isSuccess = update(Wrappers.lambdaUpdate(OrderDon.class)
-				.set(OrderDon::getStatus, order.getStatus())
-				.in(OrderDon::getStatus, List.of(OrderDon.Status.noPayment, OrderDon.Status.close))
-				.eq(OrderDon::getId, order.getId()));
-		if (!isSuccess) {
-			log.info("微信回调商家订单号:{}订单状态已修改", order.getOrderNo());
-			return;
-		}
 
-		if (!order.getIsNoLogin()) {
-			//更新座位信息
-			updateGroupsTicket(order, goodsDon, sku);
-			if (order.getMoney().compareTo(BigDecimal.ZERO) > 0 && order.getIsDistribute()) {
-				TASK_POOL.execute(() -> distributeWaitingSendPointsRecord(order));
-			}
-			if (goodsDon.getType() == 1) {
-				//无车队,新增车队
-				checkNoGroupsTripsAndSendMsg(sku, order);
-			}
-			//完成任务
-			TASK_POOL.execute(() -> {
-				TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
-						.eq(TaskType::getName, TaskTypeEnum.yh_order.getDesc()).last("limit 1"));
-				taskService.completeTask(taskType, order.getUserId());
-			});
-			//客服续费订单
-			handleServiceRenewOrder(order);
-		}
-		//购买Midjourney课程 赠送Midjourney车票
-		if (goodsId != null && goodsId.equals(27l)) {
-			order.setStatus(OrderDon.Status.complete);
-			TASK_POOL.execute(() -> sendMidjourneyTicketIfCourse(order.getUserId()));
-		}
-		this.updateById(order);
-		//配置了特定奖池,增加抽奖机会
-		TASK_POOL.execute(() -> {
-			try {
-				marketFrontService.addSpecificChanceNum(order.getUserId(), order.getId(), order.getGoodsId(), order.getSkuId());
-				if (goodsDon.getType() == 2) {
-					equipmentDistributeService.addDistributeBenefitsChance(order.getUserId(), order.getId());
-				}
-			} catch (Exception e) {
-				log.error("wx增加抽奖机会错误,orderId:{},error:{}", order.getId(), e);
-			}
-		});
-
-		TASK_POOL.execute(()->{
-			try {
-				orderDonPostService.postData((order.getId()));
-			} catch (Exception e) {
-				log.error("回传错误 {}",StringUtil.getErrorText(e));
-			}
-		});
+		unifiedHandlerOrderNotify(order, goodsDon, sku);
 	}
 
 	@Override
@@ -670,6 +706,12 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
 					userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getBalance(), UserBalanceSourceRecord.Source.close);
 				}
+
+				//是否是礼品卡 现金支付订单
+				BigDecimal gcCash = orderDon.getGcCash();
+				if (gcCash != null && gcCash.compareTo(BigDecimal.ZERO) > 0) {
+					giftCardOrderUseRecordService.returnGiftCardCash(orderDon.getId());
+				}
 			}
 		}
 	}
@@ -795,7 +837,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		orderDon.setRealMoney(orderDon.getMoney());
 		//扣除使用优惠券、余额的订单金额
-		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon.getType());
+		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon.getType(), payRequest.getGcCash(), payRequest.getGcpIds());
 		this.saveOrUpdate(orderDon);
 		//订单金额为0 且订单为已完成 更新虚物车票
 		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
@@ -807,6 +849,13 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				closeOrder(orderDon.getId(), null);
 			});
 		}
+		//礼品卡现金使用记录
+		if (CollUtil.isNotEmpty(orderDon.getGcUseRecords())) {
+			orderDon.getGcUseRecords().forEach(data -> {
+				data.setOrderId(orderDon.getId());
+			});
+			giftCardOrderUseRecordService.saveBatch(orderDon.getGcUseRecords());
+		}
 		return orderDon;
 	}
 
@@ -873,78 +922,14 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		// 更改订单状态
 		orderDon.setTransactionId(transactionId);
-		orderDon.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
 		orderDon.setPayTime(payTime);
 		orderDon.setShopId(appId);
 		orderDon.setType(OrderDon.Type.ALI_PAY);
-		if (orderDon.getIsNoLogin()) {
-			orderDon.setStatus(OrderDon.Status.hasPayment);
-		}
-		boolean isSuccess = update(Wrappers.lambdaUpdate(OrderDon.class)
-				.set(OrderDon::getStatus, orderDon.getStatus())
-				.in(OrderDon::getStatus, List.of(OrderDon.Status.noPayment, OrderDon.Status.close))
-				.eq(OrderDon::getId, orderDon.getId()));
-		if (!isSuccess) {
-			log.info("支付宝回调商家订单号:{}订单状态已修改", orderDon.getOrderNo());
-			return;
-		}
-		if (!orderDon.getIsNoLogin()) {
-			//更新座位信息
-			updateGroupsTicket(orderDon, goodsDon, sku);
-			if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0 && orderDon.getIsDistribute()) {
-				TASK_POOL.execute(() -> distributeWaitingSendPointsRecord(orderDon));
-			}
-			if (goodsDon.getType() == 1) {
-				//无车队,新增车队
-				checkNoGroupsTripsAndSendMsg(sku, orderDon);
-			}
-			//完成任务
-			TASK_POOL.execute(() -> {
-				TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
-						.eq(TaskType::getName, TaskTypeEnum.yh_order.getDesc()).last("limit 1"));
-				taskService.completeTask(taskType, orderDon.getUserId());
-			});
-			//客服续费订单
-			handleServiceRenewOrder(orderDon);
-		}
-		//购买Midjourney课程 赠送Midjourney车票
-		if (goodsId != null && goodsId.equals(27l)) {
-			orderDon.setStatus(OrderDon.Status.complete);
-			TASK_POOL.execute(() -> sendMidjourneyTicketIfCourse(orderDon.getUserId()));
-		}
-		this.updateById(orderDon);
-		//配置了特定奖池,增加抽奖机会
-		TASK_POOL.execute(() -> {
-			try {
-				marketFrontService.addSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getSkuId());
-				if (goodsDon.getType() == 2) {
-					equipmentDistributeService.addDistributeBenefitsChance(orderDon.getUserId(), orderDon.getId());
-				}
-				//若该订单使用了规定推广者的兑换码 增加上下级关系
-				if (StrUtil.isNotBlank(orderDon.getCouponExCode())) {
-					addDistributeCouponCode(orderDon.getUserId(), orderDon.getCouponExCode());
-				}
-			} catch (Exception e) {
-				log.error("zfb增加抽奖机会错误,orderId:{},error:{}", orderDon.getId(), e);
-			}
-		});
 
-		TASK_POOL.execute(()->{
-			try {
-				orderDonPostService.postData((orderDon.getId()));
-			} catch (Exception e) {
-				log.error("回传错误 {}",StringUtil.getErrorText(e));
-			}
-		});
+		unifiedHandlerOrderNotify(orderDon, goodsDon, sku);
 	}
 
 	public void setRelation(Long relationId, Long groupsId, Long userId, Long goodsId, Boolean isLoginPopularize) {
-		if (isLoginPopularize == null || !isLoginPopularize) {
-			int noPayCount = count(Wrappers.lambdaQuery(OrderDon.class).eq(OrderDon::getUserId, userId).eq(OrderDon::getGoodsId, goodsId).eq(OrderDon::getStatus, OrderDon.Status.noPayment.toString()));
-			if (noPayCount > 0) {
-				throw new BusinessRuntimeException("您有未支付订单.");
-			}
-		}
 		if (!redisService.setNx(RedisKey.GROUPS_RELATION_NUM_KEY + relationId, userId, 60 * 5L)) {
 			log.info("=====>用户:{}未抢到座位:{}", userId, relationId);
 			throw new BusinessRuntimeException("客官手慢啦,该座位已经有人啦!");
@@ -1110,91 +1095,15 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		this.updateById(orderDon);
 	}
 
-	public AliPayParams commonAliPay(Long orderId, String returnUrl, String productCode, String appId, String qrPayMode) throws Exception {
-		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(appId).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
-		// 创建API对应的request
-		AlipayRequest alipayRequest = getAliAayRequest(orderId, productCode, qrPayMode);
-		if (alipayRequest == null) {
-			throw BusinessRuntimeException.getInstance("支付宝不支持该支付方式:{0}", productCode);
-		}
-		//回调地址
-		String host = envCommonService.getHost();
-		String notifyUrl = String.format("%s%s", host, BaseZfbConfig.notifyUrl);
-		if (BaseZfbConfig.qrPayMode_redirect.equals(qrPayMode)) {
-			returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.loginReturnUrl);
-			alipayRequest.setReturnUrl(returnUrl);
-		} else if (StrUtil.isNotBlank(returnUrl)) {
-			alipayRequest.setReturnUrl(returnUrl);
-		}
-		alipayRequest.setNotifyUrl(notifyUrl);
-		String form = null;
-		try {
-			//调用SDK生成表单
-			//pagePay 统一下单接口
-			form = alipayClient.pageExecute(alipayRequest).getBody();
-		} catch (AlipayApiException e) {
-			log.error("支付宝生成表单错误:{}", e == null ? null : e.getMessage());
-		}
-		log.info("支付宝返回参数:{}", form);
-		return new AliPayParams(form);
-	}
-
-	/**
-	 * 支付宝获取不同的request
-	 * @param productCode 销售产品码,与支付宝签约的产品码名称
-	 * @return
-	 */
-	private AlipayRequest getAliAayRequest(Long orderId, String productCode, String qrPayMode) throws Exception {
-		OrderAttach attach = new OrderAttach();
-		attach.setO(orderId);
-		String body = Codec.DoBase64.custom()
-				.setData(Jsons.toJson(attach)).encodeAsText();
-		OrderDon orderDon = orderDonMapper.selectById(orderId);
-		if (orderDon.getType() != OrderDon.Type.ALI_PAY) {
-			orderDon.setType(OrderDon.Type.ALI_PAY);
-			orderDonMapper.updateById(orderDon);
-		}
-		GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
-		GoodsDon goodsDon = goodsDonMapper.selectById(goodsDonSku.getGoodsId());
-		String subject = goodsDon.getTitle().contains("ChatGPT") ? "AI订阅" : goodsDon.getTitle();
-		if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode)) {
-			//手机网站支付
-			AlipayTradeWapPayRequest alipayTradeWapPayRequest = new AlipayTradeWapPayRequest();
-			//手机网站支付支付参数
-			AlipayTradeWapPayModel alipayTradeWapPayModel = new AlipayTradeWapPayModel();
-			alipayTradeWapPayModel.setBody(body);
-			alipayTradeWapPayModel.setOutTradeNo(orderDon.getOrderNo());
-			alipayTradeWapPayModel.setTotalAmount(orderDon.getMoney().divide(new BigDecimal(100), 2, RoundingMode.HALF_EVEN).toString());
-			alipayTradeWapPayModel.setSubject(subject);
-			alipayTradeWapPayModel.setProductCode(productCode);
-			//5分钟订单失效时间
-			alipayTradeWapPayModel.setTimeExpire(DateUtil.offsetMinute(orderDon.getCreatedTime(), 5).toString());
-			alipayTradeWapPayRequest.setBizModel(alipayTradeWapPayModel);
-			return alipayTradeWapPayRequest;
-		} else if (ZfbProductCode.PC_WEB.getProductCode().equals(productCode)) {
-			//电脑网站支付
-			AlipayTradePagePayRequest alipayTradePagePayRequest = new AlipayTradePagePayRequest();
-			//电脑网站支付参数
-			AlipayTradePagePayModel alipayTradePagePayModel = new AlipayTradePagePayModel();
-			alipayTradePagePayModel.setBody(body);
-			alipayTradePagePayModel.setOutTradeNo(orderDon.getOrderNo());
-			alipayTradePagePayModel.setTotalAmount(orderDon.getMoney().divide(new BigDecimal(100), 2, RoundingMode.HALF_EVEN).toString());
-			alipayTradePagePayModel.setSubject(subject);
-			alipayTradePagePayModel.setProductCode(productCode);
-			//5分钟订单失效时间
-			alipayTradePagePayModel.setTimeExpire(DateUtil.offsetMinute(orderDon.getCreatedTime(), 5).toString());
-			alipayTradePagePayModel.setQrPayMode(qrPayMode);
-			alipayTradePagePayRequest.setBizModel(alipayTradePagePayModel);
-			return alipayTradePagePayRequest;
-		}
-		return null;
-	}
-
 	public void updateCarParkAndSendMsg(GoodsDon goodsDon, GoodsDonSku sku, OrderDon order) {
 		if (goodsDon.getType() == 1) {
 			log.info("虚物订单orderNo:{}开始更新车票信息", order.getOrderNo());
 			//修改车位状态
 			GroupsRelation relation = groupsRelationMapper.selectById(order.getRelationId());
+			if (relation == null) {
+				log.info("无需更新车票信息");
+				return;
+			}
 			if (order.getIsDp()) {
 				//是否已经发送优惠加购车票
 				OrderDiscountPlusPurchaseSkuRelation purchaseSkuRelation = orderDiscountPlusPurchaseSkuRelationMapper.selectOne(Wrappers.lambdaQuery(OrderDiscountPlusPurchaseSkuRelation.class)
@@ -1961,7 +1870,52 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 	/**
 	 * 使用优惠营销 订单金额抵扣
 	 */
-	public void deductOrderMoney(OrderDon orderDon, CouponUser couponUser, BigDecimal balance, User user, BigDecimal skuMoney, Integer goodsType) {
+	public void deductOrderMoney(OrderDon orderDon, CouponUser couponUser, BigDecimal balance, User user, BigDecimal skuMoney, Integer goodsType, BigDecimal gcCash, List<Long> gcpIds) {
+		//礼品卡现金支付 不参与其他优惠
+		if (gcCash != null && gcCash.compareTo(BigDecimal.ZERO) > 0) {
+			if (CollUtil.isEmpty(gcpIds)) {
+				throw BusinessRuntimeException.getInstance("礼品卡现金支付参数异常");
+			}
+			BigDecimal money = orderDon.getMoney();
+			if (gcCash.compareTo(money) > 0) {
+				gcCash = money;
+			}
+			List<GiftCardUserRecord> availableGiftCards = giftCardUserRecordService.list(Wrappers.lambdaQuery(GiftCardUserRecord.class)
+					.eq(GiftCardUserRecord::getToUserId, user.getId())
+					.in(GiftCardUserRecord::getId, gcpIds)
+					.eq(GiftCardUserRecord::getIsPay, true)
+					.eq(GiftCardUserRecord::getGcType, 1)
+					.gt(GiftCardUserRecord::getRemainCash, 0));
+			if (availableGiftCards.size() != gcpIds.size()) {
+				throw BusinessRuntimeException.getInstance("礼品卡使用异常,请刷新页面重试");
+			}
+			//需要扣除的礼品卡现金
+			BigDecimal deductCash = gcCash;
+			List<GiftCardOrderUseRecord> gcUseRecords = new ArrayList<>();
+			for (GiftCardUserRecord giftCard : availableGiftCards) {
+				if (deductCash.compareTo(BigDecimal.ZERO) <= 0) {
+					break;
+				}
+				BigDecimal remainCash = giftCard.getRemainCash();
+				//扣完
+				if (remainCash.compareTo(deductCash) == 0) {
+					deductGiftCardCash(user.getId(), giftCard.getId(), deductCash, remainCash, gcUseRecords);
+					deductCash = BigDecimal.ZERO;
+				} else if (remainCash.compareTo(deductCash) < 0) {
+					deductGiftCardCash(user.getId(), giftCard.getId(), remainCash, remainCash, gcUseRecords);
+					deductCash = deductCash.subtract(remainCash);
+				} else if (remainCash.compareTo(deductCash) > 0) {
+					deductGiftCardCash(user.getId(), giftCard.getId(), deductCash, remainCash, gcUseRecords);
+					deductCash = BigDecimal.ZERO;
+				}
+			}
+			orderDon.setMoney(orderDon.getMoney().subtract(gcCash));
+			orderDon.setGcCash(gcCash);
+			if (!gcUseRecords.isEmpty()) {
+				orderDon.setGcUseRecords(gcUseRecords);
+			}
+			return;
+		}
 		//存在优惠券
 		if (couponUser != null) {
 			Long couponId = couponUser.getCouponId();
@@ -2042,11 +1996,13 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		GoodsDonSku sku = goodsDonSkuMapper.selectById(orderDon.getSkuId());
 		GoodsDon goodsDon = goodsDonMapper.selectById(sku.getGoodsId());
-		orderDon.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
+		unifiedHandlerOrderNotify(orderDon, goodsDon, sku);
+	}
 
-		if (orderDon.getIsNoLogin()) {
-			orderDon.setStatus(OrderDon.Status.hasPayment);
-		}
+	/**
+	 * 统一订单信息回调
+	 */
+	public void unifiedHandlerOrderNotify(OrderDon orderDon, GoodsDon goodsDon, GoodsDonSku sku) {
 		boolean isSuccess = update(Wrappers.lambdaUpdate(OrderDon.class)
 				.set(OrderDon::getStatus, orderDon.getStatus())
 				.in(OrderDon::getStatus, List.of(OrderDon.Status.noPayment, OrderDon.Status.close))
@@ -2055,34 +2011,40 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			log.info("支付宝回调商家订单号:{}订单状态已修改", orderDon.getOrderNo());
 			return;
 		}
+		orderDon.setStatus(goodsDon.getType() == 1 && goodsDon.getSecondType() == 2 ? OrderDon.Status.complete : OrderDon.Status.hasPayment);
+
+		if (orderDon.getIsNoLogin()) {
+			orderDon.setStatus(OrderDon.Status.hasPayment);
+		}
+		Long goodsId = goodsDon.getId();
 		if (!orderDon.getIsNoLogin()) {
 			//更新座位信息
 			updateGroupsTicket(orderDon, goodsDon, sku);
-			if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0 && orderDon.getIsDistribute()) {
-				TASK_POOL.execute(() -> distributeWaitingSendPointsRecord(orderDon));
-			}
 			if (goodsDon.getType() == 1) {
 				//无车队,新增车队
 				checkNoGroupsTripsAndSendMsg(sku, orderDon);
 			}
-			//完成任务
-			TASK_POOL.execute(() -> {
-				TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
-						.eq(TaskType::getName, TaskTypeEnum.yh_order.getDesc()).last("limit 1"));
-				taskService.completeTask(taskType, orderDon.getUserId());
-			});
 			//客服续费订单
 			handleServiceRenewOrder(orderDon);
 		}
-		//购买Midjourney课程 赠送Midjourney车票
-		if (goodsId != null && goodsId.equals(27l)) {
-			orderDon.setStatus(OrderDon.Status.complete);
-			TASK_POOL.execute(() -> sendMidjourneyTicketIfCourse(orderDon.getUserId()));
-		}
 		this.updateById(orderDon);
-		//配置了特定奖池,增加抽奖机会
-		TASK_POOL.execute(() -> {
+
+		TASK_POOL.execute(()->{
 			try {
+				//发放积分
+				if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0 && orderDon.getIsDistribute()) {
+					TASK_POOL.execute(() -> distributeWaitingSendPointsRecord(orderDon));
+				}
+				//完成任务
+				TaskType taskType = taskTypeMapper.selectOne(Wrappers.lambdaQuery(TaskType.class)
+						.eq(TaskType::getName, TaskTypeEnum.yh_order.getDesc()).last("limit 1"));
+				taskService.completeTask(taskType, orderDon.getUserId());
+				//购买Midjourney课程 赠送Midjourney车票
+				if (goodsId != null && goodsId.equals(27l)) {
+					orderDon.setStatus(OrderDon.Status.complete);
+					TASK_POOL.execute(() -> sendMidjourneyTicketIfCourse(orderDon.getUserId()));
+				}
+				//配置了特定奖池,增加抽奖机会
 				marketFrontService.addSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getSkuId());
 				if (goodsDon.getType() == 2) {
 					equipmentDistributeService.addDistributeBenefitsChance(orderDon.getUserId(), orderDon.getId());
@@ -2091,9 +2053,126 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				if (StrUtil.isNotBlank(orderDon.getCouponExCode())) {
 					addDistributeCouponCode(orderDon.getUserId(), orderDon.getCouponExCode());
 				}
+
+				//礼品卡
+				if (goodsDon.getSpecialType() != null && goodsDon.getSpecialType() == GoodsDon.SpecialType.giftCard) {
+					List<GiftCardUserRecord> GiftCardUserRecords = giftCardUserRecordService.list(Wrappers.lambdaQuery(GiftCardUserRecord.class)
+							.eq(GiftCardUserRecord::getOrderId, orderDon.getId())
+							.eq(GiftCardUserRecord::getIsPay, false));
+					if (CollUtil.isNotEmpty(GiftCardUserRecords)) {
+						GiftCardUserRecords.forEach(data->{
+							giftCardUserRecordService.update(null, Wrappers.lambdaUpdate(GiftCardUserRecord.class)
+									.set(GiftCardUserRecord::getIsPay, true)
+									.set(GiftCardUserRecord::getRc, RandomUtil.randomString(6))
+									.set(GiftCardUserRecord::getPayTime, Optional.ofNullable(orderDon.getPayTime()).orElse(orderDon.getCreatedTime()))
+									.eq(GiftCardUserRecord::getId, data.getId())
+									.eq(GiftCardUserRecord::getIsPay, false));
+						});
+					}
+				}
+
+				//礼品卡购买记录
+				Object giftCardPay = redisService.get(RedisService.key.GIFT_CARD_USER_PAY_SUCCESS_RECORD_KEY.getName() + orderDon.getId());
+				if (giftCardPay != null) {
+					List<GiftCardPayReq> giftCardPayReqs = Jsons.parseList(giftCardPay, GiftCardPayReq.class);
+					if (CollUtil.isNotEmpty(giftCardPayReqs)) {
+						log.info("记录用户userId:{}订单orderId:{}购买成功礼品卡", orderDon.getUserId(), orderDon.getId());
+						giftCardUserPayRecord(giftCardPayReqs, orderDon);
+					}
+				}
+			} catch (Exception e) {
+				log.error("回调修改订单信息错误,orderId:{},error:{}", orderDon.getId(), StringUtil.getErrorText(e));
+			}
+		});
+
+		TASK_POOL.execute(()->{
+			try {
+				orderDonPostService.postData((orderDon.getId()));
 			} catch (Exception e) {
-				log.error("zfb增加抽奖机会错误,orderId:{},error:{}", orderDon.getId(), e);
+				log.error("回传错误 {}",StringUtil.getErrorText(e));
 			}
 		});
 	}
+
+	public void setDistributeOrderMark(OrderDon orderDon, Integer goodsType, Long userId) {
+		if (userId == null || userId == 0) {
+			return;
+		}
+		//虚拟商品订单,是否是分销订单
+		if (goodsType == 1 || goodsType == 2) {
+			//若该订单使用了规定推广者的兑换码 增加上下级关系
+			if (StrUtil.isNotBlank(orderDon.getCouponExCode()) && orderDon.getUserId() != 0) {
+				addDistributeCouponCode(orderDon.getUserId(), orderDon.getCouponExCode());
+			}
+			UserDistributeShared userDistributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class).eq(UserDistributeShared::getUserId, userId).last("limit 1"));
+			if (userDistributeShared != null) {
+				orderDon.setIsDistribute(true);
+				UserDistribute userDistribute = userDistributeMapper.selectOne(Wrappers.lambdaQuery(UserDistribute.class).eq(UserDistribute::getUserId, userDistributeShared.getSharedId()));
+				if (userDistribute != null) {
+					orderDon.setIsFixedDistribute(true);
+					orderDon.setCpsPopularizeId(userDistributeShared.getDsPopularizeId());
+				}
+			}
+		}
+	}
+
+	private void deductGiftCardCash(Long userId, Long gcId, BigDecimal deductCash, BigDecimal gcRemainCash, List<GiftCardOrderUseRecord> gcUseRecords) {
+		Boolean is_update = giftCardUserRecordService.update(null, Wrappers.lambdaUpdate(GiftCardUserRecord.class)
+				.set(GiftCardUserRecord::getRemainCash, gcRemainCash.subtract(deductCash))
+				.eq(GiftCardUserRecord::getId, gcId)
+				.eq(GiftCardUserRecord::getIsPay, true)
+				.eq(GiftCardUserRecord::getRemainCash, gcRemainCash));
+		if (!is_update) {
+			throw BusinessRuntimeException.getInstance("礼品卡支付异常,请刷新页面重试");
+		}
+		//记录使用关系 订单关闭 退款使用
+		GiftCardOrderUseRecord useRecord = new GiftCardOrderUseRecord();
+		useRecord.setUserId(userId);
+		useRecord.setCash(deductCash);
+		useRecord.setGcId(gcId);
+		gcUseRecords.add(useRecord);
+	}
+
+	/**
+	 * 用户购买成功礼品卡记录
+	 */
+	private void giftCardUserPayRecord(List<GiftCardPayReq> giftCards, OrderDon orderDon) {
+		//礼品卡规格
+		Map<Long, Integer> giftCardPayNumMap = new ConcurrentHashMap<>();
+		AtomicInteger init_size = new AtomicInteger(0);
+		giftCards.stream().forEach(data -> {
+			giftCardPayNumMap.putIfAbsent(data.getGcId(), data.getNum());
+			init_size.addAndGet(data.getNum());
+		});
+		List<GiftCardGoodsSkuFrontView> giftCardViews = beanSearcher.searchAll(GiftCardGoodsSkuFrontView.class, MapUtils.builder().field(GiftCardGoodsSkuFrontView::getId, giftCardPayNumMap.keySet()).build());
+		if (giftCardViews.size() != giftCards.size()) {
+			throw BusinessRuntimeException.getInstance("系统异常,请刷新页面重试");
+		}
+		List<GiftCardUserRecord> gcUserPayRecords = new ArrayList<>(init_size.get());
+		for (GiftCardGoodsSkuFrontView data : giftCardViews) {
+			//礼品卡数量
+			for (Integer i = 0; i < giftCardPayNumMap.get(data.getId()); i++) {
+				//礼品卡关系
+				GiftCardUserRecord giftCardUserRecord = new GiftCardUserRecord();
+				String gcDetail;
+				if (data.getGcType() == 1) {
+					gcDetail = String.format("现金卡%s", data.getCash().divide(BigDecimal.valueOf(100)));
+					giftCardUserRecord.setCash(data.getCash());
+					giftCardUserRecord.setRemainCash(data.getCash());
+				} else {
+					gcDetail = String.format("虚拟卡%s%s", data.getGcGoodsTitle(), data.getGcSpecVal());
+					giftCardUserRecord.setGcGoodsId(data.getGcGoodsId());
+					giftCardUserRecord.setGcSkuId(data.getGcSkuId());
+				}
+				giftCardUserRecord.setOrderId(orderDon.getId());
+				giftCardUserRecord.setUserId(orderDon.getUserId());
+				giftCardUserRecord.setGcType(data.getGcType());
+				giftCardUserRecord.setGcDetail(gcDetail);
+				gcUserPayRecords.add(giftCardUserRecord);
+			}
+		}
+		if (CollUtil.isNotEmpty(gcUserPayRecords)) {
+			giftCardUserRecordService.saveBatch(gcUserPayRecords);
+		}
+	}
 }

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

@@ -46,4 +46,9 @@ public interface UserService extends IService<User> {
 	User webLogin(LoginReq loginReq) throws Exception;
 
 	String bindWxAccountRedirect(String code, String state) throws Exception;
+
+	/**
+	 * 领取礼品卡
+	 */
+	void receiveGiftCardByRc(Long userId, String code);
 }

+ 56 - 0
netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java

@@ -14,7 +14,9 @@ import com.cyksj.common.util.Codec;
 import com.cyksj.common.util.Jsons;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.config.wxlogin.WxOpenPlatYHLXLoginConfig;
+import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.PhoneCodeMapper;
+import com.cyksj.mapper.GiftCardUserRecordMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.channel.ChannelPopularizeMapper;
 import com.cyksj.mapper.manage.cps.UserDistributePopularizeMapper;
@@ -25,6 +27,7 @@ import com.cyksj.model.request.LoginReq;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.distribute.DistributeService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
+import com.cyksj.service.exchange.ExchangeCodeService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.market.task.BindTaskService;
 import com.cyksj.service.sys.SysConfigService;
@@ -34,6 +37,7 @@ 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 org.springframework.util.Assert;
 
 import java.util.ArrayList;
@@ -75,6 +79,12 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 
 	private final WxOpenPlatYHLXLoginConfig wxOpenPlatYHLXLoginConfig;
 
+	private final GiftCardUserRecordMapper GiftCardUserRecordMapper;
+
+	private final ExchangeCodeService exchangeCodeService;
+
+	private final GoodsDonSkuMapper goodsDonSkuMapper;
+
 	private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
 	@Override
@@ -496,6 +506,52 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 		return redisService.getStr(re.getMappingId().toString());
 	}
 
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void receiveGiftCardByRc(Long userId, String code) {
+		GiftCardUserRecord giftCardUserRecord = GiftCardUserRecordMapper.selectOne(Wrappers.lambdaQuery(GiftCardUserRecord.class)
+				.eq(GiftCardUserRecord::getRc, code).last("limit 1"));
+		if (giftCardUserRecord == null) {
+			throw BusinessRuntimeException.getInstance("好友赠送礼品卡不存在");
+		}
+		if (!giftCardUserRecord.getIsPay()) {
+			throw BusinessRuntimeException.getInstance("无效礼品卡,好友未购买");
+		}
+		if (giftCardUserRecord.getUserId().equals(userId)) {
+			throw BusinessRuntimeException.getInstance("无法领取自己购买的礼品卡");
+		}
+		if (giftCardUserRecord.getToUserId() != 0 && giftCardUserRecord.getToUserId().equals(userId)) {
+			throw BusinessRuntimeException.getInstance("好友赠送礼品卡已被领取");
+		}
+		if (giftCardUserRecord.getToUserId().equals(userId)) {
+			throw BusinessRuntimeException.getInstance("您已领取该礼品卡");
+		}
+		giftCardUserRecord.setToUserId(userId);
+		int update = GiftCardUserRecordMapper.update(null, Wrappers.lambdaUpdate(GiftCardUserRecord.class)
+				.set(giftCardUserRecord.getGcType() == 2, GiftCardUserRecord::getIsUsed, true)
+				.set(GiftCardUserRecord::getToUserId, userId)
+				.set(GiftCardUserRecord::getIsSend, true)
+				.set(GiftCardUserRecord::getReceivedTime, DateTime.now())
+				.eq(GiftCardUserRecord::getId, giftCardUserRecord.getId())
+				.eq(GiftCardUserRecord::getIsPay, true)
+				.eq(GiftCardUserRecord::getToUserId, 0));
+		if (update > 0) {
+			//虚拟卡
+			//直接发送 对应规格车票
+			if (giftCardUserRecord.getGcType() == 2) {
+				Long gcSkuId = giftCardUserRecord.getGcSkuId();
+				log.info("用户userId:{}领取礼品卡id:{},开始发放虚拟车票skuId:{}", userId, giftCardUserRecord.getId(), gcSkuId);
+				GoodsDonSku sku = goodsDonSkuMapper.selectById(gcSkuId);
+				if (sku == null) {
+					log.info("礼品卡id:{}虚拟车票skuId:{}不存在", giftCardUserRecord.getId(), gcSkuId);
+					throw BusinessRuntimeException.getInstance("该礼品卡对应的虚拟卡不存在,请联系客服");
+				}
+				exchangeCodeService.getRelationNoOrder(sku, userId);
+				log.info("发送至用户userId:{}礼品卡虚拟车票结束", userId);
+			}
+		}
+	}
+
 	/**
 	 * 发放新用户福利
 	 */

+ 31 - 8
netflix-web/src/main/java/com/cyksj/web/controller/goods/GoodsDonController.java

@@ -15,8 +15,8 @@ import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
 import com.cyksj.mapper.GoodsDonSkuMapper;
 import com.cyksj.mapper.OrderDonMapper;
-import com.cyksj.mapper.SysConfigMapper;
 import com.cyksj.mapper.RegisterOrderDonMapper;
+import com.cyksj.mapper.SysConfigMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
@@ -32,7 +32,9 @@ import org.springframework.web.bind.annotation.*;
 import javax.servlet.http.HttpServletRequest;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Collectors;
 
 /**
  * @author chan
@@ -76,7 +78,7 @@ public class GoodsDonController {
                     .orderByAsc(GoodsDonSku::getPrice)
                     .last("limit 1")
                     .select(GoodsDonSku::getPrice));
-            Optional.ofNullable(goodsDonSku).ifPresent(sku->{
+            Optional.ofNullable(goodsDonSku).ifPresent(sku -> {
                 goods.setPrice(goodsDonSku.getPrice());
                 goods.setSoldNum(goods.getVirtualSold() + orderDonMapper.selectCount(Wrappers.lambdaQuery(OrderDon.class)
                         .eq(OrderDon::getGoodsId, goods.getId())
@@ -195,7 +197,7 @@ public class GoodsDonController {
                     .orderBy(OrderCommentFrontView::getId).desc()
                     .build());
             data.setComments(comments);
-	        data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1));
+            data.setNotifyMsg(getPayMsgTime(data.getId(), now, 1));
         });
         redisService.setNx(pcCacheKey, list, RedisService.key.YH_HOME_PAGHE_CACHE.getTimeout());
         return GatewayResponse.SUCCESS.newBuilder().toResult(list);
@@ -255,12 +257,12 @@ public class GoodsDonController {
         }
         MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
         List<RegisterGoodsDonView> dataList = beanSearcher.searchAll(RegisterGoodsDonView.class, builder.build());
-	    DateTime now = DateTime.now();
-	    dataList.forEach(data->{
+        DateTime now = DateTime.now();
+        dataList.forEach(data -> {
             Integer sold = registerOrderDonMapper.selectCount(Wrappers.lambdaQuery(RegisterOrderDon.class)
                     .eq(RegisterOrderDon::getGoodsId, data.getId()).notIn(RegisterOrderDon::getStatus, Constant.noOrderStatus));
             data.setSold(sold + data.getVirtualSold());
-		    data.setNotifyMsg(getPayMsgTime(data.getId(), now, 2));
+            data.setNotifyMsg(getPayMsgTime(data.getId(), now, 2));
         });
         redisService.setNx(registerCacheKey, dataList, RedisService.key.REGISTER_HOME_PAGE_CACHE.getTimeout());
         return GatewayResponse.SUCCESS.newBuilder().toResult(dataList);
@@ -271,7 +273,7 @@ public class GoodsDonController {
      * 获取商品详情
      */
     @GetMapping("/get/{id}")
-    public Result<GoodsDonViews> getDetail(@PathVariable Long id) {
+    public Result<GoodsDonViews> getDetail(@PathVariable Long id) throws Exception {
         GoodsDonViews views = beanSearcher.searchFirst(GoodsDonViews.class, MapUtils.builder().field(GoodsDonViews::getId, id).build());
 
         views.setSpecs(beanSearcher.searchFirst(GoodsDonSpecFrontView.class, MapUtils.builder().field(GoodsDonSpecFrontView::getGoodsId, views.getId()).build()));
@@ -288,6 +290,17 @@ public class GoodsDonController {
                         .build()));
             }
         });
+
+        //礼品卡
+        if (StrUtil.isNotBlank(views.getGiftCards())) {
+            List<Long> giftSkuIds = Jsons.parseList(views.getGiftCards(), Long.class);
+            if (CollUtil.isNotEmpty(giftSkuIds)) {
+                views.setGiftCardsView(beanSearcher.searchAll(GoodsSkuGiftCardView.class, MapUtils.builder()
+                        .field(GoodsSkuGiftCardView::getSkuId, giftSkuIds).op(Operator.InList)
+                        .onlySelect(GoodsSkuGiftCardView::getGoodsId, GoodsSkuGiftCardView::getTitle, GoodsSkuGiftCardView::getSpecVal)
+                        .build()));
+            }
+        }
         return GatewayResponse.SUCCESS.newBuilder().toResult(views);
     }
 
@@ -311,7 +324,7 @@ public class GoodsDonController {
             if (goodsDon != null && StrUtil.isNotEmpty(goodsDon.getRecommendGoods())) {
                 List<Long> recommend_gidList = Jsons.parseList(goodsDon.getRecommendGoods(), Long.class);
                 List<GoodsRecommendViews> goodsRecommendViews = beanSearcher.searchAll(GoodsRecommendViews.class, MapUtils.builder().field(GoodsRecommendViews::getGoodsId, recommend_gidList).op(Operator.InList).build());
-                goodsRecommendViews.forEach(data->{
+                goodsRecommendViews.forEach(data -> {
                     Integer sold = registerOrderDonMapper.selectCount(Wrappers.lambdaQuery(RegisterOrderDon.class)
                             .eq(RegisterOrderDon::getGoodsId, data.getGoodsId()).notIn(RegisterOrderDon::getStatus, Constant.noOrderStatus));
                     data.setSold(sold + data.getVirtualSold());
@@ -349,6 +362,16 @@ public class GoodsDonController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
 
+    /**
+     * 获取礼品卡平台性情
+     */
+    @GetMapping("/get/card/{id}")
+    public Result<Map<Integer, List<GiftCardGoodsSkuFrontView>>> getGiftCardDetail(@PathVariable Long id) {
+        List<GiftCardGoodsSkuFrontView> giftCardGoodsSkuFrontViews = beanSearcher.searchAll(GiftCardGoodsSkuFrontView.class, MapUtils.builder().field(GiftCardGoodsSkuFrontView::getGoodsId, id).build());
+        Map<Integer, List<GiftCardGoodsSkuFrontView>> map = giftCardGoodsSkuFrontViews.stream().collect(Collectors.groupingBy(GiftCardGoodsSkuFrontView::getGcType));
+        return GatewayResponse.SUCCESS.newBuilder().toResult(map);
+    }
+
     public List<Long> getFilterGoodsIds() {
         //过滤杭州Ai ChatGPT平台
         //获取当前ip地址

+ 72 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/GiftCardController.java

@@ -0,0 +1,72 @@
+package com.cyksj.web.controller.manage.goods;
+
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.GiftCardGoodsSku;
+import com.cyksj.model.views.GiftCardGoodsSkuView;
+import com.cyksj.model.views.GiftCardUserPayView;
+import com.cyksj.service.giftcard.GiftCardGoodsSkuService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+
+/*
+ *项目名: netflix
+ *文件名: GiftCardController
+ *创建者: JavaZou
+ *创建时间:2023/8/29 18:15
+ */
+@RequestMapping("/manage/giftCard")
+@RestController
+@RequiredArgsConstructor
+public class GiftCardController {
+	private final GiftCardGoodsSkuService giftCardGoodsSkuService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	/**
+	 * 设置礼品卡 规格
+	 */
+	@PostMapping("/set")
+	public Result<String> setGiftCardSku(@RequestBody GiftCardGoodsSku giftCardSku) {
+		giftCardGoodsSkuService.setOrUpdateGiftCardSku(giftCardSku);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 修改礼品卡 规格
+	 */
+	@PutMapping("/put")
+	public Result<String> updateGiftCardSku(@RequestBody GiftCardGoodsSku giftCardSku) {
+		if (giftCardSku.getId() == null) {
+			throw BusinessRuntimeException.getInstance("请指定要修改的礼品卡");
+		}
+		giftCardGoodsSkuService.setOrUpdateGiftCardSku(giftCardSku);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 获取礼品卡规格 配置
+	 */
+	@GetMapping("/get")
+	public Result<SearchResult<GiftCardGoodsSkuView>> getGiftCardGoodsSku() {
+		SearchResult<GiftCardGoodsSkuView> list = beanSearcher.search(GiftCardGoodsSkuView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+	}
+
+	/**
+	 * 礼品卡用户购买记录
+	 */
+	@GetMapping("/get/pay")
+	public Result<SearchResult<GiftCardUserPayView>> getGiftCardPayRecord() {
+		SearchResult<GiftCardUserPayView> search = beanSearcher.search(GiftCardUserPayView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+}

+ 1 - 7
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -15,7 +15,6 @@ import com.cyksj.config.zfb.ZfbProductCode;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.enums.GatewayResponse;
-import com.cyksj.mapper.OrderDonMapper;
 import com.cyksj.mapper.OrderDonWaybillMapper;
 import com.cyksj.mapper.UserMapper;
 import com.cyksj.mapper.channel.UserPayEquipmentAvailableBenefitsMapper;
@@ -87,9 +86,6 @@ public class OrderController {
     @Resource
     private HttpServletResponse response;
 
-    @Autowired
-    private OrderDonMapper orderDonMapper;
-
     @Autowired
     private UserBindDetailMapper userBindDetailMapper;
 
@@ -128,9 +124,7 @@ public class OrderController {
     @PostMapping("/post/submit")
     public Result<OrderDon> submit(@Validated @RequestBody OrderPayRequest payRequest) throws Exception {
         final String methodName = "吊起微信支付";
-        if (payRequest.getIsNoLogin() == null || !payRequest.getIsNoLogin()) {
-            payRequest.setUserId(StpUserUtil.getLoginIdAsLong());
-        }
+        payRequest.setUserId(StpUserUtil.getUserIdAfterLogin());
         log.info("{}[start] params:{}",methodName,payRequest);
 
         OrderDon orderDon = orderDonService.submit(payRequest);

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

@@ -110,9 +110,13 @@ public class DistributePopularizeController {
 		BigDecimal oneHundred = BigDecimal.valueOf(100);
 		search.getDataList().forEach(data -> {
 			GoodsDon goodsDon = goodsDonMapper.selectById(data.getGoodsId());
-			GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(data.getSkuId());
 			data.setGoodsTitle(goodsDon.getTitle());
-			data.setSpecVal(goodsDonSku.getSpecVal());
+			if (StrUtil.isEmpty(data.getSpecVal())) {
+				GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(data.getSkuId());
+				if (goodsDonSku != null) {
+					data.setSpecVal(goodsDonSku.getSpecVal());
+				}
+			}
 			data.setWaitGetMoney(data.getPoints().divide(points).multiply(money).divide(oneHundred));
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);

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

@@ -338,4 +338,43 @@ public class UserController {
         UserAuthLoginResp loginPhoneRep = new UserAuthLoginResp(StpUserUtil.getTokenValue(), switch_user.getShowId(), switch_user.getNickname(), switch_user.getHeadimgurl());
         return GatewayResponse.SUCCESS.newBuilder().toResult(loginPhoneRep);
     }
+
+    /**
+     * 个人礼品卡列表
+     * @param type 1自购,2、获赠
+     * @return
+     */
+    @GetMapping("/get/giftCard")
+    public Result<SearchResult<GiftCardUserPayFrontView>> getGiftCard(@RequestParam(defaultValue = "1") Integer type) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        String condition = StrUtil.EMPTY;
+        if (type == 1) {
+            condition += String.format("and user_id = %s", userId);
+        } else {
+            condition += String.format("and to_user_id = %s", userId);
+        }
+        SearchResult<GiftCardUserPayFrontView> view = beanSearcher.search(GiftCardUserPayFrontView.class, MapUtils.builder()
+                .put("condition", condition)
+                .orderBy(GiftCardUserPayFrontView::getId).desc().build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(view);
+    }
+
+    /**
+     * 礼品卡分享详情
+     */
+    @GetMapping("/get/giftCard/detail/{code}")
+    public Result<GiftCardDetailFrontView> getGiftCardDetailByCode(@PathVariable String code) {
+        GiftCardDetailFrontView detail = beanSearcher.searchFirst(GiftCardDetailFrontView.class, MapUtils.builder().field(GiftCardDetailFrontView::getCode, code).build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(detail);
+    }
+
+    /**
+     * 领取他人礼品卡
+     */
+    @PostMapping("/receive/giftCard/{code}")
+    public Result<String> receiveGiftCardByRc(@PathVariable String code) {
+        long userId = 32121l;
+        userService.receiveGiftCardByRc(userId, code);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
 }

+ 7 - 0
netflix-web/src/main/java/com/cyksj/web/util/StpUserUtil.java

@@ -86,6 +86,13 @@ public class StpUserUtil {
         return stpLogic.isLogin();
     }
 
+    public static Long getUserIdAfterLogin() {
+        if (isLogin()) {
+            return StpUserUtil.getLoginIdAsLong();
+        }
+        return null;
+    }
+
     public static void checkLogin() {
         stpLogic.checkLogin();
     }