zoujiajian пре 1 година
родитељ
комит
ec04f0d10c
52 измењених фајлова са 2872 додато и 5 уклоњено
  1. 7 0
      netflix-common/src/main/java/com/cyksj/common/constant/Constant.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleMapper.java
  3. 17 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleOrderDonMapper.java
  4. 17 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleUserAccountMapper.java
  5. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleUserDepositMapper.java
  6. 17 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleUserReturnRecordMapper.java
  7. 17 0
      netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleUserSkuPayRecordMapper.java
  8. 2 0
      netflix-dao/src/main/java/com/cyksj/mapper/manage/statistics/StatisticsExportMapper.java
  9. 26 0
      netflix-dao/src/main/java/com/cyksj/model/dto/GoodsWholesaleUserDepositDto.java
  10. 70 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesale.java
  11. 119 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesaleOrderDon.java
  12. 22 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesaleUserAccount.java
  13. 113 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesaleUserDeposit.java
  14. 33 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesaleUserReturnRecord.java
  15. 31 0
      netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesaleUserSkuPayRecord.java
  16. 3 1
      netflix-dao/src/main/java/com/cyksj/model/entity/UserBalanceSourceRecord.java
  17. 2 0
      netflix-dao/src/main/java/com/cyksj/model/request/AlipayOrderDonReq.java
  18. 35 0
      netflix-dao/src/main/java/com/cyksj/model/request/GoodsWholesaleOrderPayReq.java
  19. 2 0
      netflix-dao/src/main/java/com/cyksj/model/request/OrderRefundReq.java
  20. 26 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleFrontOrderView.java
  21. 66 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleFrontView.java
  22. 81 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleOrderDonView.java
  23. 78 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleOrderView.java
  24. 71 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleUserDepositView.java
  25. 76 0
      netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleView.java
  26. 5 0
      netflix-dao/src/main/java/com/cyksj/model/views/GroupsDataStatisticsView.java
  27. 44 0
      netflix-dao/src/main/java/com/cyksj/model/views/WholeGoodsSkuPayUserDetailView.java
  28. 38 0
      netflix-dao/src/main/java/com/cyksj/model/views/WholesaleUserRequirementView.java
  29. 16 0
      netflix-dao/src/main/resources/mapper/GoodsWholesaleOrderDonMapper.xml
  30. 14 0
      netflix-dao/src/main/resources/mapper/GoodsWholesaleUserAccountMapper.xml
  31. 14 0
      netflix-dao/src/main/resources/mapper/GoodsWholesaleUserReturnRecordMapper.xml
  32. 16 0
      netflix-dao/src/main/resources/mapper/GoodsWholesaleUserSkuPayRecordMapper.xml
  33. 8 0
      netflix-dao/src/main/resources/mapper/StatisticsExportMapper.xml
  34. 10 0
      netflix-service/src/main/java/com/cyksj/common/EnvCommonService.java
  35. 4 0
      netflix-service/src/main/java/com/cyksj/config/zfb/BaseZfbConfig.java
  36. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  37. 31 0
      netflix-service/src/main/java/com/cyksj/service/goods/GoodsWholesaleService.java
  38. 235 0
      netflix-service/src/main/java/com/cyksj/service/goods/impl/GoodsWholesaleServiceImpl.java
  39. 2 0
      netflix-service/src/main/java/com/cyksj/service/mange/RefreshCacheService.java
  40. 6 0
      netflix-service/src/main/java/com/cyksj/service/mange/impl/RefreshCacheServiceImpl.java
  41. 2 0
      netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java
  42. 33 0
      netflix-service/src/main/java/com/cyksj/service/order/GoodsWholesalePayService.java
  43. 3 0
      netflix-service/src/main/java/com/cyksj/service/order/OrderRefundService.java
  44. 585 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/GoodsWholesalePayServiceImpl.java
  45. 137 0
      netflix-service/src/main/java/com/cyksj/service/order/impl/OrderRefundServiceImpl.java
  46. 5 0
      netflix-service/src/main/java/com/cyksj/service/pay/AliPayCommonService.java
  47. 92 0
      netflix-service/src/main/java/com/cyksj/service/pay/impl/AliPayCommonServiceImpl.java
  48. 2 1
      netflix-web/src/main/java/com/cyksj/config/SaTokenConfigure.java
  49. 2 1
      netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java
  50. 295 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonWholeSaleController.java
  51. 0 2
      netflix-web/src/main/java/com/cyksj/web/controller/payment/OrderController.java
  52. 315 0
      netflix-web/src/main/java/com/cyksj/web/controller/wholesale/GoodsWholesaleWebController.java

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

@@ -383,4 +383,11 @@ public interface Constant {
 	Long SPECIAL_DISTRIBUTE_USER_ID = 469739l;
 
 	Long LUMA_GOODS_ID = 87l;
+
+	/**
+	 * 批发押金配置key
+	 */
+	String WHOLESALE_DEPOSIT_KEY = "wholesale_deposit_key";
+
+	String SHOP = "店铺";
 }

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsWholesale;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/8/21 15:49
+ */
+public interface GoodsWholesaleMapper extends BaseMapper<GoodsWholesale> {
+}

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleOrderDonMapper.java

@@ -0,0 +1,17 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsWholesaleOrderDon;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleOrderDonMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 12:24
+ */
+public interface GoodsWholesaleOrderDonMapper extends BaseMapper<GoodsWholesaleOrderDon> {
+	Integer getUserWholesaleNumByUserIds(@Param("list") List<Long> userIdList, @Param("skuId") Long skuId);
+}

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleUserAccountMapper.java

@@ -0,0 +1,17 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsWholesaleUserAccount;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleUserAccountMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 17:15
+ */
+public interface GoodsWholesaleUserAccountMapper extends BaseMapper<GoodsWholesaleUserAccount> {
+	void batchInsert(@Param("userId") Long userId, @Param("orderId") Long orderId, @Param("list") List<GoodsWholesaleUserAccount> insert);
+}

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

@@ -0,0 +1,13 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsWholesaleUserDeposit;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleUserDepositMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/8/21 15:52
+ */
+public interface GoodsWholesaleUserDepositMapper extends BaseMapper<GoodsWholesaleUserDeposit> {
+}

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleUserReturnRecordMapper.java

@@ -0,0 +1,17 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsWholesaleUserReturnRecord;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleUserReturnRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/8/28 11:40
+ */
+public interface GoodsWholesaleUserReturnRecordMapper extends BaseMapper<GoodsWholesaleUserReturnRecord> {
+	GoodsWholesaleUserReturnRecord selectGoodsWholeReturnBalanceRecordByUserId(@Param("list") List<Long> userIdList, @Param("skuId") Long skuId);
+}

+ 17 - 0
netflix-dao/src/main/java/com/cyksj/mapper/GoodsWholesaleUserSkuPayRecordMapper.java

@@ -0,0 +1,17 @@
+package com.cyksj.mapper;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.GoodsWholesaleUserSkuPayRecord;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: GoodsWholesaleUserSkuPayRecordMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/9/14 10:19
+ */
+public interface GoodsWholesaleUserSkuPayRecordMapper extends BaseMapper<GoodsWholesaleUserSkuPayRecord> {
+	List<GoodsWholesaleUserSkuPayRecord> selectUserHasPaySkuDifferRecord(@Param("userIds") List<Long> userIdList, @Param("skuId") Long skuId);
+}

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/mapper/manage/statistics/StatisticsExportMapper.java

@@ -82,4 +82,6 @@ public interface StatisticsExportMapper{
 	Integer getYearNumOfRenewalsByGoodsId(@Param("goodsId") Long goodsId, @Param("lastElevMonth") String lastElevMonth, @Param("lastYearMonth") String lastYearMonth);
 
 	Integer getActualNumberOfRenewalsByGoodsId(@Param("goodsId") Long goodsId, @Param("lastElevMonth") String lastElevMonth, @Param("lastYearMonth") String lastYearMonth);
+
+	BigDecimal getWholesaleOrderMoney(@Param("startDate") String startDate, @Param("endDate") String endDate);
 }

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/dto/GoodsWholesaleUserDepositDto.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.dto;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleUserDepositDto
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 14:06
+ */
+@Getter
+@Setter
+public class GoodsWholesaleUserDepositDto {
+	/**
+	 * 押金
+	 */
+	private BigDecimal deposit;
+
+	/**
+	 * 笔数
+	 */
+	private Integer num;
+}

+ 70 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesale.java

@@ -0,0 +1,70 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldStrategy;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesale
+ * 创建者: JavaZou
+ * 创建时间:2024/8/21 15:48
+ */
+@Getter
+@Setter
+public class GoodsWholesale extends BaseEntity{
+	private Long goodsId;
+
+	private Long skuId;
+
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String skuName;
+
+	private String config;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private List<GoodsWholesaleConfig> wholesaleConfig;
+
+	/**
+	 * 返差价
+	 */
+	private Boolean isReturn;
+
+	/**
+	 * 图片
+	 */
+	@TableField(updateStrategy = FieldStrategy.IGNORED)
+	private String picture;
+
+	private Integer sorted;
+
+	private Boolean status;
+
+	private Boolean deleted;
+
+	@Getter
+	@Setter
+	public static class GoodsWholesaleConfig {
+		/**
+		 * 开始个数
+		 */
+		private Integer start;
+
+		/**
+		 * 结束个数
+		 * 填999就代表无穷大
+		 */
+		private Integer end;
+
+		/**
+		 * 每个单价
+		 */
+		private BigDecimal single;
+	}
+}

+ 119 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesaleOrderDon.java

@@ -0,0 +1,119 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.fasterxml.jackson.annotation.JsonIgnore;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleOrderDon
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 12:22
+ */
+@Getter
+@Setter
+public class GoodsWholesaleOrderDon extends BaseEntity{
+	private Long userId;
+
+	private String orderNo;
+
+	/**
+	 * 批发id
+	 */
+	private Long pid;
+
+	private Long goodsId;
+
+	private Long skuId;
+
+	private Type type;
+
+	private BigDecimal money;
+
+	private BigDecimal balance;
+
+	private Integer num;
+
+	private String source;
+
+	private Status status;
+
+	private Date payTime;
+
+	private String shopId;
+
+	private String outRefundNo;
+
+	/**
+	 * 是否网页支付
+	 */
+	private Boolean isWebPay;
+
+	private String transactionId;
+
+	/**
+	 * 买家id
+	 */
+	private String buyerId;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private Boolean isDeposit;
+
+	private BigDecimal refundMoney;
+
+	@DbIgnore
+	@TableField(exist = false)
+	@JsonIgnore
+	private Boolean isRecordDiffer = false;
+
+	public enum Status {
+		/**
+		 * 订单状态
+		 */
+		close("已关闭"),
+		noPayment("待付款"),
+		hasPayment("已付款"),
+		complete("已完成"),
+		refund("已退款"),
+		;
+
+		private String desc;
+
+		Status(String desc) {
+			this.desc = desc;
+		}
+
+		public String getDesc() {
+			return desc;
+		}
+	}
+
+	@Getter
+	@AllArgsConstructor
+	public enum Type{
+		WeChat("wechat","微信"),
+		ALI_PAY("zfb","支付宝"),
+		EX_CODE("exchange_code","兑换码"),
+		LOTTERY("lottery","抽奖"),
+		EQUIPMENT("equipment", "实物设备分销"),
+		PAY_EQUIPMENT("pay_equipment", "自购设备"),
+		BALANCE("balance", "余额支付"),
+		PAYPAL("paypal","paypal支付"),
+		STRIPE("stripe","stripe支付")
+		;
+		String type;
+		String desc;
+
+		public static GoodsWholesaleOrderDon.Type getType(String type) {
+			return Arrays.stream(GoodsWholesaleOrderDon.Type.values()).filter(tp -> tp.getType().equals(type)).findFirst().orElse(ALI_PAY);
+		}
+	}
+}

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

@@ -0,0 +1,22 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleUserAccount
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 17:11
+ */
+@Getter
+@Setter
+public class GoodsWholesaleUserAccount extends BaseEntity{
+	private Long userId;
+
+	private Long orderId;
+
+	private String account;
+
+	private String password;
+}

+ 113 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesaleUserDeposit.java

@@ -0,0 +1,113 @@
+package com.cyksj.model.entity;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleUserDeposit
+ * 创建者: JavaZou
+ * 创建时间:2024/8/21 15:52
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_wholesale_user_deposit gwud")
+public class GoodsWholesaleUserDeposit extends BaseEntity {
+	private Long userId;
+
+	private BigDecimal money;
+
+	private Type type;
+
+	/**
+	 * 支付状态
+	 */
+	private Status status;
+
+	/**
+	 * 累积批发
+	 */
+	@TableField(exist = false)
+	@DbIgnore
+	private Integer total;
+
+	/**
+	 * 操作人
+	 */
+	private String operator;
+
+	/**
+	 * 商户id
+	 */
+	private String shopId;
+
+	private String orderNo;
+
+	private String refundOutNo;
+
+	private String transactionId;
+
+	private Boolean isWebPay;
+
+	/**
+	 * 批发数达标
+	 */
+	private Boolean isGoal;
+
+	private Date payTime;
+
+	private String buyerId;
+
+	@DbIgnore
+	@TableField(exist = false)
+	private Boolean isDeposit;
+
+	@DbField("select nickname from user where id = gwud.user_id limit 1")
+	@TableField(exist = false)
+	private String nickname;
+
+	public enum Status {
+		/**
+		 * 订单状态
+		 */
+		noPayment("待付款"),
+		hasPayment("已付款"),
+		refund("已退款"),
+		;
+
+		private String desc;
+
+		Status(String desc) {
+			this.desc = desc;
+		}
+
+		public String getDesc() {
+			return desc;
+		}
+	}
+
+
+	@Getter
+	@AllArgsConstructor
+	public enum Type {
+		WeChat("wechat", "微信"),
+		ALI_PAY("zfb", "支付宝"),
+		PAYPAL("paypal", "paypal支付"),
+		STRIPE("stripe", "stripe支付");
+		String type;
+		String desc;
+
+		public static GoodsWholesaleUserDeposit.Type getType(String type) {
+			return Arrays.stream(GoodsWholesaleUserDeposit.Type.values()).filter(tp -> tp.getType().equals(type)).findFirst().orElse(ALI_PAY);
+		}
+	}
+}

+ 33 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesaleUserReturnRecord.java

@@ -0,0 +1,33 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleUserReturnRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/8/28 11:36
+ */
+@Getter
+@Setter
+public class GoodsWholesaleUserReturnRecord extends BaseEntity{
+
+	private Long goodsId;
+
+	private Long skuId;
+
+	private Long userId;
+
+	/**
+	 * 批发数目
+	 */
+	private Integer num;
+
+	/**
+	 * 返差价余额
+	 */
+	private BigDecimal returnBalance;
+}

+ 31 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/GoodsWholesaleUserSkuPayRecord.java

@@ -0,0 +1,31 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: GoodsWholesaleUserSkuPayRecord
+ * 创建者: JavaZou
+ * 创建时间:2024/9/14 10:17
+ */
+@Getter
+@Setter
+public class GoodsWholesaleUserSkuPayRecord extends BaseEntity{
+	private Long userId;
+
+	private Long orderId;
+
+	private Long goodsId;
+
+	private Long skuId;
+
+	private Integer num;
+
+	/**
+	 * 单价
+	 */
+	private BigDecimal single;
+}

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

@@ -34,7 +34,9 @@ public class UserBalanceSourceRecord extends BaseEntity{
 		rd_comment("实物评论"),
 		price_differ("订单补差价"),
 		compensate("系统补偿"),
-		manual("手动扣除")
+		manual("手动扣除"),
+		wholesale_differ("返批发差价"),
+		wholesale_order("批发订单"),
 		;
 		String desc;
 

+ 2 - 0
netflix-dao/src/main/java/com/cyksj/model/request/AlipayOrderDonReq.java

@@ -30,4 +30,6 @@ public class AlipayOrderDonReq {
 	private String payMode;
 
 	private String returnUrl;
+
+	private Boolean isDeposit = false;
 }

+ 35 - 0
netflix-dao/src/main/java/com/cyksj/model/request/GoodsWholesaleOrderPayReq.java

@@ -0,0 +1,35 @@
+package com.cyksj.model.request;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleOrderPayReq
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 18:41
+ */
+@Getter
+@Setter
+public class GoodsWholesaleOrderPayReq {
+	@NotNull
+	private Long id;
+
+	private Long userId;
+
+	/**
+	 * 数量
+	 */
+	@NotNull
+	@Min(value = 1)
+	private Integer num;
+
+	/**
+	 * 余额
+	 */
+	private BigDecimal balance;
+}

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

@@ -53,4 +53,6 @@ public class OrderRefundReq {
 	 * 扣除的余额
 	 */
 	private BigDecimal deductBalance;
+
+	private Long adminId;
 }

+ 26 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleFrontOrderView.java

@@ -0,0 +1,26 @@
+package com.cyksj.model.views;
+
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: GoodsWholesaleFrontOrderView
+ * 创建者: JavaZou
+ * 创建时间:2024/9/11 15:27
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select distinct goods_id from goods_wholesale_order_don :uid:) gw left join goods_don g on g.id = gw.goods_id")
+public class GoodsWholesaleFrontOrderView {
+	@DbField("gw.goods_id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.logo")
+	private String logo;
+}

+ 66 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleFrontView.java

@@ -0,0 +1,66 @@
+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;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleFrontView
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 17:46
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_wholesale gw" +
+		" inner join goods_don g on g.id = gw.goods_id and g.status is true and g.deleted is true" +
+		" inner join goods_don_sku sku on sku.id = gw.sku_id and sku.status is true",
+		where = "gw.status is true and gw.deleted is true",
+		orderBy = "gw.sorted asc")
+public class GoodsWholesaleFrontView {
+	@DbField("gw.id")
+	private Long id;
+
+	@DbField("gw.goods_id")
+	private Long goodsId;
+
+	@DbField("gw.sku_id")
+	private Long skuId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("g.logo")
+	private String logo;
+
+	@DbField("g.banner")
+	private String banner;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("gw.sku_name")
+	private String skuName;
+
+	@DbField("sku.price")
+	private BigDecimal price;
+
+	@DbField("ifnull(gw.picture,sku.picture)")
+	private String picture;
+
+	@DbField("gw.config")
+	private String config;
+
+	@DbField("gw.is_return")
+	private Boolean isReturn;
+
+	@DbIgnore
+	private Integer total;
+
+	@DbField("gw.sorted")
+	private Integer sorted;
+}

+ 81 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleOrderDonView.java

@@ -0,0 +1,81 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GoodsWholesaleOrderDon;
+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;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleOrderDonView
+ * 创建者: JavaZou
+ * 创建时间:2024/9/3 16:15
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_wholesale_order_don go left join goods_don g on g.id = go.goods_id " +
+		" left join goods_don_sku sku on sku.id = go.sku_id" +
+		" left join goods_wholesale gw on gw.id = go.pid")
+public class GoodsWholesaleOrderDonView {
+	@DbField("go.id")
+	private Long orderId;
+
+	/**
+	 * 批发id
+	 */
+	@DbField("go.pid")
+	private Long pid;
+
+	@DbField("go.order_no")
+	private String orderNo;
+
+	@DbField("go.transaction_id")
+	private String transactionId;
+
+	@DbField("go.money")
+	private BigDecimal money;
+
+	@DbField("go.num")
+	private Integer num;
+
+	@DbField("go.type")
+	private GoodsWholesaleOrderDon.Type type;
+
+	@DbField("go.user_id")
+	private Long userId;
+
+	@DbField("go.goods_id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("go.sku_id")
+	private Long skuId;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("gw.sku_name")
+	private String skuName;
+
+	@DbField("go.balance")
+	private BigDecimal balance;
+
+	@DbField("go.status")
+	private GoodsWholesaleOrderDon.Status status;
+
+	@DbField("go.pay_time")
+	private Date payTime;
+
+	@DbField("go.created_time")
+	private Date createdTime;
+
+	@DbIgnore
+	private Boolean isDeposit;
+}

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

@@ -0,0 +1,78 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GoodsWholesaleOrderDon;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleOrderView
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 14:51
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_wholesale_order_don go left join goods_don_sku sku on sku.id = go.sku_id" +
+		" left join goods_don g on g.id = go.goods_id " +
+		" left join user u on u.id = go.user_id")
+public class GoodsWholesaleOrderView {
+
+	@DbField("go.id")
+	private Long id;
+
+	@DbField("go.goods_id")
+	private Long goodsId;
+
+	@DbField("go.sku_id")
+	private Long skuId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("go.num")
+	private Integer num;
+
+	@DbField("u.id")
+	private Long userId;
+
+	@DbField("u.nickname")
+	private String nickname;
+
+	@DbField("go.order_no")
+	private String orderNo;
+
+	@DbField("go.transaction_id")
+	private String transactionId;
+
+	@DbField("go.money")
+	private BigDecimal money;
+
+	@DbField("go.balance")
+	private BigDecimal balance;
+
+	@DbField("go.status")
+	private GoodsWholesaleOrderDon.Status status;
+
+	@DbField("go.type")
+	private GoodsWholesaleOrderDon.Type type;
+
+	@DbField("go.pay_time")
+	private Date payTime;
+
+	@DbField("go.source")
+	private String source;
+
+	@DbField("select count(1) > 0 from goods_wholesale_user_account gwua where gwua.order_id = go.id")
+	private Boolean isAccount;
+
+	@DbField("go.created_time")
+	private Date createdTime;
+}

+ 71 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GoodsWholesaleUserDepositView.java

@@ -0,0 +1,71 @@
+package com.cyksj.model.views;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.cyksj.model.entity.GoodsWholesaleUserDeposit;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: GoodsWholesaleUserDepositView
+ * 创建者: JavaZou
+ * 创建时间:2024/9/10 13:52
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_wholesale_user_deposit guwd left join user u on u.id = guwd.user_id")
+public class GoodsWholesaleUserDepositView {
+	@DbField("guwd.id")
+	private Long orderId;
+
+	@DbField("guwd.user_id")
+	private Long userId;
+
+	@DbField("guwd.money")
+	private BigDecimal money;
+
+	@DbField("guwd.type")
+	private GoodsWholesaleUserDeposit.Type type;
+
+	/**
+	 * 支付状态
+	 */
+	@DbField("guwd.status")
+	private GoodsWholesaleUserDeposit.Status status;
+
+	/**
+	 * 累积批发
+	 */
+	@TableField(exist = false)
+	@DbIgnore
+	private Integer total;
+
+
+	@DbField("guwd.order_no")
+	private String orderNo;
+
+	@DbField("guwd.transaction_id")
+	private String transactionId;
+
+	/**
+	 * 批发数达标
+	 */
+	@DbField("guwd.is_goal")
+	private Boolean isGoal;
+
+	@DbField("guwd.pay_time")
+	private Date payTime;
+
+	@DbIgnore
+	private Boolean isDeposit;
+
+	@DbField("u.nickname")
+	private String nickname;
+}
+

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

@@ -0,0 +1,76 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.GoodsWholesale;
+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;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleView
+ * 创建者: JavaZou
+ * 创建时间:2024/8/29 12:07
+ */
+@Getter
+@Setter
+@SearchBean(tables = "goods_wholesale gw left join goods_don g on g.id = gw.goods_id" +
+		" left join goods_don_sku sku on sku.id = gw.sku_id",
+		where = "gw.deleted is true")
+public class GoodsWholesaleView {
+	@DbField("gw.id")
+	private Long id;
+
+	@DbField("g.id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbField("sku.id")
+	private Long skuId;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("gw.sku_name")
+	private String skuName;
+
+	@DbField("sku.price")
+	private BigDecimal price;
+
+	@DbField("gw.status")
+	private Boolean status;
+
+	@DbField("gw.sorted")
+	private Integer sorted;
+
+	@DbField("gw.config")
+	private String config;
+
+	@DbIgnore
+	private List<GoodsWholesale.GoodsWholesaleConfig> wholesaleConfig;
+
+	/**
+	 * 返差价
+	 */
+	@DbField("gw.is_return")
+	private Boolean isReturn;
+
+	/**
+	 * 图片
+	 */
+	@DbField("gw.picture")
+	private String picture;
+
+	@DbField("gw.created_time")
+	private Date createdTime;
+
+	@DbField("gw.update_time")
+	private Date updateTime;
+}

+ 5 - 0
netflix-dao/src/main/java/com/cyksj/model/views/GroupsDataStatisticsView.java

@@ -95,4 +95,9 @@ public class GroupsDataStatisticsView {
 
 	private List<RealGoodsSourceData> realGoodsSourceDataList;
 
+	/**
+	 * 批发销售金额
+	 */
+	private BigDecimal wholesaleOrderMoney;
+
 }

+ 44 - 0
netflix-dao/src/main/java/com/cyksj/model/views/WholeGoodsSkuPayUserDetailView.java

@@ -0,0 +1,44 @@
+package com.cyksj.model.views;
+
+import com.cyksj.model.entity.BaseEntity;
+import com.ejlchina.searcher.bean.DbField;
+import com.ejlchina.searcher.bean.DbIgnore;
+import com.ejlchina.searcher.bean.SearchBean;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: WholeGoodsSkuPayUserDetailView
+ * 创建者: JavaZou
+ * 创建时间:2024/9/11 11:53
+ */
+@Getter
+@Setter
+@SearchBean(tables = "(select id,sku_id,goods_id,user_id from goods_wholesale_order_don :oid:) o left join goods_don g on g.id = o.goods_id" +
+		" left join goods_don_sku sku on sku.id = o.sku_id")
+public class WholeGoodsSkuPayUserDetailView extends BaseEntity {
+	@DbIgnore
+	private Integer total;
+
+	@DbField("o.user_id")
+	private Long userId;
+
+	@DbField("o.sku_id")
+	private Long skuId;
+
+	@DbField("sku.spec_val")
+	private String specVal;
+
+	@DbField("o.goods_id")
+	private Long goodsId;
+
+	@DbField("g.title")
+	private String title;
+
+	@DbIgnore
+	private Integer goal;
+
+	@DbIgnore
+	private Boolean isReturn;
+}

+ 38 - 0
netflix-dao/src/main/java/com/cyksj/model/views/WholesaleUserRequirementView.java

@@ -0,0 +1,38 @@
+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;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: WholesaleUserRequirementView
+ * 创建者: JavaZou
+ * 创建时间:2024/9/10 11:23
+ */
+@Getter
+@Setter
+@SearchBean(tables = "form_fields_data fd",
+		where = "promotion_id = 4",
+		groupBy = "user_id")
+public class WholesaleUserRequirementView {
+	@DbField("fd.user_id")
+	private Long userId;
+
+	@DbField("select nickname from user where id = fd.user_id")
+	private String nickname;
+
+	@DbField("GROUP_CONCAT(fd.content SEPARATOR '|')")
+	private String content;
+
+	@DbIgnore
+	private Integer num;
+
+	@DbIgnore
+	private String source;
+
+	@DbIgnore
+	private Integer total;
+}

+ 16 - 0
netflix-dao/src/main/resources/mapper/GoodsWholesaleOrderDonMapper.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.GoodsWholesaleOrderDonMapper">
+
+
+    <select id="getUserWholesaleNumByUserIds" resultType="java.lang.Integer">
+        select ifnull(sum(num),0) from goods_wholesale_order_don where status not in ('close','noPayment','refund') and user_id in
+        <foreach collection="list" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        <if test="skuId != null">
+            and sku_id = #{skuId}
+        </if>
+    </select>
+</mapper>

+ 14 - 0
netflix-dao/src/main/resources/mapper/GoodsWholesaleUserAccountMapper.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.GoodsWholesaleUserAccountMapper">
+
+    <insert id="batchInsert">
+        insert ignore into
+        goods_wholesale_user_account(`user_id`,`order_id`,`account`,`password`,`created_time`,`update_time`)
+        values
+        <foreach collection="list" item="item" separator=",">
+            (#{userId},#{orderId},#{item.account},#{item.password},now(),now())
+        </foreach>
+    </insert>
+</mapper>

+ 14 - 0
netflix-dao/src/main/resources/mapper/GoodsWholesaleUserReturnRecordMapper.xml

@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.cyksj.mapper.GoodsWholesaleUserReturnRecordMapper">
+
+    <select id="selectGoodsWholeReturnBalanceRecordByUserId"
+            resultType="com.cyksj.model.entity.GoodsWholesaleUserReturnRecord">
+        select * from goods_wholesale_user_return_record where user_id in
+        <foreach collection="list" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        and sku_id = #{skuId}
+        order by num desc limit 1
+    </select>
+</mapper>

+ 16 - 0
netflix-dao/src/main/resources/mapper/GoodsWholesaleUserSkuPayRecordMapper.xml

@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="com.cyksj.mapper.GoodsWholesaleUserSkuPayRecordMapper">
+
+    <select id="selectUserHasPaySkuDifferRecord"
+            resultType="com.cyksj.model.entity.GoodsWholesaleUserSkuPayRecord">
+        select gor.* from (select id from goods_wholesale_order_don where status not in ('close','noPayment','refund')
+        and
+        user_id in
+        <foreach collection="userIds" item="item" open="(" separator="," close=")">
+            #{item}
+        </foreach>
+        and sku_id = #{skuId}) o inner join goods_wholesale_user_sku_pay_record gor on gor.order_id = o.id
+    </select>
+</mapper>

+ 8 - 0
netflix-dao/src/main/resources/mapper/StatisticsExportMapper.xml

@@ -594,4 +594,12 @@
             and `status` not in ('close', 'noPayment', 'refund')
             and goods_id = #{goodsId} and user_id = o.user_id limit 1)
     </select>
+
+    <select id="getWholesaleOrderMoney" resultType="java.math.BigDecimal">
+        select ifnull((sum(money) - ifnull(sum(refund_money),0))/100,0)
+        from goods_wholesale_order_don
+        where `status` not in ('close', 'noPayment', 'refund')
+          and created_time >= #{startDate}
+          and created_time &lt; #{endDate}
+    </select>
 </mapper>

+ 10 - 0
netflix-service/src/main/java/com/cyksj/common/EnvCommonService.java

@@ -32,6 +32,9 @@ public class EnvCommonService {
 	@Value(value = "${wechat.domain}")
 	private String domain;
 
+	@Value(value = "${wechat.notifyDomain}")
+	private String notifyDomain;
+
 	public String getHost() {
 		if (isPreEnv()) {
 			return domain.replaceAll("8081", "8082");
@@ -39,6 +42,13 @@ public class EnvCommonService {
 		return domain;
 	}
 
+	public String getNotifyHost() {
+		if (isPreEnv()) {
+			return notifyDomain.replaceAll("8081", "8082");
+		}
+		return notifyDomain;
+	}
+
 	public String getDomain() {
 		return this.getHost().substring(0, this.getHost().indexOf("80"));
 	}

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

@@ -48,6 +48,10 @@ public class BaseZfbConfig {
 
 	public static String zfb_register_notify_url = "applets/register/prepay/zfb/notify";
 
+	public static String wholesaleNotifyUrl = "applet/wholesale/zfb/notify";
+
+	public static String wholesaleDepositNotifyUrl = "applet/wholesale/deposit/zfb/notify";
+
 	/**
 	 * qr_pay_mode PC扫码支付的方式。 跳转模式
 	 */

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

@@ -846,6 +846,7 @@ public class RedisService {
         LUMA_USER("luma_user:", "luma_user", 60 * 60 * 2L),
         LUMA_NUM_LIMIT("luma_num_limit:", "luma次数", 60 * 60 * 48L),
         NF_SET_TIME_LIMIT("nf_set_time_limit:", "设置pin码", 60l),
+        GOODS_WHOLESALE_KEY("yh_home_paghe_cache:wholesale_key", "平台批发", 60 * 60 * 4L),
         ;
 
         private String name;

+ 31 - 0
netflix-service/src/main/java/com/cyksj/service/goods/GoodsWholesaleService.java

@@ -0,0 +1,31 @@
+package com.cyksj.service.goods;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.GoodsWholesale;
+import com.cyksj.model.entity.GoodsWholesaleUserAccount;
+import com.cyksj.model.request.OrderRefundReq;
+
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleService
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 11:49
+ */
+public interface GoodsWholesaleService extends IService<GoodsWholesale> {
+	void depositRefund(Long id, Long adminId) throws Exception;
+
+	void wxRefundNotify(Map<String, String> map) throws Exception;
+
+	void uploadAccount(List<Object> acountList, Long orderId);
+
+	 void saveOrUpdateWholesale(GoodsWholesale wholesale) throws Exception;
+
+	void updateOrderAccount(List<GoodsWholesaleUserAccount> goodsWholesaleUserAccounts);
+
+	void insertOrderAccount(List<GoodsWholesaleUserAccount> goodsWholesaleUserAccounts);
+
+	void wholesaleOrderRefund(OrderRefundReq refundReq) throws Exception;
+}

+ 235 - 0
netflix-service/src/main/java/com/cyksj/service/goods/impl/GoodsWholesaleServiceImpl.java

@@ -0,0 +1,235 @@
+package com.cyksj.service.goods.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.constant.Constant;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Codec;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.Xmls;
+import com.cyksj.mapper.GoodsWholesaleMapper;
+import com.cyksj.mapper.GoodsWholesaleOrderDonMapper;
+import com.cyksj.mapper.GoodsWholesaleUserAccountMapper;
+import com.cyksj.mapper.GoodsWholesaleUserDepositMapper;
+import com.cyksj.mapper.channel.ShopConfigMapper;
+import com.cyksj.mapper.manage.cms.CmsUserMapper;
+import com.cyksj.mapper.sys.SysConfigMapper;
+import com.cyksj.model.dto.GoodsWholesaleUserDepositDto;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.OrderRefundReq;
+import com.cyksj.service.goods.GoodsWholesaleService;
+import com.cyksj.service.order.OrderRefundService;
+import com.cyksj.service.user.UserBindRelationService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.dao.DuplicateKeyException;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 11:49
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class GoodsWholesaleServiceImpl extends ServiceImpl<GoodsWholesaleMapper, GoodsWholesale> implements GoodsWholesaleService {
+	private final GoodsWholesaleUserDepositMapper goodsWholesaleUserDepositMapper;
+
+	private final OrderRefundService orderRefundService;
+
+	private final ShopConfigMapper shopConfigMapper;
+
+	private final CmsUserMapper cmsUserMapper;
+
+	private final GoodsWholesaleOrderDonMapper wholesaleOrderDonMapper;
+
+	private final GoodsWholesaleUserAccountMapper goodsWholesaleUserAccountMapper;
+
+	private final SysConfigMapper sysConfigMapper;
+
+	private final UserBindRelationService userBindRelationService;
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void depositRefund(Long id, Long adminId) throws Exception {
+		GoodsWholesaleUserDeposit goodsWholesaleUserDeposit = goodsWholesaleUserDepositMapper.selectById(id);
+		if (goodsWholesaleUserDeposit == null) {
+			throw BusinessRuntimeException.getInstance("记录不存在");
+		}
+		if (goodsWholesaleUserDeposit.getStatus() == GoodsWholesaleUserDeposit.Status.refund) {
+			throw BusinessRuntimeException.getInstance("押金已退");
+		}
+
+		int update = goodsWholesaleUserDepositMapper.update(null, Wrappers.lambdaUpdate(GoodsWholesaleUserDeposit.class)
+				.set(GoodsWholesaleUserDeposit::getStatus, GoodsWholesaleUserDeposit.Status.refund)
+				.eq(GoodsWholesaleUserDeposit::getId, id)
+				.eq(GoodsWholesaleUserDeposit::getStatus, GoodsWholesaleUserDeposit.Status.hasPayment));
+		if (update == 0) {
+			throw BusinessRuntimeException.getInstance("押金已退");
+		}
+		String outRefundNo = orderRefundService.refundWholesaleUserDeposit(goodsWholesaleUserDeposit);
+		goodsWholesaleUserDeposit.setRefundOutNo(outRefundNo);
+		Optional.ofNullable(cmsUserMapper.selectById(adminId)).ifPresent(cu -> goodsWholesaleUserDeposit.setOperator(cu.getNickname()));
+		//是否达到目标额
+		setStatusIfGoal(goodsWholesaleUserDeposit);
+		goodsWholesaleUserDeposit.setStatus(GoodsWholesaleUserDeposit.Status.refund);
+		goodsWholesaleUserDepositMapper.updateById(goodsWholesaleUserDeposit);
+	}
+
+	@Override
+	public void wxRefundNotify(Map<String, String> map) throws Exception {
+		// 对退款数据 解密
+		String md5Key = Codec.DoDigest.custom().setAlgorithm(Codec.DoDigest.Algorithm.MD5).setStringData(shopConfigMapper.getByAppId(map.get("mch_id")).getSecret()).toHexString();
+		String reqInfoXml = Codec.DoCipher.custom().setAlgorithm(Codec.DoCipher.Trans.AES_ECB_PKCS7Padding).setBase64Data(map.get("req_info")).setStringKey(md5Key).ofDecrypt().toText();
+		log.info("=== 退款数据解密: \n {}", reqInfoXml);
+		Map<String, String> reqInfoMap = Xmls.toMap(reqInfoXml);
+		// 退款失败
+		if (StrUtil.equals("CHANGE", reqInfoMap.get("refund_status"))) {
+			throw BusinessRuntimeException.getInstance("退款异常.");
+		} else if (StrUtil.equals("REFUNDCLOSE", reqInfoMap.get("refund_status"))) {
+			throw BusinessRuntimeException.getInstance("退款关闭.");
+		}
+		/* 此处处理业务逻辑 */
+		String outRefundNo = reqInfoMap.get("out_refund_no");
+		String transactionId = reqInfoMap.get("transaction_id");
+		String refundFee = reqInfoMap.get("refund_fee");
+		GoodsWholesaleUserDeposit userDeposit = goodsWholesaleUserDepositMapper.selectOne(Wrappers.lambdaQuery(GoodsWholesaleUserDeposit.class).eq(GoodsWholesaleUserDeposit::getTransactionId, transactionId).last("limit 1"));
+		if (userDeposit == null) {
+			log.error("退款回调,transactionId:{}订单不存在", transactionId);
+			return;
+		}
+		log.info("微信退款: 退款单号[{}] 退款成功.", outRefundNo);
+		if (userDeposit.getStatus()!= GoodsWholesaleUserDeposit.Status.refund) {
+			userDeposit.setStatus(GoodsWholesaleUserDeposit.Status.refund);
+			goodsWholesaleUserDepositMapper.updateById(userDeposit);
+		}
+	}
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void uploadAccount(List<Object> acountList, Long orderId) {
+		GoodsWholesaleOrderDon orderDon = wholesaleOrderDonMapper.selectById(orderId);
+
+		if (orderDon.getStatus() != GoodsWholesaleOrderDon.Status.hasPayment) {
+			throw BusinessRuntimeException.getInstance("订单状态错误");
+		}
+
+		int update = wholesaleOrderDonMapper.update(null, Wrappers.lambdaUpdate(GoodsWholesaleOrderDon.class)
+				.set(GoodsWholesaleOrderDon::getStatus, GoodsWholesaleOrderDon.Status.complete)
+				.eq(GoodsWholesaleOrderDon::getStatus, GoodsWholesaleOrderDon.Status.hasPayment)
+				.eq(GoodsWholesaleOrderDon::getId, orderId));
+		if (update == 0) {
+			throw BusinessRuntimeException.getInstance("账号已发货");
+		}
+		String regex = "----";
+
+		List<GoodsWholesaleUserAccount> insert = new ArrayList<>();
+
+		GoodsWholesaleUserAccount goodsWholesaleUserAccount = null;
+
+		for (Object obj : acountList) {
+			Map<String, Object> map = Jsons.toMap(obj);
+
+			String data = map.get(0).toString();
+
+			String[] split = data.split(regex);
+
+			String account = split[0];
+			String password = split[1];
+
+			goodsWholesaleUserAccount = new GoodsWholesaleUserAccount();
+
+			goodsWholesaleUserAccount.setAccount(account);
+			goodsWholesaleUserAccount.setPassword(password);
+			insert.add(goodsWholesaleUserAccount);
+		}
+
+		goodsWholesaleUserAccountMapper.batchInsert(orderDon.getUserId(), orderId, insert);
+	}
+
+	@Override
+	public void saveOrUpdateWholesale(GoodsWholesale wholesale) throws Exception {
+		List<GoodsWholesale.GoodsWholesaleConfig> wholesaleConfig = wholesale.getWholesaleConfig();
+		String config = Jsons.toJson(wholesaleConfig);
+		wholesale.setConfig(config);
+		try {
+			this.saveOrUpdate(wholesale);
+		} catch (DuplicateKeyException e) {
+			throw BusinessRuntimeException.getInstance("已存在该批发规格");
+		}
+	}
+
+	@Override
+	public void updateOrderAccount(List<GoodsWholesaleUserAccount> goodsWholesaleUserAccounts) {
+		goodsWholesaleUserAccounts.forEach(order -> {
+			goodsWholesaleUserAccountMapper.updateById(order);
+			if (order.getId() == null) {
+				goodsWholesaleUserAccountMapper.insert(order);
+			}
+		});
+	}
+
+	@Override
+	public void insertOrderAccount(List<GoodsWholesaleUserAccount> goodsWholesaleUserAccounts) {
+		goodsWholesaleUserAccounts.forEach(order -> {
+			goodsWholesaleUserAccountMapper.insert(order);
+		});
+		if (CollUtil.isNotEmpty(goodsWholesaleUserAccounts)) {
+			Long orderId = goodsWholesaleUserAccounts.get(0).getOrderId();
+			GoodsWholesaleOrderDon orderDon = wholesaleOrderDonMapper.selectById(orderId);
+			orderDon.setStatus(GoodsWholesaleOrderDon.Status.complete);
+			wholesaleOrderDonMapper.updateById(orderDon);
+		}
+	}
+
+	@Override
+	public void wholesaleOrderRefund(OrderRefundReq refundReq) throws Exception {
+		Long orderId = refundReq.getOrderId();
+		GoodsWholesaleOrderDon orderDon = wholesaleOrderDonMapper.selectById(orderId);
+		if (orderDon == null) {
+			return;
+		}
+		//余额
+		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
+			return;
+		}
+		if (orderDon.getStatus() == GoodsWholesaleOrderDon.Status.refund) {
+			return;
+		}
+		orderDon.setRefundMoney(refundReq.getRefundMoney());
+		String outRefundNo = orderRefundService.refundWholesaleOrder(orderDon);
+		orderDon.setOutRefundNo(outRefundNo);
+		orderDon.setStatus(GoodsWholesaleOrderDon.Status.refund);
+		wholesaleOrderDonMapper.updateById(orderDon);
+	}
+
+	private void setStatusIfGoal(GoodsWholesaleUserDeposit goodsWholesaleUserDeposit) throws Exception {
+		//是否已满足 批发足够账号
+		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.WHOLESALE_DEPOSIT_KEY)
+				.last("limit 1"));
+		if (sysConfig == null || StrUtil.isEmpty(sysConfig.getSysValue())) {
+			log.error("押金配置已失效");
+			return;
+		}
+		GoodsWholesaleUserDepositDto goodsWholesaleUserDepositDto = Jsons.parseObject(sysConfig.getSysValue(), GoodsWholesaleUserDepositDto.class);
+		Integer num = goodsWholesaleUserDepositDto.getNum();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(goodsWholesaleUserDeposit.getUserId(), null);
+		Integer payNum = wholesaleOrderDonMapper.getUserWholesaleNumByUserIds(userIdList, null);
+		if (payNum >= num) {
+			//批发数量已达
+			goodsWholesaleUserDeposit.setIsGoal(true);
+		}
+	}
+}

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/mange/RefreshCacheService.java

@@ -32,4 +32,6 @@ public interface RefreshCacheService {
 	void refreshUserShopMangeCache(String customId);
 
 	void goodsQuestionCache();
+
+	void refreshWholesaleGoods();
 }

+ 6 - 0
netflix-service/src/main/java/com/cyksj/service/mange/impl/RefreshCacheServiceImpl.java

@@ -60,4 +60,10 @@ public class RefreshCacheServiceImpl implements RefreshCacheService {
 		//售后缓存
 		redisService.del(redisService.keys(RedisService.key.YH_GOODS_QUESTIONS_DETAIL.name().toLowerCase() + "*").toArray(String[]::new));
 	}
+
+	@Override
+	public void refreshWholesaleGoods() {
+		Set<String> keys = redisService.keys(RedisService.key.GOODS_WHOLESALE_KEY.getName() + "*");
+		redisService.del(keys.toArray(String[]::new));
+	}
 }

+ 2 - 0
netflix-service/src/main/java/com/cyksj/service/mange/statistics/impl/StatisticsDataServiceImpl.java

@@ -450,9 +450,11 @@ public class StatisticsDataServiceImpl implements StatisticsDataService {
 		BigDecimal unBIndGroupsAiOrderMoney = Optional.ofNullable(statisticsExportMapper.getMonthGoodsTypeAmountOfOrderByType(4, null, 1l, startDate, endDate, true)).orElse(BigDecimal.ZERO);
 		//设备销售金额
 		BigDecimal unBIndGroupsEpOrderMoney = Optional.ofNullable(statisticsExportMapper.getMonthGoodsTypeAmountOfOrderByType(4, 2, null, startDate, endDate, true)).orElse(BigDecimal.ZERO);
+		BigDecimal wholesaleOrderMoney = Optional.ofNullable(statisticsExportMapper.getWholesaleOrderMoney(startDate, endDate)).orElse(BigDecimal.ZERO);
 		groupsDataStatisticsView.setUnBIndGroupsStreamingMoney(unBIndGroupsStreamingMoney);
 		groupsDataStatisticsView.setUnBIndGroupsAiOrderMoney(unBIndGroupsAiOrderMoney);
 		groupsDataStatisticsView.setUnBIndGroupsEpOrderMoney(unBIndGroupsEpOrderMoney);
+		groupsDataStatisticsView.setWholesaleOrderMoney(wholesaleOrderMoney);
 	}
 
 	public void getNatureOrderData(GroupsDataStatisticsView groupsDataStatisticsView, String startDate, String endDate) {

+ 33 - 0
netflix-service/src/main/java/com/cyksj/service/order/GoodsWholesalePayService.java

@@ -0,0 +1,33 @@
+package com.cyksj.service.order;
+
+import com.cyksj.model.dto.AliPayParams;
+import com.cyksj.model.entity.GoodsWholesaleOrderDon;
+import com.cyksj.model.entity.GoodsWholesaleUserDeposit;
+import com.cyksj.model.request.AlipayOrderDonReq;
+import com.cyksj.model.request.GoodsWholesaleOrderPayReq;
+
+import java.util.Map;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesalePayService
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 18:43
+ */
+public interface GoodsWholesalePayService {
+	GoodsWholesaleOrderDon unifiedPay(GoodsWholesaleOrderPayReq payReq) throws Exception;
+
+	AliPayParams aliPayWholesale(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception;
+
+	AliPayParams zfbWholesaleWebQrCode(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception;
+
+	void aliPayWholesaleNotify(Map<String, String> params) throws Exception;
+
+	GoodsWholesaleUserDeposit submitDeposit(Long userId) throws Exception;
+
+	void aliPayWholesaleDepositNotify(Map<String, String> params) throws Exception;
+
+	void closeWholesaleOrder(Long orderId, long userId) throws Exception;
+
+	Object getOrderStatus(Long userId, Integer type, Long orderId);
+}

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

@@ -25,4 +25,7 @@ public interface OrderRefundService {
 	 */
 	void refundUpgradeRecord(UpgradeOrderDon orderDon, BigDecimal refundMoney, UpgradePackage upgradePackage, String operator, String outRefundNo, String refundType, String chatImg);
 
+	String refundWholesaleUserDeposit(GoodsWholesaleUserDeposit goodsWholesaleUserDeposit) throws Exception;
+
+	String refundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception;
 }

+ 585 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/GoodsWholesalePayServiceImpl.java

@@ -0,0 +1,585 @@
+package com.cyksj.service.order.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.lang.Assert;
+import cn.hutool.core.util.StrUtil;
+import com.alipay.api.internal.util.AlipaySignature;
+import com.alipay.api.response.AlipayTradeQueryResponse;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.constant.Constant;
+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.BaseZfbConfig;
+import com.cyksj.mapper.*;
+import com.cyksj.mapper.channel.ShopConfigMapper;
+import com.cyksj.mapper.sys.SysConfigMapper;
+import com.cyksj.model.dto.AliPayParams;
+import com.cyksj.model.dto.GoodsWholesaleUserDepositDto;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.AlipayOrderDonReq;
+import com.cyksj.model.request.GoodsWholesaleOrderPayReq;
+import com.cyksj.model.request.OrderAttach;
+import com.cyksj.model.views.GoodsWholesaleOrderDonView;
+import com.cyksj.model.views.GoodsWholesaleUserDepositView;
+import com.cyksj.service.order.GoodsWholesalePayService;
+import com.cyksj.service.order.OrderDonService;
+import com.cyksj.service.order.OrderRefundService;
+import com.cyksj.service.pay.AliPayCommonService;
+import com.cyksj.service.user.UserBenefitsService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.cyksj.service.wechat.WeChatService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.stream.Collectors;
+
+/**
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesalePayServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 18:43
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class GoodsWholesalePayServiceImpl implements GoodsWholesalePayService {
+	private final GoodsWholesaleOrderDonMapper goodsWholesaleOrderDonMapper;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final GoodsWholesaleMapper goodsWholesaleMapper;
+
+	private final GoodsDonSkuMapper skuMapper;
+
+	private static final Sequence SEQUENCE = new Sequence(0);
+
+	private final AliPayCommonService aliPayCommonService;
+
+	private final ShopConfigMapper shopConfigMapper;
+
+	private final GoodsWholesaleUserReturnRecordMapper goodsWholesaleUserReturnRecordMapper;
+
+	private final SysConfigMapper sysConfigMapper;
+
+	private final GoodsWholesaleUserDepositMapper depositMapper;
+
+	private final OrderRefundService orderRefundService;
+
+	private final UserBenefitsService userBenefitsService;
+
+	private final UserMapper userMapper;
+
+	private final BeanSearcher beanSearcher;
+
+	private final OrderDonService orderDonService;
+
+	private final WeChatService weChatService;
+
+	private final GoodsDonMapper goodsDonMapper;
+
+	private final GoodsWholesaleUserSkuPayRecordMapper goodsWholesaleUserSkuPayRecordMapper;
+
+	@Override
+	public GoodsWholesaleOrderDon unifiedPay(GoodsWholesaleOrderPayReq payReq) throws Exception {
+		Long userId = payReq.getUserId();
+		Long id = payReq.getId();
+		GoodsWholesale goodsWholesale = goodsWholesaleMapper.selectById(id);
+		Assert.notNull(goodsWholesale, "商品不存在");
+
+		if (!goodsWholesale.getStatus()) {
+			Assert.notNull(goodsWholesale, "商品已下架");
+		}
+		if (!goodsWholesale.getDeleted()) {
+			throw BusinessRuntimeException.getInstance("商品不存在");
+		}
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		Integer selectCount = goodsWholesaleOrderDonMapper.selectCount(Wrappers.lambdaQuery(GoodsWholesaleOrderDon.class)
+				.eq(GoodsWholesaleOrderDon::getSkuId, goodsWholesale.getSkuId())
+				.in(GoodsWholesaleOrderDon::getUserId, userIdList)
+				.eq(GoodsWholesaleOrderDon::getStatus, GoodsWholesaleOrderDon.Status.noPayment));
+		if (selectCount > 0) {
+			throw BusinessRuntimeException.getInstance("已有待支付订单");
+		}
+		GoodsDonSku sku = skuMapper.selectById(goodsWholesale.getSkuId());
+		if (sku == null) {
+			throw BusinessRuntimeException.getInstance("规格不存在");
+		}
+		if (!sku.getStatus()) {
+			throw BusinessRuntimeException.getInstance("规格已下架");
+		}
+		GoodsWholesaleOrderDon orderDon = new GoodsWholesaleOrderDon();
+		//设置订单金额
+		getNeedPaySinglePrice(orderDon, sku, payReq.getNum(), goodsWholesale, userIdList);
+		User user = userMapper.selectById(userId);
+		BigDecimal balance = payReq.getBalance();
+		orderDon.setUserId(userId);
+		orderDon.setGoodsId(goodsWholesale.getGoodsId());
+		orderDon.setSkuId(goodsWholesale.getSkuId());
+		//批发id
+		orderDon.setPid(id);
+		String orderNo = SEQUENCE.nextId().toString();
+		orderDon.setOrderNo(orderNo);
+		orderDon.setStatus(GoodsWholesaleOrderDon.Status.noPayment);
+		orderDon.setNum(payReq.getNum());
+		if (balance != null) {
+			deductBalancePayOrderMoney(orderDon, balance, user);
+		}
+		//余额支付
+		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) == 0) {
+			orderDon.setStatus(GoodsWholesaleOrderDon.Status.hasPayment);
+			orderDon.setType(GoodsWholesaleOrderDon.Type.BALANCE);
+			orderDon.setPayTime(DateTime.now());
+		}
+		orderDon.setType(GoodsWholesaleOrderDon.Type.ALI_PAY);
+		goodsWholesaleOrderDonMapper.insert(orderDon);
+		//是否需要记录差价
+		if (orderDon.getIsRecordDiffer()) {
+			//记录此时购买该级别的数量 返差价
+			recordUserPaySkuDifferPrice(orderDon);
+		}
+		//已支付回调
+		if (orderDon.getStatus() == GoodsWholesaleOrderDon.Status.hasPayment) {
+			//处理批发订单回调
+			unifiedHandleGoodsWholesaleOrderDon(orderDon);
+		}
+		return orderDon;
+	}
+
+	private void recordUserPaySkuDifferPrice(GoodsWholesaleOrderDon orderDon) {
+		GoodsWholesaleUserSkuPayRecord skuPayRecord = new GoodsWholesaleUserSkuPayRecord();
+		skuPayRecord.setSkuId(orderDon.getSkuId());
+		skuPayRecord.setGoodsId(orderDon.getGoodsId());
+		skuPayRecord.setNum(orderDon.getNum());
+		BigDecimal totalMoney = orderDon.getMoney().add(Optional.ofNullable(orderDon.getBalance()).orElse(BigDecimal.ZERO));
+		BigDecimal single = totalMoney.divide(BigDecimal.valueOf(orderDon.getNum()));
+		skuPayRecord.setSingle(single);
+		skuPayRecord.setOrderId(orderDon.getId());
+		skuPayRecord.setUserId(orderDon.getUserId());
+		goodsWholesaleUserSkuPayRecordMapper.insert(skuPayRecord);
+	}
+
+	@Override
+	public AliPayParams aliPayWholesale(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception {
+		if (re.getIsDeposit()) {
+			return aliPayCommonService.aliPayUnifiedWholesaleDeposit(re, productCode, qrPayMode);
+		}
+		return aliPayCommonService.aliPayUnifiedWholesale(re, productCode, qrPayMode);
+	}
+
+	@Override
+	public AliPayParams zfbWholesaleWebQrCode(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception {
+		if (re.getIsDeposit()) {
+			return aliPayCommonService.aliPayUnifiedWholesaleDeposit(re, productCode, qrPayMode);
+		}
+		return aliPayCommonService.aliPayUnifiedWholesale(re, productCode, qrPayMode);
+	}
+
+	@Override
+	public void aliPayWholesaleNotify(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();
+		GoodsWholesaleOrderDon orderDon = goodsWholesaleOrderDonMapper.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 = Optional.ofNullable(params.get("buyer_id")).orElse(params.get("buyer_open_id"));
+		log.info("批发支付宝回调信息:{}", Jsons.toJson(params));
+		if (!orderDon.getStatus().equals(GoodsWholesaleOrderDon.Status.noPayment) && !orderDon.getStatus().equals(GoodsWholesaleOrderDon.Status.close)) {
+			log.info("批发支付宝已回调,重复修改状态 id:{}", orderDon.getId());
+			return;
+		}
+		Date payTime = DateTime.now();
+		if (StringUtils.isNotBlank(payTimeStr)) {
+			payTime = DateUtil.parse(payTimeStr, "yyyy-MM-dd HH:mm:ss");
+		}
+		// 更改订单状态
+		orderDon.setStatus(GoodsWholesaleOrderDon.Status.hasPayment);
+		orderDon.setTransactionId(transactionId);
+		orderDon.setPayTime(payTime);
+		orderDon.setShopId(appId);
+		orderDon.setType(GoodsWholesaleOrderDon.Type.ALI_PAY);
+		orderDon.setBuyerId(buyerId);
+		goodsWholesaleOrderDonMapper.updateById(orderDon);
+		//处理批发订单回调
+		unifiedHandleGoodsWholesaleOrderDon(orderDon);
+	}
+
+	private void returnWholesaleBalanceDiffer(GoodsWholesaleOrderDon orderDon, List<Long> userIdList) throws Exception {
+		//批发补差价
+		Long skuId = orderDon.getSkuId();
+		GoodsWholesale goodsWholesale = goodsWholesaleMapper.selectOne(Wrappers.lambdaQuery(GoodsWholesale.class)
+				.eq(GoodsWholesale::getSkuId, skuId)
+				.eq(GoodsWholesale::getDeleted, 1)
+				.eq(GoodsWholesale::getStatus, 1)
+				.last("limit 1"));
+		if (goodsWholesale != null && goodsWholesale.getIsReturn()) {
+			//目前购买多少个
+			Integer payNum = goodsWholesaleOrderDonMapper.getUserWholesaleNumByUserIds(userIdList, orderDon.getSkuId());
+			log.info("目前用户userId:{}购买批发数量:{}", orderDon.getUserId(), payNum);
+			List<GoodsWholesale.GoodsWholesaleConfig> configs = Jsons.parseList(goodsWholesale.getConfig(), GoodsWholesale.GoodsWholesaleConfig.class);
+			if (configs.size() == 1) {
+				return;
+			}
+			GoodsWholesale.GoodsWholesaleConfig firstConfig = configs.get(0);
+			GoodsWholesale.GoodsWholesaleConfig endConfig = configs.get(configs.size() - 1);
+			//未超过第一档
+			if (payNum <= firstConfig.getEnd()) {
+				return;
+			}
+			configs.remove(endConfig);
+			GoodsWholesaleUserReturnRecord goodsWholesaleUserReturnRecord = goodsWholesaleUserReturnRecordMapper.selectGoodsWholeReturnBalanceRecordByUserId(userIdList, skuId);
+			if (goodsWholesaleUserReturnRecord != null) {
+				log.info("用户:{}之前已返差价", orderDon.getUserId());
+				return;
+			}
+			//最高
+			if (payNum >= endConfig.getStart()) {
+				BigDecimal returnBalance = BigDecimal.ZERO;
+				List<GoodsWholesaleUserSkuPayRecord> userHasPaySkuDifferRecord = goodsWholesaleUserSkuPayRecordMapper.selectUserHasPaySkuDifferRecord(userIdList, skuId);
+				if (CollUtil.isEmpty(userHasPaySkuDifferRecord)) {
+					log.info("用户:{}无skuId:{}返差价的数量", orderDon.getUserId(), orderDon.getSkuId());
+					return;
+				}
+				BigDecimal endConfigSingle = endConfig.getSingle();
+				for (GoodsWholesaleUserSkuPayRecord skuPayRecord : userHasPaySkuDifferRecord) {
+					Integer num = skuPayRecord.getNum();
+					BigDecimal thisLevelSingle = skuPayRecord.getSingle();
+					returnBalance = returnBalance.add(thisLevelSingle.subtract(endConfigSingle).multiply(BigDecimal.valueOf(num)));
+				}
+				try {
+					log.info("用户:{}批发返skuId:{}差价", orderDon.getUserId(), skuId);
+					GoodsWholesaleUserReturnRecord newRecord = new GoodsWholesaleUserReturnRecord();
+					newRecord.setNum(endConfig.getStart() - 1);
+					newRecord.setGoodsId(orderDon.getGoodsId());
+					newRecord.setSkuId(orderDon.getSkuId());
+					newRecord.setReturnBalance(returnBalance);
+					newRecord.setUserId(orderDon.getUserId());
+					goodsWholesaleUserReturnRecordMapper.insert(newRecord);
+					//返余额差价
+					userBenefitsService.addUserBalance(orderDon.getUserId(), returnBalance, UserBalanceSourceRecord.Source.wholesale_differ, 0l, orderDon.getId(), UserBalanceSourceRecord.Source.wholesale_differ.getDesc(), true);
+				} catch (Exception e) {
+					log.error("返用户:{}差价错误:{}", orderDon.getUserId(), StringUtil.getErrorText(e));
+				}
+			}
+		}
+	}
+
+	@Override
+	public GoodsWholesaleUserDeposit submitDeposit(Long userId) throws Exception {
+		//是否已支付押金
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+
+		GoodsWholesaleUserDeposit deposit = depositMapper.selectOne(Wrappers.lambdaQuery(GoodsWholesaleUserDeposit.class).in(GoodsWholesaleUserDeposit::getUserId, userIdList));
+		if (deposit != null && deposit.getStatus() == GoodsWholesaleUserDeposit.Status.hasPayment) {
+			throw BusinessRuntimeException.getInstance("您已支付过押金");
+		}
+
+		if (deposit == null) {
+			deposit = new GoodsWholesaleUserDeposit();
+			deposit.setUserId(userId);
+			String orderNo = SEQUENCE.nextId().toString();
+			deposit.setOrderNo(orderNo);
+			deposit.setType(GoodsWholesaleUserDeposit.Type.ALI_PAY);
+		}
+		deposit.setStatus(GoodsWholesaleUserDeposit.Status.noPayment);
+		SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+				.eq(SysConfig::getSysKey, Constant.WHOLESALE_DEPOSIT_KEY)
+				.last("limit 1"));
+		if (sysConfig == null || StrUtil.isEmpty(sysConfig.getSysValue())) {
+			throw BusinessRuntimeException.getInstance("未配置押金,请联系客服");
+		}
+		GoodsWholesaleUserDepositDto goodsWholesaleUserDepositDto = Jsons.parseObject(sysConfig.getSysValue(), GoodsWholesaleUserDepositDto.class);
+		deposit.setMoney(goodsWholesaleUserDepositDto.getDeposit());
+
+		if (deposit.getId() == null) {
+			depositMapper.insert(deposit);
+		} else {
+			if (StrUtil.isNotBlank(deposit.getRefundOutNo())) {
+				deposit.setOrderNo(SEQUENCE.nextId().toString());
+			}
+			depositMapper.updateById(deposit);
+		}
+		return deposit;
+	}
+
+	@Override
+	public void aliPayWholesaleDepositNotify(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();
+		GoodsWholesaleUserDeposit orderDon = depositMapper.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 = Optional.ofNullable(params.get("buyer_id")).orElse(params.get("buyer_open_id"));
+		log.info("押金支付宝回调信息:{}", Jsons.toJson(params));
+		if (!orderDon.getStatus().equals(GoodsWholesaleUserDeposit.Status.noPayment)) {
+			log.info("押金支付宝已回调,重复修改状态 id:{}", orderDon.getId());
+			return;
+		}
+		Date payTime = DateTime.now();
+		if (StringUtils.isNotBlank(payTimeStr)) {
+			payTime = DateUtil.parse(payTimeStr, "yyyy-MM-dd HH:mm:ss");
+		}
+		// 更改订单状态
+		orderDon.setStatus(GoodsWholesaleUserDeposit.Status.hasPayment);
+		orderDon.setTransactionId(transactionId);
+		orderDon.setPayTime(payTime);
+		orderDon.setShopId(appId);
+		orderDon.setType(GoodsWholesaleUserDeposit.Type.ALI_PAY);
+		orderDon.setBuyerId(buyerId);
+		orderDon.setRefundOutNo(StrUtil.EMPTY);
+		depositMapper.updateById(orderDon);
+	}
+
+	@Override
+	public void closeWholesaleOrder(Long orderId, long userId) throws Exception {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		GoodsWholesaleOrderDon orderDon = goodsWholesaleOrderDonMapper.selectOne(Wrappers.lambdaQuery(GoodsWholesaleOrderDon.class)
+				.eq(GoodsWholesaleOrderDon::getId, orderId)
+				.in(GoodsWholesaleOrderDon::getUserId, userIdList)
+				.last("limit 1"));
+		if (orderDon == null) {
+			return;
+		}
+		if (orderDon.getStatus() != GoodsWholesaleOrderDon.Status.noPayment) {
+			return;
+		}
+		orderDon.setStatus(GoodsWholesaleOrderDon.Status.close);
+		GoodsWholesaleOrderDon.Status hasPaid = isHasPaid(orderDon);
+		if (hasPaid == GoodsWholesaleOrderDon.Status.hasPayment) {
+			unifiedHandleGoodsWholesaleOrderDon(orderDon);
+		}
+		goodsWholesaleOrderDonMapper.updateById(orderDon);
+	}
+
+	@Override
+	public Object getOrderStatus(Long userId, Integer type, Long orderId) {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		if (type == 1) {
+			GoodsWholesaleUserDepositView goodsWholesaleUserDepositView = beanSearcher.searchFirst(GoodsWholesaleUserDepositView.class, MapUtils.builder().field(GoodsWholesaleUserDepositView::getUserId, userIdList).op(Operator.InList).build());
+			if (goodsWholesaleUserDepositView != null) {
+				goodsWholesaleUserDepositView.setIsDeposit(true);
+			}
+			return goodsWholesaleUserDepositView;
+		}
+		GoodsWholesaleOrderDonView orderDon = beanSearcher.searchFirst(GoodsWholesaleOrderDonView.class, MapUtils.builder().field(GoodsWholesaleOrderDonView::getUserId, userIdList).op(Operator.InList)
+				.field(GoodsWholesaleOrderDonView::getOrderId, orderId).build());
+		if (orderDon != null) {
+			orderDon.setIsDeposit(false);
+		}
+		return orderDon;
+	}
+
+
+	/**
+	 * 退还押金
+	 */
+	public void returnDeposit(GoodsWholesaleOrderDon orderDon, List<Long> userIdList) throws Exception {
+		GoodsWholesaleUserDeposit goodsWholesaleUserDeposit = depositMapper.selectOne(Wrappers.lambdaQuery(GoodsWholesaleUserDeposit.class)
+				.in(GoodsWholesaleUserDeposit::getUserId, userIdList)
+				.eq(GoodsWholesaleUserDeposit::getStatus, GoodsWholesaleUserDeposit.Status.hasPayment)
+				.last("limit 1"));
+		if (goodsWholesaleUserDeposit != null) {
+			//是否已满足 批发足够账号
+			SysConfig sysConfig = sysConfigMapper.selectOne(Wrappers.lambdaQuery(SysConfig.class)
+					.eq(SysConfig::getSysKey, Constant.WHOLESALE_DEPOSIT_KEY)
+					.last("limit 1"));
+			if (sysConfig == null || StrUtil.isEmpty(sysConfig.getSysValue())) {
+				log.error("押金配置已失效");
+				return;
+			}
+			GoodsWholesaleUserDepositDto goodsWholesaleUserDepositDto = Jsons.parseObject(sysConfig.getSysValue(), GoodsWholesaleUserDepositDto.class);
+			Integer num = goodsWholesaleUserDepositDto.getNum();
+			Integer payNum = goodsWholesaleOrderDonMapper.getUserWholesaleNumByUserIds(userIdList, null);
+			if (payNum >= num) {
+				//腿还押金
+				try {
+					String outNo = orderRefundService.refundWholesaleUserDeposit(goodsWholesaleUserDeposit);
+					goodsWholesaleUserDeposit.setRefundOutNo(outNo);
+					goodsWholesaleUserDeposit.setStatus(GoodsWholesaleUserDeposit.Status.refund);
+					//批发数量已达
+					goodsWholesaleUserDeposit.setIsGoal(true);
+					depositMapper.updateById(goodsWholesaleUserDeposit);
+				} catch (Exception e) {
+					log.info("押金退款错误:{}", StringUtil.getErrorText(e));
+				}
+			}
+		}
+	}
+
+	private void getNeedPaySinglePrice(GoodsWholesaleOrderDon orderDon, GoodsDonSku sku, Integer thisPayNum, GoodsWholesale goodsWholesale, List<Long> userIdList) throws Exception {
+		//是否交过押金
+		GoodsWholesaleUserDeposit deposit = depositMapper.selectOne(Wrappers.lambdaQuery(GoodsWholesaleUserDeposit.class)
+				.in(GoodsWholesaleUserDeposit::getUserId, userIdList)
+				.last("limit 1"));
+		//未支付押金 或批发数量未达到且已退款 使用规格单价
+		if (deposit == null || (!deposit.getIsGoal() && deposit.getStatus() == GoodsWholesaleUserDeposit.Status.refund)) {
+			orderDon.setMoney(BigDecimal.valueOf(thisPayNum).multiply(sku.getPrice()));
+			return;
+		}
+		String configStr = goodsWholesale.getConfig();
+		List<GoodsWholesale.GoodsWholesaleConfig> configs = Jsons.parseList(configStr, GoodsWholesale.GoodsWholesaleConfig.class);
+		GoodsWholesale.GoodsWholesaleConfig firstConfig = configs.get(0);
+		Integer hasPaidNum = goodsWholesaleOrderDonMapper.getUserWholesaleNumByUserIds(userIdList, goodsWholesale.getSkuId());
+		Integer endPayNum = hasPaidNum + thisPayNum;
+		//未超过第一档
+		if (endPayNum <= firstConfig.getEnd()) {
+			orderDon.setIsRecordDiffer(true);
+			orderDon.setMoney(BigDecimal.valueOf(thisPayNum).multiply(firstConfig.getSingle()));
+			return;
+		}
+		if (configs.size() == 1) {
+			throw BusinessRuntimeException.getInstance("您已无法批发下单该规格");
+		}
+		GoodsWholesale.GoodsWholesaleConfig endConfig = configs.get(configs.size() - 1);
+		//超过最后
+		if (endPayNum >= endConfig.getStart()) {
+			orderDon.setMoney(BigDecimal.valueOf(thisPayNum).multiply(endConfig.getSingle()));
+			return;
+		}
+		if (endConfig.getEnd().intValue() != 999 && endPayNum > endConfig.getEnd()) {
+			throw BusinessRuntimeException.getInstance("您已超过购买该规格批发数量");
+		}
+		Optional<GoodsWholesale.GoodsWholesaleConfig> first = configs.stream().filter(config -> config.getStart() <= endPayNum && config.getEnd() >= endPayNum).collect(Collectors.toList()).stream().findFirst();
+		GoodsWholesale.GoodsWholesaleConfig thisLevel = first.get();
+		BigDecimal single = thisLevel.getSingle();
+		BigDecimal needPayMoney = BigDecimal.valueOf(thisPayNum).multiply(single);
+		orderDon.setMoney(needPayMoney);
+		//是否需要记录差价
+		orderDon.setIsRecordDiffer(true);
+
+
+//		//之前的
+//		List<GoodsWholesale.GoodsWholesaleConfig> before = configs.stream().filter(config -> config.getEnd() < finalLevel.getStart() && config.getEnd() > hasPaidNum).collect(Collectors.toList());
+//		BigDecimal finalPayMoney = BigDecimal.ZERO;
+//		Integer finalLevelPayNum = thisPayNum;
+//		Integer beforeHasPayNum = hasPaidNum;
+//		for (GoodsWholesale.GoodsWholesaleConfig goodsWholesaleConfig : before) {
+//			Integer thisLevelPayNum = goodsWholesaleConfig.getEnd() - beforeHasPayNum;
+//			beforeHasPayNum = goodsWholesaleConfig.getEnd();
+//			finalPayMoney = finalPayMoney.add(BigDecimal.valueOf(thisLevelPayNum).multiply(goodsWholesaleConfig.getSingle()));
+//			finalLevelPayNum -= thisLevelPayNum;
+//		}
+//		if (finalLevelPayNum > 0) {
+//			finalPayMoney = finalPayMoney.add(BigDecimal.valueOf(finalLevelPayNum).multiply(finalLevel.getSingle()));
+//		}
+//		orderDon.setMoney(finalPayMoney);
+	}
+
+	/**
+	 * 统一处理批发订单回调
+	 */
+	public void unifiedHandleGoodsWholesaleOrderDon(GoodsWholesaleOrderDon orderDon) throws Exception {
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(orderDon.getUserId(), null);
+		//退还押金
+		returnDeposit(orderDon, userIdList);
+		//返批发余额差价
+		returnWholesaleBalanceDiffer(orderDon, userIdList);
+
+		//余额使用记录
+		if (orderDon.getBalance().compareTo(BigDecimal.ZERO) > 0) {
+			Long goodsId = orderDon.getGoodsId();
+			GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
+			userBenefitsService.recordBalanceBySource(orderDon.getUserId(), orderDon.getBalance().negate(), UserBalanceSourceRecord.Source.wholesale_order, orderDon.getId(), goodsDon.getTitle() + UserBalanceSourceRecord.Source.wholesale_order.getDesc());
+		}
+	}
+
+	/**
+	 * 扣除余额
+	 */
+	public void deductBalancePayOrderMoney(GoodsWholesaleOrderDon 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(GoodsWholesaleOrderDon.Type.BALANCE);
+			}
+			BigDecimal userBalance = user.getBalance();
+			//扣除余额 是否成功
+			Integer success = userMapper.deductBalance(user.getId(), subBalance, userBalance);
+			if (success != 1) throw BusinessRuntimeException.getInstance("您的余额不足!");
+			orderDon.setBalance(subBalance);
+		}
+	}
+
+	public GoodsWholesaleOrderDon.Status isHasPaid(GoodsWholesaleOrderDon orderDon) {
+		if (orderDon.getType() == GoodsWholesaleOrderDon.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(GoodsWholesaleOrderDon.Status.hasPayment);
+						orderDon.setPayTime(DateTime.now());
+						orderDon.setTransactionId(reMap.get("transaction_id"));
+					}
+				}
+			} catch (Exception e) {
+
+			}
+		} else if (orderDon.getType() == GoodsWholesaleOrderDon.Type.ALI_PAY) {
+			try {
+				AlipayTradeQueryResponse zfbOrderDetail = orderDonService.getZfbOrderDetail(orderDon.getShopId(), orderDon.getOrderNo());
+				if (zfbOrderDetail != null) {
+					String tradeStatus = zfbOrderDetail.getTradeStatus();
+					if ("TRADE_SUCCESS".equals(tradeStatus)) {
+						orderDon.setStatus(GoodsWholesaleOrderDon.Status.hasPayment);
+						orderDon.setTransactionId(zfbOrderDetail.getTradeNo());
+						Date sendPayDate = zfbOrderDetail.getSendPayDate();
+						orderDon.setPayTime(sendPayDate);
+						//买家支付宝账号
+						String buyerId = Optional.ofNullable(zfbOrderDetail.getBuyerUserId()).orElse(zfbOrderDetail.getBuyerOpenId());
+						orderDon.setBuyerId(buyerId);
+					}
+				}
+			} catch (Exception e) {
+
+			}
+		}
+		return orderDon.getStatus();
+	}
+
+}

+ 137 - 0
netflix-service/src/main/java/com/cyksj/service/order/impl/OrderRefundServiceImpl.java

@@ -145,6 +145,97 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 		refundUpgradeOrderDonMapper.insert(refund);
 	}
 
+	@Override
+	public String refundWholesaleUserDeposit(GoodsWholesaleUserDeposit goodsWholesaleUserDeposit) throws Exception {
+		GoodsWholesaleUserDeposit.Type type = goodsWholesaleUserDeposit.getType();
+		if (type == GoodsWholesaleUserDeposit.Type.WeChat) {
+			return wxRefundWholesaleUserDeposit(goodsWholesaleUserDeposit);
+		}
+		if (type == GoodsWholesaleUserDeposit.Type.ALI_PAY) {
+			return zfbRefundWholesaleUserDeposit(goodsWholesaleUserDeposit);
+		}
+		return StrUtil.EMPTY;
+	}
+
+	private String wxRefundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception {
+		BigDecimal money = orderDon.getRefundMoney();
+		if (money.compareTo(BigDecimal.ZERO) <=0){
+			return StrUtil.EMPTY;
+		}
+		long time = System.currentTimeMillis();
+		//退款订单号
+		String outRefundNo = Codec.DoDigest.custom()
+				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
+				.setStringData(time + String.valueOf(orderDon.getId()))
+				.toHexString();
+		log.info("退押金退款订单号:{}", outRefundNo);
+		weChatService.refundWxOrder(weChatConfig.getAppid(),
+				Optional.ofNullable(orderDon.getShopId()).orElse(ShopConfig.WX_DEFAULT_APP_ID),
+				orderDon.getTransactionId(),
+				outRefundNo,
+				money,
+				money,
+				weChatConfig.getDomain() + "manage/goods/whole/sale/deposit/refund/notify");
+		//记录退款信息
+		return outRefundNo;
+	}
+
+	private String zfbRefundWholesaleUserDeposit(GoodsWholesaleUserDeposit goodsWholesaleUserDeposit) throws Exception {
+		BigDecimal money = goodsWholesaleUserDeposit.getMoney();
+		if (money.compareTo(BigDecimal.ZERO) <=0){
+			return StrUtil.EMPTY;
+		}
+		AlipayTradeRefundResponse response;
+		//支付宝退款
+		AlipayClient alipayClient = AliPayClientFactory.getAlipayClient(Optional.ofNullable(goodsWholesaleUserDeposit.getShopId()).orElse(ShopConfig.ZFB_DEFAULT_APP_ID));
+		AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
+		AlipayTradeRefundModel model = new AlipayTradeRefundModel();
+		//支付宝交易号
+		model.setTradeNo(goodsWholesaleUserDeposit.getTransactionId());
+		model.setRefundAmount(money.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(goodsWholesaleUserDeposit.getId()))
+				.toHexString();
+		//退款请求号
+		model.setOutRequestNo(outRefundNo);
+		request.setBizModel(model);
+		String shopId = goodsWholesaleUserDeposit.getShopId();
+		ShopConfig shopConfig = shopConfigMapper.selectOne(Wrappers.lambdaQuery(ShopConfig.class).eq(ShopConfig::getAppId, goodsWholesaleUserDeposit.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());
+		return outRefundNo;
+	}
+
+	private String wxRefundWholesaleUserDeposit(GoodsWholesaleUserDeposit goodsWholesaleUserDeposit) throws Exception {
+		BigDecimal money = goodsWholesaleUserDeposit.getMoney();
+		if (money.compareTo(BigDecimal.ZERO) <=0){
+			return StrUtil.EMPTY;
+		}
+		long time = System.currentTimeMillis();
+		//退款订单号
+		String outRefundNo = Codec.DoDigest.custom()
+				.setAlgorithm(Codec.DoDigest.Algorithm.MD5)
+				.setStringData(time + String.valueOf(goodsWholesaleUserDeposit.getId()))
+				.toHexString();
+		log.info("退押金退款订单号:{}", outRefundNo);
+		weChatService.refundWxOrder(weChatConfig.getAppid(),
+				Optional.ofNullable(goodsWholesaleUserDeposit.getShopId()).orElse(ShopConfig.WX_DEFAULT_APP_ID),
+				goodsWholesaleUserDeposit.getTransactionId(),
+				outRefundNo,
+				money,
+				money,
+				weChatConfig.getDomain() + "manage/goods/whole/sale/deposit/refund/notify");
+		//记录退款信息
+		return outRefundNo;
+	}
 
 	public String wxRefund(OrderRefundReq refundReq, OrderDon orderDon) throws Exception {
 		if (orderDon.getMoney().compareTo(BigDecimal.ZERO) <=0){
@@ -287,4 +378,50 @@ public class OrderRefundServiceImpl implements OrderRefundService {
 		apiContext.setConfigurationMap(sdkConfig);
 		return apiContext;
 	}
+
+	@Override
+	public String refundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception {
+		GoodsWholesaleOrderDon.Type type = orderDon.getType();
+		if (type == GoodsWholesaleOrderDon.Type.WeChat) {
+			return wxRefundWholesaleOrder(orderDon);
+		}
+		if (type == GoodsWholesaleOrderDon.Type.ALI_PAY) {
+			return zfbRefundWholesaleOrder(orderDon);
+		}
+		return StrUtil.EMPTY;
+	}
+
+	private String zfbRefundWholesaleOrder(GoodsWholesaleOrderDon orderDon) throws Exception {
+		BigDecimal money = orderDon.getRefundMoney();
+		if (money.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(money.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());
+		return outRefundNo;
+	}
 }

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

@@ -20,5 +20,10 @@ 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;
+
+	AliPayParams aliPayUnifiedWholesale(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception;
+
+	AliPayParams aliPayUnifiedWholesaleDeposit(AlipayOrderDonReq re, String productCode, String qrPayMode) throws Exception;
 }

+ 92 - 0
netflix-service/src/main/java/com/cyksj/service/pay/impl/AliPayCommonServiceImpl.java

@@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.toolkit.Assert;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.cyksj.common.EnvCommonService;
 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;
@@ -66,6 +67,12 @@ public class AliPayCommonServiceImpl implements AliPayCommonService {
 
 	private final UpgradePackageMapper upgradePackageMapper;
 
+	private final GoodsWholesaleOrderDonMapper goodsWholesaleOrderDonMapper;
+
+	private final GoodsWholesaleUserDepositMapper depositMapper;
+
+	private static final Sequence SEQUENCE = new Sequence(0);
+
 	@Override
 	public AliPayParams unifiedPayRegister(Long orderId, String productCode, String payMode, String returnUrl) throws Exception {
 		RegisterOrderDon orderDon = registerOrderDonMapper.selectById(orderId);
@@ -296,4 +303,89 @@ public class AliPayCommonServiceImpl implements AliPayCommonService {
 				notifyUrl,
 				returnUrl);
 	}
+
+	@Override
+	public AliPayParams aliPayUnifiedWholesale(AlipayOrderDonReq re, String productCode, String payMode) throws Exception {
+		Long orderId = re.getOrderId();
+		String returnUrl = re.getReturnUrl();
+		GoodsWholesaleOrderDon orderDon = goodsWholesaleOrderDonMapper.selectById(orderId);
+		//获取支付宝默认商户
+		String appId = sysConfigService.getDefaultShopConfigByType("zfb");
+		if (GoodsWholesaleOrderDon.Type.ALI_PAY != orderDon.getType()) {
+			orderDon.setType(GoodsWholesaleOrderDon.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);
+		}
+		goodsWholesaleOrderDonMapper.updateById(orderDon);
+		GoodsDon goodsDon = goodsDonMapper.selectById(orderDon.getGoodsId());
+		String subject = goodsDon.getTitle();
+		//回调地址
+		String host = envCommonService.getNotifyHost();
+		String notifyUrl = String.format("%s%s", host, BaseZfbConfig.wholesaleNotifyUrl);
+		//是否在微信内支付 微信内支付宝支付后 支付宝回调页面不跳转
+		Boolean isWx = Optional.ofNullable(re.getIsWx()).orElse(false);
+		if (StrUtil.isEmpty(returnUrl) && 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.getUpdateTime(),
+				subject,
+				productCode,
+				payMode,
+				notifyUrl,
+				returnUrl);
+	}
+
+	@Override
+	public AliPayParams aliPayUnifiedWholesaleDeposit(AlipayOrderDonReq re, String productCode, String payMode) throws Exception {
+		Long orderId = re.getOrderId();
+		String returnUrl = re.getReturnUrl();
+		GoodsWholesaleUserDeposit orderDon = depositMapper.selectById(orderId);
+		//获取支付宝默认商户
+		String appId = sysConfigService.getDefaultShopConfigByType("zfb");
+		if (GoodsWholesaleUserDeposit.Type.ALI_PAY != orderDon.getType()) {
+			orderDon.setType(GoodsWholesaleUserDeposit.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);
+		}
+		depositMapper.updateById(orderDon);
+		String subject = "押金";
+		//回调地址
+		String host = envCommonService.getNotifyHost();
+		String notifyUrl = String.format("%s%s", host, BaseZfbConfig.wholesaleDepositNotifyUrl);
+		//是否在微信内支付 微信内支付宝支付后 支付宝回调页面不跳转
+		Boolean isWx = Optional.ofNullable(re.getIsWx()).orElse(false);
+		if (StrUtil.isEmpty(returnUrl) && ZfbProductCode.MOBILE_WEB.getProductCode().equals(productCode) && !isWx) {
+			//默认跳转页
+			returnUrl = String.format("%s%s", envCommonService.getDomain(), BaseZfbConfig.DEFAULT_URL);
+		}
+		//退款后重新支付
+		if (orderDon.getStatus() == GoodsWholesaleUserDeposit.Status.refund) {
+			orderDon.setOrderNo(SEQUENCE.nextId().toString());
+		}
+		return builderPayParams(orderDon.getId(),
+				orderDon.getOrderNo(),
+				orderDon.getShopId(),
+				orderDon.getMoney(),
+				orderDon.getUpdateTime(),
+				subject,
+				productCode,
+				payMode,
+				notifyUrl,
+				returnUrl);
+	}
 }

+ 2 - 1
netflix-web/src/main/java/com/cyksj/config/SaTokenConfigure.java

@@ -41,7 +41,8 @@ public class SaTokenConfigure implements WebMvcConfigurer {
 						"/manage/account/put/account",
 						"/manage/coupon/get/classificationList",
 						"/manage/coupon/get/couponList",
-						"manage/order/wx/refund/notify"));
+						"manage/order/wx/refund/notify",
+						"/manage/goods/whole/sale/deposit/refund/notify"));
 		//注解权限校验
 		registry.addInterceptor(new SaAnnotationInterceptor()).addPathPatterns("/**");
 	}

+ 2 - 1
netflix-web/src/main/java/com/cyksj/web/controller/group/GroupRelationController.java

@@ -519,7 +519,8 @@ public class GroupRelationController {
     @GetMapping("/check/questionnaire/{promotionId}")
     public Result<Boolean> checkQuestionnaire(@PathVariable Long promotionId) {
         long userId = StpUserUtil.getLoginIdAsLong();
-        Integer count = formFieldsDataMapper.selectCount(Wrappers.lambdaQuery(FormFieldsData.class).eq(FormFieldsData::getUserId, userId).eq(FormFieldsData::getPromotionId, promotionId));
+        List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+        Integer count = formFieldsDataMapper.selectCount(Wrappers.lambdaQuery(FormFieldsData.class).in(FormFieldsData::getUserId, userIdList).eq(FormFieldsData::getPromotionId, promotionId));
         return GatewayResponse.SUCCESS.newBuilder().toResult(count > 0);
     }
 

+ 295 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/goods/CmsGoodsDonWholeSaleController.java

@@ -0,0 +1,295 @@
+package com.cyksj.web.controller.manage.goods;
+
+import cn.dev33.satoken.stp.StpUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.excel.EasyExcel;
+import com.cyksj.common.annotation.Log;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.IoKit;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.common.util.Xmls;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsWholesaleOrderDonMapper;
+import com.cyksj.mapper.GoodsWholesaleUserAccountMapper;
+import com.cyksj.model.entity.GoodsWholesale;
+import com.cyksj.model.entity.GoodsWholesaleUserAccount;
+import com.cyksj.model.entity.GoodsWholesaleUserDeposit;
+import com.cyksj.model.request.OrderRefundReq;
+import com.cyksj.model.views.GoodsWholesaleOrderView;
+import com.cyksj.model.views.GoodsWholesaleView;
+import com.cyksj.model.views.WholesaleUserRequirementView;
+import com.cyksj.service.goods.GoodsWholesaleService;
+import com.cyksj.service.mange.RefreshCacheService;
+import com.cyksj.service.user.UserBindRelationService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * admin/批发下单
+ * 项目名: yhlxj
+ * 文件名: CmsGoodsDonWholeSaleController
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 11:46
+ */
+@RequestMapping("/manage/goods/whole/sale")
+@RestController
+@RequiredArgsConstructor
+@Slf4j
+public class CmsGoodsDonWholeSaleController {
+	private final GoodsWholesaleService goodsWholesaleService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final GoodsWholesaleOrderDonMapper goodsWholesaleOrderDonMapper;
+
+	private final RefreshCacheService refreshCacheService;
+
+	private final GoodsWholesaleUserAccountMapper wholesaleUserAccountMapper;
+
+	/**
+	 * 新增批发平台
+	 */
+	@PostMapping("/post")
+	public Result<String> saveWholesale(@RequestBody GoodsWholesale wholesale) throws Exception {
+		goodsWholesaleService.saveOrUpdateWholesale(wholesale);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+
+	/**
+	 * 编辑批发平台
+	 */
+	@PutMapping("/update")
+	public Result<String> updateWholesale(@RequestBody GoodsWholesale wholesale) throws Exception {
+		goodsWholesaleService.saveOrUpdateWholesale(wholesale);
+		refreshCacheService.refreshWholesaleGoods();
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 平台批发排序
+	 */
+	@PutMapping("/sorted")
+	public Result<String> sortedWholesale(@RequestBody GoodsWholesale wholesale) throws Exception {
+		Long id = wholesale.getId();
+		Integer sorted = wholesale.getSorted();
+		GoodsWholesale byId = goodsWholesaleService.getById(id);
+		if (byId != null) {
+			byId.setSorted(sorted);
+			goodsWholesaleService.updateById(byId);
+			refreshCacheService.refreshWholesaleGoods();
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 删除批发平台
+	 */
+	@DeleteMapping("/delete/{id}")
+	public Result<String> deleteWholesaleById(@PathVariable Long id) {
+		GoodsWholesale byId = goodsWholesaleService.getById(id);
+		if (byId != null) {
+			byId.setDeleted(false);
+			goodsWholesaleService.updateById(byId);
+			refreshCacheService.refreshWholesaleGoods();
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 批发平台列表
+	 */
+	@GetMapping("/get")
+	public Result<SearchResult<GoodsWholesaleView>> getWholesale() {
+		SearchResult<GoodsWholesaleView> search = beanSearcher.search(GoodsWholesaleView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		search.getDataList().forEach(data->{
+			try {
+				data.setWholesaleConfig(Jsons.parseList(data.getConfig(), GoodsWholesale.GoodsWholesaleConfig.class));
+			} catch (Exception e) {
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 批发平台上下架
+	 */
+	@PutMapping("/update/status/{id}")
+	public Result<String> updateStatusById(@PathVariable Long id) {
+		GoodsWholesale byId = goodsWholesaleService.getById(id);
+		if (byId != null) {
+			byId.setStatus(!byId.getStatus());
+			goodsWholesaleService.updateById(byId);
+			refreshCacheService.refreshWholesaleGoods();
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 用户批发情况
+	 */
+	@GetMapping("/get/user/requirement/info")
+	public Result<SearchResult<WholesaleUserRequirementView>> userRequirementInfo() {
+		SearchResult<WholesaleUserRequirementView> search = beanSearcher.search(WholesaleUserRequirementView.class, MapUtils.flatBuilder(request.getParameterMap()).build());
+		search.getDataList().forEach(data->{
+			List<Long> userIdList = null;
+			try {
+				userIdList = userBindRelationService.getRelationUserIdList(data.getUserId(), null);
+				Integer total = goodsWholesaleOrderDonMapper.getUserWholesaleNumByUserIds(userIdList, null);
+				data.setTotal(total);
+				String content = data.getContent();
+				if (StrUtil.isNotBlank(content)) {
+					String[] split = content.split("\\|");
+					data.setSource(split[0]);
+					data.setNum(Integer.parseInt(split[1]));
+				}
+			} catch (Exception e) {
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+
+	//----------------------------------------------------------------------- 押金管理
+
+	/**
+	 * 押金列表
+	 * @return
+	 */
+	@GetMapping("/get/deposit")
+	public Result<SearchResult<GoodsWholesaleUserDeposit>> getDeposit() {
+		SearchResult<GoodsWholesaleUserDeposit> search = beanSearcher.search(GoodsWholesaleUserDeposit.class, MapUtils.flatBuilder(request.getParameterMap())
+				.build());
+		search.getDataList().forEach(data -> {
+			List<Long> userIdList = userBindRelationService.getRelationUserIdList(data.getUserId(), null);
+			Integer total = goodsWholesaleOrderDonMapper.getUserWholesaleNumByUserIds(userIdList, null);
+			data.setTotal(total);
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 押金退款
+	 */
+	@PostMapping("/deposit/refund/{id}")
+	@Log(module = "批发押金退款", businessType = BusinessType.POST, isSaveRequestData = true)
+	public Result<String> depositRefund(@PathVariable Long id) throws Exception {
+		long adminId = StpUtil.getLoginIdAsLong();
+		goodsWholesaleService.depositRefund(id, adminId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 押金退款回调
+	 */
+	@PostMapping("/deposit/refund/notify")
+	public Result<String> depositRefundWxNotify(HttpServletResponse response) throws Exception {
+		String xml = IoKit.toString(request.getInputStream());
+		log.info("=== 押金退款成功的回调: \n {}", xml);
+
+		// 解析xml
+		Map<String, String> map = Xmls.toMap(xml);
+
+		// 退款失败
+		if (!StrUtil.equals("SUCCESS", map.get("return_code"))) {
+			throw BusinessRuntimeException.getInstance("退款失败.");
+		}
+
+		goodsWholesaleService.wxRefundNotify(map);
+
+		String toWechatXmlResponse = "<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>";
+
+		OutputStream out = null;
+		try {
+			out = response.getOutputStream();
+			IoKit.write(toWechatXmlResponse, out);
+		} catch (Throwable e) {
+			throw BusinessRuntimeException.getInstance(e == null ? null : e.getMessage());
+		} finally {
+			IoKit.close(out);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 批发订单
+	 */
+	@GetMapping("/get/order/list")
+	public Result<SearchResult<GoodsWholesaleOrderView>> getOrderList() {
+		SearchResult<GoodsWholesaleOrderView> search = beanSearcher.search(GoodsWholesaleOrderView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.orderBy(GoodsWholesaleOrderView::getId).desc()
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 批发订单退款
+	 */
+	@PostMapping("/refund/order")
+	@Log(module = "批发订单退款", businessType = BusinessType.POST, isSaveRequestData = true)
+	public Result<String> wholesaleOrderRefund(@RequestBody @Validated OrderRefundReq refundReq) throws Exception {
+		long adminId = StpUtil.getLoginIdAsLong();
+		refundReq.setAdminId(adminId);
+		goodsWholesaleService.wholesaleOrderRefund(refundReq);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 上传账号
+	 */
+	@GetMapping("/upload/account")
+	public Result<String> uploadAccount(MultipartFile file, Long orderId) throws IOException {
+		List<Object> acountList = EasyExcel.read(file.getInputStream()).sheet().headRowNumber(0).doReadSync();
+		goodsWholesaleService.uploadAccount(acountList, orderId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 订单账号详情
+	 */
+	@GetMapping("/get/order/account/{orderId}")
+	public Result<SearchResult<GoodsWholesaleUserAccount>> getOrderAccount(@PathVariable Long orderId) {
+		SearchResult<GoodsWholesaleUserAccount> search = beanSearcher.search(GoodsWholesaleUserAccount.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(GoodsWholesaleUserAccount::getOrderId, orderId)
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 新增订单账号信息
+	 */
+	@PostMapping("/post/order/account")
+	public Result<String> insertOrderAccount(@RequestBody List<GoodsWholesaleUserAccount> goodsWholesaleUserAccounts) {
+		goodsWholesaleService.insertOrderAccount(goodsWholesaleUserAccounts);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 编辑订单账号信息
+	 */
+	@PutMapping("/update/order/account")
+	public Result<String> updateOrderAccount(@RequestBody List<GoodsWholesaleUserAccount> goodsWholesaleUserAccounts) {
+		goodsWholesaleService.updateOrderAccount(goodsWholesaleUserAccounts);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+}

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

@@ -325,7 +325,6 @@ public class OrderController {
      * 手机支付
 	 */
 	@PostMapping("/post/pay/zfb")
-    @Deprecated
     public Result<String> aliPay(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
         AliPayParams aliPayParams = orderDonService.aliPay(re, ZfbProductCode.MOBILE_WEB.getProductCode(), null);
 //        response.setContentType("text/html;charset=" + BaseZfbConfig.charset);
@@ -340,7 +339,6 @@ public class OrderController {
      * 套餐支付宝支付
      */
     @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(),null);
         return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());

+ 315 - 0
netflix-web/src/main/java/com/cyksj/web/controller/wholesale/GoodsWholesaleWebController.java

@@ -0,0 +1,315 @@
+package com.cyksj.web.controller.wholesale;
+
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.config.zfb.BaseZfbConfig;
+import com.cyksj.config.zfb.ZfbProductCode;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.mapper.GoodsWholesaleMapper;
+import com.cyksj.mapper.GoodsWholesaleOrderDonMapper;
+import com.cyksj.mapper.GoodsWholesaleUserDepositMapper;
+import com.cyksj.mapper.GoodsWholesaleUserReturnRecordMapper;
+import com.cyksj.model.dto.AliPayParams;
+import com.cyksj.model.entity.*;
+import com.cyksj.model.request.AlipayOrderDonReq;
+import com.cyksj.model.request.GoodsWholesaleOrderPayReq;
+import com.cyksj.model.response.AliPayTradeStatus;
+import com.cyksj.model.views.GoodsWholesaleFrontOrderView;
+import com.cyksj.model.views.GoodsWholesaleFrontView;
+import com.cyksj.model.views.GoodsWholesaleOrderDonView;
+import com.cyksj.model.views.WholeGoodsSkuPayUserDetailView;
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.order.GoodsWholesalePayService;
+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.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * server/批发下单
+ * 项目名: yhlxj
+ * 文件名: GoodsWholesaleWebControlelr
+ * 创建者: JavaZou
+ * 创建时间:2024/8/26 17:41
+ */
+@RestController
+@RequestMapping("/applet/wholesale")
+@RequiredArgsConstructor
+@Slf4j
+public class GoodsWholesaleWebController {
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final RedisService redisService;
+
+	private final GoodsWholesaleOrderDonMapper orderDonMapper;
+
+	private final UserBindRelationService userBindRelationService;
+
+	private final GoodsWholesaleUserDepositMapper goodsWholesaleUserDepositMapper;
+
+	private final GoodsWholesalePayService goodsWholesalePayService;
+
+	private final GoodsWholesaleMapper goodsWholesaleMapper;
+
+	private final GoodsWholesaleUserReturnRecordMapper returnRecordMapper;
+
+	/**
+	 * 平台批发列表
+	 */
+	@GetMapping("/get")
+	public Result<List<GoodsWholesaleFrontView>> goodsWholesaleList() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		String key = RedisService.key.GOODS_WHOLESALE_KEY.getName();
+		List<GoodsWholesaleFrontView> list = (List<GoodsWholesaleFrontView>) redisService.get(key);
+
+		if (list == null) {
+			list = beanSearcher.searchAll(GoodsWholesaleFrontView.class, MapUtils.builder().build());
+			redisService.setNx(key, list, RedisService.key.GOODS_WHOLESALE_KEY.getTimeout());
+		}
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		list.forEach(data->{
+			data.setTotal(orderDonMapper.getUserWholesaleNumByUserIds(userIdList, data.getSkuId()));
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(list);
+	}
+
+	/**
+	 * 押金支付详情
+	 */
+	@GetMapping("/get/deposit/detail")
+	public Result<GoodsWholesaleUserDeposit> getUserDepositDetail() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		GoodsWholesaleUserDeposit goodsWholesaleUserDeposit = goodsWholesaleUserDepositMapper.selectOne(Wrappers.lambdaQuery(GoodsWholesaleUserDeposit.class)
+				.in(GoodsWholesaleUserDeposit::getUserId, userIdList)
+				.last("limit 1")
+				.select(GoodsWholesaleUserDeposit::getId, GoodsWholesaleUserDeposit::getIsGoal, GoodsWholesaleUserDeposit::getMoney, GoodsWholesaleUserDeposit::getStatus));
+		if (goodsWholesaleUserDeposit == null) {
+			return GatewayResponse.SUCCESS.newBuilder().toResult(goodsWholesaleUserDeposit);
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsWholesaleUserDeposit);
+	}
+
+	/**
+	 * 当前批发规格已购买详情
+	 */
+	@GetMapping("/get/sku/detail")
+	public Result<WholeGoodsSkuPayUserDetailView> getUserPayWholesaleSkuDetail(@RequestParam(required = true) Long orderId) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		WholeGoodsSkuPayUserDetailView wholeGoodsSkuPayUserDetailView = beanSearcher.searchFirst(WholeGoodsSkuPayUserDetailView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.put("oid", String.format("where id = %s", orderId))
+				.field(WholeGoodsSkuPayUserDetailView::getUserId, userIdList).op(Operator.InList)
+				.build());
+		wholeGoodsSkuPayUserDetailView.setTotal(orderDonMapper.getUserWholesaleNumByUserIds(userIdList, wholeGoodsSkuPayUserDetailView.getSkuId()));
+
+		GoodsWholesale goodsWholesale = goodsWholesaleMapper.selectOne(Wrappers.lambdaQuery(GoodsWholesale.class)
+				.eq(GoodsWholesale::getSkuId, wholeGoodsSkuPayUserDetailView.getSkuId())
+				.eq(GoodsWholesale::getDeleted, 1)
+				.last("limit 1"));
+		wholeGoodsSkuPayUserDetailView.setIsReturn(goodsWholesale.getIsReturn());
+		if (goodsWholesale != null && goodsWholesale.getIsReturn()) {
+			String configStr = goodsWholesale.getConfig();
+			List<GoodsWholesale.GoodsWholesaleConfig> configs = null;
+			try {
+				configs = Jsons.parseList(configStr, GoodsWholesale.GoodsWholesaleConfig.class);
+				GoodsWholesale.GoodsWholesaleConfig endConfig = configs.get(configs.size() - 1);
+				wholeGoodsSkuPayUserDetailView.setGoal(endConfig.getStart());
+			} catch (Exception e) {
+			}
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult(wholeGoodsSkuPayUserDetailView);
+	}
+
+	@GetMapping("/get/order/goods")
+	public Result<List<GoodsWholesaleFrontOrderView>> getWholesaleOrderGoodsList() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		String userIds = userIdList.stream().map(id -> id.toString()).collect(Collectors.joining(","));
+		List<GoodsWholesaleFrontOrderView> goodsWholesaleFrontOrderViews = beanSearcher.searchAll(GoodsWholesaleFrontOrderView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.put("uid", String.format("where user_id in (%s)", userIds)).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsWholesaleFrontOrderViews);
+	}
+
+	/**
+	 * 支付押金
+	 */
+	@PostMapping("/post/submit/deposit")
+	public Result<GoodsWholesaleUserDeposit> submitDeposit() throws Exception {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		GoodsWholesaleUserDeposit deposit = goodsWholesalePayService.submitDeposit(userId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(deposit);
+	}
+
+	/**
+	 * 下单批发
+	 */
+	@PostMapping("/post/submit")
+	public Result<GoodsWholesaleOrderDon> submit(@RequestBody @Validated GoodsWholesaleOrderPayReq payReq) throws Exception {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		payReq.setUserId(userId);
+		GoodsWholesaleOrderDon orderDon = goodsWholesalePayService.unifiedPay(payReq);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(orderDon);
+	}
+
+	/**
+	 * 取消批发订单
+	 */
+	@PutMapping("/close/order/{orderId}")
+	public Result<String> closeWholesaleOrder(@PathVariable Long orderId) throws Exception {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		goodsWholesalePayService.closeWholesaleOrder(orderId, userId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 批发支付宝支付
+	 * 手机
+	 */
+	@PostMapping("/post/pay/wholesale/zfb")
+	public Result<String> aliPayWholesale(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
+		AliPayParams aliPayParams = goodsWholesalePayService.aliPayWholesale(re, ZfbProductCode.MOBILE_WEB.getProductCode(),null);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
+	}
+
+	/**
+	 * 批发支付宝web支付
+	 * pc网页内嵌二维码
+	 */
+	@PostMapping("/post/pay/wholesale/web/zfb")
+	public Result<String> zfbWholesaleWebQrCode(@RequestBody @Validated AlipayOrderDonReq re) throws Exception {
+		AliPayParams aliPayParams = goodsWholesalePayService.zfbWholesaleWebQrCode(re, ZfbProductCode.PC_WEB.getProductCode(), BaseZfbConfig.qrPayMode_orderCode);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(aliPayParams.getBody());
+	}
+
+	/**
+	 * 批发支付宝回调
+	 */
+	@PostMapping("/zfb/notify")
+	public String aliPayWholesaleNotify(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);
+			goodsWholesalePayService.aliPayWholesaleNotify(params);
+		} else {
+			log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo);
+			return "fail";
+		}
+		return "success";
+	}
+
+	/**
+	 * 批发押金支付宝回调
+	 */
+	@PostMapping("/deposit/zfb/notify")
+	public String aliPayWholesaleDepositNotify(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);
+			goodsWholesalePayService.aliPayWholesaleDepositNotify(params);
+		} else {
+			log.error("支付宝回调 error 状态不符合 成功或完成 status:{} ,orderNo:{}", tradeStatus, orderNo);
+			return "fail";
+		}
+		return "success";
+	}
+
+	/**
+	 * 查询订单状态
+	 */
+	@GetMapping("/get/order/status/{orderId}")
+	public Result<Object> getOrderStatus(@RequestParam(defaultValue = "2") Integer type, @PathVariable Long orderId) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		Object o = goodsWholesalePayService.getOrderStatus(userId, type, orderId);
+		return GatewayResponse.SUCCESS.newBuilder().toResult(o);
+	}
+
+	/**
+	 * 批发订单列表
+	 */
+	@GetMapping("/get/orders")
+	public Result<SearchResult<GoodsWholesaleOrderDonView>> getOrders() {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		SearchResult<GoodsWholesaleOrderDonView> search = beanSearcher.search(GoodsWholesaleOrderDonView.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(GoodsWholesaleOrderDonView::getUserId, userIdList).op(Operator.InList)
+				.orderBy(GoodsWholesaleOrderDonView::getCreatedTime).desc().build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 订单对应账号列表
+	 */
+	@GetMapping("/get/order/account/{orderId}")
+	public Result<SearchResult<GoodsWholesaleUserAccount> > getOrderAccount(@PathVariable Long orderId) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		SearchResult<GoodsWholesaleUserAccount> search = beanSearcher.search(GoodsWholesaleUserAccount.class, MapUtils.flatBuilder(request.getParameterMap())
+				.field(GoodsWholesaleUserAccount::getUserId, userIdList).op(Operator.InList)
+				.field(GoodsWholesaleUserAccount::getOrderId, orderId)
+				.build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 是否已返差价
+	 */
+	@GetMapping("/return/differ")
+	public Result<GoodsWholesaleUserReturnRecord> returnDiffer(@RequestParam(required = true) Long orderId) {
+		long userId = StpUserUtil.getLoginIdAsLong();
+		List<Long> userIdList = userBindRelationService.getRelationUserIdList(userId, null);
+		GoodsWholesaleOrderDon orderDon = orderDonMapper.selectById(orderId);
+		GoodsWholesaleUserReturnRecord returnRecord = returnRecordMapper.selectOne(Wrappers.lambdaQuery(GoodsWholesaleUserReturnRecord.class)
+				.in(GoodsWholesaleUserReturnRecord::getUserId, userIdList)
+				.eq(GoodsWholesaleUserReturnRecord::getSkuId, orderDon.getSkuId())
+				.last("limit 1")
+				.select(GoodsWholesaleUserReturnRecord::getReturnBalance, GoodsWholesaleUserReturnRecord::getSkuId, GoodsWholesaleUserReturnRecord::getNum));
+		return GatewayResponse.SUCCESS.newBuilder().toResult(returnRecord);
+	}
+
+
+	/**
+	 * 获取支付宝回调参数
+	 */
+	private static Map<String, String> convertRequestParamsToMap(HttpServletRequest request) {
+		Map<String, String> retMap = new HashMap<>();
+		Set<Map.Entry<String, String[]>> entrySet = request.getParameterMap().entrySet();
+		for (Map.Entry<String, String[]> entry : entrySet) {
+			String name = entry.getKey();
+			String[] values = entry.getValue();
+			int valLen = values.length;
+			if (valLen == 1) {
+				retMap.put(name, values[0]);
+			} else if (valLen > 1) {
+				StringBuilder sb = new StringBuilder();
+				for (String val : values) {
+					sb.append(",").append(val);
+				}
+				retMap.put(name, sb.substring(1));
+			} else {
+				retMap.put(name, "");
+			}
+		}
+		return retMap;
+	}
+
+}