Ver Fonte

银河币功能

zoujiajian há 1 ano atrás
pai
commit
f3d30d3f9d
55 ficheiros alterados com 1624 adições e 189 exclusões
  1. 10 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 10 0
      netflix-common/src/main/java/com/cyksj/common/constant/PointsRecordConst.java
  3. 4 9
      netflix-common/src/main/java/com/cyksj/common/util/SmsUtil.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonGalaxyCoinRecordMapper.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/OrderDonGalaxyCoinRenewRelateMapper.java
  6. 21 0
      netflix-dao/src/main/java/com/cyksj/mapper/UserGalaxyCoinRecordMapper.java
  7. 2 2
      netflix-dao/src/main/java/com/cyksj/mapper/UserMapper.java
  8. 0 32
      netflix-dao/src/main/java/com/cyksj/mapper/market/sign/UserPointsRecordMapper.java
  9. 20 0
      netflix-dao/src/main/java/com/cyksj/model/dto/GalaxyCoinConsumeRateDto.java
  10. 31 0
      netflix-dao/src/main/java/com/cyksj/model/dto/GalaxyCoinPayConfigDto.java
  11. 47 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonGalaxyCoinRecord.java
  12. 17 0
      netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonGalaxyCoinRenewRelate.java
  13. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/TaskFollowPlatVerify.java
  14. 5 0
      netflix-dao/src/main/java/com/cyksj/model/entity/TaskType.java
  15. 4 1
      netflix-dao/src/main/java/com/cyksj/model/entity/User.java
  16. 3 1
      netflix-dao/src/main/java/com/cyksj/model/entity/UserBalanceSourceRecord.java
  17. 45 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UserGalaxyCoinRecord.java
  18. 0 15
      netflix-dao/src/main/java/com/cyksj/model/entity/UserPointsRecord.java
  19. 22 1
      netflix-dao/src/main/java/com/cyksj/model/entity/VipOrderDon.java
  20. 3 3
      netflix-dao/src/main/java/com/cyksj/model/manage/views/MaliceUserView.java
  21. 12 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonBackView.java
  22. 3 3
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UserView.java
  23. 21 0
      netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java
  24. 15 2
      netflix-dao/src/main/java/com/cyksj/model/request/OrderRefundReq.java
  25. 5 3
      netflix-dao/src/main/java/com/cyksj/model/request/TaskFollowReq.java
  26. 6 0
      netflix-dao/src/main/java/com/cyksj/model/request/VipOrderDonPayReq.java
  27. 12 0
      netflix-dao/src/main/java/com/cyksj/model/views/CmsVipOrderDonView.java
  28. 148 0
      netflix-dao/src/main/java/com/cyksj/model/views/GalaxyCoinRenewTicketsView.java
  29. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/RefundOrderDonView.java
  30. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/RefundUpdradeOrderDonView.java
  31. 3 0
      netflix-dao/src/main/java/com/cyksj/model/views/TaskFollowVerifyView.java
  32. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/TaskFrontView.java
  33. 7 2
      netflix-dao/src/main/java/com/cyksj/model/views/UserPersonalView.java
  34. 6 0
      netflix-dao/src/main/java/com/cyksj/model/views/UserSyncInfoView.java
  35. 2 1
      netflix-dao/src/main/resources/mapper/CouponUserMapper.xml
  36. 28 0
      netflix-service/src/main/java/com/cyksj/service/coin/UserGalaxyCoinService.java
  37. 237 0
      netflix-service/src/main/java/com/cyksj/service/coin/impl/UserGalaxyCoinServiceImpl.java
  38. 2 0
      netflix-service/src/main/java/com/cyksj/service/exchange/impl/ExchangeCodeServiceImpl.java
  39. 83 18
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  40. 52 14
      netflix-service/src/main/java/com/cyksj/service/mange/vip/impl/CmsVipOrderServiceImpl.java
  41. 0 5
      netflix-service/src/main/java/com/cyksj/service/market/MarketFrontService.java
  42. 15 27
      netflix-service/src/main/java/com/cyksj/service/market/impl/MarketFrontServiceImpl.java
  43. 0 2
      netflix-service/src/main/java/com/cyksj/service/market/task/TaskService.java
  44. 3 17
      netflix-service/src/main/java/com/cyksj/service/market/task/impl/TaskServiceImpl.java
  45. 324 9
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  46. 192 7
      netflix-service/src/main/java/com/cyksj/service/order/impl/VipOrderDonServiceImpl.java
  47. 2 0
      netflix-service/src/main/java/com/cyksj/service/user/impl/UserServiceImpl.java
  48. 96 0
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  49. 9 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  50. 12 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/vip/CmsVipController.java
  51. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/market/LuckyDrawFrontController.java
  52. 7 7
      netflix-web/src/main/java/com/cyksj/web/controller/market/SignFrontController.java
  53. 1 1
      netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java
  54. 10 6
      netflix-web/src/main/java/com/cyksj/web/controller/user/UserController.java
  55. 17 0
      netflix-web/src/main/java/com/cyksj/web/controller/vip/VipUserOrderController.java

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

@@ -616,4 +616,14 @@ public interface Constant {
 	 * 异常奈飞车票更换其他规格key
 	 */
 	String ERROR_NETFLIX_CHANGE_OTHER_SKU_KEY = "error_netflix_change_other_sku_key";
+
+	/**
+	 * 银河币消费返回比例
+	 */
+	String GALAXY_COIN_CONSUME_RETURN_RATE_KEY = "galaxy_coin_consume_return_rate_key";
+
+	/**
+	 * 银河币消费支付抵扣key
+	 */
+	String GALAXY_COIN_PAY_DEDUCT_KEY = "galaxy_coin_pay_deduct_key";
 }

+ 10 - 0
netflix-common/src/main/java/com/cyksj/common/constant/PointsRecordConst.java

@@ -8,4 +8,14 @@ public interface PointsRecordConst {
 	String POINTS_LOTTERY = "积分抽奖";
 
 	String TASK = "任务奖励";
+
+	String ORDER_CASHBACK = "下单奖励";
+
+	String ORDER = "下单";
+
+	String ORDER_REFUND = "订单退款";
+
+	String ORDER_CLOSE = "订单关闭";
+
+	String ORDER_REFUND_SUB = "订单退款扣除奖励";
 }

+ 4 - 9
netflix-common/src/main/java/com/cyksj/common/util/SmsUtil.java

@@ -112,16 +112,11 @@ public class SmsUtil {
     }
 
     public static Boolean sendTencent(Integer cid, String mobile, String msg) {
-//        String templateId = TENCENT_SMS_TEMPLATE_ID;
-//        if (cid != 86) {
-//            templateId = TENCENT_SMS_INTERNATIONAL_TEMPLATE_ID;
-//        }
-//        return commonSendTencentSmsMsg(templateId, cid, mobile, msg);
-        try {
-            return SmsUtil.sendLuoKey2Msg(mobile, String.format("尊敬的用户,您的验证码为%s,此验证码仅用于银河录像。【崇宇信息】", msg));
-        } catch (Exception e) {
+        String templateId = TENCENT_SMS_TEMPLATE_ID;
+        if (cid != 86) {
+            templateId = TENCENT_SMS_INTERNATIONAL_TEMPLATE_ID;
         }
-        return false;
+        return commonSendTencentSmsMsg(templateId, cid, mobile, msg);
     }
 
     public static Boolean sendAccountInternalSmsMsg(Integer cid, String mobile, String msg) {

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.OrderDonGalaxyCoinRecord;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: OrderDonGalaxyCoinRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/7/7 12:21
+ */
+public interface OrderDonGalaxyCoinRecordMapper extends BaseMapper<OrderDonGalaxyCoinRecord> {
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.OrderDonGalaxyCoinRenewRelate;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: OrderDonGalaxyCoinRenewRelateMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/7/14 11:11
+ */
+public interface OrderDonGalaxyCoinRenewRelateMapper extends BaseMapper<OrderDonGalaxyCoinRenewRelate> {
+}

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/mapper/UserGalaxyCoinRecordMapper.java

@@ -0,0 +1,21 @@
+package com.cyksj.mapper;
+
+import cn.hutool.core.date.DateTime;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.UserGalaxyCoinRecord;
+import org.apache.ibatis.annotations.Param;
+import org.apache.ibatis.annotations.Select;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserGalaxyCoinRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2025/7/7 15:19
+ */
+public interface UserGalaxyCoinRecordMapper extends BaseMapper<UserGalaxyCoinRecord> {
+
+	@Select("select sum(remain_galaxy_coin) from user_galaxy_coin_record where user_id = #{userId} and is_expired is false and expiry_time <= #{expiryTime}")
+	BigDecimal selectExpiredGalaxyCoinAfterDays(@Param("userId") Long userId, @Param("expiryTime") DateTime expiryTime);
+}

+ 2 - 2
netflix-dao/src/main/java/com/cyksj/mapper/UserMapper.java

@@ -28,8 +28,8 @@ public interface UserMapper extends BaseMapper<User> {
     @Update("update user set points = points + #{addPoints} where id = #{id} and points = #{originalPoints}")
     Integer updatePoints(@Param("id") Long id, @Param("originalPoints") BigDecimal originalPoints, @Param("addPoints") BigDecimal addPoints);
 
-    @Update("update user set active_points = active_points - #{subPoints} where active_points > 0 and active_points >= #{subPoints} and id = #{userId}")
-    Integer subActivePoints(@Param("userId") Long userId, @Param("subPoints") BigDecimal subPoints);
+    @Update("update user set galaxy_coin = galaxy_coin - #{subGalaxyCoin} where galaxy_coin = #{userGalaxyCoin} and galaxy_coin >= #{subGalaxyCoin} and id = #{userId}")
+    Integer subUserGalaxyCoin(@Param("userId") Long userId, @Param("subGalaxyCoin") BigDecimal subGalaxyCoin, @Param("userGalaxyCoin") BigDecimal userGalaxyCoin);
 
     @Select("select id from user where nickname like concat('%',#{nickname},'%')")
     List<Long> selectListByNickname(String nickname);

+ 0 - 32
netflix-dao/src/main/java/com/cyksj/mapper/market/sign/UserPointsRecordMapper.java

@@ -1,32 +0,0 @@
-package com.cyksj.mapper.market.sign;
-
-import com.baomidou.mybatisplus.core.mapper.BaseMapper;
-import com.cyksj.model.entity.UserPointsRecord;
-import org.apache.ibatis.annotations.Param;
-import org.apache.ibatis.annotations.Select;
-import org.apache.ibatis.annotations.Update;
-
-import java.util.Date;
-
-public interface UserPointsRecordMapper extends BaseMapper<UserPointsRecord> {
-	@Update("update user set active_points = active_points + #{points} where id = #{userId}")
-	void updateUserPoints(@Param("userId") Long userId, @Param("points") Integer points);
-
-	@Select("select ifnull(sum(points),0) from user_points_record ur where created_time between #{yesZeroDate} and #{thisZeroDate} and points > 0")
-	Integer getTodayNumOfPoints(@Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
-
-	@Select("select ifnull(sum(points),0) from user_points_record ur where points > 0")
-	Integer getSumOfPoints();
-
-	@Select("select ifnull(sum(points),0) from user_points_record ur where created_time between #{yesZeroDate} and #{thisZeroDate} and points < 0")
-	Integer getTodayUseOfPoints(@Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
-
-	@Select("select ifnull(sum(points),0) from user_points_record ur where points < 0")
-	Integer getSumUseOfPoints();
-
-	@Select("select count(*) from user_points_record ur where created_time between #{yesZeroDate} and #{thisZeroDate} and points < 0 and remark = #{remark}")
-	Integer getTodayNumOfLottery(@Param("remark") String remark, @Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
-
-	@Select("select count(*) from sign_user where update_time between #{yesZeroDate} and #{thisZeroDate} and day_period = #{dayPeriod}")
-	Integer getSignDayByCondition(@Param("dayPeriod") Integer dayPeriod, @Param("yesZeroDate") Date yesZeroDate, @Param("thisZeroDate") Date thisZeroDate);
-}

+ 20 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/GalaxyCoinConsumeRateDto.java

@@ -0,0 +1,20 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GalaxyCoinConsumeRateDto
+ * 创建者: JavaZou
+ * 创建时间:2025/7/1 11:54
+ */
+@Getter
+@Setter
+public class GalaxyCoinConsumeRateDto {
+	private BigDecimal money;
+
+	private BigDecimal galaxyCoin;
+}

+ 31 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/GalaxyCoinPayConfigDto.java

@@ -0,0 +1,31 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GalaxyCoinPayConfigDto
+ * 创建者: JavaZou
+ * 创建时间:2025/7/1 17:45
+ */
+@Getter
+@Setter
+public class GalaxyCoinPayConfigDto {
+	/**
+	 * 按多以银河币抵扣
+	 */
+	private BigDecimal galaxyCoin;
+
+	/**
+	 * 抵扣比例金额
+	 */
+	private BigDecimal money;
+
+	/**
+	 * 最多可抵扣商品总价的比例
+	 */
+	private BigDecimal maxRate;
+}

+ 47 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonGalaxyCoinRecord.java

@@ -0,0 +1,47 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: OrderDonGalaxyCoinRecord
+ * 创建者: JavaZou
+ * 创建时间:2025/7/7 12:20
+ */
+@Getter
+@Setter
+public class OrderDonGalaxyCoinRecord extends BaseEntity{
+	private Long orderId;
+
+	private String orderNo;
+
+	private Long userId;
+
+	private BigDecimal galaxyCoin;
+
+	private BigDecimal deductMoney;
+
+	private BigDecimal refundGalaxyCoin;
+
+	/**
+	 * 0.普通订单 1.会员订单 2.套餐升级订单
+	 */
+	private Integer source;
+
+
+	@Getter
+	public enum Source{
+		ordinary("普通订单"),
+		vip("会员订单"),
+		upgrade("套餐升级订单"),
+		;
+		String desc;
+
+		Source(String desc) {
+			this.desc = desc;
+		}
+	}
+}

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/OrderDonGalaxyCoinRenewRelate.java

@@ -0,0 +1,17 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: OrderDonGalaxyCoinRenewRelate
+ * 创建者: JavaZou
+ * 创建时间:2025/7/14 11:10
+ */
+@Getter
+@Setter
+public class OrderDonGalaxyCoinRenewRelate extends BaseEntity{
+
+	private Long orderId;
+}

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

@@ -22,6 +22,11 @@ public class TaskFollowPlatVerify extends BaseEntity {
 
 	private String platNickname;
 
+	/**
+	 * 推广贴链接
+	 */
+	private String link;
+
 	private String img;
 
 	private Status status;

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

@@ -13,4 +13,9 @@ import lombok.Setter;
 @Setter
 public class TaskType extends BaseEntity{
 	private String name;
+
+	/**
+	 * 是否需要审核 默认false
+	 */
+	private Boolean isVerify;
 }

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

@@ -55,7 +55,10 @@ public class User extends BaseEntity implements Serializable{
 
     private BigDecimal points;
 
-    private BigDecimal activePoints;
+    /**
+     * 银河币
+     */
+    private BigDecimal galaxyCoin;
 
     /**
      * 余额 分

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

@@ -33,6 +33,7 @@ public class UserBalanceSourceRecord extends BaseEntity {
 	public enum Source {
 		payment("购买"),
 		refund("退款"),
+		order_close("订单关闭"),
 		clear_valid("未到期车票清除"),
 		ds_transport("分销实物发货"),
 		follow_task("关注引导"),
@@ -46,7 +47,8 @@ public class UserBalanceSourceRecord extends BaseEntity {
 		wholesale_order("批发订单"),
 		vip_order("会员下单"),
 		vip_refund("会员退款"),
-		TICKET_REPLACE("车票替换")
+		TICKET_REPLACE("车票替换"),
+		vip_order_close("会员订单关闭"),
 		;
 		String desc;
 

+ 45 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UserGalaxyCoinRecord.java

@@ -0,0 +1,45 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserGalaxyCoinRecord
+ * 创建者: JavaZou
+ * 创建时间:2025/7/7 15:14
+ */
+@Getter
+@Setter
+public class UserGalaxyCoinRecord extends BaseEntity{
+	private Long userId;
+
+	private Long orderId;
+
+	private BigDecimal galaxyCoin;
+
+	/**
+	 * 剩余可用银河币
+	 */
+	private BigDecimal remainGalaxyCoin;
+
+	/**
+	 * 是否已使用
+	 */
+	private Boolean isUsed;
+
+	/**
+	 * 过期时间
+	 */
+	private Date expiryTime;
+
+	/**
+	 *  0.普通订单 1.会员订单 2.套餐升级订单
+	 */
+	private Integer source;
+
+	private String remark;
+}

+ 0 - 15
netflix-dao/src/main/java/com/cyksj/model/entity/UserPointsRecord.java

@@ -1,15 +0,0 @@
-package com.cyksj.model.entity;
-
-
-import lombok.Getter;
-import lombok.Setter;
-
-@Getter
-@Setter
-public class UserPointsRecord extends BaseEntity{
-    private Long userId;
-
-    private Integer points;
-
-    private String remark;
-}

+ 22 - 1
netflix-dao/src/main/java/com/cyksj/model/entity/VipOrderDon.java

@@ -50,9 +50,29 @@ public class VipOrderDon extends BaseEntity{
 	 */
 	private String openId;
 
+	/**
+	 * 续费月数
+	 */
+	private Integer num;
+
 	/** 金额 */
 	private BigDecimal money;
 
+	/**
+	 * 抵扣金额
+	 */
+	private BigDecimal deductMoney;
+
+	/**
+	 * 实际可抵扣金额(超过)
+	 */
+	private BigDecimal actuallyDeductMoney;
+
+	/**
+	 * 超出抵扣会员可延长多少天
+	 */
+	private Integer extendsDays;
+
 	/**
 	 * 海外支付金额
 	 */
@@ -165,7 +185,8 @@ public class VipOrderDon extends BaseEntity{
 		ALI_PAY("zfb","支付宝"),
 		BALANCE("balance", "余额支付"),
 		PAYPAL("paypal","paypal支付"),
-		STRIPE("stripe","stripe支付")
+		STRIPE("stripe","stripe支付"),
+		GALAXY_COIN("galaxy_coin","银河币支付"),
 		;
 		String type;
 		String desc;

+ 3 - 3
netflix-dao/src/main/java/com/cyksj/model/manage/views/MaliceUserView.java

@@ -83,10 +83,10 @@ public class MaliceUserView {
 	private String email;
 
 	/**
-	 * 活跃抽奖积分
+	 * 银河币
 	 */
-	@DbField("u.active_points")
-	private BigDecimal activePoints;
+	@DbField("u.galaxy_coin")
+	private BigDecimal galaxyCoin;
 
 	@DbField("u.register_env")
 	private String registerEnv;

+ 12 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/OrderDonBackView.java

@@ -129,6 +129,18 @@ public class OrderDonBackView {
 	@DbField("o.refund_money")
 	private BigDecimal refundMoney;
 
+	/**
+	 * 银河币
+	 */
+	@DbIgnore
+	private BigDecimal galaxyCoin;
+
+	/**
+	 * 银河币抵扣金额
+	 */
+	@DbIgnore
+	private BigDecimal galaxyCoinDeductMoney;
+
 	@DbField("o.refund_balance")
 	private BigDecimal refundBalance;
 

+ 3 - 3
netflix-dao/src/main/java/com/cyksj/model/manage/views/UserView.java

@@ -83,10 +83,10 @@ public class UserView {
     private String email;
 
     /**
-     * 活跃抽奖积分
+     * 银河币
      */
-    @DbField("u.active_points")
-    private BigDecimal activePoints;
+    @DbField("u.galaxy_coin")
+    private BigDecimal galaxyCoin;
 
     @DbField("u.register_env")
     private String registerEnv;

+ 21 - 0
netflix-dao/src/main/java/com/cyksj/model/request/OrderPayRequest.java

@@ -107,6 +107,11 @@ public class OrderPayRequest {
      */
     private BigDecimal balance;
 
+    /**
+     * 银河币支付
+     */
+    private BigDecimal galaxyCoin;
+
     private String callback;
 
     private String callbackType;
@@ -208,4 +213,20 @@ public class OrderPayRequest {
      * 平台下单环境
      */
     private GoodsClickUserOrderRecord.EnvType envType;
+
+    /**
+     * 是否是银河币新入口续费
+     */
+    private RenewSource renewSource;
+
+    @Getter
+    public enum RenewSource{
+        galaxyCoin("银河币"),
+        ;
+        String desc;
+
+        RenewSource(String desc) {
+            this.desc = desc;
+        }
+    }
 }

+ 15 - 2
netflix-dao/src/main/java/com/cyksj/model/request/OrderRefundReq.java

@@ -32,7 +32,7 @@ public class OrderRefundReq {
 
 	/**
 	 * 退款类型
-	 * 订单金额、余额
+	 * 订单金额、余额、金额和余额混合bxj
 	 */
 	private String refundType;
 
@@ -69,4 +69,17 @@ public class OrderRefundReq {
 	 * 加购订单退款车票ids
 	 */
 	private List<Long> dpRelationIds;
-}
+
+	@Getter
+	public enum RefundType {
+		balance("余额退款"),
+		money("现金退款"),
+		bxj("余额现金"),
+		;
+		String desc;
+
+		RefundType(String desc) {
+			this.desc = desc;
+		}
+	}
+}

+ 5 - 3
netflix-dao/src/main/java/com/cyksj/model/request/TaskFollowReq.java

@@ -4,7 +4,6 @@ import lombok.Getter;
 import lombok.Setter;
 
 import javax.validation.constraints.Min;
-import javax.validation.constraints.NotEmpty;
 import javax.validation.constraints.NotNull;
 
 /*
@@ -31,14 +30,17 @@ public class TaskFollowReq {
 	/**
 	 * 所在平台昵称
 	 */
-	@NotEmpty(message = "昵称不能为空")
 	private String platNickname;
 
 	/**
 	 * 关注平台截图
 	 */
-	@NotEmpty(message = "截图不能为空")
 	private String img;
 
 	private Long userId;
+
+	/**
+	 * 推广贴链接
+	 */
+	private String link;
 }

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

@@ -65,4 +65,10 @@ public class VipOrderDonPayReq {
 	 * 是否抵扣
 	 */
 	private Boolean isDeduct = false;
+
+
+	/**
+	 * 银河币支付
+	 */
+	private BigDecimal galaxyCoin;
 }

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

@@ -90,4 +90,16 @@ public class CmsVipOrderDonView {
 
 	@DbField("o.created_time")
 	private Date createdTime;
+
+	/**
+	 * 银河币
+	 */
+	@DbIgnore
+	private BigDecimal galaxyCoin;
+
+	/**
+	 * 银河币抵扣金额
+	 */
+	@DbIgnore
+	private BigDecimal galaxyCoinDeductMoney;
 }

+ 148 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GalaxyCoinRenewTicketsView.java

@@ -0,0 +1,148 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GroupsRelation;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj11111111
+ * 文件名: GalaxyCoinRenewTicketsView
+ * 创建者: JavaZou
+ * 创建时间:2025/7/14 11:26
+ */
+@Getter
+@Setter
+@SearchBean(tables = "groups_relation gr left join groups_trips gt on gt.id = gr.groups_id " +
+		"left join goods_don_sku sku on gt.sku_id = sku.id " +
+		"left join goods_don g on g.id = sku.goods_id ",
+		where = ":condition:")
+public class GalaxyCoinRenewTicketsView {
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("sku.id")
+	private Long skuId;
+
+	@DbField("g.status")
+	private Boolean goodsStatus;
+
+	@DbField("sku.status")
+	private Boolean skuStatus;
+
+	@DbField("sku.months")
+	private Integer months;
+
+	@DbField("sku.days")
+	private Integer days;
+
+	@DbField("sku.num")
+	private Integer skuNum;
+
+	/**
+	 * 二级分类
+	 * 虚物品 1邀请制 2非邀请制
+	 */
+	@DbField("g.second_type")
+	private Integer secondType;
+
+	/**
+	 * 是否是多人规格
+	 */
+	@DbIgnore
+	private Boolean isMulti;
+
+	@DbField("sku.is_mirror")
+	private Boolean isMirror;
+
+	@DbField("sku.price")
+	private BigDecimal price;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("gr.id")
+	private Long relationId;
+
+	@DbField("gr.num")
+	private Integer num;
+
+	@DbField("gr.groups_id")
+	private Long groupId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.logo")
+	private String logo;
+
+	@DbField("g.img")
+	private String img;
+
+	@DbField("g.type")
+	@JsonIgnore
+	private Integer goodsType;
+
+	@DbField("gr.user_id")
+	@JsonIgnore
+	private Long userId;
+
+	@DbField("gr.start_time")
+	private Date startTime;
+
+	@DbField("gr.expiry_time")
+	private Date expiryTime;
+
+	@DbField("gr.status")
+	private String status;
+
+	/**
+	 * 店铺id
+	 */
+	@DbField("gr.yhs_id")
+	private Long yhsId;
+
+	/**
+	 * 店铺类型
+	 * 0无 1.普通店铺 2.镜像店铺
+	 */
+	@DbField("gr.cmt")
+	private Integer cmt;
+
+	/**
+	 * 车票获取类型 默认1购买,2.体验 3.镜像裂变
+	 */
+	@DbField("gr.aq_type")
+	private Integer aqType;
+
+	/**
+	 * 是否是VIP
+	 */
+	@DbField("gr.is_vip")
+	private Boolean isVip;
+
+	/**
+	 * 代充类型
+	 */
+	@DbField("gr.recharge_status")
+	private GroupsRelation.RechargeStatus rechargeStatus;
+
+	@DbIgnore
+	private String remainDays;
+
+	@DbField("gt.status")
+	private String groupsStatus;
+
+	/**
+	 * 最高抵扣可用银河币
+	 */
+	@DbIgnore
+	private BigDecimal maxGalaxyCoinDeduct = BigDecimal.ZERO;
+}

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

@@ -52,6 +52,12 @@ public class RefundOrderDonView {
 	@DbField("rd.refund_fee")
 	private BigDecimal refundMoney;
 
+	/**
+	 * 退款余额
+	 */
+	@DbField("rd.refund_balance")
+	private BigDecimal refundBalance;
+
 	@DbField("rd.goods_id")
 	private Long goodsId;
 

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

@@ -56,6 +56,12 @@ public class RefundUpdradeOrderDonView {
 	@DbField("rd.refund_fee")
 	private BigDecimal refundMoney;
 
+	/**
+	 * 退款余额
+	 */
+	@DbField("rd.refund_balance")
+	private BigDecimal refund_balance;
+
 	@DbField("rd.package_id")
 	private Long packageId;
 

+ 3 - 0
netflix-dao/src/main/java/com/cyksj/model/views/TaskFollowVerifyView.java

@@ -38,6 +38,9 @@ public class TaskFollowVerifyView {
 	@DbField("tv.img")
 	private String img;
 
+	@DbField("tv.link")
+	private String link;
+
 	@DbField("t.points")
 	private Integer points;
 

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

@@ -37,6 +37,12 @@ public class TaskFrontView {
 	@DbField("t.type_id")
 	private Long typeId;
 
+	/**
+	 * 是否需要审核 默认false
+	 */
+	@DbField("tt.is_verify")
+	private Boolean isVerify;
+
 	@DbField("t.description")
 	private String description;
 

+ 7 - 2
netflix-dao/src/main/java/com/cyksj/model/views/UserPersonalView.java

@@ -30,9 +30,14 @@ public class UserPersonalView {
 	private Integer numOfTickets;
 
 	/**
-	 * 我的积分
+	 * 我的银河币
 	 */
-	private BigDecimal activePoints;
+	private BigDecimal galaxyCoin;
+
+	/**
+	 * 30天内即将过期银河币
+	 */
+	private BigDecimal expiredGalaxyCoin;
 
 	/**
 	 * 我的余额

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

@@ -3,6 +3,7 @@ package com.cyksj.model.views;
 import lombok.Getter;
 import lombok.Setter;
 
+import java.math.BigDecimal;
 import java.util.Date;
 
 /**
@@ -29,4 +30,9 @@ public class UserSyncInfoView {
 	 * 会员过期时间
 	 */
 	private Date vipExpiryTime;
+
+	/**
+	 * 银河币
+	 */
+	private BigDecimal galaxyCoin;
 }

+ 2 - 1
netflix-dao/src/main/resources/mapper/CouponUserMapper.xml

@@ -295,7 +295,7 @@
                cu.valid_end_time,
                if(type = 'discount', sku.price * (1 - c.discount), c.reduce_money) as couponMoney
         from (select * from coupon_user where user_id = #{userId} and status = 'unused' and valid_start_time &lt; now() and valid_end_time > now()) cu
-                 inner join coupon c on c.id = cu.coupon_id
+                 inner join coupon c on c.id = cu.coupon_id and c.use_scope != 'renew'
                  inner join coupon_sku cs on cs.coupon_id = c.id and cs.goods_id = #{goodsId}
                  inner join goods_don_sku sku on sku.id = cs.sku_id and sku.status is true and sku.price = #{price}
         order by couponMoney desc limit 1
@@ -312,6 +312,7 @@
                  inner join coupon c on c.id = cu.coupon_id
                  inner join coupon_sku cs on cs.coupon_id = c.id and cs.sku_id = #{skuId}
                  inner join goods_don_sku sku on sku.id = cs.sku_id and sku.status is true
+        and c.use_scope != 'renew'
         order by couponMoney desc limit 1
     </select>
 </mapper>

+ 28 - 0
netflix-service/src/main/java/com/cyksj/service/coin/UserGalaxyCoinService.java

@@ -0,0 +1,28 @@
+package com.cyksj.service.coin;
+
+import com.cyksj.model.entity.OrderDonGalaxyCoinRecord;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserGalaxyCoinService
+ * 创建者: JavaZou
+ * 创建时间:2025/7/1 15:29
+ */
+public interface UserGalaxyCoinService {
+
+	void sendGalaxyCoinRecord(Long userId, Integer galaxyCoin, String remark, Boolean isLottery);
+
+	void recordUseRecord(Long orderId, Long userId, BigDecimal galaxyCoin, String remark, Boolean available, OrderDonGalaxyCoinRecord.Source source);
+
+	void recordOrderRefundGalaxyCoinIfValid(Long orderId, Long userId, BigDecimal galaxyCoin, OrderDonGalaxyCoinRecord.Source source);
+
+	void subOrderGenerateGalaxyCoin(Long orderId, OrderDonGalaxyCoinRecord.Source source);
+
+	void handleUserGalaxyCoinOrderNotify(Long orderId, Long userId, String orderNo, OrderDonGalaxyCoinRecord.Source source);
+
+	void sendOrderCashback(Long orderId, Long userId, Integer galaxyCoin, String remark, OrderDonGalaxyCoinRecord.Source source);
+
+	void sendOrderGalaxyCloseOrder(Long orderId, Long userId, BigDecimal galaxyCoin, OrderDonGalaxyCoinRecord.Source source);
+}

+ 237 - 0
netflix-service/src/main/java/com/cyksj/service/coin/impl/UserGalaxyCoinServiceImpl.java

@@ -0,0 +1,237 @@
+package com.cyksj.service.coin.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.constant.PointsRecordConst;
+import com.cyksj.mapper.OrderDonGalaxyCoinRecordMapper;
+import com.cyksj.mapper.UserGalaxyCoinRecordMapper;
+import com.cyksj.mapper.UserMapper;
+import com.cyksj.model.entity.OrderDonGalaxyCoinRecord;
+import com.cyksj.model.entity.User;
+import com.cyksj.model.entity.UserGalaxyCoinRecord;
+import com.cyksj.service.coin.UserGalaxyCoinService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: UserGalaxyCoinServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2025/7/1 15:29
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class UserGalaxyCoinServiceImpl implements UserGalaxyCoinService {
+	private final UserGalaxyCoinRecordMapper userGalaxyCoinRecordMapper;
+
+	private final UserMapper userMapper;
+
+	private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;
+
+	@Override
+	public void sendGalaxyCoinRecord(Long userId, Integer galaxyCoin, String remark, Boolean isLottery) {
+		if (!isLottery) {
+			sendGalaxyCoinHandle(userId, null, galaxyCoin, remark, true, true, null);
+		}
+	}
+
+	/**
+	 * @param isRecord  是否记录
+	 * @param available 该笔银河币是否可用
+	 */
+	public void sendGalaxyCoinHandle(Long userId, Long orderId, Integer galaxyCoin, String remark, Boolean isRecord, Boolean available, OrderDonGalaxyCoinRecord.Source source) {
+		//银河币为0不处理
+		if (galaxyCoin == 0) {
+			return;
+		}
+		while (true) {
+			User user = userMapper.selectById(userId);
+			if (user == null) {
+				log.error("用户:{}不存在,无法发送银河币", userId);
+				break;
+			}
+			BigDecimal userGalaxyCoin = user.getGalaxyCoin();
+			if (galaxyCoin < 0 && userGalaxyCoin.compareTo(BigDecimal.ZERO) == 0) {
+				log.info("用户:{}银河币数量为0,无法扣除", userId);
+				break;
+			}
+			BigDecimal needHandleGalaxyCoin = userGalaxyCoin.add(BigDecimal.valueOf(galaxyCoin));
+			BigDecimal finalRecordGalaxyCoin = BigDecimal.valueOf(galaxyCoin);
+			//不足部分 只扣除用户已有的银河币
+			if (needHandleGalaxyCoin.compareTo(BigDecimal.ZERO) < 0) {
+				needHandleGalaxyCoin = BigDecimal.ZERO;
+				//记录该笔银河币
+				if (finalRecordGalaxyCoin.compareTo(BigDecimal.ZERO) < 0) {
+					finalRecordGalaxyCoin = userGalaxyCoin.negate();
+				} else finalRecordGalaxyCoin = userGalaxyCoin;
+			}
+			int update = userMapper.update(null, Wrappers.lambdaUpdate(User.class)
+					.set(User::getGalaxyCoin, needHandleGalaxyCoin)
+					.eq(User::getId, user.getId())
+					.eq(User::getGalaxyCoin, userGalaxyCoin));
+			if (update == 1) {
+				if (isRecord) {
+					recordUseRecord(orderId, userId, finalRecordGalaxyCoin, remark, available, source);
+				}
+				break;
+			}
+		}
+	}
+
+	/**
+	 * 记录银河币详情
+	 */
+	@Override
+	public void recordUseRecord(Long orderId, Long userId, BigDecimal galaxyCoin, String remark, Boolean available, OrderDonGalaxyCoinRecord.Source source) {
+		UserGalaxyCoinRecord userGalaxyCoinRecord = new UserGalaxyCoinRecord();
+		userGalaxyCoinRecord.setOrderId(orderId);
+		userGalaxyCoinRecord.setUserId(userId);
+		userGalaxyCoinRecord.setGalaxyCoin(galaxyCoin);
+		userGalaxyCoinRecord.setRemainGalaxyCoin(userGalaxyCoinRecord.getGalaxyCoin());
+		//退款类型
+		if (StrUtil.equals(PointsRecordConst.ORDER_REFUND, remark)) {
+			//90天
+			userGalaxyCoinRecord.setExpiryTime(DateUtil.offsetDay(DateTime.now(), 90));
+		} else {
+			//年底失效
+			userGalaxyCoinRecord.setExpiryTime(DateUtil.offsetMonth(DateTime.now(), 12));
+		}
+		//下单 标记该笔银河币记录为已使用
+		//该银河币是否可用
+		if (!available) {
+			userGalaxyCoinRecord.setIsUsed(Boolean.TRUE);
+			//下单时,剩余是0
+			userGalaxyCoinRecord.setRemainGalaxyCoin(BigDecimal.ZERO);
+		}
+		if (source != null) {
+			userGalaxyCoinRecord.setSource(source.ordinal());
+		}
+		userGalaxyCoinRecord.setRemark(remark);
+		userGalaxyCoinRecordMapper.insert(userGalaxyCoinRecord);
+	}
+
+	@Override
+	public void recordOrderRefundGalaxyCoinIfValid(Long orderId, Long userId, BigDecimal galaxyCoin, OrderDonGalaxyCoinRecord.Source source) {
+		UserGalaxyCoinRecord userGalaxyCoinRecord = userGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+				.eq(UserGalaxyCoinRecord::getOrderId, orderId)
+				.eq(UserGalaxyCoinRecord::getRemark, PointsRecordConst.ORDER)
+				.last("limit 1"));
+		if (userGalaxyCoinRecord == null) {
+			log.info("订单:{}银河币使用记录不存在", orderId);
+			return;
+		}
+		if (userGalaxyCoinRecord.getExpiryTime().compareTo(DateTime.now()) < 0) {
+			log.info("该笔订单:{}银河币有效期:{}已过", orderId, userGalaxyCoinRecord.getExpiryTime());
+			return;
+		}
+		//发送银河币
+		sendGalaxyCoinHandle(userId, orderId, galaxyCoin.intValue(), PointsRecordConst.ORDER_REFUND, true, true, source);
+	}
+
+	@Override
+	public void subOrderGenerateGalaxyCoin(Long orderId, OrderDonGalaxyCoinRecord.Source source) {
+		UserGalaxyCoinRecord userGalaxyCoinRecord = userGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+				.eq(UserGalaxyCoinRecord::getOrderId, orderId)
+				.eq(UserGalaxyCoinRecord::getSource, source.ordinal())
+				.eq(UserGalaxyCoinRecord::getRemark, PointsRecordConst.ORDER_CASHBACK)
+				.last("limit 1"));
+		if (userGalaxyCoinRecord != null) {
+			BigDecimal galaxyCoin = userGalaxyCoinRecord.getGalaxyCoin();
+			//扣除记录 对应的银河币不可用
+			log.info("订单退款,扣除该笔订单oid:{}返现的银河币", orderId);
+			BigDecimal thisReturnRemainGalaxyCoin = userGalaxyCoinRecord.getRemainGalaxyCoin();
+			//扣除其他
+			if (thisReturnRemainGalaxyCoin.compareTo(galaxyCoin) < 0) {
+				//银河币抵扣
+				List<UserGalaxyCoinRecord> availableGalaxyCoinList = userGalaxyCoinRecordMapper.selectList(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+						.eq(UserGalaxyCoinRecord::getUserId, userGalaxyCoinRecord.getUserId())
+						.eq(UserGalaxyCoinRecord::getIsUsed, Boolean.FALSE)
+						.gt(UserGalaxyCoinRecord::getExpiryTime, DateTime.now())
+						.gt(UserGalaxyCoinRecord::getRemainGalaxyCoin, 0));
+				//需要使用的银河币
+				BigDecimal userFinalUseGalaxyCoin = galaxyCoin.subtract(thisReturnRemainGalaxyCoin);
+				for (UserGalaxyCoinRecord galaxyCoinRecord : availableGalaxyCoinList) {
+					if (userFinalUseGalaxyCoin.compareTo(BigDecimal.ZERO) <= 0) {
+						break;
+					}
+					BigDecimal remainGalaxyCoin = galaxyCoinRecord.getRemainGalaxyCoin();
+					Long galaxyCoinRecordId = galaxyCoinRecord.getId();
+					//扣完
+					if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) == 0) {
+						//完全抵扣
+						Integer update = deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
+						if (update == 1) {
+							userFinalUseGalaxyCoin = BigDecimal.ZERO;
+						}
+					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) < 0) {
+						//不足以抵扣
+						Integer update = deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
+						if (update == 1) {
+							userFinalUseGalaxyCoin = userFinalUseGalaxyCoin.subtract(remainGalaxyCoin);
+						}
+					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) > 0) {
+						//足以抵扣
+						Integer update = deductUserGalaxyCoin(galaxyCoinRecordId, userFinalUseGalaxyCoin, remainGalaxyCoin, false);
+						if (update == 1) {
+							userFinalUseGalaxyCoin = BigDecimal.ZERO;
+						}
+					}
+				}
+			}
+			sendGalaxyCoinHandle(userGalaxyCoinRecord.getUserId(), orderId, galaxyCoin.negate().intValue(), PointsRecordConst.ORDER_REFUND_SUB, true, false, source);
+			userGalaxyCoinRecord.setIsUsed(Boolean.TRUE);
+			userGalaxyCoinRecordMapper.updateById(userGalaxyCoinRecord);
+		}
+	}
+
+	/**
+	 * 订单回调时,扣除已使用的银河币 并记录使用记录
+	 */
+	@Override
+	public void handleUserGalaxyCoinOrderNotify(Long orderId, Long userId, String orderNo, OrderDonGalaxyCoinRecord.Source source) {
+		//银河币使用记录
+		OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = orderDonGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonGalaxyCoinRecord.class)
+				.eq(OrderDonGalaxyCoinRecord::getOrderNo, orderNo)
+				.eq(OrderDonGalaxyCoinRecord::getSource, source.ordinal())
+				.last("limit 1"));
+		if (orderDonGalaxyCoinRecord != null) {
+			//使用记录
+			recordUseRecord(orderId, userId, orderDonGalaxyCoinRecord.getGalaxyCoin().negate(), PointsRecordConst.ORDER, false, source);
+			orderDonGalaxyCoinRecord.setRefundGalaxyCoin(orderDonGalaxyCoinRecord.getGalaxyCoin());
+			orderDonGalaxyCoinRecord.setOrderId(orderId);
+			orderDonGalaxyCoinRecordMapper.updateById(orderDonGalaxyCoinRecord);
+		}
+	}
+
+	/**
+	 * 订单支付成功 返银河币
+	 */
+	@Override
+	public void sendOrderCashback(Long orderId, Long userId, Integer galaxyCoin, String remark, OrderDonGalaxyCoinRecord.Source source) {
+		sendGalaxyCoinHandle(userId, orderId, galaxyCoin, remark, true, true, source);
+	}
+
+	public void sendOrderGalaxyCloseOrder(Long orderId, Long userId, BigDecimal galaxyCoin, OrderDonGalaxyCoinRecord.Source source) {
+		sendGalaxyCoinHandle(userId, orderId, galaxyCoin.intValue(), PointsRecordConst.ORDER_CLOSE, true, true, source);
+	}
+
+	private Integer deductUserGalaxyCoin(Long galaxyCoinRecordId, BigDecimal deductGalaxyCoin, BigDecimal remainGalaxyCoin, boolean isUsed) {
+		Integer update = userGalaxyCoinRecordMapper.update(null, Wrappers.lambdaUpdate(UserGalaxyCoinRecord.class)
+				.set(UserGalaxyCoinRecord::getRemainGalaxyCoin, remainGalaxyCoin.subtract(deductGalaxyCoin))
+				.set(isUsed, UserGalaxyCoinRecord::getIsUsed, isUsed)
+				.eq(UserGalaxyCoinRecord::getId, galaxyCoinRecordId)
+				.eq(UserGalaxyCoinRecord::getIsUsed, Boolean.FALSE)
+				.eq(UserGalaxyCoinRecord::getRemainGalaxyCoin, remainGalaxyCoin));
+		if (update == 0) {
+			log.info("此次扣除银河币错误,继续扣除");
+		}
+		return update;
+	}
+}

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/exchange/impl/ExchangeCodeServiceImpl.java

@@ -248,6 +248,8 @@ public class ExchangeCodeServiceImpl extends ServiceImpl<ExchangeCodeMapper, Exc
 		exchangeCodeReq.setNumber(1);
 //		exchangeCodeReq.setGoodsId(goodsId);
 		exchangeCodeReq.setSkuIds(List.of(skuId).toString());
+		//兑换码
+		exchangeCodeReq.setCodeType(1);
 		if (type != null) {
 			exchangeCodeReq.setType(type);
 		}

+ 83 - 18
netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java

@@ -50,6 +50,7 @@ import com.cyksj.model.request.ClickOutReq;
 import com.cyksj.model.request.OrderBalanceRefundReq;
 import com.cyksj.model.request.OrderRefundReq;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.coin.UserGalaxyCoinService;
 import com.cyksj.service.coupon.CouponFontService;
 import com.cyksj.service.distribute.equipment.EquipmentDistributeService;
 import com.cyksj.service.giftcard.GiftCardOrderUseRecordService;
@@ -222,6 +223,10 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
     private final NetflixUserChangeOtherTicketRecordMapper netflixUserChangeOtherTicketRecordMapper;
 
+    private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;
+
+    private final UserGalaxyCoinService userGalaxyCoinService;
+
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
     @Override
@@ -566,9 +571,28 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
                 orderDon.setRefundBalance(orderDonRefundBalance.add(refundBalance));
             }
 
-            //若存在余额支付,退还余额
-            if (isOnly == null && orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
-                userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getBalance(), UserBalanceSourceRecord.Source.refund, 0L, orderDon.getId(), upgradePackage.getName() + UserBalanceSourceRecord.Source.refund.getDesc(), true);
+//            //若存在余额支付,退还余额
+//            if (isOnly == null && orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
+//                userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getBalance(), UserBalanceSourceRecord.Source.refund, 0L, orderDon.getId(), upgradePackage.getName() + UserBalanceSourceRecord.Source.refund.getDesc(), true);
+//            }
+
+            //是否全额退款
+//            BigDecimal orderDonRefundMoney = Optional.ofNullable(orderDon.getRefundMoney()).orElse(BigDecimal.ZERO);
+//            BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
+//            if (orderDonRefundMoney.add(orderDonRefundBalance).compareTo(orderDon.getMoney().add(Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO))) == 0) {
+//                //是否使用银河币支付
+//                OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = orderDonGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonGalaxyCoinRecord.class)
+//                        .eq(OrderDonGalaxyCoinRecord::getOrderId, orderDon.getId())
+//                        .eq(OrderDonGalaxyCoinRecord::getSource, OrderDonGalaxyCoinRecord.Source.upgrade.ordinal())
+//                        .last("limit 1"));
+//                if (orderDonGalaxyCoinRecord != null) {
+//                    //有效时,返还银河币 并记录
+//                    userGalaxyCoinService.recordOrderRefundGalaxyCoinIfValid(orderDon.getId(), orderDonGalaxyCoinRecord.getUserId(), orderDonGalaxyCoinRecord.getGalaxyCoin().abs(), OrderDonGalaxyCoinRecord.Source.upgrade);
+//                }
+//            }
+            //扣除 该笔订单产生的返现银河币
+            if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) {
+                userGalaxyCoinService.subOrderGenerateGalaxyCoin(orderDon.getId(), OrderDonGalaxyCoinRecord.Source.upgrade);
             }
 
             if (UpgradeOrderDon.Type.BALANCE.getType().equals(refundType)) {
@@ -578,6 +602,7 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             }
         });
     }
+
     /**
      * 校验订单是否符合退款操作
      */
@@ -588,9 +613,9 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         BigDecimal orderDonRefundMoney = Optional.ofNullable(orderDon.getRefundMoney()).orElse(BigDecimal.ZERO);
         BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
         String refundType = refundReq.getRefundType();
-        if (orderDon.getType() == UpgradeOrderDon.Type.BALANCE && !UpgradeOrderDon.Type.BALANCE.getType().equals(refundType)) {
-            throw BusinessRuntimeException.getInstance("余额支付的订单不支持金额退款");
-        }
+//        if (orderDon.getType() == UpgradeOrderDon.Type.BALANCE && !UpgradeOrderDon.Type.BALANCE.getType().equals(refundType)) {
+//            throw BusinessRuntimeException.getInstance("余额支付的订单不支持金额退款");
+//        }
         if (UpgradeOrderDon.Status.refund == orderDon.getStatus()) {
             throw BusinessRuntimeException.getInstance("该订单已退款");
         }
@@ -600,18 +625,29 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
         BigDecimal refundMoney = refundReq.getRefundMoney();
         BigDecimal money = orderDon.getMoney();
+        BigDecimal balance = orderDon.getBalance();
+        BigDecimal refundBalance = refundReq.getRefundBalance();
         //余额退款
         if (UpgradeOrderDon.Type.BALANCE.getType().equals(refundType)) {
-            BigDecimal balance = orderDon.getBalance();
             refundMoney = orderDonRefundBalance.add(refundMoney);
-            if (UpgradeOrderDon.Type.BALANCE == orderDon.getType() && refundMoney.compareTo(balance) > 0) {
-                throw BusinessRuntimeException.getInstance("退款余额大于订单支付余额");
-            }
             if (UpgradeOrderDon.Type.BALANCE != orderDon.getType() && refundMoney.compareTo(money) > 0) {
                 throw BusinessRuntimeException.getInstance("退款余额大于订单支付金额");
             }
             orderDon.setRefundBalance(refundMoney);
             orderDon.setRefundMoney(BigDecimal.ZERO);
+        } else if (OrderRefundReq.RefundType.bxj.name().equals(refundType)) {
+            balance = balance.add(money);
+            if (refundBalance.compareTo(balance) > 0) {
+                throw BusinessRuntimeException.getInstance("退款余额大于订单支付余额");
+            }
+            refundBalance = refundBalance.add(orderDonRefundBalance);
+            orderDon.setRefundBalance(refundBalance);
+
+            refundMoney = orderDonRefundMoney.add(refundMoney);
+            if (refundMoney.compareTo(money) > 0) {
+                throw BusinessRuntimeException.getInstance("退款金额大于订单支付金额");
+            }
+            orderDon.setRefundMoney(refundMoney);
         } else {
             //退金额
             refundMoney = orderDonRefundMoney.add(refundMoney);
@@ -921,9 +957,9 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         BigDecimal orderDonRefundMoney = Optional.ofNullable(orderDon.getRefundMoney()).orElse(BigDecimal.ZERO);
         BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
         String refundType = refundReq.getRefundType();
-        if (orderDon.getType() == OrderDon.Type.BALANCE && !OrderDon.Type.BALANCE.getType().equals(refundType)) {
-            throw BusinessRuntimeException.getInstance("余额支付的订单不支持金额退款");
-        }
+//        if (orderDon.getType() == OrderDon.Type.BALANCE && !OrderDon.Type.BALANCE.getType().equals(refundType)) {
+//            throw BusinessRuntimeException.getInstance("余额支付的订单不支持金额退款");
+//        }
         if (OrderDon.Status.refund == orderDon.getStatus()) {
             throw BusinessRuntimeException.getInstance("该订单已退款");
         }
@@ -968,19 +1004,29 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             }
         }
         BigDecimal refundMoney = refundReq.getRefundMoney();
+        BigDecimal refundBalance = refundReq.getRefundBalance();
         BigDecimal money = orderDon.getMoney();
+        BigDecimal balance = orderDon.getBalance();
         //余额退款
         if (OrderDon.Type.BALANCE.getType().equals(refundType)) {
-            BigDecimal balance = orderDon.getBalance();
             refundMoney = orderDonRefundBalance.add(refundMoney);
-            if (OrderDon.Type.BALANCE == orderDon.getType() && refundMoney.compareTo(balance) > 0) {
-                throw BusinessRuntimeException.getInstance("退款余额大于订单支付余额");
-            }
             if (OrderDon.Type.BALANCE != orderDon.getType() && refundMoney.compareTo(money) > 0) {
                 throw BusinessRuntimeException.getInstance("退款余额大于订单支付金额");
             }
             orderDon.setRefundBalance(refundMoney);
-            orderDon.setRefundMoney(BigDecimal.ZERO);
+        } else if (OrderRefundReq.RefundType.bxj.name().equals(refundType)) {
+            balance = balance.add(money);
+            if (refundBalance.compareTo(balance) > 0) {
+                throw BusinessRuntimeException.getInstance("退款余额大于订单总金额");
+            }
+            refundBalance = refundBalance.add(orderDonRefundBalance);
+            orderDon.setRefundBalance(refundBalance);
+
+            refundMoney = orderDonRefundMoney.add(refundMoney);
+            if (refundMoney.compareTo(money) > 0) {
+                throw BusinessRuntimeException.getInstance("退款金额大于订单支付金额");
+            }
+            orderDon.setRefundMoney(refundMoney);
         } else {
             //退金额
             refundMoney = orderDonRefundMoney.add(refundMoney);
@@ -1046,6 +1092,25 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
             }
             userBenefitsService.addUserBalance(orderDon.getUserId(), addBalance, UserBalanceSourceRecord.Source.refund, orderDon.getYhsId(), orderDon.getId(), goodsDon.getTitle() + UserBalanceSourceRecord.Source.refund.getDesc(), true);
         }
+        //是否全额退款
+//        BigDecimal orderDonRefundMoney = Optional.ofNullable(orderDon.getRefundMoney()).orElse(BigDecimal.ZERO);
+//        BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
+//        if (orderDonRefundMoney.add(orderDonRefundBalance).compareTo(orderDon.getMoney().add(Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO))) == 0) {
+//            //是否使用银河币支付
+//            OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = orderDonGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonGalaxyCoinRecord.class)
+//                    .eq(OrderDonGalaxyCoinRecord::getSource, OrderDonGalaxyCoinRecord.Source.ordinary.ordinal())
+//                    .eq(OrderDonGalaxyCoinRecord::getOrderId, orderDon.getId())
+//                    .last("limit 1"));
+//            if (orderDonGalaxyCoinRecord != null) {
+//                //有效时,返还银河币 并记录
+//                userGalaxyCoinService.recordOrderRefundGalaxyCoinIfValid(orderDon.getId(), orderDonGalaxyCoinRecord.getUserId(), orderDonGalaxyCoinRecord.getGalaxyCoin().abs(), OrderDonGalaxyCoinRecord.Source.ordinary);
+//            }
+//        }
+
+        //扣除 该笔订单产生的返现银河币
+        if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) {
+            userGalaxyCoinService.subOrderGenerateGalaxyCoin(orderDon.getId(), OrderDonGalaxyCoinRecord.Source.ordinary);
+        }
 
         try {
             marketFrontService.subSpecificChanceNum(orderDon.getUserId(), orderDon.getId(), orderDon.getGoodsId(), orderDon.getUpdateTime());

+ 52 - 14
netflix-service/src/main/java/com/cyksj/service/mange/vip/impl/CmsVipOrderServiceImpl.java

@@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.mapper.GroupsRelationMapper;
+import com.cyksj.mapper.OrderDonGalaxyCoinRecordMapper;
 import com.cyksj.mapper.manage.distribute.DistributeWaitingSendPointsMapper;
 import com.cyksj.mapper.manage.distribute.UserDistributeMapper;
 import com.cyksj.mapper.vip.RefundVipOrderDonMapper;
@@ -13,6 +14,7 @@ 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.service.coin.UserGalaxyCoinService;
 import com.cyksj.service.mange.vip.CmsVipOrderService;
 import com.cyksj.service.order.OrderRefundService;
 import com.cyksj.service.relation.GroupRelationClearService;
@@ -56,6 +58,10 @@ public class CmsVipOrderServiceImpl implements CmsVipOrderService {
 
 	private final UserDistributeMapper userDistributeMapper;
 
+	private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;
+
+	private final UserGalaxyCoinService userGalaxyCoinService;
+
 	@Override
 	public void refundOrders(OrderRefundReq refundReq) throws Exception {
 		VipOrderDon orderDon = vipOrderDonMapper.selectById(refundReq.getOrderId());
@@ -88,14 +94,33 @@ public class CmsVipOrderServiceImpl implements CmsVipOrderService {
 			orderDon.setRefundBalance(orderDonRefundBalance.add(refundBalance));
 		}
 		//若存在余额支付,退还余额
-		if (isOnly == null && orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
-			BigDecimal addBalance = orderDon.getBalance();
-			//需额外扣除余额
-			if (deductBalance != null && deductBalance.compareTo(BigDecimal.ZERO) > 0) {
-				addBalance = addBalance.subtract(deductBalance);
-			}
-			userBenefitsService.addUserBalance(orderDon.getUserId(), addBalance, UserBalanceSourceRecord.Source.vip_refund, null, orderDon.getId(), orderDon.getPayTitle() + UserBalanceSourceRecord.Source.vip_refund.getDesc(), true);
+//		if (isOnly == null && orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
+//			BigDecimal addBalance = orderDon.getBalance();
+//			//需额外扣除余额
+//			if (deductBalance != null && deductBalance.compareTo(BigDecimal.ZERO) > 0) {
+//				addBalance = addBalance.subtract(deductBalance);
+//			}
+//			userBenefitsService.addUserBalance(orderDon.getUserId(), addBalance, UserBalanceSourceRecord.Source.vip_refund, null, orderDon.getId(), orderDon.getPayTitle() + UserBalanceSourceRecord.Source.vip_refund.getDesc(), true);
+//		}
+		//是否全额退款
+//		BigDecimal orderDonRefundMoney = Optional.ofNullable(orderDon.getRefundMoney()).orElse(BigDecimal.ZERO);
+//		BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
+//		if (orderDonRefundMoney.add(orderDonRefundBalance).compareTo(orderDon.getMoney().add(Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO))) == 0) {
+//			//是否使用银河币支付
+//			OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = orderDonGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonGalaxyCoinRecord.class)
+//					.eq(OrderDonGalaxyCoinRecord::getSource, OrderDonGalaxyCoinRecord.Source.vip.ordinal())
+//					.eq(OrderDonGalaxyCoinRecord::getOrderId, orderDon.getId())
+//					.last("limit 1"));
+//			if (orderDonGalaxyCoinRecord != null) {
+//				//有效时,返还银河币 并记录
+//				userGalaxyCoinService.recordOrderRefundGalaxyCoinIfValid(orderDon.getId(), orderDonGalaxyCoinRecord.getUserId(), orderDonGalaxyCoinRecord.getGalaxyCoin().abs(), OrderDonGalaxyCoinRecord.Source.vip);
+//			}
+//		}
+		//扣除 该笔订单产生的返现银河币
+		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) {
+			userGalaxyCoinService.subOrderGenerateGalaxyCoin(orderDon.getId(), OrderDonGalaxyCoinRecord.Source.vip);
 		}
+
 		//扣除会员时长
 		List<Long> userIdList = userBindRelationService.getRelationUserIdList(orderDon.getUserId(), null);
 		VipUser vipUser = vipUserMapper.selectOne(Wrappers.lambdaQuery(VipUser.class)
@@ -206,9 +231,10 @@ public class CmsVipOrderServiceImpl implements CmsVipOrderService {
 			throw BusinessRuntimeException.getInstance("订单状态异常");
 		}
 		Long userId = orderDon.getUserId();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
 		//会员是否已过期
 		VipUser vipUser = vipUserMapper.selectOne(Wrappers.lambdaQuery(VipUser.class)
-				.eq(VipUser::getUserId, userId)
+				.in(VipUser::getUserId, userIdList)
 				.gt(VipUser::getExpiryTime, DateTime.now())
 				.last("limit 1"));
 		if (vipUser == null) {
@@ -216,22 +242,34 @@ public class CmsVipOrderServiceImpl implements CmsVipOrderService {
 		}
 		String refundType = refundReq.getRefundType();
 		BigDecimal refundMoney = refundReq.getRefundMoney();
+		BigDecimal refundBalance = refundReq.getRefundBalance();
 		BigDecimal money = orderDon.getMoney();
+		BigDecimal balance = orderDon.getBalance();
 		BigDecimal orderDonRefundMoney = Optional.ofNullable(orderDon.getRefundMoney()).orElse(BigDecimal.ZERO);
 		BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
 		//余额退款
 		if (OrderDon.Type.BALANCE.getType().equals(refundType)) {
-			BigDecimal balance = orderDon.getBalance();
 			refundMoney = orderDonRefundBalance.add(refundMoney);
-			if (VipOrderDon.Type.BALANCE == orderDon.getType() && refundMoney.compareTo(balance) > 0) {
-				throw BusinessRuntimeException.getInstance("退款余额大于订单支付余额");
-			}
 			if (VipOrderDon.Type.BALANCE != orderDon.getType() && refundMoney.compareTo(money) > 0) {
 				throw BusinessRuntimeException.getInstance("退款余额大于订单支付金额");
 			}
 			orderDon.setRefundBalance(refundMoney);
-			orderDon.setRefundMoney(BigDecimal.ZERO);
-		} else {
+		} else if (OrderRefundReq.RefundType.bxj.name().equals(refundType)) {
+			//该订单实际可抵扣金额 可退成余额
+			BigDecimal actuallyDeductMoney = Optional.ofNullable(orderDon.getActuallyDeductMoney()).orElse(BigDecimal.ZERO);
+			balance = balance.add(actuallyDeductMoney).add(money);
+			refundBalance = refundBalance.add(orderDonRefundBalance);
+			if (refundBalance.compareTo(balance) > 0) {
+				throw BusinessRuntimeException.getInstance("退款余额大于订单总金额");
+			}
+			orderDon.setRefundBalance(refundBalance);
+
+			refundMoney = orderDonRefundMoney.add(refundMoney);
+			if (refundMoney.compareTo(money) > 0) {
+				throw BusinessRuntimeException.getInstance("退款金额大于订单支付金额");
+			}
+			orderDon.setRefundMoney(refundMoney);
+		}else {
 			//退金额
 			refundMoney = orderDonRefundMoney.add(refundMoney);
 			if (refundMoney.compareTo(money) > 0) {

+ 0 - 5
netflix-service/src/main/java/com/cyksj/service/market/MarketFrontService.java

@@ -17,11 +17,6 @@ public interface MarketFrontService {
 
 	SignUser getUserSignDetail(Long userId);
 
-	/**
-	 * 记录积分明细,发放积分
-	 */
-	void pointsRecord(Long userId, Integer points, String remark, Boolean isLottery);
-
 	LuckyDrawView lottery(Long userId, LuckyDraw.DrawType drawType) throws Exception;
 
 	void receivedLuckyDraw(Long userId, LuckyDrawReq luckyDrawReq);

+ 15 - 27
netflix-service/src/main/java/com/cyksj/service/market/impl/MarketFrontServiceImpl.java

@@ -21,7 +21,6 @@ import com.cyksj.mapper.market.draw.LuckyDrawSpecificChanceMapper;
 import com.cyksj.mapper.market.draw.LuckyDrawSpecificChanceRecordMapper;
 import com.cyksj.mapper.market.sign.SignConfigMapper;
 import com.cyksj.mapper.market.sign.SignUserMapper;
-import com.cyksj.mapper.market.sign.UserPointsRecordMapper;
 import com.cyksj.mapper.market.task.TaskFollowPlatVerifyMapper;
 import com.cyksj.mapper.market.task.TaskUserCompleteRecordMapper;
 import com.cyksj.mapper.market.task.UserBindDetailMapper;
@@ -32,6 +31,7 @@ import com.cyksj.model.request.TaskFollowReq;
 import com.cyksj.model.views.LuckyDrawView;
 import com.cyksj.model.views.TaskFrontView;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.coin.UserGalaxyCoinService;
 import com.cyksj.service.exchange.ExchangeCodeService;
 import com.cyksj.service.mange.coupon.CouponCommonService;
 import com.cyksj.service.market.MarketFrontService;
@@ -61,8 +61,6 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 
 	private final SignConfigMapper signConfigMapper;
 
-	private final UserPointsRecordMapper userPointsRecordMapper;
-
 	private final SysConfigService sysConfigService;
 
 	private final UserMapper userMapper;
@@ -105,6 +103,8 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 
 	private final GroupRelationFrontService groupRelationFrontService;
 
+	private final UserGalaxyCoinService userGalaxyCoinService;
+
 	@Override
 	public SignUser signByUserId(Long userId) {
 		//第一次签到
@@ -163,20 +163,6 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 		return signUser;
 	}
 
-	@Override
-	public void pointsRecord(Long userId, Integer points, String remark, Boolean isLottery) {
-		UserPointsRecord userPointsRecord = new UserPointsRecord();
-		userPointsRecord.setUserId(userId);
-		userPointsRecord.setPoints(points);
-		userPointsRecord.setRemark(remark);
-		userPointsRecordMapper.insert(userPointsRecord);
-
-		if (!isLottery) {
-			//发放爱心
-			userPointsRecordMapper.updateUserPoints(userId, points);
-		}
-	}
-
 
 	@Override
 	@Transactional(rollbackFor = Throwable.class)
@@ -216,7 +202,7 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 		LuckyDrawRecord record = new LuckyDrawRecord();
 		BeanUtil.copyProperties(luckyDraw, record, "status");
 		if (luckyDraw.getType() == LuckyDraw.Type.points) {
-			pointsRecord(userId, luckyDraw.getPoints(), PointsRecordConst.LOTTERY, false);
+			userGalaxyCoinService.sendGalaxyCoinRecord(userId, luckyDraw.getPoints(), PointsRecordConst.LOTTERY, false);
 			record.setStatus(LuckyDrawRecord.Status.success);
 		} else if (luckyDraw.getType() == LuckyDraw.Type.coupon) {
 			//发放优惠券
@@ -309,7 +295,7 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 		if (data.getCouponId() != null && data.getCouponId() != 0) {
 			couponCommonService.sendCouponToUser(userId, data.getCouponId(), null, null, null, CouponUser.Channel.task);
 		}
-		pointsRecord(userId, data.getPoints(), PointsRecordConst.TASK, false);
+		userGalaxyCoinService.sendGalaxyCoinRecord(userId, data.getPoints(), PointsRecordConst.TASK, false);
 		//改变状态
 		TaskUserCompleteRecord record = new TaskUserCompleteRecord();
 		record.setId(data.getTaskCompleteRecordId());
@@ -325,7 +311,8 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 		Long userId = taskFollowReq.getUserId();
 		TaskFrontView data = beanSearcher.searchFirst(TaskFrontView.class, MapUtils.builder()
 				.field(TaskFrontView::getId, taskId).build());
-		if (!"关注引导".equals(data.getTypeName())) {
+		//非审核
+		if (!data.getIsVerify()) {
 			throw BusinessRuntimeException.getInstance("");
 		}
 		TaskFollowPlatVerify taskFollowPlatVerify = new TaskFollowPlatVerify();
@@ -333,6 +320,7 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 		taskFollowPlatVerify.setUserId(userId);
 		taskFollowPlatVerify.setPlatNickname(taskFollowReq.getPlatNickname());
 		taskFollowPlatVerify.setImg(taskFollowReq.getImg());
+		taskFollowPlatVerify.setLink(taskFollowReq.getLink());
 		try {
 			taskFollowPlatVerifyMapper.insert(taskFollowPlatVerify);
 			TaskUserCompleteRecord record = new TaskUserCompleteRecord();
@@ -427,7 +415,7 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 				points = signConfigMapper.selectOne(Wrappers.lambdaQuery(SignConfig.class)
 						.orderByAsc(SignConfig::getId).last("limit 1")).getMaxPoints();
 			}
-			pointsRecord(signUser.getUserId(), points, PointsRecordConst.SIGN, false);
+			userGalaxyCoinService.sendGalaxyCoinRecord(signUser.getUserId(), points, PointsRecordConst.SIGN, false);
 		}
 		signUser.setPoints(points);
 	}
@@ -602,16 +590,16 @@ public class MarketFrontServiceImpl implements MarketFrontService {
 	public void luckyDrawNormalCheck(Long userId) {
 		SysConfig lottery_points_limit = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class).eq(SysConfig::getSysKey, Constant.LOTTERY_POINTS_LIMIT).last("limit 1"));
 		User user = userMapper.selectById(userId);
-		BigDecimal subPoints = BigDecimal.valueOf(Long.parseLong(lottery_points_limit.getSysValue()));
-		if (user.getActivePoints().compareTo(subPoints) < 0) {
-			throw BusinessRuntimeException.getInstance("积分不足");
+		BigDecimal subGalaxyCoin = BigDecimal.valueOf(Long.parseLong(lottery_points_limit.getSysValue()));
+		if (user.getGalaxyCoin().compareTo(subGalaxyCoin) < 0) {
+			throw BusinessRuntimeException.getInstance("银河币不足");
 		}
 		//扣减积分
-		Integer sub = userMapper.subActivePoints(userId, subPoints);
+		Integer sub = userMapper.subUserGalaxyCoin(userId, subGalaxyCoin, user.getGalaxyCoin());
 		if (sub != 1) {
-			throw BusinessRuntimeException.getInstance("积分不足");
+			throw BusinessRuntimeException.getInstance("银河币不足");
 		}
-		pointsRecord(userId, -subPoints.intValue(), PointsRecordConst.POINTS_LOTTERY, true);
+		userGalaxyCoinService.sendGalaxyCoinRecord(userId, -subGalaxyCoin.intValue(), PointsRecordConst.POINTS_LOTTERY, true);
 	}
 
 	public List<Long> luckyDrawSpecificCheck(Long userId) throws Exception {

+ 0 - 2
netflix-service/src/main/java/com/cyksj/service/market/task/TaskService.java

@@ -20,6 +20,4 @@ public interface TaskService {
 	void completeTask(TaskType type, Long userId);
 
 	void batchVerifyFollow( List<TaskFollowPlatVerify> taskFollowPlatVerifyList);
-
-	void pointsRecord(Long userId, Integer points, String remark, Boolean isLottery);
 }

+ 3 - 17
netflix-service/src/main/java/com/cyksj/service/market/task/impl/TaskServiceImpl.java

@@ -10,13 +10,13 @@ import com.cyksj.common.constant.PointsRecordConst;
 import com.cyksj.common.constant.TaskTypeEnum;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.mapper.manage.distribute.UserDistributeSharedMapper;
-import com.cyksj.mapper.market.sign.UserPointsRecordMapper;
 import com.cyksj.mapper.market.task.TaskFollowPlatVerifyMapper;
 import com.cyksj.mapper.market.task.TaskMapper;
 import com.cyksj.mapper.market.task.TaskTypeMapper;
 import com.cyksj.mapper.market.task.TaskUserCompleteRecordMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.views.TaskView;
+import com.cyksj.service.coin.UserGalaxyCoinService;
 import com.cyksj.service.market.task.TaskService;
 import com.cyksj.service.user.UserBenefitsService;
 import com.ejlchina.searcher.BeanSearcher;
@@ -52,7 +52,7 @@ public class TaskServiceImpl implements TaskService {
 
 	private final TaskFollowPlatVerifyMapper taskFollowPlatVerifyMapper;
 
-	private final UserPointsRecordMapper userPointsRecordMapper;
+	private final UserGalaxyCoinService userGalaxyCoinService;
 
 	private final BeanSearcher beanSearcher;
 
@@ -149,7 +149,7 @@ public class TaskServiceImpl implements TaskService {
 					}
 					if (verifyStatus == success) {
 						record.setStatus(TaskUserCompleteRecord.Status.received);
-						this.pointsRecord(record.getUserId(), record.getPoints(), PointsRecordConst.TASK, false);
+						userGalaxyCoinService.sendGalaxyCoinRecord(record.getUserId(), record.getPoints(), PointsRecordConst.TASK, false);
 						TaskView taskView = beanSearcher.searchFirst(TaskView.class, MapUtils.builder().field(TaskView::getId, dbPlatVerify.getTaskId()).build());
 						if (taskView != null) {
 							if ("关注引导".equals(taskView.getTypeName()) && taskView.getBalance().compareTo(BigDecimal.ZERO) > 0) {
@@ -167,20 +167,6 @@ public class TaskServiceImpl implements TaskService {
 		});
 	}
 
-	@Override
-	public void pointsRecord(Long userId, Integer points, String remark, Boolean isLottery) {
-		UserPointsRecord userPointsRecord = new UserPointsRecord();
-		userPointsRecord.setUserId(userId);
-		userPointsRecord.setPoints(points);
-		userPointsRecord.setRemark(remark);
-		userPointsRecordMapper.insert(userPointsRecord);
-
-		if (!isLottery) {
-			//发放爱心
-			userPointsRecordMapper.updateUserPoints(userId, points);
-		}
-	}
-
 	public void checkTask(Task task) {
 		Long typeId = task.getTypeId();
 		TaskType taskType = taskTypeMapper.selectById(typeId);

+ 324 - 9
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -25,6 +25,7 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.cyksj.common.EnvCommonService;
 import com.cyksj.common.constant.Constant;
+import com.cyksj.common.constant.PointsRecordConst;
 import com.cyksj.common.constant.TaskTypeEnum;
 import com.cyksj.common.constant.TransferConstant;
 import com.cyksj.common.exception.BusinessRuntimeException;
@@ -77,6 +78,7 @@ import com.cyksj.model.manage.views.UpgradeOrderDetailView;
 import com.cyksj.model.request.*;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
+import com.cyksj.service.coin.UserGalaxyCoinService;
 import com.cyksj.service.corp.WxCorpOps;
 import com.cyksj.service.coupon.CouponFontService;
 import com.cyksj.service.distribute.UserBusinessFrontService;
@@ -370,6 +372,14 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	private final GoodsClickUserOrderRecordMapper goodsClickUserOrderRecordMapper;
 
+	private final UserGalaxyCoinService userGalaxyCoinService;
+
+	private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;
+
+	private final UserGalaxyCoinRecordMapper userGalaxyCoinRecordMapper;
+
+	private final OrderDonGalaxyCoinRenewRelateMapper orderDonGalaxyCoinRenewRelateMapper;
+
 	private final List<String> noChekGoodsTemp = List.of("Apple One", "Youtube", "Spotify");
 
 	@Transactional(rollbackFor = Throwable.class)
@@ -622,7 +632,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		if (sku != null) {
 			//扣除使用优惠券、余额的订单金额
-			deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon, payRequest.getGcCash(), payRequest.getGcpIds(), payRequest.getIsAcReduce(), subsidyId);
+			deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon, payRequest.getGcCash(), payRequest.getGcpIds(), payRequest.getIsAcReduce(), subsidyId, sku, payRequest.getGalaxyCoin());
 		}
 
 		if (isSpecificPrice && (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0 || orderDon.getMoney().compareTo(specificPrice) != 0)) {
@@ -643,6 +653,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		this.saveOrUpdate(orderDon);
 
 		Long orderId = orderDon.getId();
+		//使用银河币记录
+		userGalaxyCoinService.handleUserGalaxyCoinOrderNotify(orderDon.getId(), orderDon.getUserId(), orderDon.getOrderNo(), OrderDonGalaxyCoinRecord.Source.ordinary);
 		Long fUid = orderDon.getUserId();
 		if (orderDon.getIsDp() != null && orderDon.getIsDp()) {
 			//保存订单优惠加购规格 关系
@@ -798,6 +810,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		recordUserMirrorShopOrderRelate(orderId, payRequest.getUserId(), payRequest.getCmt(), payRequest.getCustomId());
 		//记录用户环境下单数据
 		recordEnvTypeOrderRelate(orderId, payRequest.getGoodsId(), payRequest.getEnvType());
+		//记录银河币新入口续费数据
+		recordOrderDonGalaxyCoinRenewRelate(orderId, payRequest.getRenewSource());
 	}
 
 	/**
@@ -841,6 +855,14 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 	}
 
+	private void recordOrderDonGalaxyCoinRenewRelate(Long orderId, OrderPayRequest.RenewSource renewSource) {
+		if (renewSource != null && renewSource == OrderPayRequest.RenewSource.galaxyCoin) {
+			OrderDonGalaxyCoinRenewRelate orderDonGalaxyCoinRenewRelate = new OrderDonGalaxyCoinRenewRelate();
+			orderDonGalaxyCoinRenewRelate.setOrderId(orderId);
+			orderDonGalaxyCoinRenewRelateMapper.insert(orderDonGalaxyCoinRenewRelate);
+		}
+	}
+
 	private Boolean checkIsNeedGroupsRelation(GoodsDon goodsDon) {
 		if (goodsDon.getType() == 1) {
 			//礼品卡特殊类型不需要车票
@@ -1057,7 +1079,16 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				}
 				//返还余额
 				if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
-					userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getBalance(), null, null, null, null, false);
+					userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getBalance(), UserBalanceSourceRecord.Source.order_close, null, orderId, UserBalanceSourceRecord.Source.order_close.getDesc(), true);
+				}
+
+				//返回银河币
+				UserGalaxyCoinRecord userGalaxyCoinRecord = userGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+						.eq(UserGalaxyCoinRecord::getOrderId, orderDon.getId())
+						.eq(UserGalaxyCoinRecord::getSource, OrderDonGalaxyCoinRecord.Source.ordinary.ordinal())
+						.last("limit 1"));
+				if (userGalaxyCoinRecord != null) {
+					userGalaxyCoinService.sendOrderGalaxyCloseOrder(orderDon.getId(), orderDon.getUserId(), userGalaxyCoinRecord.getGalaxyCoin().abs(), OrderDonGalaxyCoinRecord.Source.ordinary);
 				}
 
 				//是否是礼品卡 现金支付订单
@@ -1207,7 +1238,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//续费订单
 		orderDon.setOrderType(2);
 		orderDon.setStatus(OrderDon.Status.noPayment);
-		orderDon.setUserId(relation.getUserId());
+		orderDon.setUserId(userId);
 		//续费后 是否需要更换车票
 		if (isChangeTicket) {
 			orderDon.setIsChangeTicket(isChangeTicket);
@@ -1238,10 +1269,12 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			orderDon.setMoney(sku.getPrice().multiply(discount));
 		}
 		//扣除使用优惠券、余额的订单金额
-		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon, payRequest.getGcCash(), payRequest.getGcpIds(), false, null);
+		deductOrderMoney(orderDon, couponUser, payRequest.getBalance(), user, sku.getPrice(), goodsDon, payRequest.getGcCash(), payRequest.getGcpIds(), false, null, sku, payRequest.getGalaxyCoin());
 		this.saveOrUpdate(orderDon);
 
 		Long orderId = orderDon.getId();
+		//使用银河币记录
+		userGalaxyCoinService.handleUserGalaxyCoinOrderNotify(orderDon.getId(), orderDon.getUserId(), orderDon.getOrderNo(), OrderDonGalaxyCoinRecord.Source.ordinary);
 		//礼品卡现金使用记录
 		if (CollUtil.isNotEmpty(orderDon.getGcUseRecords())) {
 			orderDon.getGcUseRecords().forEach(data -> {
@@ -2484,7 +2517,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 	/**
 	 * 使用优惠营销 订单金额抵扣
 	 */
-	public void deductOrderMoney(OrderDon orderDon, CouponUser couponUser, BigDecimal balance, User user, BigDecimal skuMoney, GoodsDon goodsDon, BigDecimal gcCash, List<Long> gcpIds, Boolean isAcReduce, Long subsidyId) throws Exception {
+	public void deductOrderMoney(OrderDon orderDon, CouponUser couponUser, BigDecimal balance, User user, BigDecimal skuMoney, GoodsDon goodsDon, BigDecimal gcCash, List<Long> gcpIds, Boolean isAcReduce, Long subsidyId, GoodsDonSku sku, BigDecimal galaxyCoin) throws Exception {
 		Integer goodsType = goodsDon.getType();
 		if (gcCash != null && gcCash.compareTo(BigDecimal.ZERO) > 0 && couponUser != null && (balance != null && balance.compareTo(BigDecimal.ZERO) > 0)) {
 			throw BusinessRuntimeException.getInstance("现金卡不能与其他优惠叠加使用");
@@ -2660,10 +2693,112 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		if (goodsDon.getIsThirdGoods()) {
 			return;
 		}
+		//存在银河币
+		deductGalaxyCoinPayOrderMoney(orderDon, sku.getPrice(), galaxyCoin, user);
 		//存在余额
 		deductBalancePayOrderMoney(orderDon, balance, user);
 	}
 
+	public void deductGalaxyCoinPayOrderMoney(OrderDon orderDon, BigDecimal renewSkuDiscountPrice, BigDecimal toUseGalaxyCoin, User user) {
+		//存在银河币
+		if (toUseGalaxyCoin != null && toUseGalaxyCoin.compareTo(BigDecimal.ZERO) > 0) {
+			BigDecimal userGalaxyCoin = user.getGalaxyCoin();
+			if (userGalaxyCoin.compareTo(toUseGalaxyCoin) < 0) {
+				throw BusinessRuntimeException.getInstance("您的银河币不足!");
+			}
+			BigDecimal orderMoney = orderDon.getMoney();
+			//订单金额不大于0
+			if (orderMoney.compareTo(BigDecimal.ZERO) == 0) {
+				return;
+			}
+			//去掉余额 多出的部分
+			BigDecimal subGalxyCoin = toUseGalaxyCoin;
+			SysConfig galaxyCoinPayConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+					.eq(SysConfig::getSysKey, Constant.GALAXY_COIN_PAY_DEDUCT_KEY).last("limit 1"));
+			GalaxyCoinPayConfigDto galaxyCoinPayConfigDto = null;
+			if (galaxyCoinPayConfig != null && StrUtil.isNotEmpty(galaxyCoinPayConfig.getSysValue())) {
+				try {
+					galaxyCoinPayConfigDto = Jsons.parseObject(galaxyCoinPayConfig.getSysValue(), GalaxyCoinPayConfigDto.class);
+				} catch (Exception e) {
+				}
+				if (galaxyCoinPayConfigDto == null) {
+					throw BusinessRuntimeException.getInstance("银河币抵扣系统错误,请联系客服");
+				}
+				//每个银河币可抵扣金额
+				BigDecimal deductMoneyEachCoin = galaxyCoinPayConfigDto.getMoney().divide(galaxyCoinPayConfigDto.getGalaxyCoin());
+				//此次使用抵扣金额
+				BigDecimal thisDeductMoney = toUseGalaxyCoin.multiply(deductMoneyEachCoin);
+				//该笔平台最高可抵扣金额
+				BigDecimal maxDeductMoney = renewSkuDiscountPrice.multiply(galaxyCoinPayConfigDto.getMaxRate());
+				if (thisDeductMoney.compareTo(maxDeductMoney) > 0) {
+					thisDeductMoney = maxDeductMoney;
+				}
+				//此次使用的银河币超过订单金额
+				if (thisDeductMoney.compareTo(orderMoney) > 0) {
+					thisDeductMoney = orderMoney;
+				}
+				//此时需要扣除的银河币
+				subGalxyCoin = thisDeductMoney.divide(deductMoneyEachCoin);
+				//银河币抵扣
+				List<UserGalaxyCoinRecord> availableGalaxyCoinList = userGalaxyCoinRecordMapper.selectList(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+						.eq(UserGalaxyCoinRecord::getUserId, orderDon.getUserId())
+						.eq(UserGalaxyCoinRecord::getIsUsed, Boolean.FALSE)
+						.gt(UserGalaxyCoinRecord::getExpiryTime, DateTime.now())
+						.gt(UserGalaxyCoinRecord::getRemainGalaxyCoin, 0));
+				//需要使用的银河币
+				BigDecimal userFinalUseGalaxyCoin = subGalxyCoin;
+				for (UserGalaxyCoinRecord galaxyCoinRecord : availableGalaxyCoinList) {
+					if (userFinalUseGalaxyCoin.compareTo(BigDecimal.ZERO) <= 0) {
+						break;
+					}
+					BigDecimal remainGalaxyCoin = galaxyCoinRecord.getRemainGalaxyCoin();
+					Long galaxyCoinRecordId = galaxyCoinRecord.getId();
+					//扣完
+					if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) == 0) {
+						//完全抵扣
+						deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
+						userFinalUseGalaxyCoin = BigDecimal.ZERO;
+					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) < 0) {
+						//不足以抵扣
+						deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
+						userFinalUseGalaxyCoin = userFinalUseGalaxyCoin.subtract(remainGalaxyCoin);
+					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) > 0) {
+						//足以抵扣
+						deductUserGalaxyCoin(galaxyCoinRecordId, userFinalUseGalaxyCoin, remainGalaxyCoin, false);
+						userFinalUseGalaxyCoin = BigDecimal.ZERO;
+					}
+				}
+				//最终消耗的银河币需要为0 大于0则说明抵扣失败
+				if (userFinalUseGalaxyCoin.compareTo(BigDecimal.ZERO) > 0) {
+					throw BusinessRuntimeException.getInstance("您的银河币不足!");
+				}
+				//扣除银河币 是否成功
+				Integer success = userMapper.subUserGalaxyCoin(user.getId(), subGalxyCoin, userGalaxyCoin);
+				if (success != 1) throw BusinessRuntimeException.getInstance("您的银河币不足!");
+				//记录使用详情
+				OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = new OrderDonGalaxyCoinRecord();
+				orderDonGalaxyCoinRecord.setUserId(user.getId());
+				orderDonGalaxyCoinRecord.setOrderNo(orderDon.getOrderNo());
+				orderDonGalaxyCoinRecord.setGalaxyCoin(subGalxyCoin);
+				orderDonGalaxyCoinRecord.setDeductMoney(thisDeductMoney);
+				orderDonGalaxyCoinRecordMapper.insert(orderDonGalaxyCoinRecord);
+				orderDon.setMoney(orderMoney.subtract(thisDeductMoney));
+			}
+		}
+	}
+
+	private void deductUserGalaxyCoin(Long galaxyCoinRecordId, BigDecimal deductGalaxyCoin, BigDecimal remainGalaxyCoin, boolean isUsed) {
+		Integer update = userGalaxyCoinRecordMapper.update(null, Wrappers.lambdaUpdate(UserGalaxyCoinRecord.class)
+				.set(UserGalaxyCoinRecord::getRemainGalaxyCoin, remainGalaxyCoin.subtract(deductGalaxyCoin))
+				.set(isUsed, UserGalaxyCoinRecord::getIsUsed, isUsed)
+				.eq(UserGalaxyCoinRecord::getId, galaxyCoinRecordId)
+				.eq(UserGalaxyCoinRecord::getIsUsed, Boolean.FALSE)
+				.eq(UserGalaxyCoinRecord::getRemainGalaxyCoin, remainGalaxyCoin));
+		if (update == 0) {
+			throw BusinessRuntimeException.getInstance("银河币抵扣异常,请刷新页面重试");
+		}
+	}
+
 	/**
 	 * 生成用户使用折扣链接记录
 	 */
@@ -2826,6 +2961,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
 			userBenefitsService.recordBalanceBySource(orderDon.getUserId(), orderDon.getBalance().negate(), UserBalanceSourceRecord.Source.payment, orderDon.getId(), goodsDon.getTitle() + UserBalanceSourceRecord.Source.payment.getDesc(), null, null);
 		}
+		//是否需要返回银河币
+		AtomicBoolean isNeedReturnGalaxyCoin = new AtomicBoolean(Boolean.TRUE);
 
 		TASK_POOL.execute(() -> {
 			try {
@@ -2874,6 +3011,7 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 							giftCardUserPayRecord(giftCardOrderRelate.getGcPayDetail(), orderDon);
 						}
 					}
+					isNeedReturnGalaxyCoin.set(Boolean.FALSE);
 				}
 				//下级渠道目标额达标 提成金额发放
 				sendSubDistributeRewards(orderDon);
@@ -2962,6 +3100,11 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				}
 			}
 		}
+
+		//银河币返回
+		if (isNeedReturnGalaxyCoin.get()) {
+			returnGalaxyCoin(orderDon);
+		}
 	}
 
 	private void handleUserMirrorSHopOrderDon(OrderDon orderDon) throws Exception {
@@ -3446,6 +3589,10 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//存在余额
 		if (balance != null && balance.compareTo(BigDecimal.ZERO) > 0) {
 			BigDecimal money = orderDon.getMoney();
+			//订单金额不大于0
+			if (money.compareTo(BigDecimal.ZERO) == 0) {
+				return;
+			}
 			//去掉余额 多出的部分
 			BigDecimal subBalance = balance;
 			orderDon.setMoney(money.subtract(subBalance));
@@ -3869,10 +4016,12 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			upgradeOrderDon.setMoney(payRequest.getDonMoney());
 			upgradeOrderDon.setStatus(UpgradeOrderDon.Status.noPayment);
 			upgradeOrderDon.setType(UpgradeOrderDon.Type.ALI_PAY);
+			deductUpgradeBalancePayOrderMoney(upgradeOrderDon, payRequest,user);
 			upgradeOrderDonMapper.insert(upgradeOrderDon);
 
-			deductUpgradeBalancePayOrderMoney(upgradeOrderDon, payRequest.getBalance(),user);
 			Long orderId = upgradeOrderDon.getId();
+			//使用银河币记录
+			userGalaxyCoinService.handleUserGalaxyCoinOrderNotify(upgradeOrderDon.getId(), upgradeOrderDon.getUserId(), upgradeOrderDon.getOrderNo(), OrderDonGalaxyCoinRecord.Source.upgrade);
 			if (upgradeOrderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
 				upgradeOrderDon = upgradeOrderDonMapper.selectById(orderId);
 				unifiedHandlerUpgradeOrderNotify(upgradeOrderDon, upgradePackage);
@@ -3887,7 +4036,12 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		return null;
 	}
 
-	public void deductUpgradeBalancePayOrderMoney(UpgradeOrderDon orderDon, BigDecimal balance, User user) {
+	public void deductUpgradeBalancePayOrderMoney(UpgradeOrderDon orderDon, OrderPayRequest payRequest, User user) {
+		BigDecimal galaxyCoin = payRequest.getGalaxyCoin();
+		//存在银河币
+		deductGalaxyCoinPayUpgradeOrderMoney(orderDon, orderDon.getMoney(), galaxyCoin, user);
+
+		BigDecimal balance = payRequest.getBalance();
 		//存在余额
 		if (balance != null && balance.compareTo(BigDecimal.ZERO) > 0) {
 			BigDecimal money = orderDon.getMoney();
@@ -4071,6 +4225,34 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				}
 			}
 		}
+
+		//银河币返回
+		returnUpgradeGalaxyCoin(orderDon);
+	}
+
+	private void returnUpgradeGalaxyCoin(UpgradeOrderDon orderDon) {
+		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) {
+			Long userId = orderDon.getUserId();
+			BigDecimal money = orderDon.getMoney();
+			SysConfig galaxyCoinConsumeReturnRateConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+					.eq(SysConfig::getSysKey, Constant.GALAXY_COIN_CONSUME_RETURN_RATE_KEY)
+					.last("limit 1"));
+			BigDecimal retrunGalaxyCoin = BigDecimal.ZERO;
+			if (galaxyCoinConsumeReturnRateConfig != null && StrUtil.isNotEmpty(galaxyCoinConsumeReturnRateConfig.getSysValue())) {
+				try {
+					GalaxyCoinConsumeRateDto galaxyCoinConsumeRateDto = Jsons.parseObject(galaxyCoinConsumeReturnRateConfig.getSysValue(), GalaxyCoinConsumeRateDto.class);
+					BigDecimal moneyAvg = galaxyCoinConsumeRateDto.getMoney();
+					//返回银河币倍数
+					BigDecimal number = money.divide(moneyAvg, 0, RoundingMode.DOWN);;
+					retrunGalaxyCoin = number.multiply(galaxyCoinConsumeRateDto.getGalaxyCoin());
+					//发送银河币并记录
+					userGalaxyCoinService.sendOrderCashback(orderDon.getId(), userId, retrunGalaxyCoin.intValue(), PointsRecordConst.ORDER_CASHBACK, OrderDonGalaxyCoinRecord.Source.upgrade);
+				} catch (Exception e) {
+					log.error("发送用户:{}银河币points:{}套餐升级错误:{}", userId, retrunGalaxyCoin, StringUtil.getErrorText(e));
+				}
+
+			}
+		}
 	}
 
 
@@ -4104,6 +4286,14 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
 					userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getBalance(), null, null, null, null, false);
 				}
+				//返回银河币
+				UserGalaxyCoinRecord userGalaxyCoinRecord = userGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+						.eq(UserGalaxyCoinRecord::getOrderId, orderDon.getId())
+						.eq(UserGalaxyCoinRecord::getSource, OrderDonGalaxyCoinRecord.Source.upgrade.ordinal())
+						.last("limit 1"));
+				if (userGalaxyCoinRecord != null) {
+					userGalaxyCoinService.sendOrderGalaxyCloseOrder(orderDon.getId(), orderDon.getUserId(), userGalaxyCoinRecord.getGalaxyCoin().abs(), OrderDonGalaxyCoinRecord.Source.upgrade);
+				}
 			}
 		}
 	}
@@ -4239,6 +4429,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//虚拟商品订单,是否是分销订单
 		setDistributeOrderMark(orderDon, goodsDon.getType(), user.getId());
 
+		//存在银河币
+		deductGalaxyCoinPayOrderMoney(orderDon, discountPrice, payRequest.getGalaxyCoin(), user);
 		//存在余额
 		deductBalancePayOrderMoney(orderDon, payRequest.getBalance(), user);
 
@@ -4246,6 +4438,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//记录续费升级的规格
 		recordRenewOrderDon(orderDon, renewUpgradePackage, groupsTrips);
 		Long orderId = orderDon.getId();
+		//使用银河币记录
+		userGalaxyCoinService.handleUserGalaxyCoinOrderNotify(orderDon.getId(), orderDon.getUserId(), orderDon.getOrderNo(), OrderDonGalaxyCoinRecord.Source.ordinary);
 		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
 			orderDon = orderDonMapper.selectById(orderId);
 			unifiedHandlerOrderNotify(orderDon, goodsDon, renewSku);
@@ -4255,8 +4449,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 				closeOrder(orderId, null);
 			});
 		}
-		//记录用户镜像店铺订单
-		recordUserMirrorShopOrderRelate(orderDon.getId(), payRequest.getUserId(), payRequest.getCmt(), payRequest.getCustomId());
+		//统一处理订单记录操作
+		unifiedHandlerOrderRecordFunc(orderId, payRequest);
 
 		//记录镜像过期车票 续费订单关联
 		if (groupsRelation.getExpiryTime() != null && groupsRelation.getExpiryTime().compareTo(DateTime.now()) <= 0) {
@@ -4345,6 +4539,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			//续费订单
 			orderDon.setOrderType(2);
 		}
+		//订单实际支付金额
+		BigDecimal orderDonMoney = orderDon.getMoney();
 		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) < 0) {
 			throw BusinessRuntimeException.getInstance("订单金额错误");
 		}
@@ -4373,6 +4569,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			//虚拟商品订单,是否是分销订单
 			setDistributeOrderMark(orderDon, goodsDon.getType(), user.getId());
 		}
+		//存在银河币
+		deductGalaxyCoinPayOrderMoney(orderDon, orderDonMoney, orderPayRequest.getGalaxyCoin(), user);
 		BigDecimal balance = orderPayRequest.getBalance();
 		//存在余额
 		deductBalancePayOrderMoney(orderDon, balance, user);
@@ -4380,6 +4578,8 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		//设置订单支付商品信息
 		setOrderDonPayTile(null, null, null, orderDon, goodsDon, sku, null);
 		this.saveOrUpdate(orderDon);
+		//使用银河币记录
+		userGalaxyCoinService.handleUserGalaxyCoinOrderNotify(orderDon.getId(), orderDon.getUserId(), orderDon.getOrderNo(), OrderDonGalaxyCoinRecord.Source.ordinary);
 		if (orderDon.getStatus() == OrderDon.Status.noPayment) {
 			jobManager.addJob(EXPIRY_TIME, () -> {
 				closeOrder(orderDon.getId(), null);
@@ -4807,4 +5007,119 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			}
 		}
 	}
+
+	public void returnGalaxyCoin(OrderDon orderDon) {
+		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) {
+			Long userId = orderDon.getUserId();
+			BigDecimal money = orderDon.getMoney();
+			SysConfig galaxyCoinConsumeReturnRateConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+					.eq(SysConfig::getSysKey, Constant.GALAXY_COIN_CONSUME_RETURN_RATE_KEY)
+					.last("limit 1"));
+			BigDecimal retrunGalaxyCoin = BigDecimal.ZERO;
+			if (galaxyCoinConsumeReturnRateConfig != null && StrUtil.isNotEmpty(galaxyCoinConsumeReturnRateConfig.getSysValue())) {
+				try {
+					GalaxyCoinConsumeRateDto galaxyCoinConsumeRateDto = Jsons.parseObject(galaxyCoinConsumeReturnRateConfig.getSysValue(), GalaxyCoinConsumeRateDto.class);
+					BigDecimal moneyAvg = galaxyCoinConsumeRateDto.getMoney();
+					//返回银河币倍数
+					BigDecimal number = money.divide(moneyAvg, 0, RoundingMode.DOWN);
+					retrunGalaxyCoin = number.multiply(galaxyCoinConsumeRateDto.getGalaxyCoin());
+					//发送银河币并记录
+					userGalaxyCoinService.sendOrderCashback(orderDon.getId(), userId, retrunGalaxyCoin.intValue(), PointsRecordConst.ORDER_CASHBACK, OrderDonGalaxyCoinRecord.Source.ordinary);
+				} catch (Exception e) {
+					log.error("发送用户:{}银河币points:{}错误:{}", userId, retrunGalaxyCoin, StringUtil.getErrorText(e));
+				}
+
+			}
+		}
+	}
+
+	public void deductGalaxyCoinPayUpgradeOrderMoney(UpgradeOrderDon orderDon, BigDecimal discountPrice, BigDecimal toUseGalaxyCoin, User user) {
+		//存在银河币
+		if (toUseGalaxyCoin != null && toUseGalaxyCoin.compareTo(BigDecimal.ZERO) > 0) {
+			BigDecimal userGalaxyCoin = user.getGalaxyCoin();
+			if (userGalaxyCoin.compareTo(toUseGalaxyCoin) < 0) {
+				throw BusinessRuntimeException.getInstance("您的银河币不足!");
+			}
+			BigDecimal orderMoney = orderDon.getMoney();
+			//订单金额不大于0
+			if (orderMoney.compareTo(BigDecimal.ZERO) == 0) {
+				return;
+			}
+			//去掉余额 多出的部分
+			BigDecimal subGalxyCoin;
+			SysConfig galaxyCoinPayConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+					.eq(SysConfig::getSysKey, Constant.GALAXY_COIN_PAY_DEDUCT_KEY).last("limit 1"));
+			GalaxyCoinPayConfigDto galaxyCoinPayConfigDto = null;
+			if (galaxyCoinPayConfig != null && StrUtil.isNotEmpty(galaxyCoinPayConfig.getSysValue())) {
+				try {
+					galaxyCoinPayConfigDto = Jsons.parseObject(galaxyCoinPayConfig.getSysValue(), GalaxyCoinPayConfigDto.class);
+				} catch (Exception e) {
+				}
+				if (galaxyCoinPayConfigDto == null) {
+					throw BusinessRuntimeException.getInstance("银河币抵扣系统错误,请联系客服");
+				}
+				//每个银河币可抵扣金额
+				BigDecimal deductMoneyEachCoin = galaxyCoinPayConfigDto.getMoney().divide(galaxyCoinPayConfigDto.getGalaxyCoin());
+				//此次使用抵扣金额
+				BigDecimal thisDeductMoney = toUseGalaxyCoin.multiply(deductMoneyEachCoin);
+				//该笔平台最高可抵扣金额
+				BigDecimal maxDeductMoney = discountPrice.multiply(galaxyCoinPayConfigDto.getMaxRate());
+				if (thisDeductMoney.compareTo(maxDeductMoney) > 0) {
+					thisDeductMoney = maxDeductMoney;
+				}
+				//此次使用的银河币超过订单金额
+				if (thisDeductMoney.compareTo(orderMoney) > 0) {
+					thisDeductMoney = orderMoney;
+				}
+				//此时需要扣除的银河币
+				subGalxyCoin = thisDeductMoney.divide(deductMoneyEachCoin);
+				//银河币抵扣
+				List<UserGalaxyCoinRecord> availableGalaxyCoinList = userGalaxyCoinRecordMapper.selectList(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+						.eq(UserGalaxyCoinRecord::getUserId, orderDon.getUserId())
+						.eq(UserGalaxyCoinRecord::getIsUsed, Boolean.FALSE)
+						.gt(UserGalaxyCoinRecord::getExpiryTime, DateTime.now())
+						.gt(UserGalaxyCoinRecord::getRemainGalaxyCoin, 0));
+				//需要使用的银河币
+				BigDecimal userFinalUseGalaxyCoin = subGalxyCoin;
+				for (UserGalaxyCoinRecord galaxyCoinRecord : availableGalaxyCoinList) {
+					if (userFinalUseGalaxyCoin.compareTo(BigDecimal.ZERO) <= 0) {
+						break;
+					}
+					BigDecimal remainGalaxyCoin = galaxyCoinRecord.getRemainGalaxyCoin();
+					Long galaxyCoinRecordId = galaxyCoinRecord.getId();
+					//扣完
+					if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) == 0) {
+						//完全抵扣
+						deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
+						userFinalUseGalaxyCoin = BigDecimal.ZERO;
+					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) < 0) {
+						//不足以抵扣
+						deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
+						userFinalUseGalaxyCoin = userFinalUseGalaxyCoin.subtract(remainGalaxyCoin);
+					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) > 0) {
+						//足以抵扣
+						deductUserGalaxyCoin(galaxyCoinRecordId, userFinalUseGalaxyCoin, remainGalaxyCoin, false);
+						userFinalUseGalaxyCoin = BigDecimal.ZERO;
+					}
+				}
+				//最终消耗的银河币需要为0 大于0则说明抵扣失败
+				if (userFinalUseGalaxyCoin.compareTo(BigDecimal.ZERO) > 0) {
+					throw BusinessRuntimeException.getInstance("您的银河币不足!");
+				}
+				//扣除银河币 是否成功
+				Integer success = userMapper.subUserGalaxyCoin(user.getId(), subGalxyCoin, userGalaxyCoin);
+				if (success != 1) throw BusinessRuntimeException.getInstance("您的银河币不足!");
+				//记录使用详情
+				OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = new OrderDonGalaxyCoinRecord();
+				orderDonGalaxyCoinRecord.setUserId(user.getId());
+				orderDonGalaxyCoinRecord.setOrderNo(orderDon.getOrderNo());
+				orderDonGalaxyCoinRecord.setGalaxyCoin(subGalxyCoin);
+				orderDonGalaxyCoinRecord.setDeductMoney(thisDeductMoney);
+				//套餐升级来源
+				orderDonGalaxyCoinRecord.setSource(OrderDonGalaxyCoinRecord.Source.upgrade.ordinal());
+				orderDonGalaxyCoinRecordMapper.insert(orderDonGalaxyCoinRecord);
+				orderDon.setMoney(orderMoney.subtract(thisDeductMoney));
+			}
+		}
+	}
 }

+ 192 - 7
netflix-service/src/main/java/com/cyksj/service/order/impl/VipOrderDonServiceImpl.java

@@ -14,10 +14,12 @@ import com.alipay.api.response.AlipayTradeQueryResponse;
 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.constant.PointsRecordConst;
 import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.snowflake.Sequence;
 import com.cyksj.common.util.Codec;
 import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.StringUtil;
 import com.cyksj.config.zfb.AliPayClientFactory;
 import com.cyksj.config.zfb.BaseZfbConfig;
 import com.cyksj.config.zfb.ZfbProductCode;
@@ -31,6 +33,8 @@ import com.cyksj.mapper.vip.VipOrderDonDeductRelationMapper;
 import com.cyksj.mapper.vip.VipOrderDonMapper;
 import com.cyksj.mapper.vip.VipUserMapper;
 import com.cyksj.model.dto.AliPayParams;
+import com.cyksj.model.dto.GalaxyCoinConsumeRateDto;
+import com.cyksj.model.dto.GalaxyCoinPayConfigDto;
 import com.cyksj.model.dto.VipDeductDto;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.GroupsRelationView;
@@ -40,12 +44,15 @@ import com.cyksj.model.request.VipOrderDonPayReq;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.chatgpt.ChatGptAccountService;
 import com.cyksj.service.claude.ClaudeService;
+import com.cyksj.service.coin.UserGalaxyCoinService;
 import com.cyksj.service.order.VipOrderDonService;
 import com.cyksj.service.pay.AliPayCommonService;
 import com.cyksj.service.relation.GroupRelationFrontService;
+import com.cyksj.service.sys.SysConfigService;
 import com.cyksj.service.user.UserBenefitsService;
 import com.cyksj.service.user.UserBindRelationService;
 import com.cyksj.service.vip.VipFrontService;
+import com.cyksj.task.JobManager;
 import com.ejlchina.searcher.BeanSearcher;
 import com.ejlchina.searcher.param.Operator;
 import com.ejlchina.searcher.util.MapUtils;
@@ -133,6 +140,18 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 
 	private final BusinessDistributeDefaultRateConfigMapper businessDistributeDefaultRateConfigMapper;
 
+	private final SysConfigService sysConfigService;
+
+	private final UserGalaxyCoinRecordMapper userGalaxyCoinRecordMapper;
+
+	private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;
+
+	private final UserGalaxyCoinService userGalaxyCoinService;
+
+	private final JobManager jobManager;
+
+	private static final Long EXPIRY_TIME = 1000 * 60 * 5L;
+
 	@Override
 	public VipOrderDon submit(VipOrderDonPayReq payRequest) {
 		Long userId = payRequest.getUserId();
@@ -141,12 +160,20 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		if (user.getIsBlack()) throw BusinessRuntimeException.getInstance("系统检测操作异常,请稍后再试");
 		/* 生成订单 */
 		String donNo = SEQUENCE.nextId().toString();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		Integer selectCount = this.count(Wrappers.lambdaQuery(VipOrderDon.class)
+				.in(VipOrderDon::getUserId, userIdList)
+				.eq(VipOrderDon::getStatus, VipOrderDon.Status.noPayment));
+		if (selectCount > 0) {
+			throw BusinessRuntimeException.getInstance("您存在待支付的会员订单");
+		}
 		VipOrderDon orderDon = new VipOrderDon();
 		orderDon.setOrderNo(donNo);
 		orderDon.setOpenId(user.getOpenId());
 		//获取会员价格
 		VipDeductDto vipMoneyIfDeduct = getVipMoneyIfDeduct(user, payRequest.getIsDeduct());
 		BigDecimal vipMoney = getVipMoney();
+		BigDecimal actuallyPayMoney = vipMoney;
 		payRequest.setDonMoney(vipMoney);
 		if (vipMoneyIfDeduct != null) {
 			payRequest.setDonMoney(vipMoney.subtract(vipMoneyIfDeduct.getDeductMoney()));
@@ -161,13 +188,15 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		orderDon.setType(VipOrderDon.Type.getType(payRequest.getType()));
 		orderDon.setIsWebPay(payRequest.getIsWebPay());
 		//扣除使用优惠券、余额的订单金额
-		deductOrderMoney(orderDon, user, payRequest);
+		deductOrderMoney(orderDon, user, payRequest, actuallyPayMoney);
 		//设置订单支付商品信息
 		orderDon.setPayTitle(Constant.VIP_TITLE);
 		orderDon.setGoodsId(Constant.VIP_RELATE_GOODS_ID);
 		this.saveOrUpdate(orderDon);
 
 		Long orderId = orderDon.getId();
+		//使用银河币记录
+		userGalaxyCoinService.handleUserGalaxyCoinOrderNotify(orderDon.getId(), orderDon.getUserId(), orderDon.getOrderNo(), OrderDonGalaxyCoinRecord.Source.vip);
 		//存在抵扣 记录抵扣成功后 需清除车票的ids
 		if (vipMoneyIfDeduct != null) {
 			List<Long> deductRelationIds = vipMoneyIfDeduct.getDeductRelationIds();
@@ -178,6 +207,12 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 			orderDon = getById(orderId);
 			unifiedHandlerOrderNotify(orderDon);
 		}
+		VipOrderDon finalOrderDon = orderDon;
+		if (finalOrderDon.getStatus() == VipOrderDon.Status.noPayment) {
+			jobManager.addJob(EXPIRY_TIME, () -> {
+				closeOrderDon(finalOrderDon.getUserId(), orderId);
+			});
+		}
 		return orderDon;
 	}
 
@@ -251,6 +286,12 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		if (selectCount == 0) {
 			throw BusinessRuntimeException.getInstance("您会员已过期,无法续费");
 		}
+		Integer noPayOrderCount = this.count(Wrappers.lambdaQuery(VipOrderDon.class)
+				.in(VipOrderDon::getUserId, userIdList)
+				.eq(VipOrderDon::getStatus, VipOrderDon.Status.noPayment));
+		if (noPayOrderCount > 0) {
+			throw BusinessRuntimeException.getInstance("您存在待支付的会员订单");
+		}
 		/* 生成订单 */
 		String donNo = SEQUENCE.nextId().toString();
 		VipOrderDon orderDon = new VipOrderDon();
@@ -270,7 +311,7 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		orderDon.setType(VipOrderDon.Type.getType(payRequest.getType()));
 		orderDon.setIsWebPay(payRequest.getIsWebPay());
 		//扣除使用优惠券、余额的订单金额
-		deductOrderMoney(orderDon, user, payRequest);
+		deductOrderMoney(orderDon, user, payRequest, orderDon.getMoney());
 		//设置订单支付商品信息
 		orderDon.setPayTitle(Constant.VIP_TITLE);
 		orderDon.setGoodsId(Constant.VIP_RELATE_GOODS_ID);
@@ -278,6 +319,8 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		this.saveOrUpdate(orderDon);
 
 		Long orderId = orderDon.getId();
+		//使用银河币记录
+		userGalaxyCoinService.handleUserGalaxyCoinOrderNotify(orderDon.getId(), orderDon.getUserId(), orderDon.getOrderNo(), OrderDonGalaxyCoinRecord.Source.vip);
 		//余额支付订单
 		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
 			orderDon = getById(orderId);
@@ -301,6 +344,18 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 			log.info("关闭订单 orderId:{}", orderId);
 			orderDon.setStatus(VipOrderDon.Status.close);
 			updateById(orderDon);
+			//返还余额
+			if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
+				userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getBalance(), UserBalanceSourceRecord.Source.vip_order_close, null, orderId, UserBalanceSourceRecord.Source.vip_order_close.getDesc(), true);
+			}
+			//返回银河币
+			UserGalaxyCoinRecord userGalaxyCoinRecord = userGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+					.eq(UserGalaxyCoinRecord::getOrderId, orderDon.getId())
+					.eq(UserGalaxyCoinRecord::getSource, OrderDonGalaxyCoinRecord.Source.vip.ordinal())
+					.last("limit 1"));
+			if (userGalaxyCoinRecord != null) {
+				userGalaxyCoinService.sendOrderGalaxyCloseOrder(orderDon.getId(), orderDon.getUserId(), userGalaxyCoinRecord.getGalaxyCoin().abs(), OrderDonGalaxyCoinRecord.Source.vip);
+			}
 		}
 	}
 
@@ -388,6 +443,9 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 			handlerDistributeOrder(orderDon);
 			this.saveOrUpdate(orderDon);
 		}
+
+		//银河币返回
+		returnGalaxyCoin(orderDon);
 	}
 
 	private void sendVipTicketToUser(Long userId, Date vipStartTime, Date vipExpiryTime, List<Long> userIds, Long orderId) {
@@ -430,12 +488,104 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		}
 	}
 
-	private void deductOrderMoney(VipOrderDon orderDon, User user, VipOrderDonPayReq payRequest) {
+	private void deductOrderMoney(VipOrderDon orderDon, User user, VipOrderDonPayReq payRequest, BigDecimal actuallyPayMoney) {
+		//存在银河币
+		deductGalaxyCoinPayOrderMoney(orderDon, payRequest.getGalaxyCoin(), user, actuallyPayMoney);
 		BigDecimal balance = payRequest.getBalance();
 		//存在余额
 		deductBalancePayOrderMoney(orderDon, balance, user);
 	}
 
+	public void deductGalaxyCoinPayOrderMoney(VipOrderDon orderDon, BigDecimal toUseGalaxyCoin, User user, BigDecimal actuallyPayMoney) {
+		//存在银河币
+		if (toUseGalaxyCoin != null && toUseGalaxyCoin.compareTo(BigDecimal.ZERO) > 0) {
+			BigDecimal userGalaxyCoin = user.getGalaxyCoin();
+			if (userGalaxyCoin.compareTo(toUseGalaxyCoin) < 0) {
+				throw BusinessRuntimeException.getInstance("您的银河币不足!");
+			}
+			BigDecimal orderMoney = orderDon.getMoney();
+			//订单金额不大于0
+			if (orderMoney.compareTo(BigDecimal.ZERO) == 0) {
+				return;
+			}
+			//去掉余额 多出的部分
+			BigDecimal subGalxyCoin = toUseGalaxyCoin;
+			SysConfig galaxyCoinPayConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+					.eq(SysConfig::getSysKey, Constant.GALAXY_COIN_PAY_DEDUCT_KEY).last("limit 1"));
+			GalaxyCoinPayConfigDto galaxyCoinPayConfigDto = null;
+			if (galaxyCoinPayConfig != null && StrUtil.isNotEmpty(galaxyCoinPayConfig.getSysValue())) {
+				try {
+					galaxyCoinPayConfigDto = Jsons.parseObject(galaxyCoinPayConfig.getSysValue(), GalaxyCoinPayConfigDto.class);
+				} catch (Exception e) {
+				}
+				if (galaxyCoinPayConfigDto == null) {
+					throw BusinessRuntimeException.getInstance("银河币抵扣系统错误,请联系客服");
+				}
+				//每个银河币可抵扣金额
+				BigDecimal deductMoneyEachCoin = galaxyCoinPayConfigDto.getMoney().divide(galaxyCoinPayConfigDto.getGalaxyCoin());
+				//此次使用抵扣金额
+				BigDecimal thisDeductMoney = toUseGalaxyCoin.multiply(deductMoneyEachCoin);
+				//该笔平台最高可抵扣金额
+				BigDecimal maxDeductMoney = actuallyPayMoney.multiply(galaxyCoinPayConfigDto.getMaxRate());
+				if (thisDeductMoney.compareTo(maxDeductMoney) > 0) {
+					thisDeductMoney = maxDeductMoney;
+					//此时需要扣除的银河币
+					subGalxyCoin = thisDeductMoney.divide(deductMoneyEachCoin);
+				}
+				if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
+					orderDon.setType(VipOrderDon.Type.GALAXY_COIN);
+				}
+				//银河币抵扣
+				List<UserGalaxyCoinRecord> availableGalaxyCoinList = userGalaxyCoinRecordMapper.selectList(Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+						.eq(UserGalaxyCoinRecord::getUserId, orderDon.getUserId())
+						.eq(UserGalaxyCoinRecord::getIsUsed, Boolean.FALSE)
+						.gt(UserGalaxyCoinRecord::getExpiryTime, DateTime.now())
+						.gt(UserGalaxyCoinRecord::getRemainGalaxyCoin, 0));
+				//需要使用的银河币
+				BigDecimal userFinalUseGalaxyCoin = subGalxyCoin;
+				for (UserGalaxyCoinRecord galaxyCoinRecord : availableGalaxyCoinList) {
+					if (userFinalUseGalaxyCoin.compareTo(BigDecimal.ZERO) <= 0) {
+						break;
+					}
+					BigDecimal remainGalaxyCoin = galaxyCoinRecord.getRemainGalaxyCoin();
+					Long galaxyCoinRecordId = galaxyCoinRecord.getId();
+					//扣完
+					if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) == 0) {
+						//完全抵扣
+						deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
+						userFinalUseGalaxyCoin = BigDecimal.ZERO;
+					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) < 0) {
+						//不足以抵扣
+						deductUserGalaxyCoin(galaxyCoinRecordId, remainGalaxyCoin, remainGalaxyCoin, true);
+						userFinalUseGalaxyCoin = userFinalUseGalaxyCoin.subtract(remainGalaxyCoin);
+					} else if (remainGalaxyCoin.compareTo(userFinalUseGalaxyCoin) > 0) {
+						//足以抵扣
+						deductUserGalaxyCoin(galaxyCoinRecordId, userFinalUseGalaxyCoin, remainGalaxyCoin, false);
+						userFinalUseGalaxyCoin = BigDecimal.ZERO;
+					}
+				}
+				//最终消耗的银河币需要为0 大于0则说明抵扣失败
+				if (userFinalUseGalaxyCoin.compareTo(BigDecimal.ZERO) > 0) {
+					throw BusinessRuntimeException.getInstance("您的银河币不足!");
+				}
+				//扣除银河币 是否成功
+				Integer success = userMapper.subUserGalaxyCoin(user.getId(), subGalxyCoin, userGalaxyCoin);
+				if (success != 1) throw BusinessRuntimeException.getInstance("您的银河币不足!");
+				//记录使用详情
+				OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = new OrderDonGalaxyCoinRecord();
+				orderDonGalaxyCoinRecord.setUserId(user.getId());
+				orderDonGalaxyCoinRecord.setOrderNo(orderDon.getOrderNo());
+				orderDonGalaxyCoinRecord.setGalaxyCoin(subGalxyCoin);
+				orderDonGalaxyCoinRecord.setDeductMoney(thisDeductMoney);
+				orderDonGalaxyCoinRecord.setSource(OrderDonGalaxyCoinRecord.Source.vip.ordinal());
+				orderDonGalaxyCoinRecordMapper.insert(orderDonGalaxyCoinRecord);
+				orderDon.setMoney(orderMoney.subtract(thisDeductMoney));
+				if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
+					orderDon.setType(VipOrderDon.Type.GALAXY_COIN);
+				}
+			}
+		}
+	}
 	private VipDeductDto getVipMoneyIfDeduct(User user, Boolean isDeduct) {
 		//若用户抵扣
 		if (isDeduct) {
@@ -614,10 +764,7 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		UserDistributeShared distributeShared = userDistributeSharedMapper.selectOne(Wrappers.lambdaQuery(UserDistributeShared.class)
 				.eq(UserDistributeShared::getUserId, userId)
 				.last("limit 1"));
-		if (distributeShared == null && !distributeShared.getIsBind()) {
-			return;
-		}
-		if (!distributeShared.getIsBind()) {
+		if (distributeShared == null || !distributeShared.getIsBind()) {
 			return;
 		}
 		//分销订单
@@ -709,4 +856,42 @@ public class VipOrderDonServiceImpl extends ServiceImpl<VipOrderDonMapper, VipOr
 		userPlatDistributeRate.setSecondRate(secondRate);
 		return userPlatDistributeRate;
 	}
+
+	public void deductUserGalaxyCoin(Long galaxyCoinRecordId, BigDecimal deductGalaxyCoin, BigDecimal remainGalaxyCoin, boolean isUsed) {
+		Integer update = userGalaxyCoinRecordMapper.update(null, Wrappers.lambdaUpdate(UserGalaxyCoinRecord.class)
+				.set(UserGalaxyCoinRecord::getRemainGalaxyCoin, remainGalaxyCoin.subtract(deductGalaxyCoin))
+				.set(isUsed, UserGalaxyCoinRecord::getIsUsed, isUsed)
+				.eq(UserGalaxyCoinRecord::getId, galaxyCoinRecordId)
+				.eq(UserGalaxyCoinRecord::getIsUsed, Boolean.FALSE)
+				.eq(UserGalaxyCoinRecord::getRemainGalaxyCoin, remainGalaxyCoin));
+		if (update == 0) {
+			throw BusinessRuntimeException.getInstance("银河币抵扣异常,请刷新页面重试");
+		}
+	}
+
+
+	public void returnGalaxyCoin(VipOrderDon orderDon) {
+		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) {
+			Long userId = orderDon.getUserId();
+			BigDecimal money = orderDon.getMoney();
+			SysConfig galaxyCoinConsumeReturnRateConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+					.eq(SysConfig::getSysKey, Constant.GALAXY_COIN_CONSUME_RETURN_RATE_KEY)
+					.last("limit 1"));
+			BigDecimal retrunGalaxyCoin = BigDecimal.ZERO;
+			if (galaxyCoinConsumeReturnRateConfig != null && StrUtil.isNotEmpty(galaxyCoinConsumeReturnRateConfig.getSysValue())) {
+				try {
+					GalaxyCoinConsumeRateDto galaxyCoinConsumeRateDto = Jsons.parseObject(galaxyCoinConsumeReturnRateConfig.getSysValue(), GalaxyCoinConsumeRateDto.class);
+					BigDecimal moneyAvg = galaxyCoinConsumeRateDto.getMoney();
+					//返回银河币倍数
+					BigDecimal number = money.divide(moneyAvg, 0, RoundingMode.DOWN);;
+					retrunGalaxyCoin = number.multiply(galaxyCoinConsumeRateDto.getGalaxyCoin());
+					//发送银河币并记录
+					userGalaxyCoinService.sendOrderCashback(orderDon.getId(), userId, retrunGalaxyCoin.intValue(), PointsRecordConst.ORDER_CASHBACK, OrderDonGalaxyCoinRecord.Source.vip);
+				} catch (Exception e) {
+					log.error("发送会员用户:{}银河币points:{}错误:{}", userId, retrunGalaxyCoin, StringUtil.getErrorText(e));
+				}
+
+			}
+		}
+	}
 }

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

@@ -888,6 +888,8 @@ public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements Us
 			syncInfoView.setVipStartTime(vipUser.getStartTime());
 			syncInfoView.setVipExpiryTime(vipUser.getExpiryTime());
 		}
+		User user = userMapper.selectById(userId);
+		syncInfoView.setGalaxyCoin(user.getGalaxyCoin());
 		return syncInfoView;
 	}
 

+ 96 - 0
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java

@@ -1,6 +1,7 @@
 package com.cyksj.web.controller.group;
 
 import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.BetweenFormater;
 import cn.hutool.core.date.DateTime;
 import cn.hutool.core.date.DateUnit;
 import cn.hutool.core.date.DateUtil;
@@ -26,6 +27,7 @@ import com.cyksj.mapper.*;
 import com.cyksj.mapper.manage.form.FormFieldsDataMapper;
 import com.cyksj.mapper.manage.form.QuestionnairePromotionMapper;
 import com.cyksj.model.dto.DoubleVerifyDto;
+import com.cyksj.model.dto.GalaxyCoinPayConfigDto;
 import com.cyksj.model.dto.QuestionnaireView;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.AccountView;
@@ -44,6 +46,7 @@ import com.cyksj.service.mange.ticket.TicketAdvertiseConfigClickRecordService;
 import com.cyksj.service.order.OrderDonService;
 import com.cyksj.service.relation.GroupRelationFrontService;
 import com.cyksj.service.relation.GroupsRelationNetflixService;
+import com.cyksj.service.sys.SysConfigService;
 import com.cyksj.service.user.UserBindRelationService;
 import com.cyksj.service.user.UserService;
 import com.cyksj.web.util.StpUserUtil;
@@ -142,6 +145,10 @@ public class GroupRelationController {
 
     private final ClaudeUserMapper claudeUserMapper;
 
+    private final UserMapper userMapper;
+
+    private final SysConfigService sysConfigService;
+
     private final static Sequence SEQUENCE = new Sequence(0);
 
     @RequestMapping("/get/renewal")
@@ -1280,4 +1287,93 @@ public class GroupRelationController {
         Boolean flag = groupRelationFrontService.getMirrorPopups(userId);
         return GatewayResponse.SUCCESS.newBuilder().toResult(flag);
     }
+
+    /**
+     * 银河币续费车票列表
+     */
+    @GetMapping("/get/galaxyCoin/tickets")
+    public Result<SearchResult<GalaxyCoinRenewTicketsView>> getGalaxyCoinTickets() throws Exception {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        DateTime now = DateTime.now();
+        //非独立账号
+        String conditionSql = String.format("(gr.expiry_time is null or gr.expiry_time > '%s' or (sku.is_mirror and gr.expiry_time > '%s')) and (sku.months is null or sku.months != 300)", now, DateUtil.offsetDay(now, -7));
+        SearchResult<GalaxyCoinRenewTicketsView> search = beanSearcher.search(GalaxyCoinRenewTicketsView.class, MapUtils.flatBuilder(request.getParameterMap())
+                .field(GalaxyCoinRenewTicketsView::getUserId, userIdList).op(Operator.InList)
+                .put("condition", conditionSql)
+                .field(GalaxyCoinRenewTicketsView::getIsVip, Boolean.FALSE)
+                //购买
+                .field(GalaxyCoinRenewTicketsView::getAqType, 1)
+                //非代充
+                .field(GalaxyCoinRenewTicketsView::getRechargeStatus).op(Operator.IsNull)
+                //车队状态
+                .field(GalaxyCoinRenewTicketsView::getGroupsStatus, GroupsTrips.Status.waiting.name()).op(Operator.NotEqual)
+                .field(GalaxyCoinRenewTicketsView::getStatus, List.of(GroupsRelation.Status.validity.name(), GroupsRelation.Status.outside.name())).op(Operator.InList)
+                .field(GalaxyCoinRenewTicketsView::getSecondType, 2)
+                .orderBy(GalaxyCoinRenewTicketsView::getExpiryTime).asc()
+                .build());
+        User user = userMapper.selectById(userId);
+        if (user.getGalaxyCoin().compareTo(BigDecimal.ZERO) == 0) {
+            return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+        }
+        BigDecimal userGalaxyCoin = user.getGalaxyCoin();
+        SysConfig payDeductConfig = sysConfigService.getOne(Wrappers.lambdaQuery(SysConfig.class)
+                .eq(SysConfig::getSysKey, Constant.GALAXY_COIN_PAY_DEDUCT_KEY)
+                .last("limit 1"));
+        GalaxyCoinPayConfigDto galaxyCoinPayConfigDto = Jsons.parseObject(payDeductConfig.getSysValue(), GalaxyCoinPayConfigDto.class);
+        BigDecimal maxRate = galaxyCoinPayConfigDto.getMaxRate();
+        BigDecimal payGalaxyCoin = galaxyCoinPayConfigDto.getGalaxyCoin();
+        BigDecimal payMoney = galaxyCoinPayConfigDto.getMoney();
+        for (GalaxyCoinRenewTicketsView galaxyCoinRenewTicketsView : search.getDataList()) {
+            Long skuId = galaxyCoinRenewTicketsView.getSkuId();
+            BigDecimal maxSkuPrice = BigDecimal.ZERO;
+            if (galaxyCoinRenewTicketsView.getIsMirror() != null && galaxyCoinRenewTicketsView.getIsMirror()) {
+                List<RenewUpgradePackageFrontView> renewUpgradePackageFrontViews = beanSearcher.searchAll(RenewUpgradePackageFrontView.class, MapUtils.builder().field(RenewUpgradePackageFrontView::getSkuId, skuId).build());
+                for (RenewUpgradePackageFrontView renew : renewUpgradePackageFrontViews) {
+                    try {
+                        List<Long> upgradeSkuIds = Jsons.parseList(renew.getUpgradeSkuIds(), Long.class);
+                        GoodsDonSku maxPriceSku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
+                                .eq(GoodsDonSku::getStatus, Boolean.TRUE)
+                                .in(GoodsDonSku::getId, upgradeSkuIds)
+                                .orderByDesc(GoodsDonSku::getPrice)
+                                .last("limit 1"));
+                        BigDecimal discountMoney = maxPriceSku.getPrice().multiply(renew.getDiscount());
+                        if (discountMoney.compareTo(maxSkuPrice) > 0) {
+                            maxSkuPrice = discountMoney;
+                        }
+                    } catch (Exception e) {
+                    }
+                }
+
+            }
+            if (maxSkuPrice.compareTo(BigDecimal.ZERO) == 0) {
+                if (galaxyCoinRenewTicketsView.getGoodsId() == Constant.NETFLIX_GID) {
+                    GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
+                            .eq(GoodsDonSku::getStatus, Boolean.TRUE)
+                            .orderByDesc(GoodsDonSku::getPrice)
+                            .last("limit 1"));
+                    if (sku != null) {
+                        maxSkuPrice = sku.getPrice();
+                    }
+                } else {
+                    maxSkuPrice = goodsDonSkuMapper.selectById(skuId).getPrice();
+                }
+            }
+            //此次最大可抵扣银河币数量
+            BigDecimal maxDeductGalaxyCoin = maxSkuPrice.multiply(maxRate).divide(payMoney).multiply(payGalaxyCoin);
+            galaxyCoinRenewTicketsView.setMaxGalaxyCoinDeduct(userGalaxyCoin.compareTo(maxDeductGalaxyCoin) > 0 ? maxDeductGalaxyCoin : userGalaxyCoin);
+            if (galaxyCoinRenewTicketsView.getExpiryTime() != null && galaxyCoinRenewTicketsView.getGoodsType() == 1) {
+                String remainDays = DateUtil.formatBetween(now, galaxyCoinRenewTicketsView.getExpiryTime(), BetweenFormater.Level.DAY);
+                if ("0天".equals(remainDays)) {
+                    remainDays = "小于1天";
+                } else {
+                    //当天也算
+                    int days = Integer.parseInt(remainDays.substring(0, remainDays.indexOf("天")));
+                    remainDays = days + 1 + "天";
+                }
+                galaxyCoinRenewTicketsView.setRemainDays(remainDays);
+            }
+        }
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
 }

+ 9 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -133,6 +133,8 @@ public class CmsOrderController {
 
 	private final OrderDiscountPlusPurchaseSkuRelationMapper plusPurchaseSkuRelationMapper;
 
+	private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;
+
 	private static final GlobalThreadPoolTaskExecutor TASK_EXECUTOR = GlobalThreadPoolTaskExecutor.getInstance();
 
 	@GetMapping("/get")
@@ -319,6 +321,13 @@ public class CmsOrderController {
 					data.setIsTp(donDifferRelateView.getIsTp());
 				}
 			}
+			OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = orderDonGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonGalaxyCoinRecord.class)
+					.eq(OrderDonGalaxyCoinRecord::getOrderId, data.getId())
+					.last("limit 1"));
+			if (orderDonGalaxyCoinRecord != null) {
+				data.setGalaxyCoin(orderDonGalaxyCoinRecord.getGalaxyCoin());
+				data.setGalaxyCoinDeductMoney(orderDonGalaxyCoinRecord.getDeductMoney());
+			}
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}

+ 12 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/vip/CmsVipController.java

@@ -1,9 +1,12 @@
 package com.cyksj.web.controller.manage.vip;
 
 import cn.dev33.satoken.stp.StpUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.OrderDonGalaxyCoinRecordMapper;
 import com.cyksj.mapper.channel.ChannelPopularizeMapper;
+import com.cyksj.model.entity.OrderDonGalaxyCoinRecord;
 import com.cyksj.model.entity.VipGoodsSku;
 import com.cyksj.model.request.OrderRefundReq;
 import com.cyksj.model.views.CmsVipOrderDonView;
@@ -43,6 +46,8 @@ public class CmsVipController {
 
 	private final VipCommonService vipCommonService;
 
+	private final OrderDonGalaxyCoinRecordMapper orderDonGalaxyCoinRecordMapper;
+
 	/**
 	 * 会员订单列表
 	 */
@@ -54,6 +59,13 @@ public class CmsVipController {
 				Optional.ofNullable(channelPopularizeMapper.selectChannelByPid(data.getPopularizeId()))
 						.ifPresent(channelName -> data.setChannel(channelName));
 			}
+			OrderDonGalaxyCoinRecord orderDonGalaxyCoinRecord = orderDonGalaxyCoinRecordMapper.selectOne(Wrappers.lambdaQuery(OrderDonGalaxyCoinRecord.class)
+					.eq(OrderDonGalaxyCoinRecord::getOrderId, data.getId())
+					.last("limit 1"));
+			if (orderDonGalaxyCoinRecord != null) {
+				data.setGalaxyCoin(orderDonGalaxyCoinRecord.getGalaxyCoin());
+				data.setGalaxyCoinDeductMoney(orderDonGalaxyCoinRecord.getDeductMoney());
+			}
 		});
 		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
 	}

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/market/LuckyDrawFrontController.java

@@ -117,7 +117,7 @@ public class LuckyDrawFrontController {
 	/**
 	 * 抽奖
 	 */
-	@PostMapping("/lottery")
+//	@PostMapping("/lottery")
 	@NoSubmit
 	public Result<LuckyDrawView> lottery(@RequestParam(defaultValue = "normal") LuckyDraw.DrawType drawType) throws Exception {
 		Long userId = StpUserUtil.getLoginIdAsLong();

+ 7 - 7
netflix-web/src/main/java/com/cyksj/web/controller/market/SignFrontController.java

@@ -5,11 +5,11 @@ import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.UserGalaxyCoinRecordMapper;
 import com.cyksj.mapper.market.sign.SignConfigMapper;
-import com.cyksj.mapper.market.sign.UserPointsRecordMapper;
 import com.cyksj.model.entity.SignConfig;
 import com.cyksj.model.entity.SignUser;
-import com.cyksj.model.entity.UserPointsRecord;
+import com.cyksj.model.entity.UserGalaxyCoinRecord;
 import com.cyksj.service.market.MarketFrontService;
 import com.cyksj.web.util.StpUserUtil;
 import lombok.RequiredArgsConstructor;
@@ -23,7 +23,7 @@ import java.util.List;
 public class SignFrontController {
     private final MarketFrontService marketFrontService;
 
-    private final UserPointsRecordMapper userPointsRecordMapper;
+    private final UserGalaxyCoinRecordMapper userGalaxyCoinRecordMapper;
 
     private final SignConfigMapper signConfigMapper;
 
@@ -31,11 +31,11 @@ public class SignFrontController {
      * 用户积分详情
      */
     @GetMapping("/get/points/detail")
-    public Result<Page<UserPointsRecord>> getUserPointsDetail(@RequestParam(defaultValue = "1") Integer start, @RequestParam(defaultValue = "5") Integer limit) {
+    public Result<Page<UserGalaxyCoinRecord>> getUserPointsDetail(@RequestParam(defaultValue = "1") Integer start, @RequestParam(defaultValue = "5") Integer limit) {
         Long userId = StpUserUtil.getLoginIdAsLong();
-        return GatewayResponse.SUCCESS.newBuilder().toResult(userPointsRecordMapper.selectPage(new Page<>(start, limit), Wrappers.lambdaQuery(UserPointsRecord.class)
-                .eq(UserPointsRecord::getUserId, userId)
-                .orderByDesc(UserPointsRecord::getId)));
+        return GatewayResponse.SUCCESS.newBuilder().toResult(userGalaxyCoinRecordMapper.selectPage(new Page<>(start, limit), Wrappers.lambdaQuery(UserGalaxyCoinRecord.class)
+                .eq(UserGalaxyCoinRecord::getUserId, userId)
+                .orderByDesc(UserGalaxyCoinRecord::getId)));
     }
 
     /**

+ 1 - 1
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -446,7 +446,7 @@ public class AuthorizationController {
         badIntentionOpService.checkHandleBadUserOp(phone, verifyCode, ticket, randStr, request);
         String code = StringUtil.getRandomCodeStr(digit);
         Boolean isFlag;
-        if (false) {
+        if (!isFree) {
             isFlag = SmsUtil.sendTencent(cid, phone, code);
         } else {
             // 发送短信

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

@@ -1,6 +1,7 @@
 package com.cyksj.web.controller.user;
 
 import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
 import cn.hutool.core.util.StrUtil;
 import cn.hutool.core.util.URLUtil;
 import cn.hutool.extra.servlet.ServletUtil;
@@ -11,10 +12,7 @@ import com.cyksj.common.util.Jsons;
 import com.cyksj.dto.Result;
 import com.cyksj.enums.GatewayApiCode;
 import com.cyksj.enums.GatewayResponse;
-import com.cyksj.mapper.GoodsDonSkuMapper;
-import com.cyksj.mapper.OrderDonMapper;
-import com.cyksj.mapper.UserDistributePosterRecordMapper;
-import com.cyksj.mapper.UserIpRecordMapper;
+import com.cyksj.mapper.*;
 import com.cyksj.mapper.manage.coupon.CouponUserMapper;
 import com.cyksj.mapper.manage.distribute.*;
 import com.cyksj.mapper.mirrorshop.UserMirrorShopMapper;
@@ -45,6 +43,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -104,6 +103,8 @@ public class UserController {
 
     private final UserMirrorShopMapper userMirrorShopMapper;
 
+    private final UserGalaxyCoinRecordMapper userGalaxyCoinRecordMapper;
+
     @GetMapping(value = "/wx/whoami")
     public Result<UserWhoami> whoami() {
         long userId = StpUserUtil.getLoginIdAsLong();
@@ -185,7 +186,10 @@ public class UserController {
         personalView.setNumOfCoupons(couponSize);
         //积分
         User user = userService.getById(userId);
-        personalView.setActivePoints(user.getActivePoints());
+        personalView.setGalaxyCoin(user.getGalaxyCoin());
+        //30天内即将过期银河币数量
+        BigDecimal expiredGalaxyCoinAfterDays = userGalaxyCoinRecordMapper.selectExpiredGalaxyCoinAfterDays(userId, DateUtil.offsetDay(now, -30));
+        personalView.setExpiredGalaxyCoin(expiredGalaxyCoinAfterDays);
         //推广积分
         personalView.setPopularizePoints(user.getPoints());
         personalView.setBalance(user.getBalance());
@@ -356,7 +360,7 @@ public class UserController {
         long userId = StpUserUtil.getLoginIdAsLong();
         User user = userService.getOne(Wrappers.lambdaQuery(User.class)
                 .eq(User::getId, userId)
-                .select(User::getNickname, User::getBalance)
+                .select(User::getNickname, User::getBalance, User::getGalaxyCoin)
                 .last("limit 1"));
         return GatewayResponse.SUCCESS.newBuilder().toResult(user);
     }

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

@@ -18,7 +18,9 @@ import com.cyksj.service.paypal.PaypalV2Service;
 import com.cyksj.service.user.UserBindRelationService;
 import com.cyksj.web.util.StpUserUtil;
 import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
 import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
 import com.ejlchina.searcher.util.MapUtils;
 import com.paypal.api.payments.Links;
 import com.paypal.api.payments.Payment;
@@ -109,6 +111,21 @@ public class VipUserOrderController {
 		return GatewayResponse.SUCCESS.newBuilder().toResult(order);
 	}
 
+	/**
+	 * 订单列表
+	 */
+	@GetMapping("/get/orders")
+	public Result<SearchResult<VipOrderDon>> list(){
+		long userId = StpUserUtil.getLoginIdAsLong();
+		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+		List<Long> userIds = userBindRelationService.getRelationUserIdList(userId, null);
+		SearchResult<VipOrderDon> search = beanSearcher.search(VipOrderDon.class, builder
+				.field(VipOrderDon::getUserId, userIds).op(Operator.InList)
+				.orderBy(VipOrderDon::getId).desc()
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
 
 
 	/**