liujc 1 year ago
parent
commit
16a6d08107
30 changed files with 3203 additions and 313 deletions
  1. 35 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/EPaymentVersion.java
  2. 29 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EGoodsSource.java
  3. 56 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EGoodsType.java
  4. 25 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EOrderType.java
  5. 47 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EPaymentChannel.java
  6. 51 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EPaymentStatus.java
  7. 34 0
      cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EPaymentType.java
  8. 4 0
      cooleshow-user/user-biz/pom.xml
  9. 4 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserOrderDao.java
  10. 13 1
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/OrderSearch.java
  11. 28 169
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrder.java
  12. 15 143
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrderPayment.java
  13. 51 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/OrderStatusEnum.java
  14. 32 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CacheKey.java
  15. 82 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/RedisCacheService.java
  16. 13 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserOrderPaymentService.java
  17. 1 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserOrderService.java
  18. 74 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserPaymentCoreService.java
  19. 56 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserPaymentOrderService.java
  20. 202 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/RedisCacheServiceImpl.java
  21. 45 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderPaymentServiceImpl.java
  22. 2 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderServiceImpl.java
  23. 830 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserPaymentCoreServiceImpl.java
  24. 211 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserPaymentOrderServiceImpl.java
  25. 796 0
      cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/UserPaymentOrderWrapper.java
  26. 23 0
      cooleshow-user/user-biz/src/main/resources/config/mybatis/UserOrderMapper.xml
  27. 87 0
      cooleshow-user/user-tenant/src/main/java/com/yonge/cooleshow/tenant/controller/UserOrderController.java
  28. 77 0
      cooleshow-user/user-tenant/src/main/java/com/yonge/cooleshow/tenant/vo/UserPaymentOrderDetailVo.java
  29. 277 0
      cooleshow-user/user-tenant/src/main/java/com/yonge/cooleshow/tenant/vo/UserPaymentOrderVo.java
  30. 3 0
      toolset/toolset-payment/src/main/java/com/yonge/toolset/payment/base/enums/TradeStatusEnum.java

+ 35 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/EPaymentVersion.java

@@ -0,0 +1,35 @@
+package com.yonge.cooleshow.common.enums;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.yonge.toolset.base.enums.BaseEnum;
+
+/**
+ * 活动资源类型
+ *
+ * @Author: liweifan
+ * @Data: 2022/4/7 15:48
+ */
+public enum EPaymentVersion implements BaseEnum<String, EPaymentVersion> {
+
+    V1("20230726前 原生支付"),
+    V2("20230726后,机构"),
+    ;
+
+    @EnumValue
+    private String code;
+    private String msg;
+
+    EPaymentVersion(String msg) {
+        this.code = this.name();
+        this.msg = msg;
+    }
+
+    @Override
+    public String getCode() {
+        return this.code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+}

+ 29 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EGoodsSource.java

@@ -0,0 +1,29 @@
+package com.yonge.cooleshow.common.enums.payment;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.yonge.cooleshow.common.enums.ActivityShareEnum;
+import com.yonge.toolset.base.enums.BaseEnum;
+import lombok.Getter;
+
+/**
+ * 商品来源
+ */
+@Getter
+public enum EGoodsSource implements BaseEnum<String, EGoodsSource> {
+
+    MALL("商城"),
+    VIP("数字化器乐学练工具"),
+    ;
+
+    private final String msg;
+
+    @EnumValue
+    private final String code;
+
+    EGoodsSource(String msg) {
+        this.msg = msg;
+
+        this.code = this.name();
+    }
+
+}

+ 56 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EGoodsType.java

@@ -0,0 +1,56 @@
+package com.yonge.cooleshow.common.enums.payment;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.google.common.collect.Lists;
+import com.yonge.toolset.base.enums.BaseEnum;
+import lombok.Getter;
+
+import java.util.List;
+
+/**
+ * 商品类型类型
+ */
+@Getter
+public enum EGoodsType implements BaseEnum<String, EGoodsType> {
+
+    VIP("数字化器乐学练工具", "VIP"),
+    INSTRUMENTS("乐器购买", "MALL"),
+    TEXTBOOK("教材", "MALL"),
+    ;
+
+    private final String msg;
+    private final String source;
+
+    @EnumValue
+    private final String code;
+
+    EGoodsType(String msg, String source) {
+        this.msg = msg;
+        this.source = source;
+
+        this.code = this.name();
+    }
+
+    /**
+     * 商城商品类型
+     * @return List<EGoodsType>
+     */
+    public static List<EGoodsType> mallGoodsTypes() {
+
+        return Lists.newArrayList(INSTRUMENTS);
+    }
+
+    /**
+     * 商品类型匹配
+     * @param code 商品编码
+     * @return boolean
+     */
+    public static boolean match(String code) {
+        for (EGoodsType eGoodsType : EGoodsType.values()) {
+            if (eGoodsType.getCode().equals(code)) {
+                return true;
+            }
+        }
+        return false;
+    }
+}

+ 25 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EOrderType.java

@@ -0,0 +1,25 @@
+package com.yonge.cooleshow.common.enums.payment;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.yonge.toolset.base.enums.BaseEnum;
+import lombok.Getter;
+
+@Getter
+public enum EOrderType implements BaseEnum<String, EOrderType> {
+
+    VIP("数字化器乐学练工具"),
+    SCHOOL_REGISTER("学生报名"),
+    ;
+
+
+    private final String name;
+
+    @EnumValue
+    private final String code;
+
+    EOrderType(String name) {
+        this.name = name;
+
+        this.code = this.name();
+    }
+}

+ 47 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EPaymentChannel.java

@@ -0,0 +1,47 @@
+package com.yonge.cooleshow.common.enums.payment;
+
+import lombok.Getter;
+import org.apache.commons.lang3.StringUtils;
+
+/**
+ * 三方支付渠道
+ */
+@Getter
+public enum EPaymentChannel {
+
+    ALIPAY_QR("alipay_qr", "支付宝正扫", 1),
+    ALIPAY_WAP("alipay_wap", "支付宝H5支付", 1),
+    WX_PUB("wx_pub", "微信公众号支付", 2),
+    ;
+
+    private final String msg;
+    private final int payType;
+
+    private final String code;
+
+    EPaymentChannel(String code, String msg, int payType) {
+        this.code = code;
+        this.msg = msg;
+        this.payType = payType;
+    }
+
+    /**
+     * 支付渠道
+     * @param code 渠道商
+     * @return EPaymentChannel
+     */
+    public static EPaymentChannel get(String code) {
+
+        EPaymentChannel[] values = EPaymentChannel.values();
+        if (StringUtils.isNotBlank(code)) {
+
+            for (EPaymentChannel item : values) {
+                if (item.getCode().equals(code)) {
+                    return item;
+                }
+            }
+        }
+        return WX_PUB;
+    }
+
+}

+ 51 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EPaymentStatus.java

@@ -0,0 +1,51 @@
+package com.yonge.cooleshow.common.enums.payment;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.google.common.collect.Lists;
+import lombok.Getter;
+
+import java.util.List;
+
+/**
+ * 订单支付状态
+ */
+@Getter
+public enum EPaymentStatus  {
+
+    WAIT_PAY("待支付"),
+    PAYING("支付中"),
+    PAID("已付款"),
+    TIMEOUT("订单超时"),
+    FAIL("支付失败"),
+    CLOSED("订单关闭"),
+    REFUNDED("已退款"),
+    ;
+
+    private final String msg;
+
+    @EnumValue
+    private final String code;
+
+    EPaymentStatus(String msg) {
+        this.msg = msg;
+
+        this.code = this.name();
+    }
+
+    /**
+     * 乐团报名状态
+     * @return List<EPaymentStatus>
+     */
+    public static List<EPaymentStatus> registerStatus() {
+        return Lists.newArrayList(PAID);
+    }
+
+    /**
+     * 乐团报名订单
+     * WAIT_PAY, PAYING, 只能是已支付和退款中的订单
+     * @return List<EPaymentStatus>
+     */
+    public static List<EPaymentStatus> registerOrder() {
+        return Lists.newArrayList(PAID);
+    }
+}

+ 34 - 0
cooleshow-common/src/main/java/com/yonge/cooleshow/common/enums/payment/EPaymentType.java

@@ -0,0 +1,34 @@
+package com.yonge.cooleshow.common.enums.payment;
+
+import com.baomidou.mybatisplus.annotation.EnumValue;
+import lombok.Getter;
+
+/**
+ * 订单支付类型
+ */
+@Getter
+public enum EPaymentType {
+
+    VIP("开通会员"),
+    PRACTICE("陪练课购买"),
+    LIVE("直播课购买"),
+    VIDEO("视频课购买"),
+    MUSIC("单曲点播"),
+    PIANO_ROOM("琴房时长"),
+    ACTI_REGIST("活动报名"),
+    ALBUM("专辑购买"),
+    TENANT_ALBUM("平台专辑"),
+    ;
+
+    private final String msg;
+
+    @EnumValue
+    private final String code;
+
+    EPaymentType(String msg) {
+        this.msg = msg;
+
+        this.code = this.name();
+    }
+
+}

+ 4 - 0
cooleshow-user/user-biz/pom.xml

@@ -104,6 +104,10 @@
             <artifactId>toolset-payment</artifactId>
             <version>${project.toolset.version}</version>
         </dependency>
+        <dependency>
+            <groupId>com.microsvc.toolkit.middleware</groupId>
+            <artifactId>microsvc-middleware-payment</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 4 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dao/UserOrderDao.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.yonge.cooleshow.biz.dal.entity.UserOrder;
 import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
+import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
 import org.apache.ibatis.annotations.Param;
 import com.yonge.cooleshow.biz.dal.vo.UserOrderVo;
 import com.yonge.cooleshow.biz.dal.dto.search.OrderSearch;
@@ -89,4 +90,7 @@ public interface UserOrderDao extends BaseMapper<UserOrder>{
 	 */
     UserOrderVo getUserOrderByPaymentNoOrTransNo(@Param("paymentNo") String paymentNo,
 												 @Param("transNo") String transNo);
+
+    List<UserOrder> selectPaymentOrderPage(@Param("page") IPage<UserPaymentOrderWrapper.UserPaymentOrder> page,
+                                           @Param("query") UserPaymentOrderWrapper.UserPaymentOrderQuery query);
 }

+ 13 - 1
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/dto/search/OrderSearch.java

@@ -1,6 +1,7 @@
 package com.yonge.cooleshow.biz.dal.dto.search;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import com.yonge.cooleshow.common.enums.EPaymentVersion;
 import com.yonge.toolset.base.page.QueryInfo;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
@@ -38,7 +39,18 @@ public class OrderSearch extends QueryInfo{
 	@ApiModelProperty(hidden = true)
 	private Long bizId;
 
-	public String getSearchNo() {
+    @ApiModelProperty(value = "版本",hidden = true)
+    private EPaymentVersion paymentVersion;
+
+    public EPaymentVersion getPaymentVersion() {
+        return paymentVersion;
+    }
+
+    public void setPaymentVersion(EPaymentVersion paymentVersion) {
+        this.paymentVersion = paymentVersion;
+    }
+
+    public String getSearchNo() {
 		return searchNo;
 	}
 

+ 28 - 169
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrder.java

@@ -7,6 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
 import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
 import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
 import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
+import com.yonge.cooleshow.common.enums.EPaymentVersion;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 
@@ -14,6 +15,10 @@ import java.io.Serializable;
 import java.util.Date;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
 import org.springframework.format.annotation.DateTimeFormat;
 
 import java.math.BigDecimal;
@@ -21,18 +26,40 @@ import java.math.BigDecimal;
 /**
  * 平台订单表
  */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
 @TableName("user_order")
 @ApiModel(value = "UserOrder对象", description = "平台订单表")
 public class UserOrder implements Serializable {
-    private static final long serialVersionUID = 1L;
     @TableId(value = "id_", type = IdType.AUTO)
     private Long id;
     @ApiModelProperty("订单号 ")
     @TableField(value = "order_no_")
     private String orderNo;
+
+
+    @ApiModelProperty("支付版本 ")
+    @TableField(value = "payment_version_")
+    private EPaymentVersion paymentVersion;
+
     @ApiModelProperty("买家id ")
     @TableField(value = "user_id_")
     private Long userId;
+
+    @ApiModelProperty("支付厂商")
+    @TableField(value = "payment_vendor_")
+    private String paymentVendor;
+
+    @ApiModelProperty("支付appId")
+    @TableField(value = "payment_app_id_")
+    private String paymentAppId;
+
+    @ApiModelProperty("支付渠道")
+    @TableField(value = "payment_channel_")
+    private String paymentChannel;
+
     @ApiModelProperty(value = "推荐用户id(有推荐人的情况)")
     @TableField(value = "recom_user_id_")
     private Long recomUserId;
@@ -97,172 +124,4 @@ public class UserOrder implements Serializable {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
     private Date updateTime;
 
-    public Long getRewardId() {
-        return rewardId;
-    }
-
-    public void setRewardId(Long rewardId) {
-        this.rewardId = rewardId;
-    }
-
-    public Long getActivityId() {
-        return activityId;
-    }
-
-    public void setActivityId(Long activityId) {
-        this.activityId = activityId;
-    }
-
-
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public String getOrderNo() {
-        return orderNo;
-    }
-
-    public void setOrderNo(String orderNo) {
-        this.orderNo = orderNo;
-    }
-
-    public Long getUserId() {
-        return userId;
-    }
-
-    public void setUserId(Long userId) {
-        this.userId = userId;
-    }
-
-    public String getOrderName() {
-        return orderName;
-    }
-
-    public void setOrderName(String orderName) {
-        this.orderName = orderName;
-    }
-
-    public ClientEnum getOrderClient() {
-        return orderClient;
-    }
-
-    public void setOrderClient(ClientEnum orderClient) {
-        this.orderClient = orderClient;
-    }
-
-    public OrderTypeEnum getOrderType() {
-        return orderType;
-    }
-
-    public void setOrderType(OrderTypeEnum orderType) {
-        this.orderType = orderType;
-    }
-
-    public String getOrderDesc() {
-        return orderDesc;
-    }
-
-    public void setOrderDesc(String orderDesc) {
-        this.orderDesc = orderDesc;
-    }
-
-    public OrderStatusEnum getStatus() {
-        return status;
-    }
-
-    public void setStatus(OrderStatusEnum status) {
-        this.status = status;
-    }
-
-    public BigDecimal getOriginalPrice() {
-        return originalPrice;
-    }
-
-    public void setOriginalPrice(BigDecimal originalPrice) {
-        this.originalPrice = originalPrice;
-    }
-
-    public BigDecimal getExpectPrice() {
-        return expectPrice;
-    }
-
-    public void setExpectPrice(BigDecimal expectPrice) {
-        this.expectPrice = expectPrice;
-    }
-
-    public BigDecimal getActualPrice() {
-        return actualPrice;
-    }
-
-    public void setActualPrice(BigDecimal actualPrice) {
-        this.actualPrice = actualPrice;
-    }
-
-    public BigDecimal getCouponAmount() {
-        return couponAmount;
-    }
-
-    public void setCouponAmount(BigDecimal couponAmount) {
-        this.couponAmount = couponAmount;
-    }
-
-    public BigDecimal getPlantformFee() {
-        return plantformFee;
-    }
-
-    public void setPlantformFee(BigDecimal plantformFee) {
-        this.plantformFee = plantformFee;
-    }
-
-    public String getUserNote() {
-        return userNote;
-    }
-
-    public void setUserNote(String userNote) {
-        this.userNote = userNote;
-    }
-
-    public Date getCreateTime() {
-        return createTime;
-    }
-
-    public void setCreateTime(Date createTime) {
-        this.createTime = createTime;
-    }
-
-    public Date getPayTime() {
-        return payTime;
-    }
-
-    public void setPayTime(Date payTime) {
-        this.payTime = payTime;
-    }
-
-    public String getReason() {
-        return reason;
-    }
-
-    public void setReason(String reason) {
-        this.reason = reason;
-    }
-
-    public Date getUpdateTime() {
-        return updateTime;
-    }
-
-    public void setUpdateTime(Date updateTime) {
-        this.updateTime = updateTime;
-    }
-
-    public Long getRecomUserId() {
-        return recomUserId;
-    }
-
-    public void setRecomUserId(Long recomUserId) {
-        this.recomUserId = recomUserId;
-    }
 }

+ 15 - 143
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/entity/UserOrderPayment.java

@@ -13,12 +13,14 @@ import io.swagger.annotations.ApiModelProperty;
 import java.io.Serializable;
 import java.util.Date;
 import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
 import org.springframework.format.annotation.DateTimeFormat;
 import java.math.BigDecimal;
 
 /**
  * 平台订单支付表
  */
+@Data
 @TableName("user_order_payment")
 @ApiModel(value = "UserOrderPayment对象", description = "平台订单支付表")
 public class UserOrderPayment implements Serializable {
@@ -34,6 +36,19 @@ public class UserOrderPayment implements Serializable {
     @ApiModelProperty("支付渠道: alipay 支付宝  wx_lite 微信 ")
     @TableField(value = "pay_channel_")
     private PayChannelEnum payChannel;
+
+
+    @ApiModelProperty("支付厂商")
+    @TableField(value = "payment_vendor_")
+    private String paymentVendor;
+
+    @ApiModelProperty("支付appId")
+    @TableField(value = "payment_app_id_")
+    private String paymentAppId;
+
+    @ApiModelProperty("支付渠道")
+    @TableField(value = "payment_channel_")
+    private String paymentChannel;
     @ApiModelProperty("订单号 ")
 	@TableField(value = "order_no_")
     private String orderNo;
@@ -83,147 +98,4 @@ public class UserOrderPayment implements Serializable {
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
     private Date updateTime;
 
-    public Long getId() {
-        return id;
-    }
-
-    public void setId(Long id) {
-        this.id = id;
-    }
-
-    public OpenEnum getOpenType() {
-        return openType;
-    }
-
-    public void setOpenType(OpenEnum openType) {
-        this.openType = openType;
-    }
-
-    public PayChannelEnum getPayChannel() {
-        return payChannel;
-    }
-
-    public void setPayChannel(PayChannelEnum payChannel) {
-        this.payChannel = payChannel;
-    }
-
-    public String getOrderNo() {
-        return orderNo;
-    }
-
-    public void setOrderNo(String orderNo) {
-        this.orderNo = orderNo;
-    }
-
-    public String getPaymentNo() {
-        return paymentNo;
-    }
-
-    public void setPaymentNo(String paymentNo) {
-        this.paymentNo = paymentNo;
-    }
-
-    public String getTransNo() {
-        return transNo;
-    }
-
-    public void setTransNo(String transNo) {
-        this.transNo = transNo;
-    }
-
-    public BigDecimal getPayAmt() {
-        return payAmt;
-    }
-
-    public void setPayAmt(BigDecimal payAmt) {
-        this.payAmt = payAmt;
-    }
-
-    public BigDecimal getBackPayAmt() {
-        return backPayAmt;
-    }
-
-    public void setBackPayAmt(BigDecimal backPayAmt) {
-        this.backPayAmt = backPayAmt;
-    }
-
-    public BigDecimal getFeeAmt() {
-        return feeAmt;
-    }
-
-    public void setFeeAmt(BigDecimal feeAmt) {
-        this.feeAmt = feeAmt;
-    }
-
-    public String getPayInfo() {
-        return payInfo;
-    }
-
-    public void setPayInfo(String payInfo) {
-        this.payInfo = payInfo;
-    }
-
-    public TradeStatusEnum getStatus() {
-        return status;
-    }
-
-    public void setStatus(TradeStatusEnum status) {
-        this.status = status;
-    }
-
-    public String getPayFailMsg() {
-        return payFailMsg;
-    }
-
-    public void setPayFailMsg(String payFailMsg) {
-        this.payFailMsg = payFailMsg;
-    }
-
-    public Date getArrivalTime() {
-        return arrivalTime;
-    }
-
-    public void setArrivalTime(Date arrivalTime) {
-        this.arrivalTime = arrivalTime;
-    }
-
-    public TradeStatusEnum getCloseStatus() {
-        return closeStatus;
-    }
-
-    public void setCloseStatus(TradeStatusEnum closeStatus) {
-        this.closeStatus = closeStatus;
-    }
-
-    public String getCloseFailMsg() {
-        return closeFailMsg;
-    }
-
-    public void setCloseFailMsg(String closeFailMsg) {
-        this.closeFailMsg = closeFailMsg;
-    }
-
-    public Date getCreateTime() {
-        return createTime;
-    }
-
-    public void setCreateTime(Date createTime) {
-        this.createTime = createTime;
-    }
-
-    public Date getUpdateTime() {
-        return updateTime;
-    }
-
-    public void setUpdateTime(Date updateTime) {
-        this.updateTime = updateTime;
-    }
-
-    public String getPaymentClient() {
-        return paymentClient;
-    }
-
-    public void setPaymentClient(String paymentClient) {
-        this.paymentClient = paymentClient;
-    }
 }

+ 51 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/enums/OrderStatusEnum.java

@@ -1,6 +1,7 @@
 package com.yonge.cooleshow.biz.dal.enums;
 
 import com.baomidou.mybatisplus.annotation.EnumValue;
+import com.yonge.cooleshow.common.enums.payment.EPaymentStatus;
 import com.yonge.toolset.base.enums.BaseEnum;
 
 /**
@@ -25,6 +26,56 @@ public enum OrderStatusEnum implements BaseEnum<String, OrderStatusEnum> {
         this.msg = msg;
     }
 
+
+    //  EPaymentStatus to OrderStatusEnum
+    public static OrderStatusEnum parse(EPaymentStatus paymentStatus) {
+        if (paymentStatus == null) {
+            return null;
+        }
+        switch (paymentStatus) {
+            case WAIT_PAY:
+                return WAIT_PAY;
+            case PAYING:
+                return PAYING;
+            case PAID:
+                return PAID;
+            case TIMEOUT:
+                return CLOSE;
+            case FAIL:
+                return FAIL;
+            case CLOSED:
+                return CLOSE;
+            case REFUNDED:
+                return PAID;
+            default:
+                return null;
+        }
+    }
+
+
+
+
+    //  OrderStatusEnum 转 EPaymentStatus
+    public static EPaymentStatus parse(OrderStatusEnum orderStatusEnum) {
+        if (orderStatusEnum == null) {
+            return null;
+        }
+        switch (orderStatusEnum) {
+            case WAIT_PAY:
+                return EPaymentStatus.WAIT_PAY;
+            case PAYING:
+                return EPaymentStatus.PAYING;
+            case PAID:
+                return EPaymentStatus.PAID;
+            case CLOSE:
+                return EPaymentStatus.CLOSED;
+            case FAIL:
+                return EPaymentStatus.FAIL;
+            default:
+                return null;
+        }
+    }
+
     public String getMsg() {
         return this.msg;
     }

+ 32 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/CacheKey.java

@@ -0,0 +1,32 @@
+package com.yonge.cooleshow.biz.dal.service;
+
+/**
+ * Created by Eric.Shang on 2022/11/2.
+ */
+public interface CacheKey {
+
+    // 用户授权缓存-> userId:clientType => List
+    String USER_AUTHORIZATION_PERMISSION = "{}:{}";
+    // 用户身份-> userId:clientType:role =>
+    String USER_AUTHORIZATION_ROLE = "{}:{}:role";
+    // 应用权限授权
+    String USER_AUTHORIZATION_APP = "{}:{}:app";
+    // 验证码存储前缀
+    String BUCKET_VERIFY_CODE = "verifycode:{}";
+    // 消息类型验证码
+    String BUCKET_TYPE_VERIFY_CODE = "verifycode:{}:{}";
+    // 用户授权Token
+    String JWT_TOKEN = "token:{}:{}";
+    // 乐团编号
+    String ORCHESTRA_ID = "orchestra:{}";
+    // 乐团编号锁
+    String ORCHESTRA_LOCK = "orchestra:LOCK";
+    // 用户下单/付款/取消订单锁
+    String PAYMENT_ORDER_LOCK = "paymentorder:{}";
+    // 用户下单请求
+    String EXECUTE_ORDER_LOCK = "executeorder:{}";
+    // 用户支付配置
+    String USER_PAYMENT_CONFIG = "paymentconfig:{}:{}";
+    // 用户下单配置
+    String USER_ORDER_CONFIG = "orderconfig:{}:{}";
+}

+ 82 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/RedisCacheService.java

@@ -0,0 +1,82 @@
+package com.yonge.cooleshow.biz.dal.service;
+
+
+import java.util.List;
+
+/**
+ * Created by Eric.Shang on 2022/10/9.
+ */
+public interface RedisCacheService {
+
+    /**
+     * 缓存Key对象
+     *
+     * @param cacheKey  Key模板
+     * @param arguments 参数信息
+     * @return String
+     */
+    String getCacheKey(String cacheKey, Object... arguments);
+
+    /**
+     * 订单分布式锁
+     *
+     * @param orderNo 订单编号
+     * @return String
+     */
+    String getPaymentCacheKey(String orderNo);
+
+    /**
+     * 用户下单请求锁定
+     *
+     * @param userId 用户Id
+     * @return String
+     */
+    String getExecuteOrderCacheKey(String userId);
+
+    /**
+     * 缓存用户支付配置
+     *
+     * @param userId 用户Id
+     * @param config 支付配置信息
+     */
+    void saveUserPaymentConfig(String userId, String orderType, String config);
+
+    /**
+     * 获取用户订单支付配置
+     *
+     * @param userId 用户Id
+     * @return String
+     */
+    String getUserPaymentConfig(String userId, String orderType);
+
+    /**
+     * 删除用户支付配置
+     *
+     * @param userId 用户Id
+     */
+    void deleteUserPaymentConfig(String userId, String orderType);
+
+    /**
+     * 用户下单配置
+     *
+     * @param userId 用户Id
+     * @param config 下单配置信息
+     */
+    void saveUserOrderConfig(String userId, String orderType, String config);
+
+    /**
+     * 查询用户下单配置
+     *
+     * @param userId 用户Id
+     * @return String
+     */
+    String getUserOrderConfig(String userId, String orderType);
+
+    /**
+     * 删除用户下单配置
+     *
+     * @param userId 用户Id
+     */
+    void deleteUserOrderConfig(String userId, String orderType);
+
+}

+ 13 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserOrderPaymentService.java

@@ -10,6 +10,9 @@ import com.yonge.toolset.payment.base.enums.PayChannelEnum;
 import com.yonge.toolset.payment.base.enums.TradeStatusEnum;
 import com.yonge.toolset.payment.base.model.callback.PaymentCallBack;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * 平台订单支付表 服务类
  *
@@ -85,4 +88,14 @@ public interface UserOrderPaymentService extends IService<UserOrderPayment> {
      * @param userId 用户id
      */
     void setContractRecord(String type, Long userId);
+
+    UserOrderPayment getNewestPayment(String transNo, String merOrderNo);
+
+
+    /**
+     *  查询订单对应的支付信息
+     *
+     * @param orderNos 订单编号
+     */
+    Map<String ,UserOrderPayment> getNewestPaymentMapByOrderNos(List<String> orderNos);
 }

+ 1 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserOrderService.java

@@ -11,6 +11,7 @@ import com.yonge.cooleshow.biz.dal.vo.UserOrderDetailVo;
 import com.yonge.cooleshow.biz.dal.vo.UserOrderVo;
 import com.yonge.cooleshow.biz.dal.dto.search.OrderSearch;
 import com.yonge.cooleshow.biz.dal.vo.res.OrderPayRes;
+import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.toolset.payment.base.model.callback.PaymentCallBack;
 

+ 74 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserPaymentCoreService.java

@@ -0,0 +1,74 @@
+package com.yonge.cooleshow.biz.dal.service;
+
+import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
+import com.microsvc.toolkit.middleware.payment.common.api.entity.PaymentResp;
+import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
+import com.yonge.cooleshow.common.enums.payment.EPaymentType;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * 用户支付订单服务
+ * Created by Eric.Shang on 2022/12/22.
+ */
+public interface UserPaymentCoreService {
+
+    /**
+     * 支付回调消息
+     * @param paymentResp PaymentResp
+     */
+    void executePaymentCallback(PaymentResp paymentResp);
+
+
+    /**
+     * 支付成功处理流程
+     * @param paymentOrder UserPaymentOrderWrapper.UserPaymentOrder
+     * @param paymentResp PaymentResp
+     */
+    void executePaymentSuccess(UserPaymentOrderWrapper.UserPaymentOrder paymentOrder, PaymentResp paymentResp);
+
+    /**
+     * 取消订单支付
+     * @param paymentOrder UserPaymentOrderWrapper.UserPaymentOrder
+     * @param paymentResp PaymentResp
+     */
+    void cancelPayment(UserPaymentOrderWrapper.UserPaymentOrder paymentOrder, PaymentResp paymentResp);
+
+    /**
+     * 用户下单请求
+     * @param orderReq UserPaymentOrderWrapper.UserPaymentOrder
+     */
+    UserPaymentOrderWrapper.PaymentConfig executeOrderCreate(UserPaymentOrderWrapper.UserPaymentOrder orderReq);
+
+
+    /**
+     * 用户支付请求
+     * @param userInfo JwtUserInfo
+     * @param reqConfig UserPaymentOrderWrapper.PaymentOrderReqConfig
+     * @return UserPaymentOrderWrapper.PaymentReq
+     */
+    UserPaymentOrderWrapper.PaymentReq executePayment(JwtUserInfo<?> userInfo, UserPaymentOrderWrapper.PaymentOrderReqConfig reqConfig);
+
+    @Transactional
+    UserPaymentOrderWrapper.PaymentConfig executeOrder(UserPaymentOrderWrapper.UserPaymentOrder orderReq);
+
+    /**
+     * 用户支付请求
+     * @param reqConfig UserPaymentOrderWrapper.PaymentOrderReqConfig
+     * @return UserPaymentOrderWrapper.PaymentReq
+     */
+    UserPaymentOrderWrapper.PaymentReq executePayment(UserPaymentOrderWrapper.PaymentOrderReqConfig reqConfig);
+
+    /**
+     * 用户支付取消
+     * @param userInfo JwtUserInfo
+     * @param orderNo 订单编号
+     */
+    void cancelPayment(JwtUserInfo<?> userInfo, String orderNo);
+
+
+    /**
+     * 扫描支付超时定时
+     */
+    void scanPaymentTimeoutOrderRecord();
+
+}

+ 56 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/UserPaymentOrderService.java

@@ -0,0 +1,56 @@
+package com.yonge.cooleshow.biz.dal.service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
+
+import java.util.List;
+
+/**
+ * 平台订单表
+ * 2022-12-20 19:09:34
+ */
+public interface UserPaymentOrderService   {
+
+
+    /**
+     * 分页查询
+     * @param page IPage<com.cooleshow.edu.domain.wrapper.UserPaymentOrderWrapper.UserPaymentOrder>
+     * @param query UserPaymentOrderWrapper.UserPaymentOrderQuery
+     * @return IPage<com.cooleshow.edu.domain.wrapper.UserPaymentOrderWrapper.UserPaymentOrder>
+     */
+    IPage<UserPaymentOrderWrapper.UserPaymentOrder> selectPage(IPage<UserPaymentOrderWrapper.UserPaymentOrder> page, UserPaymentOrderWrapper.UserPaymentOrderQuery query);
+
+
+    /**
+     * 用户支付订单信息
+     * @param transNo 交易流水号
+     * @param merOrderNo 订单编号
+     * @return UserPaymentOrder
+     */
+    UserPaymentOrderWrapper.UserPaymentOrder getUserPaymentOrderByOrderNo(String transNo, String merOrderNo);
+
+    /**
+     * 用户支付订单
+     * @param userId 用户Id
+     * @param merOrderNo 商户订单编号
+     * @return UserPaymentOrder
+     */
+    UserPaymentOrderWrapper.UserPaymentOrder getUserPaymentOrderByUserId(Long userId, String merOrderNo);
+
+
+    /**
+     * 关闭用户支付订单
+     * @param id 支付订单Id
+     */
+    void closeUserPaymentOrder(Long id);
+
+
+    void updateById(UserPaymentOrderWrapper.UserPaymentOrder order);
+
+    /**
+     * 创建订单
+     *
+     */
+    void save(UserPaymentOrderWrapper.UserPaymentOrder orderReq);
+}

+ 202 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/RedisCacheServiceImpl.java

@@ -0,0 +1,202 @@
+package com.yonge.cooleshow.biz.dal.service.impl;
+
+import com.google.common.collect.Lists;
+import com.yonge.cooleshow.biz.dal.service.CacheKey;
+import com.yonge.cooleshow.biz.dal.service.RedisCacheService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.BooleanUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.redisson.api.RBucket;
+import org.redisson.api.RedissonClient;
+import org.slf4j.helpers.MessageFormatter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+/**
+ * Created by Eric.Shang on 2022/10/9.
+ */
+@Slf4j
+@Service
+public class RedisCacheServiceImpl implements RedisCacheService {
+
+    @Autowired
+    private RedissonClient redissonClient;
+
+    // 本地缓存区域
+    private static final String CACHE_DEFAULT = "cooleshow-edu-default";
+    private static final String CACHE_PERMISSION = "cooleshow-edu-permission";
+    // 应用缓存前缀
+    private static final String CACHE_APP_PREFIX = "cooleshow:edu";
+    // 验证码有效期
+    public static final int CODE_EXPIRE = 60 * 5;
+    // 发送验证码的间隔时间
+    public static final int CODE_INTERVAL_TIME = 60;
+    // Token默认失效时间
+    public static final int TOKEN_DEFAULT_EXPIRE = -1; // 默认半年有效,后面定时任务主动清除长时间未使用帐号
+    // 乐团编号时间规则
+    public static final String ORCHESTRA_ID_TIME = "yyMMddHHmmss";
+    // 乐团编号失效时间
+    public static final int ORCHESTRA_EXPIRE = 3600 * 24;
+
+    /**
+     * 缓存Key对象
+     *
+     * @param cacheKey Key模板
+     * @param arguments   参数信息
+     * @return String
+     */
+    @Override
+    public String getCacheKey(String cacheKey, Object... arguments) {
+        // 重置缓存Key,增加应用前缀
+        cacheKey = MessageFormat.format("{0}:{1}", CACHE_APP_PREFIX, cacheKey);
+        // 返回缓存对象
+        return MessageFormatter.arrayFormat(cacheKey, arguments).getMessage();
+    }
+
+
+
+    /**
+     * 订单分布式锁
+     *
+     * @param orderNo 订单编号
+     * @return String
+     */
+    @Override
+    public String getPaymentCacheKey(String orderNo) {
+        return getCacheKey(CacheKey.PAYMENT_ORDER_LOCK, orderNo);
+    }
+
+    /**
+     * 用户下单请求锁定
+     *
+     * @param userId 用户Id
+     * @return String
+     */
+    @Override
+    public String getExecuteOrderCacheKey(String userId) {
+        return getCacheKey(CacheKey.EXECUTE_ORDER_LOCK, userId);
+    }
+
+    /**
+     * 缓存用户支付配置
+     *
+     * @param userId 用户Id
+     * @param config 支付配置信息
+     */
+    @Override
+    public void saveUserPaymentConfig(String userId, String orderType, String config) {
+
+        String cacheKey = getCacheKey(CacheKey.USER_PAYMENT_CONFIG, userId, orderType);
+
+        RBucket<Object> bucket = redissonClient.getBucket(cacheKey);
+
+        // 缓存数据
+        bucket.set(config, 120L, TimeUnit.MINUTES);
+    }
+
+    /**
+     * 获取用户订单支付配置
+     *
+     * @param userId 用户Id
+     * @return String
+     */
+    @Override
+    public String getUserPaymentConfig(String userId, String orderType) {
+
+        String cacheKey = getCacheKey(CacheKey.USER_PAYMENT_CONFIG, userId, orderType);
+
+        // 获取用户支付配置信息
+        RBucket<Object> bucket = redissonClient.getBucket(cacheKey);
+        Object data = bucket.get();
+        if (Objects.isNull(data)) {
+            return StringUtils.EMPTY;
+        }
+
+        return (String) data;
+    }
+
+    /**
+     * 删除用户支付配置
+     *
+     * @param userId 用户Id
+     */
+    @Override
+    public void deleteUserPaymentConfig(String userId, String orderType) {
+
+        String cacheKey = getCacheKey(CacheKey.USER_PAYMENT_CONFIG, userId, orderType);
+
+        // 支付配置信息
+        RBucket<Object> bucket = redissonClient.getBucket(cacheKey);
+
+        // 删除支付配置缓存
+        if (bucket.isExists()) {
+            bucket.delete();
+        }
+    }
+
+    /**
+     * 用户下单配置
+     *
+     * @param userId 用户Id
+     * @param config 下单配置信息
+     */
+    @Override
+    public void saveUserOrderConfig(String userId, String orderType, String config) {
+
+        String cacheKey = getCacheKey(CacheKey.USER_ORDER_CONFIG, userId, orderType);
+
+        RBucket<Object> bucket = redissonClient.getBucket(cacheKey);
+
+        // 缓存数据
+        bucket.set(config, 120L, TimeUnit.MINUTES);
+    }
+
+    /**
+     * 查询用户下单配置
+     *
+     * @param userId 用户Id
+     * @return String
+     */
+    @Override
+    public String getUserOrderConfig(String userId, String orderType) {
+        String cacheKey = getCacheKey(CacheKey.USER_ORDER_CONFIG, userId, orderType);
+
+        // 获取用户支付配置信息
+        RBucket<Object> bucket = redissonClient.getBucket(cacheKey);
+        Object data = bucket.get();
+        if (Objects.isNull(data)) {
+            return StringUtils.EMPTY;
+        }
+
+        return (String) data;
+    }
+
+    /**
+     * 删除用户下单配置
+     *
+     * @param userId 用户Id
+     */
+    @Override
+    public void deleteUserOrderConfig(String userId, String orderType) {
+        String cacheKey = getCacheKey(CacheKey.USER_ORDER_CONFIG, userId, orderType);
+
+        // 支付配置信息
+        RBucket<Object> bucket = redissonClient.getBucket(cacheKey);
+
+        // 删除支付配置缓存
+        if (bucket.isExists()) {
+            bucket.delete();
+        }
+    }
+
+
+}

+ 45 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderPaymentServiceImpl.java

@@ -26,6 +26,8 @@ import com.yonge.toolset.payment.base.model.*;
 import com.yonge.toolset.payment.base.model.callback.PaymentCallBack;
 import com.yonge.toolset.payment.core.props.PaymentProperties;
 import com.yonge.toolset.payment.core.service.PaymentClient;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -39,6 +41,7 @@ import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.util.*;
 import java.util.concurrent.CompletableFuture;
+import java.util.stream.Collectors;
 
 
 @Service
@@ -288,6 +291,48 @@ public class UserOrderPaymentServiceImpl extends ServiceImpl<UserOrderPaymentDao
         }
     }
 
+    @Override
+    public UserOrderPayment getNewestPayment(String transNo, String merOrderNo) {
+        if (StringUtils.isBlank(transNo) && StringUtils.isBlank(merOrderNo)) {
+            return null;
+        }
+        return this.lambdaQuery()
+                .eq(StringUtils.isNotBlank(transNo),UserOrderPayment::getTransNo, transNo)
+                .eq(StringUtils.isNotBlank(merOrderNo),UserOrderPayment::getOrderNo, merOrderNo)
+                .orderByDesc(UserOrderPayment::getCreateTime)
+                .last("limit 1")
+                .one();
+    }
+
+    /**
+     * 查询订单对应的支付信息
+     *
+     * @param orderNos 订单编号
+     */
+    @Override
+    public Map<String, UserOrderPayment> getNewestPaymentMapByOrderNos(List<String> orderNos) {
+        if (CollectionUtils.isEmpty(orderNos)) {
+            return new HashMap<>();
+        }
+        List<UserOrderPayment> list = this.lambdaQuery()
+                .in(UserOrderPayment::getOrderNo, orderNos)
+                .list();
+        if (CollectionUtils.isEmpty(list)) {
+            return new HashMap<>();
+        }
+
+        Map<String, List<UserOrderPayment>> listMap = list.stream().collect(Collectors.groupingBy(UserOrderPayment::getOrderNo));
+        Map<String, UserOrderPayment> map = new HashMap<>();
+        listMap.forEach((k, v) -> {
+            // 时间倒叙排序
+            v.sort(Comparator.comparing(UserOrderPayment::getCreateTime).reversed());
+            map.put(k, v.get(0));
+        });
+
+        return map;
+
+    }
+
 
     /***
      * 处理回调-支付失败

+ 2 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserOrderServiceImpl.java

@@ -50,6 +50,7 @@ import com.yonge.cooleshow.common.constant.SysConfigConstant;
 import com.yonge.cooleshow.common.entity.HttpResponseResult;
 import com.yonge.cooleshow.common.enums.ActivityResourceEnum;
 import com.yonge.cooleshow.common.enums.CacheNameEnum;
+import com.yonge.cooleshow.common.enums.EPaymentVersion;
 import com.yonge.cooleshow.common.enums.PostStatusEnum;
 import com.yonge.cooleshow.common.service.IdGeneratorService;
 import com.yonge.toolset.base.exception.BizException;
@@ -481,6 +482,7 @@ public class UserOrderServiceImpl extends ServiceImpl<UserOrderDao, UserOrder> i
         OrderSearch search = new OrderSearch();
         search.setStatus(OrderStatusEnum.WAIT_PAY.getCode());
         search.setEndTime(LocalDateTime.now().minusMinutes(30));
+        search.setPaymentVersion(EPaymentVersion.V1);
         //查询待支付订单
         List<UserOrderVo> waitPayOrderList = baseMapper.selectAllList(search);
         for (UserOrderVo orderVo : waitPayOrderList) {

+ 830 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserPaymentCoreServiceImpl.java

@@ -0,0 +1,830 @@
+package com.yonge.cooleshow.biz.dal.service.impl;
+
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.microsvc.toolkit.common.response.paging.QueryInfo;
+import com.microsvc.toolkit.common.spring.SpringContextHolder;
+import com.microsvc.toolkit.common.tools.ThreadPool;
+import com.microsvc.toolkit.common.webportal.exception.BizException;
+import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
+import com.microsvc.toolkit.middleware.payment.common.api.BasePaymentService;
+import com.microsvc.toolkit.middleware.payment.common.api.PaymentServiceContext;
+import com.microsvc.toolkit.middleware.payment.common.api.entity.PaymentClose;
+import com.microsvc.toolkit.middleware.payment.common.api.entity.PaymentOrder;
+import com.microsvc.toolkit.middleware.payment.common.api.entity.PaymentReq;
+import com.microsvc.toolkit.middleware.payment.common.api.entity.PaymentResp;
+import com.microsvc.toolkit.middleware.payment.common.api.enums.PaymentStatus;
+import com.yonge.cooleshow.biz.dal.entity.UserOrderDetail;
+import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
+import com.yonge.cooleshow.biz.dal.service.*;
+import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
+import com.yonge.cooleshow.common.enums.ContractTemplateTypeEnum;
+import com.yonge.cooleshow.common.enums.SysUserType;
+import com.yonge.cooleshow.common.enums.payment.EGoodsType;
+import com.yonge.cooleshow.common.enums.payment.EPaymentChannel;
+import com.yonge.cooleshow.common.enums.payment.EPaymentStatus;
+import com.yonge.cooleshow.common.enums.payment.EPaymentType;
+import com.yonge.toolset.payment.util.DistributedLock;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import javax.annotation.PostConstruct;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
+
+import static com.yonge.cooleshow.common.enums.payment.EPaymentStatus.*;
+
+/**
+ * 用户支付订单服务
+ * Created by Eric.Shang on 2022/12/22.
+ */
+@Slf4j
+@Service
+public class UserPaymentCoreServiceImpl implements UserPaymentCoreService {
+
+    @Autowired
+    private RedissonClient redissonClient;
+
+    @Autowired
+    private PaymentServiceContext paymentServiceContext;
+
+    @Autowired
+    private RedisCacheService redisCacheService;
+
+    @Autowired
+    private SysUserContractRecordService sysUserContractRecordService;
+
+    @Autowired
+    private SysUserService sysUserService;
+
+    @Autowired
+    private UserPaymentOrderService userPaymentOrderService;
+
+    @Autowired
+    private UserOrderDetailService userOrderDetailService;
+
+
+    // 订单商品参数校验,获取订单支付金额
+    private static final Map<EGoodsType, Consumer<UserOrderDetail>> orderGoodsCreate = Maps.newHashMap();
+    // 支付订单类型参数校验
+    private static final Map<EPaymentType, Consumer<UserPaymentOrderWrapper.UserPaymentOrder>> orderCreate = Maps.newHashMap();
+    // 支付创建前,数据库存
+    private static final Map<EPaymentType, Consumer<UserPaymentOrderWrapper.UserPaymentOrder>> orderSuccessBefore = Maps.newHashMap();
+    // 支付创建前,数据库存
+//    private static final Map<EPaymentType, Consumer<UserPaymentOrder>> executeSuccessBefore = Maps.newHashMap();
+    // 订单完成后执行
+    private static final Map<EPaymentType, Consumer<UserPaymentOrderWrapper.UserPaymentOrder>> paymentSuccess = Maps.newHashMap();
+
+    @PostConstruct
+    private void init() {
+
+        /*订单参数校验*/
+
+        /*支付订单类型参数校验*/
+
+        /*订单创建前处理流程*/
+
+        /*订单支付完成后执行*/
+
+        /*退款订单类型参数校验*/
+
+        /*退款支付完成执行*/
+
+        log.info("---> orderCreate.Keys={}", orderGoodsCreate.keySet());
+        log.info("---> paymentSuccess.Keys={}", paymentSuccess.keySet());
+        log.info("---> orderSuccessBefore.Keys={}", orderSuccessBefore.keySet());
+    }
+
+
+    /**
+     * 支付回调消息
+     *
+     * @param paymentResp PaymentResp
+     *
+     */
+    @Transactional
+    @Override
+    public void executePaymentCallback(PaymentResp paymentResp) {
+
+        String lockName = redisCacheService.getPaymentCacheKey(paymentResp.getMerOrderNo());
+        // 订单分布式锁状态
+        DistributedLock.of(redissonClient).runIfLockCanGet(lockName, () -> {
+
+            // 获取订单信息
+            UserPaymentOrderWrapper.UserPaymentOrder paymentOrder = userPaymentOrderService.getUserPaymentOrderByOrderNo(paymentResp.getTransNo(), paymentResp.getMerOrderNo());
+            if (Objects.isNull(paymentOrder)) {
+                log.error("executePaymentCallback 无效的支付订单, paymentResp={}", JSON.toJSONString(paymentResp));
+                throw new BizException("无效的支付订单");
+            }
+
+            // 订单已关闭返回异常信息,更新订单状态为已支付,后续流程不处理,允许用户进行退款操作
+            if (EPaymentStatus.CLOSED == paymentOrder.getStatus() && StringUtils.isNotBlank(paymentOrder.getErrorMsg())) {
+
+                // 支付成功
+                if (PaymentStatus.SUCCESSED == paymentResp.getPaymentStatus()) {
+
+                    UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder
+                        .builder()
+                        .transNo(paymentResp.getTransNo())
+                        .id(paymentOrder.getId())
+                        .status(PAID)
+                        .updateTime(DateTime.now().toDate())
+                        .build();
+                    userPaymentOrderService.updateById(order);
+
+                    log.error("executePaymentCallback 关单异常,更新订单状态为已支付, error={}, status={}, paymentResp={}", paymentOrder.getErrorMsg(),
+                        paymentOrder.getStatus(), JSON.toJSONString(paymentResp));
+                }
+            }
+
+            // 订单状态为待支付、支付中时,更新订单状态;
+            if (EPaymentStatus.WAIT_PAY == paymentOrder.getStatus() || EPaymentStatus.PAYING == paymentOrder.getStatus()) {
+
+                // 支付成功
+                if (PaymentStatus.SUCCESSED == paymentResp.getPaymentStatus()) {
+                    // 根据支付回调消息,更新订单状态
+                    executePaymentSuccess(UserPaymentOrderWrapper.UserPaymentOrder.from(JSON.toJSONString(paymentOrder)), paymentResp);
+                }
+
+                // 支付失败
+                if (PaymentStatus.FAILED == paymentResp.getPaymentStatus()) {
+
+                    // 支付失败,取消订单且更新订单状态
+                    UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder
+                        .builder()
+                        .transNo(paymentResp.getTransNo())
+                        .id(paymentOrder.getId())
+                        .status(EPaymentStatus.FAIL)
+                        .updateTime(DateTime.now().toDate())
+                        .build();
+                    userPaymentOrderService.updateById(order);
+                }
+
+                log.info("executePaymentCallback WAIT_PAY, status={}, paymentResp={}", paymentOrder.getStatus(),
+                    JSON.toJSONString(paymentResp));
+            }
+
+        }, 60L, TimeUnit.SECONDS);
+
+        log.info("executePaymentCallback paymentResp={}", JSON.toJSONString(paymentResp));
+    }
+
+    /**
+     * 支付成功处理流程
+     *
+     * @param paymentOrder UserPaymentOrderWrapper.UserPaymentOrder
+     * @param paymentResp  PaymentResp
+     */
+    @Transactional
+    @Override
+    public void executePaymentSuccess(UserPaymentOrderWrapper.UserPaymentOrder paymentOrder, PaymentResp paymentResp) {
+
+        // 订单已完成,直接忽略后续流程
+        if (EPaymentStatus.WAIT_PAY != paymentOrder.getStatus() && EPaymentStatus.PAYING != paymentOrder.getStatus()) {
+            return;
+        }
+
+        // 支付回调消息,修改订单状态
+        Date date = DateTime.now().toDate();
+
+        UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder
+            .builder()
+            .id(paymentOrder.getId())
+            .status(PAID)
+            .payTime(date)
+            .updateTime(date)
+            .build();
+
+        // 三方支付费用
+        if (Objects.nonNull(paymentResp)) {
+
+            // 更新交易时间和服务费用
+            order.payTime(Optional.ofNullable(paymentResp.getTriggerTime()).orElse(order.getPayTime()))
+                .paymentChannelFee(paymentResp.getServiceCharge())
+                .setTransNo(paymentResp.getTransNo());
+        }
+        userPaymentOrderService.updateById(order);
+
+        // 不同订单类型支付成功,后续数据同步流程
+        if (paymentSuccess.containsKey(paymentOrder.getOrderType())) {
+            paymentSuccess.get(paymentOrder.getOrderType()).accept(paymentOrder);
+        }
+
+        // 生成协议
+        try {
+            sysUserContractRecordService.sign(ContractTemplateTypeEnum.BUY_ORDER, SysUserType.valueOf(paymentOrder.getPaymentClient().name()),
+                    sysUserService.findUserById(paymentOrder.getUserId()));
+        } catch (Exception e) {
+            log.error("executePaymentSuccess 生成协议失败, userId={}, orderNo={}", paymentOrder.getUserId(), paymentOrder.getOrderNo());
+        }
+
+        log.info("executePaymentSuccess userId={}, biz={}, orderNo={}", paymentOrder.getUserId(), paymentOrder.getBizId(), paymentOrder.getOrderNo());
+    }
+
+    /**
+     * 取消订单支付
+     *
+     * @param paymentOrder UserPaymentOrderWrapper.UserPaymentOrder
+     * @param paymentResp  PaymentResp
+     */
+    @Transactional
+    @Override
+    public void cancelPayment(UserPaymentOrderWrapper.UserPaymentOrder paymentOrder, PaymentResp paymentResp) {
+
+        // 同步三方订单支付状态
+        String lockName = redisCacheService.getPaymentCacheKey(paymentOrder.getOrderNo());
+
+        DistributedLock.of(redissonClient).runIfLockCanGet(lockName, () -> {
+
+            // 订单支付已完成
+            if (PaymentStatus.SUCCESSED == paymentResp.getPaymentStatus()) {
+
+                // 关闭当前事务,提交订单支付完成流程
+                ThreadPool.getExecutor().submit(() -> {
+                    // 完成订单支付流程
+                    executePaymentSuccess(paymentOrder, paymentResp);
+                });
+
+                // 提示订单支付已完成
+                throw new BizException("订单支付已完成");
+            }
+
+            // 订单未支付,后续直接更新订单状态为已关闭
+            if (PaymentStatus.PENDDING == paymentResp.getPaymentStatus()) {
+
+                UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder
+                    .builder()
+                    .id(paymentOrder.getId())
+                    //.status(EPaymentStatus.CLOSED)
+                    //.errorMsg(errorMessage)
+                    .updateTime(DateTime.now().toDate())
+                    .build();
+
+                if (StringUtils.isBlank(paymentResp.getMsg())) {
+
+                    String errorMessage = null;
+                    try {
+                        // 关闭三方支付订单状态
+                        PaymentClose paymentClose = paymentServiceContext.getPaymentService(paymentOrder.getPaymentVender())
+                            .close(paymentOrder.getTransNo(), "用户取消支付", paymentOrder.getOrderNo());
+
+                        if (Objects.nonNull(paymentClose)) {
+                            errorMessage = paymentClose.getMsg();
+
+                            // 订单取消,三方返回异常信息
+                            if (StringUtils.isNotEmpty(errorMessage)) {
+                                log.warn("cancelPayment orderNo={}, ex={}", paymentOrder.getOrderNo(), errorMessage);
+                                // 记录异常消息
+                                ThreadPool.getExecutor().submit(() -> {
+                                    order.setErrorMsg(paymentClose.getMsg());
+
+                                    // 更新订单退款异常信息
+                                    userPaymentOrderService.updateById(order);
+                                });
+                                throw new BizException("查询交易中,请耐心等待!");
+                            }
+                        }
+                    } catch (Exception e) {
+                        log.error("cancelPayment orderNo={}", paymentOrder.getOrderNo(), e);
+                        throw new BizException("查询交易中,请耐心等待!");
+                    }
+
+                    order.status(EPaymentStatus.CLOSED).setErrorMsg(errorMessage);
+                }
+
+                // 更新订单关闭状态
+                userPaymentOrderService.updateById(order);
+
+            }
+
+        }, 10L, TimeUnit.SECONDS);
+    }
+
+    /**
+     * 用户下单请求
+     *
+     * @param orderReq UserPaymentOrderWrapper.UserPaymentOrder
+     */
+    @Override
+    public UserPaymentOrderWrapper.PaymentConfig executeOrderCreate(UserPaymentOrderWrapper.UserPaymentOrder orderReq) {
+
+        try {
+
+            // 商品校验 orderCreate
+
+
+            // 用户下单请求锁
+            String lockName = redisCacheService.getExecuteOrderCacheKey(orderReq.getUserId().toString());
+            // 生成用户支付订单
+            return DistributedLock.of(redissonClient).runIfLockToFunction(lockName, this::executeOrder, orderReq, 10L);
+
+        } catch (BizException e) {
+            log.error("executeOrder BizException, orderReq={}",  orderReq.jsonString(), e);
+
+            throw e;
+        } catch (Exception e) {
+            log.error("executeOrder 下单失败,  orderReq={}", orderReq.jsonString(), e);
+
+            throw new BizException("下单失败");
+        }
+    }
+
+    /**
+     * 用户下单请求
+     *
+     * @param orderReq UserPaymentOrderWrapper.UserPaymentOrder
+     */
+    @Transactional
+    @Override
+    public UserPaymentOrderWrapper.PaymentConfig executeOrder(UserPaymentOrderWrapper.UserPaymentOrder orderReq) {
+
+        // 填充订单基本信息
+        orderReq.id(IdWorker.getId())
+            .orderNo(IdWorker.getIdStr())
+            .paymentVender(Optional.ofNullable(orderReq.getPaymentType()).orElse(paymentServiceContext.getPaymentService().venderName()))
+            .paymentChannel("")
+            .status(EPaymentStatus.WAIT_PAY)
+            .originalPrice(BigDecimal.ZERO);
+
+        // 购买商品信息
+        for (UserOrderDetail item : orderReq.getGoodsInfos()) {
+
+            item.setOrderNo(orderReq.getOrderNo());
+            item.setSubOrderNo(IdWorker.getIdStr());
+
+            // 商品基本信息
+            if (orderGoodsCreate.containsKey(item.getGoodType())) {
+                // 填充商品基础信息,校验参数合法以性
+                orderGoodsCreate.get(item.getGoodType()).accept(item);
+            }
+        }
+
+        // 计算原始价格
+        BigDecimal originalPrice = orderReq.getGoodsInfos().stream()
+            .map(UserOrderDetail::getOriginalPrice)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        // 支付金额
+        BigDecimal currentPrice = orderReq.getGoodsInfos().stream()
+            .map(UserOrderDetail::getExpectPrice)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        // 实际支付金额
+        BigDecimal cashAmount = orderReq.getGoodsInfos().stream()
+            .map(UserOrderDetail::getActualPrice)
+            .reduce(BigDecimal.ZERO, BigDecimal::add);
+
+        // 根据优惠券计算实际优惠金额
+
+        orderReq.originalPrice(originalPrice.setScale(2, RoundingMode.HALF_UP))
+            .currentPrice(currentPrice.setScale(2, RoundingMode.HALF_UP))
+            .paymentCouponAmount(BigDecimal.ZERO)
+            .actualPrice(cashAmount.setScale(2, RoundingMode.HALF_UP));
+
+        // 验证支付金额是否匹配
+        if (orderReq.getActualPrice().setScale(2, RoundingMode.HALF_UP)
+            .compareTo(orderReq.getPaymentCashAmount().setScale(2, RoundingMode.HALF_UP)) != 0) {
+            log.info("executeOrder actualPrice={}", orderReq.getActualPrice());
+            throw new BizException("支付金额不匹配");
+        }
+
+        // 订单入库前处理流程
+        if (orderSuccessBefore.containsKey(orderReq.getOrderType())) {
+            orderSuccessBefore.get(orderReq.getOrderType()).accept(orderReq);
+        }
+
+        // 验证成功后,订单入库
+
+        // 查询支付三方配置
+        BasePaymentService paymentService = paymentServiceContext.getPaymentService(orderReq.getPaymentVender());
+        if (Objects.nonNull(paymentService)) {
+            // 设置支付三方AppId
+            orderReq.setPaymentAppId(paymentService.getPaymentConfig().getAppId());
+        }
+        userPaymentOrderService.save(orderReq);
+
+        userOrderDetailService.saveBatch(orderReq.getGoodsInfos());
+
+        // 更新用户订单优惠券使用状态
+
+        String subject = orderReq.getGoodsInfos().stream()
+            .map(UserOrderDetail::getGoodName).collect(Collectors.joining(","));
+        // 返回订单支付配置参数
+        UserPaymentOrderWrapper.PaymentOrderReqConfig reqConfig = UserPaymentOrderWrapper.PaymentOrderReqConfig
+            .builder()
+            .merOrderNo(orderReq.getOrderNo())
+            .subject(subject)
+            .body(subject)
+            .price(orderReq.getPaymentCashAmount().setScale(2, RoundingMode.HALF_UP))
+            .expirationTime(DateTime.now().plusMinutes(30).toDate())
+            .wxAppId(paymentServiceContext.getPaymentService(orderReq.getPaymentVender()).getPaymentConfig().getWxAppId())
+            .userId(String.valueOf(orderReq.getUserId()))
+            .build();
+
+        // 缓存用户下单配置
+        redisCacheService.saveUserOrderConfig(String.valueOf(orderReq.getUserId()), orderReq.getOrderType().getCode(), reqConfig.jsonString());
+
+        // 若订单无需支付,直接完成订单,VIP购买
+        /*if (BigDecimal.ZERO.compareTo(orderReq.getPaymentCashAmount()) == 0 && EPaymentType.VIP == orderReq.getOrderType()) {
+            executePaymentSuccess(orderReq, null);
+        }*/
+
+        return UserPaymentOrderWrapper.PaymentConfig.builder()
+            .orderNo(orderReq.getOrderNo())
+            .paymentConfig(reqConfig)
+            .paymentType(paymentServiceContext.getPaymentService(orderReq.getPaymentVender()).venderName())
+            .build();
+    }
+
+    /**
+     * 用户支付请求
+     *
+     * @param reqConfig UserPaymentOrderWrapper.PaymentOrderReqConfig
+     * @return UserPaymentOrderWrapper.PaymentReq
+     */
+    @Transactional
+    @Override
+    public UserPaymentOrderWrapper.PaymentReq executePayment(JwtUserInfo<?> userInfo,
+                                                             UserPaymentOrderWrapper.PaymentOrderReqConfig reqConfig) {
+
+        // 设置支付用户
+        reqConfig.setUserId(userInfo.getUserId());
+
+        // 用户下单请求锁
+        String lockName = redisCacheService.getPaymentCacheKey(userInfo.getUserId());
+
+        // 分布式锁,用户支付请求
+        return DistributedLock.of(redissonClient).runIfLockToFunction(lockName, this::executePayment, reqConfig, 10L);
+    }
+
+    /**
+     * 更新用户支付订单状态
+     * @param userId 支付用户Id
+     * @param userPaymentOrder UserPaymentOrder
+     * @param paymentResp PaymentResp
+     */
+    public void updateUserPaymentOrderStatus(String userId, UserPaymentOrderWrapper.UserPaymentOrder userPaymentOrder, PaymentResp paymentResp) {
+
+        // 若三方支付已完,本地订单状态未同步
+        if (PaymentStatus.SUCCESSED == paymentResp.getPaymentStatus() && PAID != userPaymentOrder.getStatus()) {
+
+            if (EPaymentStatus.WAIT_PAY == userPaymentOrder.getStatus() || EPaymentStatus.PAYING == userPaymentOrder.getStatus()) {
+
+                // 订单完成后续流程
+                SpringContextHolder.getBean(UserPaymentCoreService.class)
+                    .executePaymentSuccess(UserPaymentOrderWrapper.UserPaymentOrder.from(JSON.toJSONString(userPaymentOrder)), paymentResp);
+            }
+
+            // 删除支付配置
+            redisCacheService.deleteUserPaymentConfig(userId, userPaymentOrder.getOrderType().getCode());
+
+            // 删除下单配置
+            redisCacheService.deleteUserOrderConfig(userId, userPaymentOrder.getOrderType().getCode());
+        }
+
+        // 三方支付失败
+        if (PaymentStatus.FAILED == paymentResp.getPaymentStatus() && EPaymentStatus.FAIL != userPaymentOrder.getStatus()) {
+
+            // 更新订单状态
+            UserPaymentOrderWrapper.UserPaymentOrder update = UserPaymentOrderWrapper.UserPaymentOrder
+                .builder()
+                .id(userPaymentOrder.getId())
+                .status(EPaymentStatus.FAIL)
+                .build();
+            userPaymentOrderService.updateById(update);
+
+            // 订单关闭流程
+            SpringContextHolder.getBean(UserPaymentCoreService.class)
+                .cancelPayment(UserPaymentOrderWrapper.UserPaymentOrder.from(JSON.toJSONString(userPaymentOrder)), paymentResp);
+
+            // 删除本地缓存
+            redisCacheService.deleteUserPaymentConfig(userId, userPaymentOrder.getOrderType().getCode());
+        }
+    }
+
+    /**
+     * 用户支付请求
+     *
+     * @param reqConfig UserPaymentOrderWrapper.PaymentOrderReqConfig
+     * @return UserPaymentOrderWrapper.PaymentReq
+     */
+    @Transactional
+    @Override
+    public UserPaymentOrderWrapper.PaymentReq executePayment(UserPaymentOrderWrapper.PaymentOrderReqConfig reqConfig) {
+
+        // 查询订单状态
+        UserPaymentOrderWrapper.UserPaymentOrder userPaymentOrder = userPaymentOrderService.getUserPaymentOrderByUserId(Long.parseLong(reqConfig.getUserId()),
+            reqConfig.getMerOrderNo());
+        if (Objects.isNull(userPaymentOrder)) {
+            throw new BizException("订单不存在");
+        }
+
+
+
+//         订单支付已完成
+        switch (userPaymentOrder.getStatus()) {
+            case PAID:
+                throw new BizException("订单已支付");
+            case CLOSED:
+                throw new BizException("订单已关闭");
+            case TIMEOUT:
+                throw new BizException("订单已超时");
+            case FAIL:
+                throw new BizException("订单支付失败");
+            default:
+                break;
+        }
+
+//         订单支付状态异常
+        if (EPaymentStatus.WAIT_PAY != userPaymentOrder.getStatus() && EPaymentStatus.PAYING != userPaymentOrder.getStatus()) {
+            throw new BizException("订单支付状态异常");
+        }
+
+        // 微信支付,需要校验code值是否为空
+        if (EPaymentChannel.WX_PUB.getCode().equals(reqConfig.getPaymentChannel())
+            && StringUtils.isBlank(reqConfig.getCode())) {
+            throw new BizException("微信支付code值为空");
+        }
+
+        // 生成订单支付参数,三方返返回异常,直接关闭订单
+        try {
+
+            // 已产生三方交易流水号,先判断三方订单支付状态若在支付中,则重复返回相同支付配置参数;避免用户重复支付
+            if (StringUtils.isNotBlank(userPaymentOrder.getTransNo())) {
+
+                // 获取缓存配置信息
+                String paymentConfig = redisCacheService.getUserPaymentConfig(reqConfig.getUserId(), userPaymentOrder.getOrderType().getCode());
+                if (StringUtils.isBlank(paymentConfig)) {
+
+                    // 支付配置已失效,待支付订单状态调整为已关闭,提醒用户重新购买
+                    PaymentClose paymentClose = paymentServiceContext.getPaymentService(userPaymentOrder.getPaymentVender())
+                        .close(userPaymentOrder.getTransNo(), "订单支付已超时", userPaymentOrder.getOrderNo());
+
+                    // 更新订单状态为已超时
+                    UserPaymentOrderWrapper.UserPaymentOrder update = UserPaymentOrderWrapper.UserPaymentOrder
+                        .builder()
+                        .id(userPaymentOrder.getId())
+                        .status(EPaymentStatus.CLOSED)
+                        .errorMsg(paymentClose.getMsg())
+                        .build();
+                    userPaymentOrderService.updateById(update);
+
+                    throw BizException.from("支付超时");
+                }
+
+                // 返回支付配置信息
+                return UserPaymentOrderWrapper.PaymentReq.from(paymentConfig);
+            }
+
+            // 查询用户下单配置
+            String ret = redisCacheService.getUserOrderConfig(reqConfig.getUserId(), userPaymentOrder.getOrderType().getCode());
+            if (StringUtils.isEmpty(ret)) {
+                throw new BizException("支付超时");
+            }
+            UserPaymentOrderWrapper.PaymentOrderReqConfig config = UserPaymentOrderWrapper.PaymentOrderReqConfig
+                .from(ret)
+                .paymentChannel(reqConfig.getPaymentChannel())
+                .merOrderNo(reqConfig.getMerOrderNo())
+                .code(reqConfig.getCode());
+
+            // 重新格式化设置价格
+            config.setPrice(config.getPrice().setScale(2, RoundingMode.HALF_UP));
+            log.info("executePayment reqConfig={}", config.jsonString());
+
+            PaymentOrder paymentOrder = JSON.parseObject(config.jsonString(), PaymentOrder.class);
+            PaymentReq paymentReq = paymentServiceContext.getPaymentService(userPaymentOrder.getPaymentVender()).pay(paymentOrder);
+            if (Objects.isNull(paymentReq)) {
+                throw BizException.from("生成支付参数异常");
+            }
+
+            // 更新订单流水号
+            UserPaymentOrderWrapper.UserPaymentOrder update = UserPaymentOrderWrapper.UserPaymentOrder
+                .builder()
+                .id(userPaymentOrder.getId())
+                .transNo(paymentReq.getTransNo())
+                .paymentChannel(reqConfig.getPaymentChannel())
+                .transPayTime(DateTime.now().toDate())
+                .status(EPaymentStatus.PAYING)
+                .build();
+            userPaymentOrderService.updateById(update);
+
+            // 缓存用户支付配置信息
+            redisCacheService.saveUserPaymentConfig(reqConfig.getUserId(), userPaymentOrder.getOrderType().getCode(),
+                JSON.toJSONString(paymentReq));
+
+            return UserPaymentOrderWrapper.PaymentReq.from(JSON.toJSONString(paymentReq));
+
+        } catch (Exception e) {
+            log.error("executePayment reqConfig={}", reqConfig.jsonString(), e);
+
+            // 拉起三方支付失败,主动调整订单状态为已关闭
+            userPaymentOrderService.closeUserPaymentOrder(userPaymentOrder.getId());
+
+            throw e;
+        }
+
+    }
+
+    /**
+     * 用户取消支付
+     *
+     * @param userInfo JwtUserInfo
+     * @param orderNo  订单编号
+     */
+    @Transactional
+    @Override
+    public void cancelPayment(JwtUserInfo<?> userInfo, String orderNo) {
+
+        // 查询订单信息,支付状态
+        UserPaymentOrderWrapper.UserPaymentOrder paymentOrder = userPaymentOrderService.getUserPaymentOrderByUserId(Long.parseLong(userInfo.getUserId()), orderNo);
+        if (Objects.isNull(paymentOrder)) {
+            throw new BizException("订单不存在");
+        }
+
+        // 订单状态处理
+        switch (paymentOrder.getStatus()) {
+            case PAID:
+                // 订单支付已完成不可取消,走申请退款流程
+                throw new BizException("订单已支付");
+            case REFUNDED:
+                // 订单已取消
+                throw new BizException("订单已取消");
+            case CLOSED:
+                throw new BizException("订单已关闭");
+            default:
+                break;
+        }
+
+        // 任务执行锁
+        String lockName = redisCacheService.getPaymentCacheKey(orderNo);
+        DistributedLock.of(redissonClient).runIfLockCanGet(lockName, () -> {
+
+            // 下单未拉起三方支付,直接关闭
+            if (StringUtils.isEmpty(paymentOrder.getTransNo())) {
+
+                // 直接关闭订单
+                UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder
+                    .builder()
+                    .id(paymentOrder.getId())
+                    .status(EPaymentStatus.CLOSED)
+                    .updateTime(DateTime.now().toDate())
+                    .build();
+                userPaymentOrderService.updateById(order);
+
+
+            } else {
+                // 获取三方支付订单信息,根据订单状处理
+                PaymentResp paymentResp = paymentServiceContext.getPaymentService(paymentOrder.getPaymentVender())
+                    .query(paymentOrder.getTransNo(), paymentOrder.getOrderNo());
+                if (Objects.isNull(paymentResp)) {
+                    throw new BizException("订单支付状态获取异常,稍后请重试");
+                }
+                // 支付订单信息
+                UserPaymentOrderWrapper.UserPaymentOrder order = UserPaymentOrderWrapper.UserPaymentOrder.from(JSON.toJSONString(paymentOrder));
+
+                // 订单取消执行流程
+                cancelPayment(order, paymentResp);
+            }
+
+        }, 10L, TimeUnit.SECONDS);
+
+    }
+
+
+    /**
+     * 扫描支付超时定时
+     */
+    @Override
+    public void scanPaymentTimeoutOrderRecord() {
+
+        // 查询半小时前创建的并且还未完成的订单 WAIT_PAY 待支付订单 PAYING 支付中订单
+        UserPaymentOrderWrapper.UserPaymentOrderQuery waitPayQuery = UserPaymentOrderWrapper.UserPaymentOrderQuery
+            .builder()
+            .paymentStatus(Lists.newArrayList(OrderStatusEnum.parse(EPaymentStatus.WAIT_PAY)))
+            .endTime(DateTime.now().minusMinutes(30).toDate())
+            .build();
+
+        IPage<UserPaymentOrderWrapper.UserPaymentOrder> page = QueryInfo.getPage(1, 10);
+        // 查询待支付订单数
+        userPaymentOrderService.selectPage(page, waitPayQuery);
+
+        // 更新订单状态
+        scheduleUpdatePaymentOrderStatus(page, waitPayQuery, EPaymentStatus.WAIT_PAY);
+
+        // 查询支付中订单,超过2个小时且还未完成自动关闭
+        UserPaymentOrderWrapper.UserPaymentOrderQuery payingQuery = UserPaymentOrderWrapper.UserPaymentOrderQuery
+            .builder()
+            .paymentStatus(Lists.newArrayList(OrderStatusEnum.parse(EPaymentStatus.PAYING)))
+            .endTime(DateTime.now().plusMinutes(120).toDate())
+            .build();
+        // 查询支付中订单数
+        userPaymentOrderService.selectPage(page, payingQuery);
+
+        // 更新订单状态
+        scheduleUpdatePaymentOrderStatus(page, payingQuery, EPaymentStatus.PAYING);
+
+    }
+
+    /**
+     * 定时更新订单状态
+     * @param page IPage<UserPaymentOrderWrapper.UserPaymentOrder>
+     * @param orderQuery UserPaymentOrderWrapper.UserPaymentOrderQuery
+     * @param paymentStatus 订单状态
+     */
+    public void scheduleUpdatePaymentOrderStatus(IPage<UserPaymentOrderWrapper.UserPaymentOrder> page,
+                                                  UserPaymentOrderWrapper.UserPaymentOrderQuery orderQuery,
+                                                  EPaymentStatus paymentStatus) {
+
+        // 分页数限制
+        int limit = 500;
+        // 计算总页数
+        int totalPages = (int) (page.getTotal() - 1) / limit + 1;
+
+        List<Integer> pageNums = IntStream.iterate(1, i -> i + 1).limit(totalPages).boxed().collect(Collectors.toList());
+
+        IPage<UserPaymentOrderWrapper.UserPaymentOrder> pages;
+        String lockName;
+        for (Integer pageNum : pageNums) {
+
+            pages = userPaymentOrderService.selectPage(QueryInfo.getPage(pageNum, limit), orderQuery);
+            if (CollectionUtils.isNotEmpty(pages.getRecords())) {
+
+                for (UserPaymentOrderWrapper.UserPaymentOrder item : pages.getRecords()) {
+
+                    lockName = redisCacheService.getPaymentCacheKey(item.getOrderNo());
+                    // 并发执行锁
+                    DistributedLock.of(redissonClient).runIfLockCanGet(lockName, () -> {
+
+                        // 订单用户信息
+                        JwtUserInfo<Object> userInfo = JwtUserInfo.builder()
+                            .userId(String.valueOf(item.getUserId()))
+                            .clientType(item.getPaymentClient().getCode())
+                            .build();
+
+                        // 用户下单超进关闭
+                        if (EPaymentStatus.WAIT_PAY == paymentStatus
+                            || new DateTime(item.getCreateTime()).plusMinutes(118).isBeforeNow()) {
+
+                            try {
+                                log.info("scanPaymentTimeoutOrderRecord WAIT_PAY, userId={}, orderNo={}", item.getUserId(), item.getOrderNo());
+                                // 关闭待支付、超时订单
+                                SpringContextHolder.getBean(UserPaymentCoreService.class).cancelPayment(userInfo, item.getOrderNo());
+                            } catch (Exception e) {
+                                log.error("scanPaymentTimeoutOrderRecord WAIT_PAY, userId={}, orderNo={}", item.getUserId(), item.getOrderNo(), e);
+                            }
+
+                        }
+
+                        // 支付时间未超时,同步订单状态
+                        if (EPaymentStatus.PAYING == paymentStatus
+                            && new DateTime(item.getCreateTime()).plusMinutes(120).isAfterNow()) {
+
+                            // 支付同小消息
+                            PaymentResp paymentResp = paymentServiceContext.getPaymentService(item.getPaymentVender()).query(item.getTransNo(), item.getOrderNo());
+                            if (Objects.nonNull(paymentResp)) {
+
+                                try {
+
+                                    log.info("scanPaymentTimeoutOrderRecord PAYMENT_SYNC, vendor={}, paymentResp={}", item.getPaymentVender(),
+                                        JSON.toJSONString(paymentResp));
+                                    // 支付成功
+                                    if (PaymentStatus.SUCCESSED == paymentResp.getPaymentStatus()) {
+                                        // 根据支付回调消息,更新订单状态
+                                        SpringContextHolder.getBean(UserPaymentCoreService.class)
+                                            .executePaymentSuccess(UserPaymentOrderWrapper.UserPaymentOrder.from(JSON.toJSONString(item)), paymentResp);
+                                    }
+
+                                } catch (Exception e) {
+                                    log.error("scanPaymentTimeoutOrderRecord PAYMENT_SYNC, userId={}, orderNo={}", item.getUserId(), item.getOrderNo(), e);
+                                }
+
+                            }
+
+                        }
+
+                    }, 60L, TimeUnit.SECONDS);
+
+                }
+            }
+        }
+        //log.info("scheduleUpdatePaymentOrderStatus PAYMENT_FINISH ------> ");
+    }
+
+
+
+}

+ 211 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/service/impl/UserPaymentOrderServiceImpl.java

@@ -0,0 +1,211 @@
+package com.yonge.cooleshow.biz.dal.service.impl;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.yonge.cooleshow.biz.dal.dao.UserOrderDao;
+import com.yonge.cooleshow.biz.dal.entity.UserOrder;
+import com.yonge.cooleshow.biz.dal.entity.UserOrderPayment;
+import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
+import com.yonge.cooleshow.biz.dal.service.UserOrderPaymentService;
+import com.yonge.cooleshow.biz.dal.service.UserOrderService;
+import com.yonge.cooleshow.biz.dal.service.UserPaymentOrderService;
+import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
+import com.yonge.cooleshow.common.enums.EPaymentVersion;
+import com.yonge.toolset.payment.base.enums.TradeStatusEnum;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.collections.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Isolation;
+import org.springframework.transaction.annotation.Propagation;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+import static com.baomidou.mybatisplus.core.toolkit.Wrappers.lambdaQuery;
+
+/**
+ * 平台订单表
+ * 2022-12-20 19:09:34
+ */
+@Slf4j
+@Service
+public class UserPaymentOrderServiceImpl  implements UserPaymentOrderService {
+
+    @Autowired
+    private UserOrderService userOrderService;
+
+    @Autowired
+    private UserOrderPaymentService userOrderPaymentService;
+
+    @Autowired
+    private UserOrderDao userOrderDao;
+
+
+    /**
+     * 用户支付订单信息
+     *
+     * @param transNo 交易流水号
+     * @param merOrderNo 订单编号
+     * @return UserPaymentOrder
+     */
+    @Override
+    public UserPaymentOrderWrapper.UserPaymentOrder getUserPaymentOrderByOrderNo(String transNo, String merOrderNo) {
+
+        // 查询订单信息
+        UserOrder one = userOrderService.lambdaQuery()
+                .eq(UserOrder::getOrderNo, merOrderNo)
+                .last("LIMIT 1")
+                .one();
+
+        if (one == null) {
+            return null;
+        }
+
+        // 查询订单支付信息
+        UserOrderPayment newestPayment = userOrderPaymentService.getNewestPayment(transNo, merOrderNo);
+
+        return UserPaymentOrderWrapper.UserPaymentOrder.from(one, newestPayment);
+
+
+    }
+
+
+    /**
+     * 分页查询
+     * @param page IPage<com.cooleshow.edu.domain.wrapper.UserPaymentOrderWrapper.UserPaymentOrder>
+     * @param query UserPaymentOrderWrapper.UserPaymentOrderQuery
+     * @return IPage<com.cooleshow.edu.domain.wrapper.UserPaymentOrderWrapper.UserPaymentOrder>
+     */
+    @Override
+    public IPage<UserPaymentOrderWrapper.UserPaymentOrder> selectPage(IPage<UserPaymentOrderWrapper.UserPaymentOrder> page,
+                                                                      UserPaymentOrderWrapper.UserPaymentOrderQuery query) {
+
+        List<UserOrder> userOrders = userOrderDao.selectPaymentOrderPage(page, query);
+
+        if (CollectionUtils.isEmpty(userOrders)) {
+            return page;
+        }
+
+        // 获取订单号
+        List<String> orderNos = userOrders.stream().map(o -> o.getOrderNo()).collect(Collectors.toList());
+
+        Map<String, UserOrderPayment> paymentMap = userOrderPaymentService.getNewestPaymentMapByOrderNos(orderNos);
+
+        List<UserPaymentOrderWrapper.UserPaymentOrder> paymentOrders = new ArrayList<>(userOrders.size());
+        for (UserOrder userOrder : userOrders) {
+            paymentOrders.add(UserPaymentOrderWrapper.UserPaymentOrder.from(userOrder, paymentMap.get(userOrder.getOrderNo())));
+        }
+
+        return page.setRecords(paymentOrders);
+    }
+
+
+    /**
+     * 用户支付订单
+     *
+     * @param userId     用户Id
+     * @param merOrderNo 商户订单编号
+     * @return UserPaymentOrder
+     */
+    @Override
+    public UserPaymentOrderWrapper.UserPaymentOrder getUserPaymentOrderByUserId(Long userId, String merOrderNo) {
+
+        UserOrder userOrder = userOrderService.lambdaQuery()
+                .eq(UserOrder::getUserId, userId)
+                .eq(UserOrder::getOrderNo, merOrderNo)
+                .last("LIMIT 1")
+                .one();
+        if (userOrder == null) {
+            return null;
+        }
+        // 查询订单支付信息
+        UserOrderPayment newestPayment = userOrderPaymentService.getNewestPayment(null, merOrderNo);
+
+        return UserPaymentOrderWrapper.UserPaymentOrder.from(userOrder, newestPayment);
+
+
+    }
+
+
+    /**
+     * 关闭用户支付订单状态
+     *
+     * @param id 用户支付订单Id
+     */
+    @Override
+    @Transactional(isolation = Isolation.READ_COMMITTED, propagation = Propagation.REQUIRES_NEW)
+    public void closeUserPaymentOrder(Long id) {
+
+        UserOrder userOrder = new UserOrder();
+        userOrder.setId(id);
+        userOrder.setStatus(OrderStatusEnum.CLOSE);
+        userOrderService.updateById(userOrder);
+    }
+
+
+    @Override
+    @Transactional
+    public void updateById(UserPaymentOrderWrapper.UserPaymentOrder order) {
+        if (order == null) {
+            return;
+        }
+
+        // 更新订单
+        UserOrder userOrder = order.toUserOrder();
+        userOrderService.updateById(userOrder);
+
+        // 更新订单支付信息
+
+        userOrder = userOrderService.getById(userOrder.getId());
+
+        UserOrderPayment newestPayment = userOrderPaymentService.getNewestPayment(order.getTransNo(), userOrder.getOrderNo());
+        if (newestPayment == null) {
+            return;
+        }
+
+        newestPayment.setOrderNo(userOrder.getOrderNo());
+        newestPayment.setPaymentVendor(order.getPaymentVender());
+        newestPayment.setPaymentChannel(order.getPaymentChannel());
+        newestPayment.setPaymentAppId(order.getPaymentAppId());
+        newestPayment.setPaymentNo(order.getOrderNo());
+        newestPayment.setTransNo(order.getTransNo());
+        newestPayment.setPayAmt(order.getPaymentCashAmount());
+        newestPayment.setFeeAmt(order.getPaymentChannelFee());
+        // 状态转换
+        switch (order.getStatus()) {
+            case TIMEOUT:
+            case FAIL:
+                newestPayment.setStatus(TradeStatusEnum.failed);
+                newestPayment.setPayFailMsg(order.getErrorMsg());
+            case PAID:
+            case REFUNDED:
+                newestPayment.setStatus(TradeStatusEnum.succeeded);
+            case CLOSED:
+                newestPayment.setStatus(TradeStatusEnum.close);
+            case PAYING:
+            case WAIT_PAY:
+            default:
+                break;
+
+        }
+        userOrderPaymentService.updateById(newestPayment);
+    }
+
+    /**
+     * 创建订单
+     *
+     * @param orderReq
+     */
+    @Override
+    @Transactional
+    public void save(UserPaymentOrderWrapper.UserPaymentOrder orderReq) {
+
+        // 更新订单
+        UserOrder userOrder = orderReq.toUserOrder();
+        userOrder.setPaymentVersion(EPaymentVersion.V2);
+
+        userOrderService.save(userOrder);
+    }
+
+}

+ 796 - 0
cooleshow-user/user-biz/src/main/java/com/yonge/cooleshow/biz/dal/wrapper/UserPaymentOrderWrapper.java

@@ -0,0 +1,796 @@
+package com.yonge.cooleshow.biz.dal.wrapper;
+
+import com.alibaba.excel.annotation.ExcelIgnore;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.fastjson.JSON;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.microsvc.toolkit.common.response.paging.QueryInfo;
+import com.sun.istack.internal.NotNull;
+import com.yonge.cooleshow.biz.dal.entity.UserOrder;
+import com.yonge.cooleshow.biz.dal.entity.UserOrderDetail;
+import com.yonge.cooleshow.biz.dal.entity.UserOrderPayment;
+import com.yonge.cooleshow.biz.dal.enums.ClientEnum;
+import com.yonge.cooleshow.biz.dal.enums.OrderStatusEnum;
+import com.yonge.cooleshow.biz.dal.enums.OrderTypeEnum;
+import com.yonge.cooleshow.common.enums.payment.EGoodsType;
+import com.yonge.cooleshow.common.enums.payment.EPaymentStatus;
+import com.yonge.cooleshow.common.enums.payment.EPaymentType;
+import io.rong.util.ParamNotNull;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.apache.commons.lang3.StringUtils;
+import org.joda.time.DateTime;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.text.MessageFormat;
+import java.util.*;
+
+/**
+ * 平台订单表
+ * 2022-12-20 19:09:34
+ */
+@ApiModel(value = "UserPaymentOrderWrapper对象", description = "平台订单表查询对象")
+public class UserPaymentOrderWrapper {
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" UserPaymentOrderQuery-平台订单表")
+    public static class UserPaymentOrderQuery implements QueryInfo {
+
+        @ApiModelProperty("当前页")
+        private Integer page;
+
+        @ApiModelProperty("分页行数")
+        private Integer rows;
+
+
+        @ApiModelProperty("订单支付状态")
+        private List<OrderStatusEnum> paymentStatus;
+
+        @ApiModelProperty("订单结束时间")
+        private Date endTime;
+
+
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static UserPaymentOrderQuery from(String json) {
+            return JSON.parseObject(json, UserPaymentOrderQuery.class);
+        }
+
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" UserPaymentOrderQuery-平台订单表")
+    public static class UserPaymentOrderExportQuery{
+
+        @ApiModelProperty("城市编码")
+        private Integer cityCode;
+
+        @ApiModelProperty("学校名称")
+        private String schoolName;
+
+        @ApiModelProperty("学员编号、姓名、手机号")
+        private String userKeyword;
+
+        @ApiModelProperty("审核人")
+        private Long auditUserId;
+
+        @ApiModelProperty("申请开始时间")
+        private Date refundStartTime;
+
+        @ApiModelProperty("申请结束时间")
+        private Date refundEndTime;
+
+        @ApiModelProperty("订单编号")
+        private String orderNo;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public String getUserKeyword() {
+            return Optional.ofNullable(userKeyword).filter(StringUtils::isNotBlank).orElse(null);
+        }
+
+        public static UserPaymentOrderQuery from(String json) {
+            return JSON.parseObject(json, UserPaymentOrderQuery.class);
+        }
+    }
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" UserPaymentOrderQuery-平台订单表")
+    public static class StudentOrderQuery implements QueryInfo {
+
+        @ApiModelProperty("当前页")
+        private Integer page;
+
+        @ApiModelProperty("分页行数")
+        private Integer rows;
+
+        @ApiModelProperty("订单状态")
+        private String orderStatus;
+
+        @ApiModelProperty("用户Id")
+        private Long userId;
+
+        @ApiModelProperty("订单支付时间(yyyy-mm)")
+        private String payMonth;
+    }
+
+    @Data
+    @ApiModel(" UserPaymentApplyOrder-平台订单表")
+    public static class UserPaymentApplyOrder{
+
+        @ApiModelProperty("业务编号")
+        private String bizId;
+
+        @ApiModelProperty("用户Id")
+        private Long userId;
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel(" UserPaymentOrder-平台订单表")
+    public static class UserPaymentOrder {
+
+        @ApiModelProperty("主键")
+        private Long id;
+
+        @ApiModelProperty("支付类型: adapay, wxpay")
+        private String paymentType;
+
+        @ApiModelProperty("支付厂商")
+        private String paymentVender;
+
+        @ApiModelProperty("支付厂商名")
+        private String paymentVenderName;
+
+
+        @ApiModelProperty(value = "推荐用户id(有推荐人的情况)")
+        private Long recomUserId;
+
+        @ApiModelProperty(value = "活动id(有活动的情况)")
+        private Long activityId;
+
+        @ApiModelProperty(value = "活动奖品id(有活动的情况)")
+        private Long rewardId;
+
+        @ApiModelProperty("支付商户号")
+        private String paymentMerchantNo;
+
+        @ApiModelProperty("支付商户号appid")
+        private String paymentAppId;
+
+        @ApiModelProperty("支付渠道")
+        private String paymentChannel;
+
+        @ApiModelProperty("用户身份")
+        private ClientEnum paymentClient;
+
+        @ApiModelProperty("用户编号")
+        private Long userId;
+
+        @ApiModelProperty("商户订单号")
+        private String orderNo;
+
+        @ApiModelProperty("交易流水号")
+        private String transNo;
+
+        @ApiModelProperty("业务类型Id,学校编号")
+        private String bizId;
+
+        @ApiModelProperty("订单类型")
+        private EPaymentType orderType;
+
+        @ApiModelProperty("订单状态")
+        private EPaymentStatus status;
+
+        @ApiModelProperty("原价")
+        private BigDecimal originalPrice;
+
+        @ApiModelProperty("现价")
+        private BigDecimal currentPrice;
+
+        @ApiModelProperty("支付现金金额")
+        private BigDecimal paymentCashAmount;
+
+        @ApiModelProperty("支付优惠金额")
+        private BigDecimal paymentCouponAmount;
+
+        @ApiModelProperty("支付通道费用")
+        private BigDecimal paymentChannelFee;
+
+        @ApiModelProperty("订单名称")
+        private String orderName;
+
+        @ApiModelProperty("订单描述信息")
+        private String orderDesc;
+
+        @ApiModelProperty("用户备注")
+        private String userNote;
+
+        @ApiModelProperty("支付拉起时间")
+        private Date transPayTime;
+
+        @ApiModelProperty("支付时间")
+        private Date payTime;
+
+        @ApiModelProperty("原因")
+        private String errorMsg;
+
+
+        @ApiModelProperty("更新时间")
+        private Date updateTime;
+
+        @ApiModelProperty("下单时间")
+        private Date createTime;
+
+
+        @ApiModelProperty("实际价格 ")
+        private BigDecimal actualPrice;
+
+
+        @ApiModelProperty("商品信息")
+        private List<UserOrderDetail> goodsInfos;
+
+
+        @ApiModelProperty("支付配置参数")
+        private PaymentConfig paymentConfig;
+
+
+        @ApiModelProperty("支付消息通知")
+        private Boolean paymentMessage;
+
+        @ApiModelProperty("取消支付标记")
+        private Boolean cancelPayment;
+
+        @ApiModelProperty("取消支付限制剩余时长")
+        private Long cancelTimes;
+
+
+        public static UserPaymentOrder from(UserOrder userOrder, UserOrderPayment userOrderPayment) {
+            if (userOrder == null ) {
+                return null;
+            }
+            if (userOrderPayment == null) {
+                userOrderPayment = new UserOrderPayment();
+            }
+            return UserPaymentOrder.builder()
+                    .id(userOrder.getId())
+                    .paymentType(userOrder.getPaymentVendor())
+                    .paymentVender(userOrder.getPaymentVendor())
+                    .paymentChannel(userOrder.getPaymentChannel())
+                    .paymentClient(userOrder.getOrderClient())
+                    .userId(userOrder.getUserId())
+                    .orderNo(userOrder.getOrderNo())
+                    .transNo(userOrderPayment.getTransNo())
+                    .bizId(null)
+                    .orderType(EPaymentType.valueOf(userOrder.getOrderType().name()))
+                    .status(OrderStatusEnum.parse(userOrder.getStatus()))
+                    .originalPrice(userOrder.getOriginalPrice())
+                    .currentPrice(userOrder.getExpectPrice())
+                    .paymentCashAmount(userOrder.getActualPrice())
+                    .paymentCouponAmount(userOrder.getCouponAmount())
+                    .paymentChannelFee(userOrderPayment.getFeeAmt())
+                    .orderName(userOrder.getOrderName())
+                    .orderDesc(userOrder.getOrderDesc())
+                    .userNote(userOrder.getUserNote())
+                    .transPayTime(userOrderPayment.getCreateTime())
+                    .payTime(userOrder.getPayTime())
+                    .errorMsg(userOrderPayment.getPayFailMsg())
+                    .updateTime(userOrder.getUpdateTime())
+                    .createTime(userOrder.getCreateTime())
+                    .actualPrice(userOrder.getActualPrice())
+                    .paymentMessage(null)
+                    .cancelPayment(null)
+                    .cancelTimes(null)
+                    .recomUserId(userOrder.getRecomUserId())
+                    .activityId(userOrder.getActivityId())
+                    .rewardId(userOrder.getRewardId())
+                    .build();
+        }
+
+        // 转 UserOrder
+        public UserOrder toUserOrder() {
+            return UserOrder.builder()
+                    .id(getId())
+                    .paymentVendor(getPaymentVender())
+                    .paymentChannel(getPaymentChannel())
+                    .paymentAppId(getPaymentAppId())
+                    .orderClient(getPaymentClient())
+                    .userId(getUserId())
+                    .orderNo(getOrderNo())
+                    .orderType(OrderTypeEnum.valueOf(getOrderType().name()))
+                    .status(OrderStatusEnum.parse(getStatus()))
+                    .originalPrice(getOriginalPrice())
+                    .expectPrice(getCurrentPrice())
+                    .actualPrice(getPaymentCashAmount())
+                    .couponAmount(getPaymentCouponAmount())
+                    .orderName(getOrderName())
+                    .orderDesc(getOrderDesc())
+                    .userNote(getUserNote())
+                    .payTime(getPayTime())
+                    .updateTime(getUpdateTime())
+                    .createTime(getCreateTime())
+                    .recomUserId(getRecomUserId())
+                    .activityId(getActivityId())
+                    .rewardId(getRewardId())
+                    .build();
+        }
+
+        public Boolean getCancelPayment() {
+            if (EPaymentStatus.PAYING == getStatus() && Objects.nonNull(getTransPayTime())) {
+                // 超过1分钟,才可以取消订单
+                return getTransPayTime().getTime() + 65 * 1000 < System.currentTimeMillis();
+            }
+            return Optional.ofNullable(cancelPayment).orElse(true);
+        }
+
+        public Long getCancelTimes() {
+            if (!getCancelPayment() && Objects.nonNull(getTransPayTime())) {
+                // 超过1分钟,才可以取消订单
+                return getTransPayTime().getTime() + 65 * 1000 - System.currentTimeMillis();
+            }
+            return Optional.ofNullable(cancelTimes).orElse(0L);
+        }
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static UserPaymentOrder from(String json) {
+            return JSON.parseObject(json, UserPaymentOrder.class);
+        }
+
+
+        public void setPayTime(Long payTime) {
+
+            if (Objects.nonNull(payTime)) {
+                // 时间戳精度为毫秒,自动*1000
+                if (payTime.toString().length() <= 10) {
+                    payTime *= 1000;
+                }
+                this.payTime = new Date(payTime);
+            }
+        }
+
+        public UserPaymentOrder paymentChannelFee(BigDecimal paymentChannelFee) {
+            this.paymentChannelFee = paymentChannelFee;
+            return this;
+        }
+
+        public UserPaymentOrder payTime(Date payTime) {
+            this.payTime = payTime;
+            return this;
+        }
+
+        public UserPaymentOrder paymentVender(String paymentVender) {
+            if (StringUtils.isBlank(this.paymentVender)) {
+                this.paymentVender = paymentVender;
+            }
+            return this;
+        }
+
+        public UserPaymentOrder paymentChannel(String paymentChannel) {
+            this.paymentChannel = paymentChannel;
+            return this;
+        }
+
+        public UserPaymentOrder paymentClient(ClientEnum paymentClient) {
+            this.paymentClient = paymentClient;
+            return this;
+        }
+
+        public UserPaymentOrder userId(Long userId) {
+            this.userId = userId;
+            return this;
+        }
+
+        public UserPaymentOrder orderNo(String orderNo) {
+            this.orderNo = orderNo;
+            return this;
+        }
+
+        public UserPaymentOrder status(EPaymentStatus status) {
+            this.status = status;
+            return this;
+        }
+
+        public UserPaymentOrder originalPrice(BigDecimal originalPrice) {
+            this.originalPrice = originalPrice;
+            return this;
+        }
+
+        public UserPaymentOrder currentPrice(BigDecimal currentPrice) {
+            this.currentPrice = currentPrice;
+            return this;
+        }
+
+        public UserPaymentOrder id(Long id) {
+            this.id = id;
+            return this;
+        }
+
+        public UserPaymentOrder paymentCashAmount(BigDecimal paymentCashAmount) {
+            this.paymentCashAmount = paymentCashAmount;
+            return this;
+        }
+
+        public UserPaymentOrder paymentCouponAmount(BigDecimal paymentCouponAmount) {
+            this.paymentCouponAmount = paymentCouponAmount;
+            return this;
+        }
+
+        public UserPaymentOrder actualPrice(BigDecimal actualPrice) {
+            this.actualPrice = actualPrice;
+            return this;
+        }
+
+
+
+        public UserPaymentOrder updateTime(Date updateTime) {
+            this.updateTime = updateTime;
+            return this;
+        }
+    }
+
+    @Data
+    @ApiModel(" StudentPaymentOrder-学员订单表")
+    public static class StudentPaymentOrder {
+        @ApiModelProperty("订单id")
+        private Long id;
+
+        @ApiModelProperty("订单编号")
+        private String orderNo;
+
+        @ApiModelProperty("订单类型")
+        private EPaymentType orderType;
+
+        @ApiModelProperty("订单状态")
+        private EPaymentStatus status;
+
+        @ApiModelProperty("支付现金金额")
+        private BigDecimal paymentCashAmount;
+
+        @ApiModelProperty("支付时间")
+        private Date payTime;
+
+        @ApiModelProperty("订单详情")
+        private List<StudentPaymentOrderDetail> studentPaymentOrderDetails;
+    }
+
+    @Data
+    @ApiModel(" StudentPaymentOrder-学员订单表")
+    public static class StudentPaymentOrderDetail {
+
+        @ApiModelProperty("订单详情编号")
+        private Long userPaymentOrderDetailId;
+
+        @ApiModelProperty("商品类型")
+        private EGoodsType goodsType;
+
+        @ApiModelProperty("商品名称")
+        private String goodsName;
+
+        @ApiModelProperty("商品图片")
+        private String goodsUrl;
+
+        @ApiModelProperty("商品数量")
+        private Integer goodsNum;
+
+        @ApiModelProperty("支付现金金额")
+        private BigDecimal paymentCashAmount;
+    }
+
+    @Data
+    public static class RefundOperatorDto {
+        @ApiModelProperty("操作人编号")
+        private Long id;
+
+        @ApiModelProperty("操作人姓名")
+        private String name;
+    }
+
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("支付配置信息")
+    public static class PaymentConfig implements Serializable {
+
+        @ApiModelProperty("商户订单编号")
+        private String orderNo;
+
+        @ApiModelProperty("支付类型: adapay, wxpay")
+        private String paymentType;
+
+        @ApiModelProperty("支付配置参数: 透传")
+        private PaymentOrderReqConfig paymentConfig;
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("订单支付参数配置")
+    public static class PaymentOrderReqConfig implements Serializable {
+
+        @ApiModelProperty("支付渠道")
+        private String paymentChannel;
+
+        @ApiModelProperty("商户订单号")
+        private String merOrderNo;
+
+        @ApiModelProperty("商品名称")
+        private String subject;
+
+        @ApiModelProperty("商品描述")
+        private String body;
+
+        @ApiModelProperty("附加信息")
+        private String addition;
+
+        @ApiModelProperty("价格")
+        private BigDecimal price;
+
+        @ApiModelProperty("银行卡类型")
+        private String bankType;
+
+        @ApiModelProperty("微信授权code")
+        private String code;
+
+        @ApiModelProperty("订单过期时间")
+        private Date expirationTime;
+
+        @ApiModelProperty("微信支付公众号")
+        private String wxAppId;
+
+        @ApiModelProperty("支付用户Id")
+        private String userId;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static PaymentOrderReqConfig from(String json) {
+            return JSON.parseObject(json, PaymentOrderReqConfig.class);
+        }
+
+
+        public PaymentOrderReqConfig paymentChannel(String paymentChannel) {
+            this.paymentChannel = paymentChannel;
+            return this;
+        }
+
+        public PaymentOrderReqConfig merOrderNo(String merOrderNo) {
+            this.merOrderNo = merOrderNo;
+            return this;
+        }
+
+        public PaymentOrderReqConfig subject(String subject) {
+            this.subject = subject;
+            return this;
+        }
+
+        public PaymentOrderReqConfig price(BigDecimal price) {
+            this.price = price;
+            return this;
+        }
+
+        public PaymentOrderReqConfig code(String code) {
+            this.code = code;
+            return this;
+        }
+
+        public PaymentOrderReqConfig userId(String userId) {
+            this.userId = userId;
+            return this;
+        }
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("用户支付参数")
+    public static class PaymentReq implements Serializable {
+
+        @ApiModelProperty("交易流水号")
+        private String transNo;
+
+        @ApiModelProperty("请求支付的参数")
+        private Map<String, Object> reqParams;
+
+        public static PaymentReq from(String json) {
+            return JSON.parseObject(json, PaymentReq.class);
+        }
+    }
+
+    @ApiModel(" UserPaymentOrder-平台订单表")
+    @Data
+    public static class UserPaymentOrderDetailVo {
+
+        @ApiModelProperty("订单编号")
+        private Long userPaymentOrderId;
+
+        @ApiModelProperty("商品名称")
+        private String goodsName;
+
+        @ApiModelProperty("商品图片")
+        private String goodsUrl;
+
+        @ApiModelProperty("商品数量")
+        private Integer goodsNum = 1;
+
+        @ApiModelProperty("原价")
+        private BigDecimal originalPrice = BigDecimal.ZERO;
+
+        @ApiModelProperty("现价")
+        private BigDecimal currentPrice = BigDecimal.ZERO;
+
+        @ApiModelProperty("实付金额")
+        private BigDecimal paymentCashAmount = BigDecimal.ZERO;
+
+        @ApiModelProperty("优惠金额")
+        private BigDecimal paymentCouponAmount = BigDecimal.ZERO;
+    }
+
+    @ApiModel(" UserPaymentOrder-平台订单表")
+    @Data
+    public static class UserPaymentOrderDetailVo1 {
+
+        @ApiModelProperty("商品名称")
+        private String goodsName;
+
+        @ApiModelProperty("商品数量")
+        private Integer goodsNum = 1;
+
+        @ApiModelProperty("支付时间")
+        private Date payTime;
+
+        @ApiModelProperty("支付时间")
+        private String orderNo;
+
+        @ApiModelProperty("订单状态")
+        private EPaymentStatus orderStatus;
+
+        @ApiModelProperty("原价")
+        private BigDecimal originalPrice = BigDecimal.ZERO;
+
+        @ApiModelProperty("现价")
+        private BigDecimal currentPrice = BigDecimal.ZERO;
+
+        @ApiModelProperty("实付金额")
+        private BigDecimal paymentCashAmount = BigDecimal.ZERO;
+
+        @ApiModelProperty("优惠金额")
+        private BigDecimal paymentCouponAmount = BigDecimal.ZERO;
+
+        public void setPayTime(Long payTime) {
+            if (Objects.nonNull(payTime)) {
+
+                if (payTime.toString().length() <= 10) {
+                    payTime *= 1000;
+                }
+
+                this.payTime = new Date(payTime);
+            }
+        }
+    }
+
+    @ApiModel(" UserPaymentOrder-平台订单表")
+    @Data
+    public static class UserPaymentOrderDetailActivateVip {
+
+        private String userNote;
+
+        private Long userId;
+
+        private ClientEnum paymentClient;
+
+        private String orderNo;
+
+        private Long userPaymentOrderDetailId;
+
+        private BigDecimal paymentCashAmount;
+
+        @ApiModelProperty("支付时间")
+        private Date payTime;
+
+        public void setPayTime(Long payTime) {
+            if (Objects.nonNull(payTime)) {
+
+                if (payTime.toString().length() <= 10) {
+                    payTime *= 1000;
+                }
+
+                this.payTime = new Date(payTime);
+            }
+        }
+    }
+
+    @ApiModel(" UserPaymentOrder-平台订单表")
+    @Data
+    public static class UserPaymentOrderVo {
+
+        @ApiModelProperty("主键")
+        private Long id;
+
+        @ApiModelProperty("商户订单号")
+        private String orderNo;
+
+        @ApiModelProperty("交易流水号")
+        private String transNo;
+
+        @ApiModelProperty("手机号")
+        private String phone;
+
+        @ApiModelProperty("用户编号")
+        private Long userId;
+
+        @ApiModelProperty("用户姓名")
+        private String nickname;
+
+        @ApiModelProperty("订单类型:  VIP(开通会员), ORCHESTRA(乐团报名)")
+        private EPaymentType orderType;
+
+        @ApiModelProperty("订单状态")
+        private EPaymentStatus orderStatus;
+
+        @ApiModelProperty("原价")
+        private BigDecimal originalPrice;
+
+        @ApiModelProperty("现价")
+        private BigDecimal currentPrice;
+
+        @ApiModelProperty("支付现金金额")
+        private BigDecimal paymentCashAmount;
+
+        @ApiModelProperty("支付优惠金额")
+        private BigDecimal paymentCouponAmount;
+
+        @ApiModelProperty("支付通道费用")
+        private BigDecimal paymentChannelFee;
+
+        @ApiModelProperty("订单描述信息")
+        private String orderDesc;
+
+        @ApiModelProperty("支付时间")
+        private Date payTime;
+
+        @ApiModelProperty("订单详情")
+        private List<UserPaymentOrderDetailVo> orderDetailList;
+
+        public void setPayTime(Long payTime) {
+            if (Objects.nonNull(payTime)) {
+
+                if (payTime.toString().length() <= 10) {
+                    payTime *= 1000;
+                }
+
+                this.payTime = new Date(payTime);
+            }
+        }
+    }
+
+}

+ 23 - 0
cooleshow-user/user-biz/src/main/resources/config/mybatis/UserOrderMapper.xml

@@ -124,6 +124,9 @@
             <if test="null != param.orderClient and '' != param.orderClient">
                 AND t.order_client_ = #{param.orderClient}
             </if>
+            <if test="param.paymentVersion != null">
+                and t.payment_version_ = #{param.paymentVersion}
+            </if>
             <if test="null != param.search and '' != param.search">
                 AND (
                 t.user_id_ LIKE CONCAT('%', #{param.search}, '%') or
@@ -186,6 +189,9 @@
             <if test="null != param.status and '' != param.status">
                 AND t.status_ = #{param.status}
             </if>
+            <if test="param.paymentVersion != null">
+                and t.payment_version_ = #{param.paymentVersion}
+            </if>
             <if test="param.startTime != null">
                 AND (
                     (p.id_ is null and t.create_time_ &gt;= #{param.startTime}) or (p.id_ is not null and p.create_time_ &gt;= #{param.startTime})
@@ -291,4 +297,21 @@
     <update id="updateStatusByOrderNo">
         update user_order set status_ = #{orderStatus},update_time_ = now() where order_no_ = #{orderNo}
     </update>
+
+    <select id="selectPaymentOrderPage" resultMap="BaseResultMap">
+        select  t.*
+        from user_order t
+            <where>
+                t.payment_version_ = 'V2'
+                <if test="query.paymentStatus != null and query.paymentStatus.size() != 0">
+                    and t.status_ in
+                    <foreach collection="query.paymentStatus" item="item" separator="," open="(" close=")">
+                        #{item}
+                    </foreach>
+                </if>
+                <if test="query.endTime != null">
+                    AND t.create_time_ &lt; #{query.endTime}
+                </if>
+            </where>
+    </select>
 </mapper>

+ 87 - 0
cooleshow-user/user-tenant/src/main/java/com/yonge/cooleshow/tenant/controller/UserOrderController.java

@@ -0,0 +1,87 @@
+package com.yonge.cooleshow.tenant.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.microsvc.toolkit.common.response.template.R;
+import com.microsvc.toolkit.common.webportal.exception.BizException;
+import com.microsvc.toolkit.config.jwt.utils.JwtUserInfo;
+import com.yonge.cooleshow.biz.dal.service.UserPaymentCoreService;
+import com.yonge.cooleshow.biz.dal.wrapper.UserPaymentOrderWrapper;
+import com.yonge.cooleshow.tenant.vo.UserPaymentOrderVo;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import java.util.Objects;
+
+@Validated
+@RestController
+@RequestMapping("/userOrder")
+@Api(tags = "用户支付订单")
+public class UserOrderController {
+
+
+
+    @Autowired
+    private UserPaymentCoreService userPaymentCoreService;
+
+    @ApiOperation(value = "用户下单", notes = "用户下单")
+    @PostMapping("/executeOrder")
+    public R<UserPaymentOrderWrapper.PaymentConfig> executeOrder(@Validated @RequestBody UserPaymentOrderVo.OrderReq orderReq) {
+
+        // 设置下单用户信息
+
+
+        // 用户下单请求
+        UserPaymentOrderWrapper.UserPaymentOrder order = JSON.parseObject(orderReq.jsonString(), UserPaymentOrderWrapper.UserPaymentOrder.class);
+        // 新增数据
+        UserPaymentOrderWrapper.PaymentConfig paymentConfig = userPaymentCoreService.executeOrderCreate(order);
+        if (Objects.isNull(paymentConfig)) {
+            throw BizException.from("下单失败");
+        }
+
+        return R.from(paymentConfig);
+    }
+
+    @ApiOperation(value = "用户付款", notes = "用户付款")
+    @PostMapping("/executePayment")
+    public R<UserPaymentOrderWrapper.PaymentReq> executePayment(@Validated @RequestBody UserPaymentOrderVo.PaymentReqConfig config) {
+
+
+
+        // 用户下单请求
+        UserPaymentOrderWrapper.PaymentOrderReqConfig reqConfig = UserPaymentOrderWrapper.PaymentOrderReqConfig.from(config.jsonString());
+
+        // 创建用户支付数据
+        UserPaymentOrderWrapper.PaymentReq paymentConfig = userPaymentCoreService.executePayment(new JwtUserInfo<>(), reqConfig);
+        if (Objects.isNull(paymentConfig)) {
+            throw BizException.from("付款失败");
+        }
+
+        return R.from(paymentConfig);
+    }
+
+    @ApiOperation(value = "取消支付", notes = "取消支付")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "orderNo", value = "订单号", dataType = "String")
+    })
+    @PostMapping("/cancelPayment/{orderNo}")
+    public R<JSONObject> cancelPayment(@PathVariable("orderNo") String orderNo) {
+
+
+        // 订单编号判断
+        if (StringUtils.isBlank(orderNo)) {
+            throw BizException.from("订单编号不能为空");
+        }
+
+        // 用户取消支付
+        userPaymentCoreService.cancelPayment(new JwtUserInfo<>(), orderNo);
+
+        return R.defaultR();
+    }
+}

+ 77 - 0
cooleshow-user/user-tenant/src/main/java/com/yonge/cooleshow/tenant/vo/UserPaymentOrderDetailVo.java

@@ -0,0 +1,77 @@
+package com.yonge.cooleshow.tenant.vo;
+
+import com.alibaba.fastjson.JSON;
+import com.microsvc.toolkit.common.response.paging.QueryInfo;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 订单详情表
+ * 2022-12-20 19:09:34
+ */
+@ApiModel(value = "UserPaymentOrderDetailVo对象", description = "订单详情表查询视图对象")
+public class UserPaymentOrderDetailVo {
+
+    @Data
+    @ApiModel(" UserPaymentOrderDetail-订单详情表")
+    public static class UserPaymentOrderDetail {
+
+		@ApiModelProperty("主键ID")
+        private Long id;
+
+		@ApiModelProperty("支付订单ID")
+        private Long userPaymentOrderId;
+
+		@ApiModelProperty("订单号")
+        private String orderNo;
+
+		@ApiModelProperty("商品类型:  VIP、开通会员 ")
+        private String goodsType;
+
+		@ApiModelProperty("商品名称")
+        private String goodsName;
+
+		@ApiModelProperty("商品图片")
+        private String goodsUrl;
+
+        @ApiModelProperty("商品Id")
+        private String goodsId;
+
+        @ApiModelProperty("商品来源")
+        private String goodsSource;
+
+		@ApiModelProperty("原价")
+        private BigDecimal originalPrice;
+
+		@ApiModelProperty("现价")
+        private BigDecimal currentPrice;
+
+		@ApiModelProperty("实付现金")
+        private BigDecimal paymentCashAmount;
+
+		@ApiModelProperty("优惠金额")
+        private BigDecimal paymentCouponAmount;
+
+		@ApiModelProperty("商品数量")
+        private Integer goodsNum;
+
+		@ApiModelProperty("更新时间")
+        private Date updateTime;
+
+		@ApiModelProperty("下单时间")
+        private Date createTime;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static UserPaymentOrderDetail from(String json) {
+            return JSON.parseObject(json, UserPaymentOrderDetail.class);
+        }
+    }
+
+}

+ 277 - 0
cooleshow-user/user-tenant/src/main/java/com/yonge/cooleshow/tenant/vo/UserPaymentOrderVo.java

@@ -0,0 +1,277 @@
+package com.yonge.cooleshow.tenant.vo;
+
+import com.alibaba.fastjson.JSON;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * 平台订单表
+ * 2022-12-20 19:09:34
+ */
+@ApiModel(value = "UserPaymentOrderVo对象", description = "平台订单表查询视图对象")
+public class UserPaymentOrderVo {
+
+    @Data
+    @ApiModel(" UserPaymentOrder-平台订单表")
+    public static class UserPaymentOrder {
+
+
+		@ApiModelProperty("主键")
+        private Long id;
+
+		@ApiModelProperty("支付厂商")
+        private String paymentVender;
+
+		@ApiModelProperty("支付渠道")
+        private String paymentChannel;
+
+		@ApiModelProperty("用户身份")
+        private String paymentClient;
+
+		@ApiModelProperty("用户编号")
+        private Long userId;
+
+		@ApiModelProperty("商户订单号")
+        private String orderNo;
+
+		@ApiModelProperty("交易流水号")
+        private String transNo;
+
+		@ApiModelProperty("业务类型Id")
+        private String bizId;
+
+		@ApiModelProperty("订单支付类型")
+        private String orderType;
+
+		@ApiModelProperty("订单状态")
+        private String status;
+
+		@ApiModelProperty("原价")
+        private BigDecimal originalPrice;
+
+		@ApiModelProperty("现价")
+        private BigDecimal currentPrice;
+
+		@ApiModelProperty("支付现金金额")
+        private BigDecimal paymentCashAmount;
+
+		@ApiModelProperty("支付优惠金额")
+        private BigDecimal paymentCouponAmount;
+
+		@ApiModelProperty("支付通道费用")
+        private BigDecimal paymentChannelFee;
+
+		@ApiModelProperty("订单名称")
+        private String orderName;
+
+		@ApiModelProperty("订单描述信息")
+        private String orderDesc;
+
+		@ApiModelProperty("用户备注")
+        private String userNote;
+
+		@ApiModelProperty("支付时间")
+        private Date payTime;
+
+		@ApiModelProperty("原因")
+        private String errorMsg;
+
+		@ApiModelProperty("收货地址")
+        private Long receiveAddress;
+
+		@ApiModelProperty("更新时间")
+        private Date updateTime;
+
+		@ApiModelProperty("下单时间")
+        private Date createTime;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public static UserPaymentOrder from(String json) {
+            return JSON.parseObject(json, UserPaymentOrder.class);
+        }
+
+
+        public UserPaymentOrder userId(String userId) {
+            this.userId = Long.parseLong(userId);
+            return this;
+        }
+
+        public UserPaymentOrder paymentClient(String paymentClient) {
+            this.paymentClient = String.valueOf(paymentClient);
+            return this;
+        }
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("下单请求对象")
+    public static class OrderReq implements Serializable {
+
+        @ApiModelProperty("支付类型: adapay, wxpay")
+        private String paymentType;
+
+        @ApiModelProperty("业务类型Id")
+        private String bizId;
+
+        @ApiModelProperty("订单类型:  VIP(开通会员), ORCHESTRA(乐团报名)")
+        private String orderType;
+
+        @ApiModelProperty("现价")
+        private BigDecimal currentPrice;
+
+        @ApiModelProperty("支付现金金额")
+        private BigDecimal paymentCashAmount;
+
+        @ApiModelProperty("支付优惠金额")
+        private BigDecimal paymentCouponAmount;
+
+        @ApiModelProperty("订单名称")
+        private String orderName;
+
+        @ApiModelProperty("订单描述信息")
+        private String orderDesc;
+
+        @ApiModelProperty("用户备注")
+        private String userNote;
+
+        @ApiModelProperty("优惠券Id;多个使用,隔开")
+        private String couponIds;
+
+        @ApiModelProperty("订单商品信息")
+        private List<OrderGoodsInfo> goodsInfos;
+
+        @ApiModelProperty(value = "用户身份", hidden = true)
+        private String paymentClient;
+
+        @ApiModelProperty(value = "用户编号", hidden = true)
+        private Long userId;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+
+        public OrderReq paymentClient(String paymentClient) {
+            this.paymentClient = String.valueOf(paymentClient);
+            return this;
+        }
+
+        public OrderReq userId(String userId) {
+            this.userId = Long.parseLong(userId);
+            return this;
+        }
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("订单商品信息")
+    public static class OrderGoodsInfo implements Serializable {
+
+        @ApiModelProperty("商品类型 ")
+        private String goodsType;
+
+        @ApiModelProperty("商品名称")
+        private String goodsName;
+
+        @ApiModelProperty("商品图片")
+        private String goodsUrl;
+
+        @ApiModelProperty("商品Id")
+        private String goodsId;
+
+        @ApiModelProperty("商品库存Id")
+        private Long goodsSkuId;
+
+        @ApiModelProperty("商品来源")
+        private String goodsSource;
+
+        @ApiModelProperty("商品描述")
+        private String description;
+
+        @ApiModelProperty("原价")
+        private BigDecimal originalPrice;
+
+        @ApiModelProperty("现价")
+        private BigDecimal currentPrice;
+
+        @ApiModelProperty("实付现金")
+        private BigDecimal paymentCashAmount;
+
+        @ApiModelProperty("优惠金额")
+        private BigDecimal paymentCouponAmount;
+
+        @ApiModelProperty("商品数量")
+        private Integer goodsNum;
+
+        @ApiModelProperty("优惠券Id")
+        private Long couponId;
+
+        public Integer getGoodsNum() {
+            return Optional.ofNullable(goodsNum).orElse(1);
+        }
+    }
+
+    @Data
+    @Builder
+    @NoArgsConstructor
+    @AllArgsConstructor
+    @ApiModel("订单支付参数配置")
+    public static class PaymentReqConfig implements Serializable {
+
+        @ApiModelProperty("支付渠道")
+        private String paymentChannel;
+
+        @ApiModelProperty("商户订单号")
+        private String merOrderNo;
+
+        @ApiModelProperty("商品名称")
+        private String subject;
+
+        @ApiModelProperty("商品描述")
+        private String body;
+
+        @ApiModelProperty("附加信息")
+        private String addition;
+
+        @ApiModelProperty("价格")
+        private BigDecimal price;
+
+        @ApiModelProperty("银行卡类型")
+        private String bankType;
+
+        @ApiModelProperty("微信授权code")
+        private String code;
+
+        @ApiModelProperty("订单过期时间")
+        private Date expirationTime;
+
+        @ApiModelProperty("微信支付公众号")
+        private String wxAppId;
+
+        @ApiModelProperty(value = "收货地址", hidden = true)
+        private Long receiveAddress;
+
+        @ApiModelProperty(value = "支付用户Id", hidden = true)
+        private String userId;
+
+        public String jsonString() {
+            return JSON.toJSONString(this);
+        }
+    }
+}

+ 3 - 0
toolset/toolset-payment/src/main/java/com/yonge/toolset/payment/base/enums/TradeStatusEnum.java

@@ -19,6 +19,9 @@ public enum TradeStatusEnum implements BaseEnum<String, TradeStatusEnum> {
     private String code;
     private String msg;
 
+
+
+
     TradeStatusEnum(String msg) {
         this.code = this.name();
         this.msg = msg;