zwhui 2 роки тому
батько
коміт
2bc5600d74
21 змінених файлів з 1190 додано та 21 видалено
  1. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/RefundUpgradeOrderDonMapper.java
  2. 55 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RefundUpgradeOrderDon.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/model/entity/UpgradeOrderDon.java
  4. 87 0
      netflix-dao/src/main/java/com/cyksj/model/excel/ExcelUpgradeOrderDonData.java
  5. 65 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDetailView.java
  6. 99 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonBackView.java
  7. 76 0
      netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonView.java
  8. 78 0
      netflix-dao/src/main/java/com/cyksj/model/views/RefundUpdradeOrderDonView.java
  9. 2 0
      netflix-service/src/main/java/com/cyksj/config/zfb/BaseZfbConfig.java
  10. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  11. 4 0
      netflix-service/src/main/java/com/cyksj/service/mange/CmsOrderDonService.java
  12. 128 3
      netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java
  13. 4 4
      netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java
  14. 9 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java
  15. 7 3
      netflix-service/src/main/java/com/cyksj/service/order/OrderRefundService.java
  16. 241 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java
  17. 73 4
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderRefundServiceImpl.java
  18. 1 0
      netflix-service/src/main/java/com/cyksj/service/pay/AliPayCommonService.java
  19. 47 3
      netflix-service/src/main/java/com/cyksj/service/pay/impl/AliPayCommonServiceImpl.java
  20. 115 4
      netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java
  21. 72 0
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RefundUpgradeOrderDon;
+
+/*
+ *项目名: netflix
+ *文件名: RefundOrderDonMapper
+ *创建者: JavaZou
+ *创建时间:2022/11/9 9:59
+ */
+public interface RefundUpgradeOrderDonMapper extends BaseMapper<RefundUpgradeOrderDon> {
+}

+ 55 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/RefundUpgradeOrderDon.java

@@ -0,0 +1,55 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: RefundOrderDon
+ *创建者: JavaZou
+ *创建时间:2022/11/8 18:16
+ */
+@Getter
+@Setter
+public class RefundUpgradeOrderDon extends BaseEntity{
+	private Long userId;
+
+	private Long orderId;
+
+	/**
+	 * 退款订单号
+	 */
+	private String outRefundNo;
+
+	/**
+	 * 套餐id
+	 */
+	private Long packageId;
+
+
+	private String packageName;
+
+	/**
+	 * 订单总金额
+	 */
+	private BigDecimal totalFee;
+
+	private BigDecimal refundFee;
+
+	private String refundDesc;
+
+	/**
+	 * 退款方式
+	 */
+	private String refundMethod;
+
+
+	private String operator;
+
+	/**
+	 * 聊天记录
+	 */
+	private String chatImg;
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/UpgradeOrderDon.java

@@ -34,11 +34,15 @@ public class UpgradeOrderDon extends BaseEntity {
      */
     private Long userId;
 
+    private Long relationId;
+
     /**
      * 原订单号
      */
     private Long originalOrderId;
 
+    private String transactionId;
+
     /**
      * 金额
      */
@@ -74,6 +78,15 @@ public class UpgradeOrderDon extends BaseEntity {
 
     private Type type;
 
+    private String shopId;
+    /**
+     * 买家支付id
+     */
+    private String buyerId;
+
+
+    private Boolean isWebPay;
+
     public enum Status {
         /**
          * 订单状态

+ 87 - 0
netflix-dao/src/main/java/com/cyksj/model/excel/ExcelUpgradeOrderDonData.java

@@ -0,0 +1,87 @@
+package com.cyksj.model.excel;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.UpgradeOrderDon;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: ExcelOrderDonData
+ *创建者: JavaZou
+ *创建时间:2022/12/29 10:25
+ */
+@Getter
+@Setter
+@SearchBean(tables = "upgrade_order_don o left join upgrade_package up on o.package_id = up.id left join sku " +
+		"left join user u on o.user_id = u.id "
+)
+public class ExcelUpgradeOrderDonData {
+
+	@DbField("o.id")
+	@ExcelIgnore
+	private Long id;
+
+	@DbField("o.relation_id")
+	@ExcelIgnore
+	private Long relationId;
+
+	@DbField("o.transaction_id")
+	@ExcelIgnore
+	private String transactionId;
+
+	@DbField("o.order_no")
+	@ExcelProperty("订单号")
+	private String orderNo;
+
+	@DbField("up.name")
+	@ExcelProperty("套餐名")
+	private String packageName;
+
+	@DbField("o.money")
+	@ExcelProperty("金额")
+	private BigDecimal money;
+
+	@DbField("u.id")
+	@ExcelProperty("用户ID")
+	private Long userId;
+
+	@DbField("u.nickname")
+	@ExcelProperty("用户名")
+	private String nickname;
+
+	@DbField("case when u.login_phone != '' then 'phone' when u.email != '' then 'email' when u.open_id != '' then 'wechat' else 'wechat' end")
+	@ExcelIgnore
+	private String register;
+
+	@DbField("case when u.login_phone != '' then concat('手机号',login_phone) when u.email != '' then concat('邮箱',email) when u.open_id != '' then '微信授权' else '微信授权' end")
+	@ExcelProperty("注册方式")
+	private String registerStr;
+
+	@DbField("o.status")
+	@ExcelIgnore
+	private UpgradeOrderDon.Status status;
+
+	@ExcelProperty("状态")
+	private String statusStr;
+
+	@DbField("o.created_time")
+	@ExcelProperty("创建时间")
+	private Date createdTime;
+
+	@DbField("o.type")
+	@ExcelIgnore
+	private UpgradeOrderDon.Type type;
+
+	@ExcelProperty("支付方式")
+	private String typeStr;
+
+}

+ 65 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDetailView.java

@@ -0,0 +1,65 @@
+package com.cyksj.model.manage.views;
+
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.OrderDonTransport;
+import com.cyksj.model.entity.OrderDonWaybill;
+import com.cyksj.model.entity.UpgradeOrderDon;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/*
+ *项目名: netflix
+ *文件名: OrderDetail
+ *创建者: JavaZou
+ *创建时间:2023/4/14 15:00
+ */
+@Getter
+@Setter
+@SearchBean(tables = "upgrade_order_don o left join upgrade_package up on o.package_id = up.id " +
+		"left join goods_don g on g.id = o.goods_id ")
+public class UpgradeOrderDetailView {
+	/**
+	 * 订单id
+	 */
+	@DbField("o.id")
+	private Long id;
+
+	/** 订单号 */
+	@DbField("o.order_no")
+	private String orderNo ;
+
+	@DbField("o.status")
+	private UpgradeOrderDon.Status status;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	/**
+	 * 微信订单号
+	 */
+	@DbField("o.transaction_id")
+	private String transactionId;
+
+	@DbField("o.user_id")
+	private Long userId;
+
+	@DbField("o.money")
+	private BigDecimal money;
+
+	@DbField("o.relation_id")
+	private Long relationId;
+
+	@DbField("o.package_id")
+	private Long packageId;
+
+	@DbField("up.name")
+	private String packageName;
+}

+ 99 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonBackView.java

@@ -0,0 +1,99 @@
+package com.cyksj.model.manage.views;
+
+import com.cyksj.model.entity.*;
+import com.cyksj.model.views.GoodsDonSkuView;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/*
+ *项目名: netflix
+ *文件名: OrderDonBackView
+ *创建者: JavaZou
+ *创建时间:2023/4/26 17:49
+ */
+@Getter
+@Setter
+@SearchBean(tables = "upgrade_order_don o left join upgrade_package up on o.package_id = up.id ",
+		where = ":condition:"
+)
+public class UpgradeOrderDonBackView {
+	@DbField("o.id")
+	private Long id;
+
+	@DbField("o.relation_id")
+	private Long relationId;
+
+	@DbField("o.order_no")
+	private String orderNo;
+
+	@DbField("o.transaction_id")
+	private String transactionId;
+
+	@DbField("up.name")
+	private String packageName;
+
+	/**
+	 * 平台id
+	 */
+	@DbField("o.goods_id")
+	private Long goodsId;
+
+	@DbField("o.user_id")
+	private Long userId;
+
+	@DbIgnore
+	private String nickname;
+
+	@DbIgnore
+	private String register;
+
+	/**
+	 * 登录注册手机号
+	 */
+	@DbIgnore
+	private String loginPhone;
+
+	/**
+	 * 登录注册邮箱
+	 */
+	@DbIgnore
+	private String email;
+
+	@DbField("o.money")
+	private BigDecimal money;
+
+	@DbField("o.balance")
+	private BigDecimal balance;
+
+	@DbField("o.refund_money")
+	private BigDecimal refundMoney;
+
+	@DbField("o.refund_balance")
+	private BigDecimal refundBalance;
+
+	@DbField("o.status")
+	private UpgradeOrderDon.Status status;
+
+	@DbField("o.type")
+	private UpgradeOrderDon.Type type;
+
+	@DbField("o.created_time")
+	private Date createdTime;
+
+	@DbField("o.pay_time")
+	private Date payTime;
+
+	/**
+	 * 下单手机号
+	 */
+	@DbField("o.phone")
+	private String orderPhone;
+
+}

+ 76 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/views/UpgradeOrderDonView.java

@@ -0,0 +1,76 @@
+package com.cyksj.model.manage.views;
+
+import com.cyksj.model.entity.GoodsDon;
+import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.OrderDonWaybill;
+import com.cyksj.model.entity.UpgradeOrderDon;
+import com.cyksj.model.views.GoodsDonSkuView;
+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;
+import java.util.List;
+
+/**
+ * @author chan
+ * @date 2022/9/27 6:56 PM
+ */
+@Getter
+@Setter
+@SearchBean(tables = "upgrade_order_don o left join upgrade_package up on o.package_id = up.id " +
+        "left join goods_don g on g.id = o.goods_id")
+public class UpgradeOrderDonView {
+
+    @DbField("o.id")
+    private Long id;
+
+    @DbField("o.relation_id")
+    private Long relationId;
+
+    @DbField("o.order_no")
+    private String orderNo;
+
+    @DbField("o.transaction_id")
+    private String transactionId;
+
+    @DbField("g.title")
+    private String title;
+
+    @DbField("g.id")
+    private Long goodsId;
+
+    @DbField("o.user_id")
+    @JsonIgnore
+    private Long userId;
+
+    @DbField("o.money")
+    private BigDecimal money;
+
+    @DbField("o.refund_money")
+    @JsonIgnore
+    private BigDecimal refundMoney;
+
+    @DbField("o.balance")
+    private BigDecimal balance;
+
+    @DbField("o.refund_desc")
+    private String refundDesc;
+
+    @DbField("o.status")
+    private OrderDon.Status status;
+
+    @DbField("o.type")
+    private UpgradeOrderDon.Type type;
+
+    @DbField("o.created_time")
+    private Date createdTime;
+
+    @DbField("o.pay_time")
+    private Date payTime;
+
+}

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

@@ -0,0 +1,78 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/*
+ *项目名: netflix
+ *文件名: RefundOrderDonView
+ *创建者: JavaZou
+ *创建时间:2023/4/17 15:49
+ */
+@Getter
+@Setter
+@SearchBean(tables = "refund_upgrade_order_don rd left join order_don o on o.id = rd.order_id")
+public class RefundUpdradeOrderDonView {
+	@DbField("rd.id")
+	private Long id;
+
+	@DbField("rd.order_id")
+	private Long orderId;
+
+	@DbField("o.order_no")
+	private String orderNo;
+
+	@DbField("o.money")
+	private BigDecimal orderMoney;
+
+	@DbField("ifnull(o.refund_money,0)")
+	private BigDecimal orderRefundMoney;
+
+	@DbField("rd.user_id")
+	private Long userId;
+
+	@DbIgnore
+	private String nickname;
+
+	/**
+	 * 退款单号
+	 */
+	@DbField("rd.out_refund_no")
+	private String outRefundNo;
+
+	/**
+	 * 退款金额
+	 */
+	@DbField("rd.refund_fee")
+	private BigDecimal refundMoney;
+
+	@DbField("rd.package_id")
+	private Long packageId;
+
+	@DbField("rd.package_name")
+	private String packageName;
+
+	/**
+	 * 退款方式
+	 */
+	@DbField("rd.refund_method")
+	private String refundMethod;
+
+	@DbField("rd.operator")
+	private String operator;
+
+	@DbField("rd.refund_desc")
+	private String refundDesc;
+
+	@DbField("rd.chat_img")
+	private String chatImg;
+
+	@DbField("rd.created_time")
+	private Date createTime;
+}

+ 2 - 0
netflix-service/src/main/java/com/cyksj/config/zfb/BaseZfbConfig.java

@@ -44,6 +44,8 @@ public class BaseZfbConfig {
 
 	public static String notifyUrl = "applets/order/prepay/zfb/notify";
 
+	public static String upgradeNotifyUrl = "applets/order/prepay/zfb/upgrade/notify";
+
 	public static String zfb_register_notify_url = "applets/register/prepay/zfb/notify";
 
 	/**

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

@@ -819,6 +819,7 @@ public class RedisService {
         EQUIPMENT_USER_SERVICE_RECORD("equipment_user_service_record:", "用户设备客服获取记录key", 60 * 60 * 24),
         INFORMATION_KEY("information_key:", "文章", 30 * 60L),
         CLOSE_ORDER_TIME_KEY("close_order_time_key:", "关闭订单key", 3 * 60),
+        CLOSE_UPGRADE_ORDER_TIME_KEY("close_upgrade_order_time_key:", "关闭订单key", 3 * 60),
         CHATGPT_CONVERSATION_LIMIT("chatgpt:conversation:limit:", "chatGpt 对话限制", 3 * 60 * 60L),
 
         CHATGPT_CAR_SCORES("chatgpt:car:scores","chatGpt 车队分数", 48 * 60 * 60L),

+ 4 - 0
netflix-service/src/main/java/com/cyksj/service/mange/CmsOrderDonService.java

@@ -35,6 +35,10 @@ public interface CmsOrderDonService extends IService<OrderDon> {
 	 * 订单统一退款
 	 */
 	void unifiedRefund(OrderRefundReq refundReq) throws Exception;
+	/**
+	 * 套餐订单统一退款
+	 */
+	void unifiedUpgradeRefund(OrderRefundReq refundReq) throws Exception;
 
 	/**
 	 * 微信退款回调

+ 128 - 3
netflix-service/src/main/java/com/cyksj/service/mange/impl/CmsOrderDonServiceImpl.java

@@ -177,6 +177,12 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
 
     private final UserDistributeSubRewardsMapper userDistributeSubRewardsMapper;
 
+    private final UpgradeOrderDonMapper upgradeOrderDonMapper;
+
+    private final UpgradePackageMapper upgradePackageMapper;
+
+    private final MidjourneyUserMapper midjourneyUserMapper;
+
     private static final GlobalThreadPoolTaskExecutor TASK_POOL = GlobalThreadPoolTaskExecutor.getInstance();
 
     @Override
@@ -361,6 +367,116 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         groupRelationFrontService.setGroupsTripsParkingTimeEmpty(sku, orderDon.getRelationId());
     }
 
+    @Override
+    @Transactional(rollbackFor = Throwable.class)
+    public void unifiedUpgradeRefund(OrderRefundReq refundReq) throws Exception {
+        UpgradeOrderDon orderDon = upgradeOrderDonMapper.selectById(refundReq.getOrderId());
+        UpgradePackage upgradePackage = upgradePackageMapper.selectById(orderDon.getPackageId());
+        if (StrUtil.isEmpty(refundReq.getRefundType())) {
+            refundReq.setRefundType("money");
+        }
+        String refundType = refundReq.getRefundType();
+        //校验订单是否符合退款
+        checkUpgradeOrderRefund(orderDon, refundReq);
+        //空订单关闭
+        if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0 && orderDon.getBalance().compareTo(BigDecimal.ZERO) == 0) {
+            orderDon.setStatus(UpgradeOrderDon.Status.refund);
+            upgradeOrderDonMapper.updateById(orderDon);
+            return;
+        }
+        //调用第三方接口退款
+        String outNo = orderRefundService.centerUpgradeRefund(refundReq, orderDon);
+        orderDon.setRefundDesc(refundReq.getRefundDesc());
+        //记录退款信息
+        commonUpgradeRefund(orderDon, refundReq.getRefundMoney(), refundReq.getOperator(), upgradePackage, outNo, refundType, refundReq.getIsOnly(), refundReq.getRefundBalance(), refundReq.getChatImg());
+        //修改订单状态
+        orderDon.setStatus(UpgradeOrderDon.Status.refund);
+        upgradeOrderDonMapper.updateById(orderDon);
+    }
+
+    /**
+     * 退款后 处理关联
+     */
+    public void commonUpgradeRefund(UpgradeOrderDon orderDon, BigDecimal refundMoney, String operator, UpgradePackage upgradePackage, String outNo, String refundType, Boolean isOnly, BigDecimal refundBalance, String chatImg) {
+        TASK_POOL.execute(() -> {
+            orderRefundService.refundUpgradeRecord(orderDon, refundMoney,upgradePackage, operator, outNo, refundType, chatImg);
+            //退等比例
+            if (isOnly != null && isOnly) {
+                userBenefitsService.addUserBalance(orderDon.getUserId(), refundBalance, UserBalanceSourceRecord.Source.refund, 0L, orderDon.getId(),  upgradePackage.getName()+ UserBalanceSourceRecord.Source.refund.getDesc(), true);
+                BigDecimal orderDonRefundBalance = Optional.ofNullable(orderDon.getRefundBalance()).orElse(BigDecimal.ZERO);
+                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 (UpgradeOrderDon.Type.BALANCE.getType().equals(refundType)) {
+                if (isOnly == null && orderDon.getMoney().compareTo(BigDecimal.ZERO) > 0) {
+                    userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getRefundBalance(), UserBalanceSourceRecord.Source.refund, 0L, orderDon.getId(), upgradePackage.getName() + UserBalanceSourceRecord.Source.refund.getDesc(), true);
+                }
+            }
+            if (upgradePackage.getGoodsId() == 26) {
+                MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class).eq(MidjourneyUser::getRelationId, orderDon.getRelationId()));
+                if (midjourneyUser != null) {
+                    int update = midjourneyUserMapper.update(null, Wrappers.lambdaUpdate(MidjourneyUser.class)
+                            .set(MidjourneyUser::getMjFastNum, midjourneyUser.getMjFastNum() < upgradePackage.getNum() ? 0 : midjourneyUser.getMjFastNum() - upgradePackage.getNum())
+                            .eq(MidjourneyUser::getId, midjourneyUser.getId()));
+                    if (update == 0) {
+                        log.info("midjourneyUser 套餐包增值失败 id:{},orderId:{}", midjourneyUser.getId(), orderDon.getId());
+                    }
+                }
+            }
+        });
+    }
+    /**
+     * 校验订单是否符合退款操作
+     */
+    private void checkUpgradeOrderRefund(UpgradeOrderDon orderDon, OrderRefundReq refundReq) {
+        if (orderDon == null) {
+            throw BusinessRuntimeException.getInstance("订单不存在");
+        }
+        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 (UpgradeOrderDon.Status.refund == orderDon.getStatus()) {
+            throw BusinessRuntimeException.getInstance("该订单已退款");
+        }
+        if (UpgradeOrderDon.Status.noPayment == orderDon.getStatus() || UpgradeOrderDon.Status.close == orderDon.getStatus()) {
+            throw BusinessRuntimeException.getInstance("订单{0}状态不支持退款", orderDon.getStatus());
+        }
+
+        BigDecimal refundMoney = refundReq.getRefundMoney();
+        BigDecimal money = orderDon.getMoney();
+        //余额退款
+        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 {
+            //退金额
+            refundMoney = orderDonRefundMoney.add(refundMoney);
+            if (refundMoney.compareTo(money) > 0) {
+                throw BusinessRuntimeException.getInstance("退款金额大于订单支付金额");
+            }
+            orderDon.setRefundMoney(refundMoney);
+        }
+        if (!redisService.setNx(String.format("%s", refundReq.getOrderId()), refundReq.getOrderId(), 10l)) {
+            throw BusinessRuntimeException.getInstance("请勿重复点击,正在退款中..");
+        }
+
+    }
     public String wxRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
         if (orderDon.getMoney().compareTo(BigDecimal.ZERO) <=0){
             return StrUtil.EMPTY;
@@ -501,7 +617,7 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
         relationClearService.clearTicket(relation, source);
 
         //是否是GPT镜像规格
-        delGptUser(orderDon.getGoodsId(), orderDon.getRelationId());
+        delMirrorUser(orderDon.getGoodsId(), orderDon.getRelationId());
 
         if (plusPurchaseSkuRelation != null && plus_relationList != null) {
             plus_relationList.remove(relationId);
@@ -850,7 +966,7 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
                 giftCardOrderUseRecordService.returnGiftCardCash(orderDon.getId());
             }
             //是否是GPT镜像规格
-            delGptUser(orderDon.getGoodsId(), orderDon.getRelationId());
+            delMirrorUser(orderDon.getGoodsId(), orderDon.getRelationId());
             //是否是分销订单
             //处理下级渠道分销提成
             handleSubRewards(orderDon);
@@ -1127,7 +1243,7 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
     /**
      * 删除gptUser
      */
-    public void delGptUser(Long goodsId, Long relationId) {
+    public void delMirrorUser(Long goodsId, Long relationId) {
         //gpt镜像
         if (goodsId != null && goodsId == 18) {
             Integer selectCount = chatgptUserMapper.selectCount(Wrappers.lambdaQuery(ChatgptUser.class)
@@ -1137,5 +1253,14 @@ public class CmsOrderDonServiceImpl extends ServiceImpl<OrderDonMapper,OrderDon>
                         .eq(ChatgptUser::getRelationId, relationId));
             }
         }
+        //mj镜像
+        if (goodsId != null && goodsId == 26) {
+            Integer selectCount = midjourneyUserMapper.selectCount(Wrappers.lambdaQuery(MidjourneyUser.class)
+                    .eq(MidjourneyUser::getRelationId, relationId));
+            if (selectCount > 0) {
+                midjourneyUserMapper.delete(Wrappers.lambdaQuery(MidjourneyUser.class)
+                        .eq(MidjourneyUser::getRelationId, relationId));
+            }
+        }
     }
 }

+ 4 - 4
netflix-service/src/main/java/com/cyksj/service/midjourney/impl/MidJourneyAccountServiceImpl.java

@@ -165,7 +165,7 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
         GoodsDonSku goodsDonSku = skuMapper.selectById(groupsTrips.getSkuId());
 
         if (goodsDonSku != null && goodsDonSku.getIsMirror()) {
-            MidjourneyUser midjourneyUser = getMidjourneyUser(userId, relationId, groupsRelation, groupsTrips, goodsDonSku);
+            MidjourneyUser midjourneyUser = getMidjourneyUser(userId, relationId, groupsRelation, goodsDonSku);
             return HOST + "/login_token?access_token=" + midjourneyUser.getUserToken();
         } else {
             throw BusinessRuntimeException.getInstance("服务器出了点问题");
@@ -202,11 +202,11 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
         return groupsTrips;
     }
 
-    private MidjourneyUser getMidjourneyUser(Long userId, Long relationId, GroupsRelation groupsRelation, GroupsTrips groupsTrips, GoodsDonSku goodsDonSku) {
+    private MidjourneyUser getMidjourneyUser(Long userId, Long relationId, GroupsRelation groupsRelation, GoodsDonSku goodsDonSku) {
         MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class).eq(MidjourneyUser::getRelationId, relationId));
         User user = userMapper.selectById(userId);
         if (midjourneyUser == null) {
-            midjourneyUser = createMidjourneyUser(groupsRelation, groupsTrips, user, goodsDonSku);
+            midjourneyUser = createMidjourneyUser(groupsRelation, user, goodsDonSku);
         } else {
             updateMidjourneyUser(groupsRelation, user, midjourneyUser);
         }
@@ -216,7 +216,7 @@ public class MidJourneyAccountServiceImpl extends ServiceImpl<MidjourneyAccountM
     /**
      * 创建MidjourneyUser
      */
-    private synchronized MidjourneyUser createMidjourneyUser(GroupsRelation groupsRelation, GroupsTrips groupsTrips, User user, GoodsDonSku goodsDonSku) {
+    private synchronized MidjourneyUser createMidjourneyUser(GroupsRelation groupsRelation, User user, GoodsDonSku goodsDonSku) {
         MidjourneyUser midjourneyUser = new MidjourneyUser();
         midjourneyUser.setExpireTime(groupsRelation.getExpiryTime());
         midjourneyUser.setName(user.getNickname());

+ 9 - 0
netflix-service/src/main/java/com/cyksj/service/order/OrderDonService.java

@@ -11,8 +11,10 @@ import com.cyksj.model.entity.OrderDetailView;
 import com.cyksj.model.entity.OrderDon;
 import com.cyksj.model.entity.RealGoodsInterestUser;
 import com.cyksj.model.entity.UpgradeOrderDon;
+import com.cyksj.model.manage.views.UpgradeOrderDetailView;
 import com.cyksj.model.request.AlipayOrderDonReq;
 import com.cyksj.model.request.OrderPayRequest;
+import org.springframework.transaction.annotation.Transactional;
 
 import java.util.Date;
 import java.util.List;
@@ -94,4 +96,11 @@ public interface OrderDonService extends IService<OrderDon> {
 
     UpgradeOrderDon submitUpgrade(OrderPayRequest payRequest);
 
+    AliPayParams aliPayUpgrade(AlipayOrderDonReq re, String productCode) throws Exception;
+
+    void aliPayUpgradeNotify(Map<String, String> params) throws Exception;
+
+    void closeUpgradeOrder(Long orderId, Long userId);
+
+    UpgradeOrderDetailView getUpgradeOrderDetail(Long orderId, Long userId);
 }

+ 7 - 3
netflix-service/src/main/java/com/cyksj/service/order/OrderRefundService.java

@@ -1,8 +1,6 @@
 package com.cyksj.service.order;
 
-import com.cyksj.model.entity.GoodsDon;
-import com.cyksj.model.entity.GoodsDonSku;
-import com.cyksj.model.entity.OrderDon;
+import com.cyksj.model.entity.*;
 import com.cyksj.model.request.OrderRefundReq;
 
 import java.math.BigDecimal;
@@ -16,9 +14,15 @@ import java.math.BigDecimal;
 public interface OrderRefundService {
 
 	String centerRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception;
+	String centerUpgradeRefund(OrderRefundReq refundReq, UpgradeOrderDon orderDon) throws Exception;
 
 	/**
 	 * 退款记录
 	 */
 	void refundRecord(OrderDon orderDon, BigDecimal refundMoney, String operator, GoodsDon goodsDon, GoodsDonSku sku, String outRefundNo, String refundType, String chatImg);
+	/**
+	 * 套餐包退款记录
+	 */
+	void refundUpgradeRecord(UpgradeOrderDon orderDon, BigDecimal refundMoney, UpgradePackage upgradePackage, String operator, String outRefundNo, String refundType, String chatImg);
+
 }

+ 241 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderDonServiceImpl.java

@@ -62,6 +62,7 @@ import com.cyksj.model.manage.dto.GiftCardDto;
 import com.cyksj.model.manage.request.ReqGoodsSkuSpec;
 import com.cyksj.model.manage.views.GroupsRelationView;
 import com.cyksj.model.manage.views.OrderDonView;
+import com.cyksj.model.manage.views.UpgradeOrderDetailView;
 import com.cyksj.model.request.*;
 import com.cyksj.model.views.*;
 import com.cyksj.redis.RedisService;
@@ -3089,6 +3090,29 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 
 	@Override
 	public UpgradeOrderDon submitUpgrade(OrderPayRequest payRequest) {
+		User user = null;
+		Long userId = payRequest.getUserId();
+		if (userId != null) {
+			int noPayCount = upgradeOrderDonMapper.selectCount(Wrappers.lambdaQuery(UpgradeOrderDon.class).eq(UpgradeOrderDon::getUserId, userId).eq(UpgradeOrderDon::getPackageId, payRequest.getPackageId())
+					.eq(UpgradeOrderDon::getStatus, UpgradeOrderDon.Status.noPayment.toString()));
+			if (noPayCount > 0) {
+				throw new BusinessRuntimeException("您有未支付订单.");
+			}
+		}
+		String orderPhone = payRequest.getPhone();
+		if (StrUtil.isNotBlank(orderPhone)) {
+			user = saveOrGetOrderPhoneUser(payRequest);
+			userId = user.getId();
+			payRequest.setUserId(userId);
+		}
+		if (userId == null) {
+			user = new User();
+			user.setId(0l);
+		} else {
+			user = userMapper.selectById(userId);
+			if (user == null) throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
+			if (user.getIsBlack()) throw BusinessRuntimeException.getInstance("系统检测操作异常,请稍后再试");
+		}
 		GroupsRelation groupsRelation = getGroupsRelation(payRequest.getUserId(), payRequest.getRelationId());
 		GroupsTrips groupsTrips = getGroupsTrips(groupsRelation);
 		GoodsDonSku goodsDonSku = goodsDonSkuMapper.selectById(groupsTrips.getSkuId());
@@ -3098,25 +3122,63 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 			if (upgradePackage == null) {
 				throw BusinessRuntimeException.getInstance("套餐包不存在");
 			}
+			if (upgradePackage.getPrice() == null || upgradePackage.getPrice().compareTo(BigDecimal.ZERO) <= 0) {
+				throw BusinessRuntimeException.getInstance("下单商品价格异常");
+			}
+			if (payRequest.getDonMoney().compareTo(upgradePackage.getPrice()) < 0) {
+				log.info("套餐包:{}支付金额:{}异常,调整用户userId:{}支付金额为:{}", upgradePackage.getName(), payRequest.getDonMoney(), user.getId(), upgradePackage.getPrice());
+				payRequest.setDonMoney(upgradePackage.getPrice());
+			}
 			MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class).eq(MidjourneyUser::getRelationId, payRequest.getRelationId()));
 			if (midjourneyUser != null){
+
 				String donNo = SEQUENCE.nextId().toString();
 				UpgradeOrderDon upgradeOrderDon = new UpgradeOrderDon();
 				upgradeOrderDon.setOrderNo(donNo);
 				upgradeOrderDon.setUserId(payRequest.getUserId());
 				upgradeOrderDon.setOriginalOrderId(groupsRelation.getOrderId());
+				upgradeOrderDon.setRelationId(payRequest.getRelationId());
 				upgradeOrderDon.setPackageId(payRequest.getPackageId());
 				upgradeOrderDon.setGoodsId(groupsTrips.getGoodsId());
 				upgradeOrderDon.setMoney(payRequest.getDonMoney());
 				upgradeOrderDon.setStatus(UpgradeOrderDon.Status.noPayment);
 				upgradeOrderDon.setType(UpgradeOrderDon.Type.ALI_PAY);
 				upgradeOrderDonMapper.insert(upgradeOrderDon);
+
+				deductUpgradeBalancePayOrderMoney(upgradeOrderDon, payRequest.getBalance(),user );
+
+				if (upgradeOrderDon.getStatus() == UpgradeOrderDon.Status.noPayment) {
+					jobManager.addJob(EXPIRY_TIME, () -> {
+						closeUpgradeOrder(upgradeOrderDon.getId(), null);
+					});
+				}
 				return upgradeOrderDon;
 			}
 		}
 		return null;
 	}
 
+	public void deductUpgradeBalancePayOrderMoney(UpgradeOrderDon orderDon, BigDecimal balance, User user) {
+		//存在余额
+		if (balance != null && balance.compareTo(BigDecimal.ZERO) > 0) {
+			BigDecimal money = orderDon.getMoney();
+			//去掉余额 多出的部分
+			BigDecimal subBalance = balance;
+			orderDon.setMoney(money.subtract(subBalance));
+			if (balance.compareTo(money) >= 0) {
+				orderDon.setMoney(BigDecimal.ZERO);
+				orderDon.setBalance(money);
+				subBalance = money;
+				orderDon.setType(UpgradeOrderDon.Type.BALANCE);
+			}
+			BigDecimal userBalance = user.getBalance();
+			//扣除余额 是否成功
+			Integer success = userMapper.deductBalance(user.getId(), subBalance, userBalance);
+			if (success != 1) throw BusinessRuntimeException.getInstance("您的余额不足!");
+			orderDon.setBalance(subBalance);
+		}
+	}
+
 	/**
 	 * 获取车位信息
 	 *
@@ -3146,4 +3208,183 @@ public class OrderDonServiceImpl extends ServiceImpl<OrderDonMapper, OrderDon> i
 		}
 		return groupsTrips;
 	}
+
+	@Override
+	public AliPayParams aliPayUpgrade(AlipayOrderDonReq re, String productCode) throws Exception {
+		return aliPayCommonService.unifiedPayUpgrade(re,productCode,null);
+	}
+
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void aliPayUpgradeNotify(Map<String, String> params) throws Exception {
+		//调用SDK验证签名
+		String body = Codec.DoBase64.custom().setData(params.get("body")).decodeAsText();
+		OrderAttach orderAttach = Jsons.parseObject(body, OrderAttach.class);
+		Long oderId = orderAttach.getO();
+		UpgradeOrderDon orderDon = upgradeOrderDonMapper.selectById(oderId);
+		if (null == orderDon) {
+			throw BusinessRuntimeException.getInstance("订单不存在.");
+		}
+		String appId = params.get("app_id");
+		boolean signVerified = AlipaySignature.rsaCheckV1(params, shopConfigMapper.getByAppId(appId).getPublicKey(), BaseZfbConfig.charset, BaseZfbConfig.signType);
+		if (!signVerified) {
+			log.error("支付宝回调校验签名错误,自定义入参:{}", params.get("body"));
+			throw BusinessRuntimeException.getInstance("支付宝回调校验签名错误");
+		}
+		String transactionId = params.get("trade_no");
+		String payTimeStr = params.get("gmt_payment");
+		//买家支付宝账号
+		String buyerId = params.get("buyer_id");
+		log.info("支付宝回调信息:{}", Jsons.toJson(params));
+		if (!orderDon.getStatus().equals(OrderDon.Status.noPayment) && !orderDon.getStatus().equals(OrderDon.Status.close)) {
+			log.info("支付宝已回调,重复修改状态 id:{}", orderDon.getId());
+			return;
+		}
+		UpgradePackage upgradePackage = upgradePackageMapper.selectById(orderDon.getPackageId());
+		Date payTime = DateTime.now();
+		if (StringUtils.isNotBlank(payTimeStr)) {
+			payTime = DateUtil.parse(payTimeStr, "yyyy-MM-dd HH:mm:ss");
+		}
+		// 更改订单状态
+		orderDon.setTransactionId(transactionId);
+		orderDon.setPayTime(payTime);
+		orderDon.setShopId(appId);
+		orderDon.setType(UpgradeOrderDon.Type.ALI_PAY);
+
+		orderDon.setBuyerId(buyerId);
+		//该支付账号id 是否被后台拉黑
+		Integer count1 = userPayOrderBlockMapper.selectCount(Wrappers.lambdaQuery(UserPayOrderBlock.class)
+				.eq(UserPayOrderBlock::getBuyerId, buyerId));
+		if (count1 > 0) {
+			log.info("该支付账号id:{} 已被后台拉黑", buyerId);
+			//notifyRefundOrder(orderDon, goodsDon, sku);
+			return;
+		}
+
+		//回调
+		unifiedHandlerUpgradeOrderNotify(orderDon,upgradePackage );
+	}
+
+
+	/**
+	 * 统一订单信息回调
+	 */
+	public void unifiedHandlerUpgradeOrderNotify(UpgradeOrderDon orderDon, UpgradePackage upgradePackage) {
+		orderDon.setStatus(UpgradeOrderDon.Status.hasPayment);
+		int isSuccess = upgradeOrderDonMapper.update(null,Wrappers.lambdaUpdate(UpgradeOrderDon.class)
+				.set(UpgradeOrderDon::getStatus, orderDon.getStatus())
+				.in(UpgradeOrderDon::getStatus, List.of(UpgradeOrderDon.Status.noPayment, UpgradeOrderDon.Status.close))
+				.eq(UpgradeOrderDon::getId, orderDon.getId()));
+		if (isSuccess == 0) {
+			log.info("该订单{}状态已修改", orderDon.getOrderNo());
+			return;
+		}
+
+		//余额使用记录
+		if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
+			userBenefitsService.recordBalanceBySource(orderDon.getUserId(), orderDon.getBalance().negate(), UserBalanceSourceRecord.Source.payment, orderDon.getId(), upgradePackage.getName() + UserBalanceSourceRecord.Source.payment.getDesc());
+		}
+
+		if (upgradePackage.getGoodsId() == 26) {
+			MidjourneyUser midjourneyUser = midjourneyUserMapper.selectOne(Wrappers.lambdaQuery(MidjourneyUser.class).eq(MidjourneyUser::getRelationId, orderDon.getRelationId()));
+			if (midjourneyUser != null) {
+				int update = midjourneyUserMapper.update(null, Wrappers.lambdaUpdate(MidjourneyUser.class)
+						.set(MidjourneyUser::getMjFastNum, midjourneyUser.getMjFastNum() + upgradePackage.getNum()).eq(MidjourneyUser::getId, midjourneyUser.getId()));
+				if (update == 0) {
+					log.info("midjourneyUser 套餐包增值失败 id:{},orderId:{}", midjourneyUser.getId(), orderDon.getId());
+				}
+			}
+		}
+	}
+
+
+	@Transactional(rollbackFor = Throwable.class)
+	@Override
+	public void closeUpgradeOrder(Long orderId, Long userId) {
+		String orderCloseKey = RedisService.key.CLOSE_UPGRADE_ORDER_TIME_KEY.getName() + orderId;
+		if (!redisService.setNx(orderCloseKey, orderId, RedisService.key.CLOSE_UPGRADE_ORDER_TIME_KEY.getTimeout())) {
+			throw BusinessRuntimeException.getInstance("订单正在关闭中..");
+		}
+		//关闭订单逻辑
+		UpgradeOrderDon orderDon = upgradeOrderDonMapper.selectById(orderId);
+		if (orderDon == null) {
+			return;
+		}
+		if (userId != null) {
+			List<Long> relationUserIdList = userBindRelationService.getRelationUserIdList(userId, null);
+			if (!relationUserIdList.contains(orderDon.getUserId())) {
+				return;
+			}
+		}
+		log.info("关闭订单 orderId:{}", orderId);
+		if (UpgradeOrderDon.Status.noPayment.equals(orderDon.getStatus())) {
+			//调用微信、支付宝第三方接口查询订单是否支付
+			UpgradeOrderDon.Status status = isHasPaid(orderDon);
+			if (status == UpgradeOrderDon.Status.noPayment) {
+				//查询微信支付是否已支付
+				orderDon.setStatus(UpgradeOrderDon.Status.close);
+				upgradeOrderDonMapper.updateById(orderDon);
+				//返还余额
+				if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
+					userBenefitsService.addUserBalance(orderDon.getUserId(), orderDon.getBalance(), null, null, null, null, false);
+				}
+			}
+		}
+	}
+
+
+	/**
+	 * 查询第三放接口订单是否已支付
+	 */
+	public UpgradeOrderDon.Status isHasPaid(UpgradeOrderDon orderDon) {
+		UpgradePackage upgradePackage = upgradePackageMapper.selectById(orderDon.getPackageId());
+		if (orderDon.getType() == UpgradeOrderDon.Type.WeChat) {
+			try {
+				Map<String, String> reMap = weChatService.getWxOrderDetail(orderDon.getShopId(), orderDon.getOrderNo());
+				if (reMap != null) {
+					String orderStatus = reMap.get("trade_state");
+					if ("SUCCESS".equals(orderStatus)) {
+						orderDon.setStatus(UpgradeOrderDon.Status.complete);
+						orderDon.setTransactionId(reMap.get("transaction_id"));
+						return updateUpgradeNoPayment(orderDon, upgradePackage);
+					}
+				}
+			} catch (Exception e) {
+
+			}
+		} else if (orderDon.getType() == UpgradeOrderDon.Type.ALI_PAY) {
+			try {
+				AlipayTradeQueryResponse zfbOrderDetail = getZfbOrderDetail(orderDon.getShopId(), orderDon.getOrderNo());
+				if (zfbOrderDetail != null) {
+					String tradeStatus = zfbOrderDetail.getTradeStatus();
+					if ("TRADE_SUCCESS".equals(tradeStatus)) {
+						orderDon.setStatus(UpgradeOrderDon.Status.complete);
+						orderDon.setTransactionId(zfbOrderDetail.getTradeNo());
+						return updateUpgradeNoPayment(orderDon, upgradePackage);
+					}
+				}
+			} catch (Exception e) {
+
+			}
+		}
+		return orderDon.getStatus();
+	}
+
+	private UpgradeOrderDon.Status updateUpgradeNoPayment(UpgradeOrderDon orderDon,UpgradePackage upgradePackage) {
+		unifiedHandlerUpgradeOrderNotify(orderDon, upgradePackage);
+		return orderDon.getStatus();
+	}
+
+
+	@Override
+	public UpgradeOrderDetailView getUpgradeOrderDetail(Long orderId, Long userId) {
+			MapBuilder builder = MapUtils.builder()
+					.field(OrderDonView::getId, orderId)
+					.orderBy(OrderDonView::getId).desc();
+			if (userId != null) {
+				builder.field(UpgradeOrderDetailView::getUserId, userId);
+			}
+        return beanSearcher.searchFirst(UpgradeOrderDetailView.class, builder.build());
+	}
 }

+ 73 - 4
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderRefundServiceImpl.java

@@ -10,10 +10,7 @@ import com.cyksj.common.exception.BusinessRuntimeException;
 import com.cyksj.common.util.Codec;
 import com.cyksj.config.WeChatConfig;
 import com.cyksj.config.zfb.AliPayClientFactory;
-import com.cyksj.mapper.OrderDonMapper;
-import com.cyksj.mapper.PaypalPayConfigMapper;
-import com.cyksj.mapper.RefundOrderDonMapper;
-import com.cyksj.mapper.StripePayConfigMapper;
+import com.cyksj.mapper.*;
 import com.cyksj.mapper.channel.ShopConfigMapper;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.request.OrderRefundReq;
@@ -64,6 +61,8 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 
 	private final RefundOrderDonMapper refundOrderDonMapper;
 
+	private final RefundUpgradeOrderDonMapper refundUpgradeOrderDonMapper;
+
 	@Override
 	public String centerRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
 		OrderDon.Type type = orderDon.getType();
@@ -83,6 +82,16 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 		return StrUtil.EMPTY;
 	}
 
+	@Override
+	public String centerUpgradeRefund(OrderRefundReq refundReq, UpgradeOrderDon orderDon) throws Exception {
+		UpgradeOrderDon.Type type = orderDon.getType();
+		String refundType = refundReq.getRefundType();
+		if (type == UpgradeOrderDon.Type.ALI_PAY && !refundType.equals(OrderDon.Type.BALANCE.getType())) {
+			return zfbUpgradeRefund(refundReq, orderDon);
+		}
+		return StrUtil.EMPTY;
+	}
+
 	@Override
 	public void refundRecord(OrderDon orderDon, BigDecimal refundMoney, String operator, GoodsDon goodsDon, GoodsDonSku sku, String outRefundNo, String refundType, String chatImg) {
 		RefundOrderDon refund = new RefundOrderDon();
@@ -109,6 +118,29 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 		refundOrderDonMapper.insert(refund);
 	}
 
+	@Override
+	public void refundUpgradeRecord(UpgradeOrderDon orderDon, BigDecimal refundMoney, UpgradePackage upgradePackage,String operator, String outRefundNo, String refundType, String chatImg) {
+		RefundUpgradeOrderDon refund = new RefundUpgradeOrderDon();
+		refund.setOrderId(orderDon.getId());
+		refund.setOutRefundNo(outRefundNo);
+		refund.setTotalFee(orderDon.getMoney());
+		refund.setRefundDesc(orderDon.getRefundDesc());
+		//退款金额
+		refund.setRefundFee(refundMoney);
+		refund.setUserId(orderDon.getUserId());
+		refund.setPackageId(orderDon.getPackageId());
+		refund.setPackageName(upgradePackage == null ? null : upgradePackage.getName());
+		refund.setRefundMethod(orderDon.getType().name());
+		refund.setOperator(operator);
+		refund.setChatImg(chatImg);
+		//退款方式
+		if (StrUtil.isNotBlank(refundType) && refundType.equals(OrderDon.Type.BALANCE.getType())) {
+			refund.setRefundMethod(refundType);
+			refund.setRefundFee(orderDon.getRefundBalance());
+		}
+		refundUpgradeOrderDonMapper.insert(refund);
+	}
+
 
 	public String wxRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
 		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) <=0){
@@ -168,6 +200,43 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 	}
 
 
+	public String zfbUpgradeRefund(OrderRefundReq refundReq, UpgradeOrderDon orderDon) throws Exception {
+		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) <=0){
+			return StrUtil.EMPTY;
+		}
+		AlipayTradeRefundResponse response;
+		//支付宝退款
+		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
+		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
+		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
+		//支付宝交易号
+		model.setTradeNo(orderDon.getTransactionId());
+		model.setRefundAmount(refundReq.getRefundMoney().divide(BigDecimal.valueOf(100), 2, RoundingMode.HALF_EVEN).toString());
+		model.setQueryOptions(List.of("gmt_refund_pay"));
+		long time = System.currentTimeMillis();
+		//退款订单号
+		String outRefundNo = Codec.DoDigest.custom()
+				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
+				.setStringData(time + String.valueOf(orderDon.getId()))
+				.toHexString();
+		//退款请求号
+		model.setOutRequestNo(outRefundNo);
+		request.setBizModel(model);
+		String shopId = orderDon.getShopId();
+		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, orderDon.getShopId()));
+		if (shopId != null && shopConfig != null && shopConfig.getIsCert()) {
+			response = alipayClient.certificateExecute(request);
+		} else {
+			response = alipayClient.execute(request);
+		}
+		if (!response.isSuccess()) throw BusinessRuntimeException.getInstance("退款失败,e:{0}", response.getSubMsg());
+//			AliPayRefundRep aliPayRefundRep = Jsons.parseObject(response.getBody(), AliPayRefundRep.class);
+//			AliPayRefundRep.AlipayTradeRefundResponse res = aliPayRefundRep.getResponse();
+//			orderDon.setRefundMoney(res.getRefundFee().multiply(BigDecimal.valueOf(100)));
+		return outRefundNo;
+	}
+
+
 	public Boolean paypalRefund(OrderRefundReq refundReq, OrderDon orderDon) throws PayPalRESTException {
 		BigDecimal net = refundReq.getRefundMoney().divide(new BigDecimal(7),2,RoundingMode.HALF_DOWN).subtract(orderDon.getAbroadTransactionFee());;
 		log.info("paypal return order:{},money:{}",orderDon.getId(),net);

+ 1 - 0
netflix-service/src/main/java/com/cyksj/service/pay/AliPayCommonService.java

@@ -20,4 +20,5 @@ public interface AliPayCommonService {
 	AliPayParams unifiedPayRegister(Long orderId, String productCode, String payMode, String returnUrl) throws Exception;
 
 	AliPayParams unifiedPay(AlipayOrderDonReq re, String productCode, String payMode) throws Exception;
+	AliPayParams unifiedPayUpgrade(AlipayOrderDonReq re, String productCode, String payMode) throws Exception;
 }

+ 47 - 3
netflix-service/src/main/java/com/cyksj/service/pay/impl/AliPayCommonServiceImpl.java

@@ -19,9 +19,7 @@ import com.cyksj.common.util.StringUtil;
 import com.cyksj.config.zfb.AliPayClientFactory;
 import com.cyksj.config.zfb.BaseZfbConfig;
 import com.cyksj.config.zfb.ZfbProductCode;
-import com.cyksj.mapper.GoodsDonMapper;
-import com.cyksj.mapper.OrderDonMapper;
-import com.cyksj.mapper.RegisterOrderDonMapper;
+import com.cyksj.mapper.*;
 import com.cyksj.mapper.channel.ShopConfigMapper;
 import com.cyksj.mapper.order.OrderDonPostMapper;
 import com.cyksj.model.dto.AliPayParams;
@@ -64,6 +62,10 @@ public class AliPayCommonServiceImpl implements AliPayCommonService {
 
 	private final OrderDonPostMapper orderDonPostMapper;
 
+	private final UpgradeOrderDonMapper	upgradeOrderDonMapper;
+
+	private final UpgradePackageMapper upgradePackageMapper;
+
 	@Override
 	public AliPayParams unifiedPayRegister(Long orderId, String productCode, String payMode, String returnUrl) throws Exception {
 		RegisterOrderDon orderDon = registerOrderDonMapper.selectById(orderId);
@@ -252,4 +254,46 @@ public class AliPayCommonServiceImpl implements AliPayCommonService {
 		}
 		return null;
 	}
+
+
+	@Override
+	public AliPayParams unifiedPayUpgrade(AlipayOrderDonReq re, String productCode, String payMode) throws Exception {
+		Long orderId = re.getOrderId();
+		String returnUrl = re.getReturnUrl();
+		UpgradeOrderDon orderDon = upgradeOrderDonMapper.selectById(orderId);
+		//获取支付宝默认商户
+		String appId = sysConfigService.getDefaultShopConfigByType("zfb");
+		if (UpgradeOrderDon.Type.ALI_PAY != orderDon.getType()) {
+			orderDon.setType(UpgradeOrderDon.Type.ALI_PAY);
+		}
+		orderDon.setShopId(appId);
+		if (ZfbProductCode.PC_WEB.getProductCode().equals(productCode)) {
+			orderDon.setIsWebPay(true);
+		}
+		if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode)) {
+			orderDon.setIsWebPay(false);
+		}
+		upgradeOrderDonMapper.updateById(orderDon);
+		UpgradePackage upgradePackage = upgradePackageMapper.selectById(orderDon.getPackageId());
+		String subject = upgradePackage.getName();
+		//回调地址
+		String host = envCommonService.getHost();
+		String notifyUrl = String.format("%s%s", host, BaseZfbConfig.upgradeNotifyUrl);
+		//是否在微信内支付 微信内支付宝支付后 支付宝回调页面不跳转
+		Boolean isWx = Optional.ofNullable(re.getIsWx()).orElse(false);
+		if (ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode) && !isWx) {
+			//默认跳转页
+			returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.DEFAULT_URL);
+		}
+        return builderPayParams(orderDon.getId(),
+				orderDon.getOrderNo(),
+				orderDon.getShopId(),
+				orderDon.getMoney(),
+				orderDon.getCreatedTime(),
+				subject,
+				productCode,
+				payMode,
+				notifyUrl,
+				returnUrl);
+	}
 }

+ 115 - 4
netflix-web/src/main/java/com/cyksj/web/controller/manage/CmsOrderController.java

@@ -28,13 +28,11 @@ import com.cyksj.mapper.manage.cms.CmsUserMapper;
 import com.cyksj.mapper.manage.coupon.CouponMapper;
 import com.cyksj.mapper.shop.YhShopMapper;
 import com.cyksj.model.entity.*;
-import com.cyksj.model.excel.ExcelOrderDonData;
-import com.cyksj.model.excel.ExcelRealGoodsOrderData;
-import com.cyksj.model.excel.ExcelRealGoodsUserInterestData;
-import com.cyksj.model.excel.ExcelRealGoodsUserInterestHasPaymentData;
+import com.cyksj.model.excel.*;
 import com.cyksj.model.manage.request.ReqSetLogisticsPost;
 import com.cyksj.model.manage.views.AccountView;
 import com.cyksj.model.manage.views.OrderDonBackView;
+import com.cyksj.model.manage.views.UpgradeOrderDonBackView;
 import com.cyksj.model.request.*;
 import com.cyksj.model.views.*;
 import com.cyksj.service.mange.CmsOrderDonService;
@@ -806,4 +804,117 @@ public class CmsOrderController {
 		}
 		return GatewayResponse.SUCCESS.newBuilder().toResult();
 	}
+
+
+
+	/**
+	 * 查询套餐订单列表
+	 */
+
+	@GetMapping("/upgrade/get")
+	@SaCheckPermission("upgradeOrder:view")
+	public Result<SearchResult<UpgradeOrderDonBackView>> getUpgradeOrder(String account, String showId, Long acId, String nickname, String register, Boolean isGoogle) {
+		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+
+		if (StrUtil.isNotBlank(account)) {
+			GroupsRelation relation = relationMapper.selectOne(Wrappers.lambdaQuery(GroupsRelation.class)
+					.eq(GroupsRelation::getAccount, account).last("limit 1"));
+			if (relation != null) {
+				builder.field(OrderDonBackView::getRelationId, relation.getId());
+			} else {
+				builder.field(OrderDonBackView::getRelationId).op(Operator.IsNull);
+			}
+		}
+		if (StrUtil.isNotBlank(showId)) {
+			builder.field(OrderDonBackView::getUserId, userService.getUserIdByShowId(showId));
+		}
+		String conditionSql = StrUtil.EMPTY;
+		if (acId != null) {
+			conditionSql += String.format(" o.user_id in (select user_id from corp_user where ac_id = %s)", acId);
+		}
+		if (!ObjectUtil.isAllEmpty(nickname, register, isGoogle)) {
+			if (StrUtil.isNotEmpty(conditionSql)) {
+				conditionSql += " and ";
+			}
+			conditionSql += " exists (select u.id from user u where u.id = o.user_id";
+			if (StrUtil.isNotEmpty(nickname)) {
+				conditionSql += String.format(" and u.nickname like '%s%%'", nickname);
+			}
+			if (StrUtil.isNotEmpty(register)) {
+				if ("phone".equals(register)) {
+					conditionSql += " and u.login_phone != ''";
+				} else if ("email".equals(register)) {
+					conditionSql += " and u.email != ''";
+				} else if ("wechat".equals(register)) {
+					conditionSql += " and u.unionid != ''";
+				}
+			}
+			if (isGoogle != null && isGoogle) {
+				conditionSql += String.format(" and u.is_google is %s", isGoogle);
+			}
+			conditionSql += " limit 1)";
+		}
+		if (StrUtil.isNotBlank(conditionSql)) {
+			builder.put("condition", conditionSql);
+		}
+		SearchResult<UpgradeOrderDonBackView> search = beanSearcher.search(UpgradeOrderDonBackView.class, builder.build());
+		search.getDataList().forEach(data -> {
+			User user = userMapper.selectById(data.getUserId());
+			if (user != null) {
+				data.setNickname(user.getNickname());
+				data.setLoginPhone(user.getLoginPhone());
+				data.setEmail(user.getEmail());
+				data.setRegister(StrUtil.isNotEmpty(user.getUnionid()) ? "wechat" : StrUtil.isNotEmpty(user.getLoginPhone()) ? "phone" : "email");
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 套餐退款订单列表
+	 */
+	@GetMapping("/get/upgrade/refund/list")
+	public Result<SearchResult<RefundOrderDonView>> getRefundUpgradeOrderDonView() {
+		SearchResult<RefundOrderDonView> search = beanSearcher.search(RefundOrderDonView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.build());
+		search.getDataList().forEach(data -> {
+			Optional.ofNullable(userService.getById(data.getUserId()))
+					.ifPresent(user -> data.setNickname(user.getNickname()));
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 套餐订单导出
+	 */
+	@GetMapping("/upgrade/export")
+	@SaCheckPermission("upgradeOrder:export")
+	@Log(module = "套餐订单管理/导出订单", businessType = BusinessType.EXPORT, isSaveRequestData = true)
+	public void exportUpgradeOrders(HttpServletResponse response) {
+		List<ExcelUpgradeOrderDonData> list = beanSearcher.searchAll(ExcelUpgradeOrderDonData.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		list.forEach(data -> {
+			data.setMoney(data.getMoney().divide(BigDecimal.valueOf(100)));
+			UpgradeOrderDon.Type type = data.getType();
+			data.setTypeStr(type != null ? type.getDesc() : "");
+			UpgradeOrderDon.Status status = data.getStatus();
+			data.setStatusStr(status != null ? status.getDesc() : "");
+		});
+		EasyExcelUtils.createExcelStreamMutilByEasyExcel(response, ExcelUpgradeOrderDonData.class, list, "订单列表", "订单列表", ExcelTypeEnum.XLSX, null);
+	}
+
+	/**
+	 * 套餐订单统一退款
+	 */
+	@PostMapping("/unified/upgrade/refund")
+	@Log(module = "套餐订单管理/统一退款", businessType = BusinessType.PUT, isSaveRequestData = true)
+	public Result<String> unifiedUpgradeRefund(@RequestBody @Validated OrderRefundReq refundReq) throws Exception {
+		long adminId = StpUtil.getLoginIdAsLong();
+		CmsUser cmsUser = cmsUserMapper.selectById(adminId);
+		if (cmsUser == null) {
+			throw BusinessRuntimeException.getGatewayApiCode(GatewayApiCode.CMS_TOKEN_VALID);
+		}
+		refundReq.setOperator(cmsUser.getNickname());
+		cmsOrderDonService.unifiedUpgradeRefund(refundReq);
+		return GatewayResponse.SUCCESS.newBuilder().toResult("退款成功");
+	}
 }

+ 72 - 0
netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java

@@ -28,6 +28,8 @@ import com.cyksj.model.dto.H5JsPayParams;
 import com.cyksj.model.entity.*;
 import com.cyksj.model.manage.views.OrderDonSearchView;
 import com.cyksj.model.manage.views.OrderDonView;
+import com.cyksj.model.manage.views.UpgradeOrderDetailView;
+import com.cyksj.model.manage.views.UpgradeOrderDonView;
 import com.cyksj.model.request.AlipayOrderDonReq;
 import com.cyksj.model.request.OrderPayRequest;
 import com.cyksj.model.response.AliPayTradeStatus;
@@ -309,6 +311,17 @@ public class OrderController {
         return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
 	}
 
+    /**
+     * 套餐支付宝支付
+     */
+    @PostMapping("/post/pay/upgrade/zfb")
+    @Deprecated
+    public Result<String> aliPayUpgrade(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
+        AliPayParams aliPayParams = orderDonService.aliPayUpgrade(re, ZfbProductCode.MOBILE_WEB.getProductCode());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
+    }
+
+
     /**
      * 支付宝web支付
      * pc网页内嵌二维码
@@ -353,6 +366,26 @@ public class OrderController {
 		return "success";
 	}
 
+    /**
+     * 支付宝套餐包回调
+     */
+    @PostMapping("/prepay/zfb/upgrade/notify")
+    public String aliPayUpgradeNotify(HttpServletRequest request) throws Exception {
+        ////将异步通知中收到的所有参数都存放到map中
+        Map<String, String> params = convertRequestParamsToMap(request);
+        String tradeStatus = params.get("trade_status");
+        String orderNo = params.get("out_trade_no");
+        if (AliPayTradeStatus.TRADE_SUCCESS.getStatus().equals(tradeStatus) || AliPayTradeStatus.TRADE_FINISHED.getStatus().equals(tradeStatus)) {
+            log.info("支付宝商家订单号orderNo:{},status:{}开始回调", orderNo, tradeStatus);
+            orderDonService.aliPayUpgradeNotify(params);
+        } else {
+            log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo);
+            return "fail";
+        }
+        return "success";
+    }
+
+
     /**
      * 支付宝转账
      */
@@ -668,4 +701,43 @@ public class OrderController {
                 .build());
         return GatewayResponse.SUCCESS.newBuilder().toResult(search);
     }
+
+
+    /**
+     * 获取套餐订单列表
+     */
+    @GetMapping("/upgrade/get")
+    public Result<SearchResult<UpgradeOrderDonView>> listUpgradeOrder(){
+        long userId = StpUserUtil.getLoginIdAsLong();
+        MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+        List<Long> userIds = UserBindRelationService.getRelationUserIdList(userId, null);
+        SearchResult<UpgradeOrderDonView> search = beanSearcher.search(UpgradeOrderDonView.class, builder
+                .field(UpgradeOrderDonView::getUserId, userIds).op(Operator.InList)
+                .orderBy(UpgradeOrderDonView::getId).desc()
+                .build());
+        return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+    }
+
+
+    /**
+     * 获取套餐订单详情
+     */
+    @GetMapping("/get/upgrade/{orderId}")
+    public Result<UpgradeOrderDetailView> upgradeOrderDetail(@PathVariable Long orderId) {
+        Long userId = StpUserUtil.getUserIdAfterLogin();
+
+        UpgradeOrderDetailView detail = orderDonService.getUpgradeOrderDetail(orderId, userId);
+
+        return GatewayResponse.SUCCESS.newBuilder().toResult(detail);
+    }
+
+    /**
+     * 取消套餐订单
+     */
+    @GetMapping("/get/close/upgrade/{orderId}")
+    public Result<String> closeUpgradeOrder(@PathVariable Long orderId) {
+        long userId = StpUserUtil.getLoginIdAsLong();
+        orderDonService.closeUpgradeOrder(orderId, userId);
+        return GatewayResponse.SUCCESS.newBuilder().toResult();
+    }
 }