Browse Source

add:商城添加支付

liujunchi 2 years ago
parent
commit
94bc1db0de
31 changed files with 2173 additions and 4 deletions
  1. 5 0
      cooleshow-mall/mall-common/pom.xml
  2. 15 0
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/UserOrderPaymentMapper.java
  3. 145 0
      cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/model/UserOrderPayment.java
  4. 184 0
      cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/UserOrderPaymentMapper.xml
  5. 40 0
      cooleshow-mall/mall-pay/pom.xml
  6. 36 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/config/HuifuConfiguration.java
  7. 68 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/enums/OrdeerCacherEnmu.java
  8. 40 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/enums/OrderStatusEnum.java
  9. 36 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/enums/PayChannelEnum.java
  10. 37 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/enums/PayStatusEnum.java
  11. 110 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/props/HuifuProperties.java
  12. 221 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/PaymentSdk.java
  13. 27 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/DeviceInfo.java
  14. 55 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/DivMember.java
  15. 147 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/OrderPayReq.java
  16. 73 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/PaymentConfirmParam.java
  17. 168 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/PaymentReq.java
  18. 100 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/res/OrderPayRes.java
  19. 27 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/service/PaymentService.java
  20. 109 0
      cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/service/impl/AdapayPaymentServiceImpl.java
  21. 7 1
      cooleshow-mall/mall-portal/pom.xml
  22. 1 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/MallPortalApplication.java
  23. 1 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/OmsPortalOrderController.java
  24. 129 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/PaymentController.java
  25. 17 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/OmsPortalOrderService.java
  26. 29 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/UserOrderPaymentService.java
  27. 186 1
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java
  28. 38 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/UserOrderPaymentServiceImpl.java
  29. 116 0
      cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/util/DistributedLock.java
  30. 1 0
      cooleshow-mall/pom.xml
  31. 5 0
      pom.xml

+ 5 - 0
cooleshow-mall/mall-common/pom.xml

@@ -19,6 +19,10 @@
 
     <dependencies>
 
+        <dependency>
+            <groupId>com.yonge.cooleshow</groupId>
+            <artifactId>cooleshow-common</artifactId>
+        </dependency>
 
         <dependency>
             <groupId>com.alibaba</groupId>
@@ -60,6 +64,7 @@
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-starter-validation</artifactId>
         </dependency>
+
     </dependencies>
 
 </project>

+ 15 - 0
cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/mapper/UserOrderPaymentMapper.java

@@ -0,0 +1,15 @@
+package com.yonge.cooleshow.mbg.mapper;
+
+import com.yonge.cooleshow.mbg.model.UmsRole;
+import com.yonge.cooleshow.mbg.model.UserOrderPayment;
+
+public interface UserOrderPaymentMapper {
+
+
+    int insert(UserOrderPayment record);
+
+
+    UserOrderPayment selectByOrderNo(String orderNo);
+
+    int updateByPrimaryKeySelective(UserOrderPayment userOrderPayment);
+}

+ 145 - 0
cooleshow-mall/mall-mbg/src/main/java/com/yonge/cooleshow/mbg/model/UserOrderPayment.java

@@ -0,0 +1,145 @@
+package com.yonge.cooleshow.mbg.model;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import org.springframework.format.annotation.DateTimeFormat;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+import java.util.Date;
+
+/**
+ * 平台订单支付表
+ */
+
+@ApiModel(value = "UserOrderPayment对象", description = "平台订单支付表")
+public class UserOrderPayment implements Serializable {
+	private static final long serialVersionUID = 1L;
+
+    private Long id;
+    @ApiModelProperty("订单号 ")
+    private String orderNo;
+    @ApiModelProperty("交易流水号 ")
+    private String transNo;
+    @ApiModelProperty("支付渠道:  alipay 支付宝  wx_lite 微信 ")
+    private String payChannel;
+    @ApiModelProperty("交易金额,必须大于0,保留两位小数点,如0.10、100.05等 ")
+    private BigDecimal payAmt;
+    @ApiModelProperty("汇付收取的服务费 ")
+    private BigDecimal feeAmt;
+    @ApiModelProperty("支付详情信息(用于拉起支付) ")
+    private String payInfo;
+    @ApiModelProperty("交易状态 pending 交易处理中 succeeded 交易成功 failed 交易失败")
+    private String status;
+    @ApiModelProperty("失败信息 ")
+    private String payFailMsg;
+    @ApiModelProperty("到账时间 ")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date arrivalTime;
+    @ApiModelProperty("创建时间 ")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
+    private Date createTime;
+    @ApiModelProperty("更新时间 ")
+    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    @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 String getOrderNo() {
+        return orderNo;
+    }
+
+    public void setOrderNo(String orderNo) {
+        this.orderNo = orderNo;
+    }
+    
+	public String getTransNo() {
+        return transNo;
+    }
+
+    public void setTransNo(String transNo) {
+        this.transNo = transNo;
+    }
+
+    public String getPayChannel() {
+        return payChannel;
+    }
+
+    public void setPayChannel(String payChannel) {
+        this.payChannel = payChannel;
+    }
+
+    public BigDecimal getPayAmt() {
+        return payAmt;
+    }
+
+    public void setPayAmt(BigDecimal payAmt) {
+        this.payAmt = payAmt;
+    }
+    
+	public String getPayInfo() {
+        return payInfo;
+    }
+
+    public void setPayInfo(String payInfo) {
+        this.payInfo = payInfo;
+    }
+
+    public String getStatus() {
+        return status;
+    }
+
+    public void setStatus(String status) {
+        this.status = status;
+    }
+
+    public Date getArrivalTime() {
+        return arrivalTime;
+    }
+
+    public void setArrivalTime(Date arrivalTime) {
+        this.arrivalTime = arrivalTime;
+    }
+
+    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 BigDecimal getFeeAmt() {
+        return feeAmt;
+    }
+
+    public void setFeeAmt(BigDecimal feeAmt) {
+        this.feeAmt = feeAmt;
+    }
+
+    public String getPayFailMsg() {
+        return payFailMsg;
+    }
+
+    public void setPayFailMsg(String payFailMsg) {
+        this.payFailMsg = payFailMsg;
+    }
+}

+ 184 - 0
cooleshow-mall/mall-mbg/src/main/resources/config/mybatis/UserOrderPaymentMapper.xml

@@ -0,0 +1,184 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.yonge.cooleshow.mbg.mapper.UserOrderPaymentMapper">
+    <resultMap id="BaseResultMap" type="com.yonge.cooleshow.mbg.model.UserOrderPayment">
+        <!--@mbg.generated-->
+        <!--@Table user_order_payment-->
+        <id column="id_" jdbcType="BIGINT" property="id" />
+        <result column="order_no_" jdbcType="VARCHAR" property="orderNo" />
+        <result column="trans_no_" jdbcType="VARCHAR" property="transNo" />
+        <result column="pay_channel_" jdbcType="VARCHAR" property="payChannel" />
+        <result column="pay_amt_" jdbcType="DECIMAL" property="payAmt" />
+        <result column="fee_amt_" jdbcType="DECIMAL" property="feeAmt" />
+        <result column="pay_info_" jdbcType="VARCHAR" property="payInfo" />
+        <result column="status_" jdbcType="VARCHAR" property="status" />
+        <result column="pay_fail_msg_" jdbcType="VARCHAR" property="payFailMsg" />
+        <result column="arrival_time_" jdbcType="TIMESTAMP" property="arrivalTime" />
+        <result column="create_time_" jdbcType="TIMESTAMP" property="createTime" />
+        <result column="update_time_" jdbcType="TIMESTAMP" property="updateTime" />
+    </resultMap>
+    <sql id="Base_Column_List">
+        <!--@mbg.generated-->
+        id_, order_no_, trans_no_, pay_channel_, pay_amt_, fee_amt_, pay_info_, status_,
+        pay_fail_msg_, arrival_time_, create_time_, update_time_
+    </sql>
+    <select id="selectByPrimaryKey" parameterType="java.lang.Long" resultMap="BaseResultMap">
+        <!--@mbg.generated-->
+        select
+        <include refid="Base_Column_List" />
+        from user_order_payment
+        where id_ = #{id,jdbcType=BIGINT}
+    </select>
+    <delete id="deleteByPrimaryKey" parameterType="java.lang.Long">
+        <!--@mbg.generated-->
+        delete from user_order_payment
+        where id_ = #{id,jdbcType=BIGINT}
+    </delete>
+    <insert id="insert" keyColumn="id_" keyProperty="id" parameterType="com.yonge.cooleshow.mbg.model.UserOrderPayment" useGeneratedKeys="true">
+        <!--@mbg.generated-->
+        insert into user_order_payment (order_no_, trans_no_, pay_channel_,
+        pay_amt_, fee_amt_, pay_info_,
+        status_, pay_fail_msg_, arrival_time_,
+        create_time_, update_time_)
+        values (#{orderNo,jdbcType=VARCHAR}, #{transNo,jdbcType=VARCHAR}, #{payChannel,jdbcType=VARCHAR},
+        #{payAmt,jdbcType=DECIMAL}, #{feeAmt,jdbcType=DECIMAL}, #{payInfo,jdbcType=VARCHAR},
+        #{status,jdbcType=VARCHAR}, #{payFailMsg,jdbcType=VARCHAR}, #{arrivalTime,jdbcType=TIMESTAMP},
+        #{createTime,jdbcType=TIMESTAMP}, #{updateTime,jdbcType=TIMESTAMP})
+    </insert>
+    <insert id="insertSelective" keyColumn="id_" keyProperty="id" parameterType="com.yonge.cooleshow.mbg.model.UserOrderPayment" useGeneratedKeys="true">
+        <!--@mbg.generated-->
+        insert into user_order_payment
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="orderNo != null">
+                order_no_,
+            </if>
+            <if test="transNo != null">
+                trans_no_,
+            </if>
+            <if test="payChannel != null">
+                pay_channel_,
+            </if>
+            <if test="payAmt != null">
+                pay_amt_,
+            </if>
+            <if test="feeAmt != null">
+                fee_amt_,
+            </if>
+            <if test="payInfo != null">
+                pay_info_,
+            </if>
+            <if test="status != null">
+                status_,
+            </if>
+            <if test="payFailMsg != null">
+                pay_fail_msg_,
+            </if>
+            <if test="arrivalTime != null">
+                arrival_time_,
+            </if>
+            <if test="createTime != null">
+                create_time_,
+            </if>
+            <if test="updateTime != null">
+                update_time_,
+            </if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="orderNo != null">
+                #{orderNo,jdbcType=VARCHAR},
+            </if>
+            <if test="transNo != null">
+                #{transNo,jdbcType=VARCHAR},
+            </if>
+            <if test="payChannel != null">
+                #{payChannel,jdbcType=VARCHAR},
+            </if>
+            <if test="payAmt != null">
+                #{payAmt,jdbcType=DECIMAL},
+            </if>
+            <if test="feeAmt != null">
+                #{feeAmt,jdbcType=DECIMAL},
+            </if>
+            <if test="payInfo != null">
+                #{payInfo,jdbcType=VARCHAR},
+            </if>
+            <if test="status != null">
+                #{status,jdbcType=VARCHAR},
+            </if>
+            <if test="payFailMsg != null">
+                #{payFailMsg,jdbcType=VARCHAR},
+            </if>
+            <if test="arrivalTime != null">
+                #{arrivalTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="createTime != null">
+                #{createTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="updateTime != null">
+                #{updateTime,jdbcType=TIMESTAMP},
+            </if>
+        </trim>
+    </insert>
+    <update id="updateByPrimaryKeySelective" parameterType="com.yonge.cooleshow.mbg.model.UserOrderPayment">
+        <!--@mbg.generated-->
+        update user_order_payment
+        <set>
+            <if test="orderNo != null">
+                order_no_ = #{orderNo,jdbcType=VARCHAR},
+            </if>
+            <if test="transNo != null">
+                trans_no_ = #{transNo,jdbcType=VARCHAR},
+            </if>
+            <if test="payChannel != null">
+                pay_channel_ = #{payChannel,jdbcType=VARCHAR},
+            </if>
+            <if test="payAmt != null">
+                pay_amt_ = #{payAmt,jdbcType=DECIMAL},
+            </if>
+            <if test="feeAmt != null">
+                fee_amt_ = #{feeAmt,jdbcType=DECIMAL},
+            </if>
+            <if test="payInfo != null">
+                pay_info_ = #{payInfo,jdbcType=VARCHAR},
+            </if>
+            <if test="status != null">
+                status_ = #{status,jdbcType=VARCHAR},
+            </if>
+            <if test="payFailMsg != null">
+                pay_fail_msg_ = #{payFailMsg,jdbcType=VARCHAR},
+            </if>
+            <if test="arrivalTime != null">
+                arrival_time_ = #{arrivalTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="createTime != null">
+                create_time_ = #{createTime,jdbcType=TIMESTAMP},
+            </if>
+            <if test="updateTime != null">
+                update_time_ = #{updateTime,jdbcType=TIMESTAMP},
+            </if>
+        </set>
+        where id_ = #{id,jdbcType=BIGINT}
+    </update>
+    <update id="updateByPrimaryKey" parameterType="com.yonge.cooleshow.mbg.model.UserOrderPayment">
+        <!--@mbg.generated-->
+        update user_order_payment
+        set order_no_ = #{orderNo,jdbcType=VARCHAR},
+        trans_no_ = #{transNo,jdbcType=VARCHAR},
+        pay_channel_ = #{payChannel,jdbcType=VARCHAR},
+        pay_amt_ = #{payAmt,jdbcType=DECIMAL},
+        fee_amt_ = #{feeAmt,jdbcType=DECIMAL},
+        pay_info_ = #{payInfo,jdbcType=VARCHAR},
+        status_ = #{status,jdbcType=VARCHAR},
+        pay_fail_msg_ = #{payFailMsg,jdbcType=VARCHAR},
+        arrival_time_ = #{arrivalTime,jdbcType=TIMESTAMP},
+        create_time_ = #{createTime,jdbcType=TIMESTAMP},
+        update_time_ = #{updateTime,jdbcType=TIMESTAMP}
+        where id_ = #{id,jdbcType=BIGINT}
+    </update>
+
+    <select id="selectByOrderNo" resultMap="BaseResultMap">
+        select
+        <include refid="Base_Column_List" />
+      from user_order_payment where order_no_ = #{orderNo} limit 1
+    </select>
+</mapper>

+ 40 - 0
cooleshow-mall/mall-pay/pom.xml

@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.yonge.cooleshow</groupId>
+        <artifactId>cooleshow-mall</artifactId>
+        <version>1.0</version>
+    </parent>
+
+    <groupId>com.yonge.cooleshow</groupId>
+    <artifactId>mall-pay</artifactId>
+    <version>1.0</version>
+    <name>mall-pay</name>
+    <description>mall-pay</description>
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>com.huifu.adapay</groupId>
+            <artifactId>adapay-java-sdk</artifactId>
+            <version>1.2.10</version>
+        </dependency>
+        <dependency>
+            <groupId>com.yonge.cooleshow</groupId>
+            <artifactId>mall-common</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 36 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/config/HuifuConfiguration.java

@@ -0,0 +1,36 @@
+package com.yonge.cooleshow.config;
+
+import com.huifu.adapay.Adapay;
+import com.huifu.adapay.model.MerConfig;
+import com.yonge.cooleshow.props.HuifuProperties;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * 路由配置信息
+ */
+@Configuration
+@EnableConfigurationProperties({HuifuProperties.class})
+public class HuifuConfiguration {
+	private static HuifuProperties huifuProperties;
+	@Bean
+	public MerConfig merConfig(HuifuProperties authProperties) {
+		this.huifuProperties = authProperties;
+
+		MerConfig merConfig = new MerConfig();
+		merConfig.setApiKey(authProperties.getApiKey());
+		merConfig.setApiMockKey(authProperties.getMockApiKey());
+		merConfig.setRSAPrivateKey(authProperties.getRsaPrivateKey());
+		try {
+			Adapay.initWithMerConfig(merConfig);
+		} catch (Exception e) {
+			e.printStackTrace();
+		}
+		return merConfig;
+	}
+
+	public static HuifuProperties getHuifuProperties(){
+		return huifuProperties;
+	}
+}

+ 68 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/enums/OrdeerCacherEnmu.java

@@ -0,0 +1,68 @@
+package com.yonge.cooleshow.enums;
+
+import com.yonge.cooleshow.common.constant.CommonConstants;
+import org.apache.commons.lang3.StringUtils;
+
+import java.time.Duration;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-04-24
+ */
+public enum OrdeerCacherEnmu {
+    LOCK_EXECUTE_ORDER("用户下单锁"),
+    LOCK_PAY_ORDER("用户付款锁"),
+    LOCK_CHANGE_ACCOUNT("账户变更锁");
+
+    ;
+    /***
+     * 缓存描述
+     * @author liweifan
+     * @updateTime 2022/3/28 16:31
+     */
+    private String msg;
+    /***
+     * 缓存时长
+     * @author liweifan
+     * @updateTime 2022/3/28 16:31
+     */
+    private Duration duration;
+
+    OrdeerCacherEnmu(String msg) {
+        this.msg = msg;
+    }
+
+    OrdeerCacherEnmu(String msg, Duration duration) {
+        this.msg = msg;
+        this.duration = duration;
+    }
+
+    public String getCode() {
+        return this.name();
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public String getRedisKey(Object... detils) {
+        String key = this.getCode();
+        for (Object detil : detils) {
+            try {
+                if (!CommonConstants.REDIS_SPLIT.equals(key.substring(key.length() - 1))) {
+                    key += CommonConstants.REDIS_SPLIT;
+                }
+                if (null != detil && StringUtils.isNotBlank(detil.toString())) {
+                    key += detil.toString();
+                }
+            } catch (Exception e) {
+            }
+        }
+        if (CommonConstants.REDIS_SPLIT.equals(key.substring(key.length() - 1))) {
+            key = key.substring(0, key.length() - 1);
+        }
+        return key;
+    }
+}

+ 40 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/enums/OrderStatusEnum.java

@@ -0,0 +1,40 @@
+package com.yonge.cooleshow.enums;
+
+import com.yonge.cooleshow.common.enums.BaseEnum;
+
+/**
+ * 订单状态 WAIT_PAY 待支付 PAYING 支付中  PAID 已付款 CLOSE 已关闭
+ * @Author: liweifan
+ * @Data: 2022/3/31 14:59
+ */
+public enum OrderStatusEnum implements BaseEnum<String, OrderStatusEnum> {
+    WAIT_PAY("WAIT_PAY","待支付"),
+    PAYING("PAYING","支付中"),
+    PAID("PAID","已付款"),
+    CLOSE("CLOSE","已关闭"),
+    FAIL("FAIL","支付失败"),
+    ;
+    private String code;
+    private String msg;
+
+    OrderStatusEnum(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public String getCode() {
+        return this.code;
+    }
+}

+ 36 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/enums/PayChannelEnum.java

@@ -0,0 +1,36 @@
+package com.yonge.cooleshow.enums;
+
+
+/**
+ * 支付渠道
+ * @author liweifan
+ * @updateTime 2022/3/31 11:30
+ */
+public enum PayChannelEnum {
+    alipay("alipay","支付宝APP支付"),
+    wx_lite("wx_lite","微信APP支付")
+    ;
+    private String code;
+    private String msg;
+
+    PayChannelEnum(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public String getCode() {
+        return this.code;
+    }
+}

+ 37 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/enums/PayStatusEnum.java

@@ -0,0 +1,37 @@
+package com.yonge.cooleshow.enums;
+
+
+/**
+ * 交易状态 pending 交易处理中 succeeded 交易成功 failed 交易失败
+ * @Author: liweifan
+ * @Data: 2022/3/31 14:59
+ */
+public enum PayStatusEnum{
+    pending("pending","交易处理中"),
+    succeeded("succeeded","交易成功"),
+    failed("failed","交易失败")
+    ;
+    private String code;
+    private String msg;
+
+    PayStatusEnum(String code, String msg) {
+        this.code = code;
+        this.msg = msg;
+    }
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+    public String getMsg() {
+        return msg;
+    }
+
+    public void setMsg(String msg) {
+        this.msg = msg;
+    }
+
+    public String getCode() {
+        return this.code;
+    }
+}

+ 110 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/props/HuifuProperties.java

@@ -0,0 +1,110 @@
+package com.yonge.cooleshow.props;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.cloud.context.config.annotation.RefreshScope;
+
+/**
+ * 权限过滤
+ */
+@RefreshScope
+@ConfigurationProperties("huifu")
+public class HuifuProperties {
+    /***
+     * 汇付 控制台 主页面应用的app_id
+     * @author liweifan
+     * @updateTime 2022/3/31 11:19
+     */
+    private String appId;
+    /***
+     * 汇付 控制台->商户信息管理->证书管理中的API Key(prod模式的API KEY)
+     * @author liweifan
+     * @updateTime 2022/3/31 11:19
+     */
+    private String apiKey;
+    /***
+     * 汇付 控制台->商户信息管理->证书管理中的API Key(mock模式的API KEY)
+     * @author liweifan
+     * @updateTime 2022/3/31 11:19
+     */
+    private String mockApiKey;
+    /***
+     * 商户发起请求时,用于请求参数加签所需要的RSA私钥
+     * @author liweifan
+     * @updateTime 2022/3/31 11:24
+     */
+    private String rsaPrivateKey;
+    /***
+     * 付款成功回调地址
+     * @author liweifan
+     * @updateTime 2022/3/31 11:24
+     */
+    private String notifyUrl;
+    /***
+     * 微信appid
+     * @author liweifan
+     * @updateTime 2022/3/31 11:24
+     */
+    private String wxAppid;
+    /***
+     * 微信secret
+     * @author liweifan
+     * @updateTime 2022/3/31 11:24
+     */
+    private String wxSecret;
+
+    public String getApiKey() {
+        return apiKey;
+    }
+
+    public void setApiKey(String apiKey) {
+        this.apiKey = apiKey;
+    }
+
+    public String getMockApiKey() {
+        return mockApiKey;
+    }
+
+    public void setMockApiKey(String mockApiKey) {
+        this.mockApiKey = mockApiKey;
+    }
+
+    public String getRsaPrivateKey() {
+        return rsaPrivateKey;
+    }
+
+    public void setRsaPrivateKey(String rsaPrivateKey) {
+        this.rsaPrivateKey = rsaPrivateKey;
+    }
+
+    public String getAppId() {
+        return appId;
+    }
+
+    public void setAppId(String appId) {
+        this.appId = appId;
+    }
+
+    public String getWxAppid() {
+        return wxAppid;
+    }
+
+    public void setWxAppid(String wxAppid) {
+        this.wxAppid = wxAppid;
+    }
+
+    public String getWxSecret() {
+        return wxSecret;
+    }
+
+    public void setWxSecret(String wxSecret) {
+        this.wxSecret = wxSecret;
+    }
+
+    public String getNotifyUrl() {
+        return notifyUrl;
+    }
+
+    public void setNotifyUrl(String notifyUrl) {
+        this.notifyUrl = notifyUrl;
+    }
+}

+ 221 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/PaymentSdk.java

@@ -0,0 +1,221 @@
+package com.yonge.cooleshow.sdk;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.huifu.adapay.core.exception.BaseAdaPayException;
+import com.huifu.adapay.model.Payment;
+import com.huifu.adapay.model.PaymentConfirm;
+import com.yonge.cooleshow.common.constant.CommonConstants;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.config.HuifuConfiguration;
+import com.yonge.cooleshow.sdk.req.PaymentReq;
+import com.yonge.toolset.thirdparty.exception.ThirdpartyException;
+import com.yonge.toolset.utils.collection.MapUtil;
+import com.yonge.toolset.utils.http.HttpUtil;
+import com.yonge.toolset.utils.string.StringUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Component
+public class PaymentSdk {
+    private final static Logger log = LoggerFactory.getLogger(PaymentSdk.class);
+
+    /**
+     * 执行一个支付交易
+     *
+     * @return 创建的支付对象
+     * @throws Exception 异常
+     */
+    public HttpResponseResult<Map<String, Object>> executePayment(PaymentReq paymentReq) {
+        paymentReq.setApp_id(HuifuConfiguration.getHuifuProperties().getAppId());
+        //创建分账对象
+        Map<String, String> div_member = new HashMap<>();
+        div_member.put("member_id", "0");
+        div_member.put("amount", paymentReq.getPay_amt());
+        div_member.put("fee_flag", "Y");
+        List<Map<String, String>> div_members = Arrays.asList(div_member);
+        paymentReq.setDiv_members(JSONObject.toJSONString(div_members));
+
+        log.info("汇付[创建支付对象] Req:{}", JSONObject.toJSONString(paymentReq));
+        //调用sdk方法,创建支付,得到支付对象
+        Map<String, Object> paymentParams = MapUtil.populateMap(new HashMap<>(), paymentReq);
+        Map<String, Object> res;
+        try {
+            res = Payment.create(paymentParams);
+        } catch (BaseAdaPayException e) {
+            return HttpResponseResult.failed(e.getMessage());
+        }
+        if (null == res) {
+            return HttpResponseResult.failed("请求失败");
+        }
+        log.info("汇付[创建支付对象] Resp:{}", res);
+        String errorCode = (String) res.get("error_code");
+        if (null != errorCode) {
+            String errorMsg = (String) res.get("error_msg");
+            return HttpResponseResult.failed(errorMsg);
+        }
+        return HttpResponseResult.succeed(res);
+    }
+
+    /**
+     * 创建确认对象
+     * 创建支付确认对象适用于延时分账的场景
+     *
+     * @return 查询的支付对象
+     * @throws Exception 异常
+     */
+    public Map<String, Object> createConfirm(Map<String, Object> confirm) throws Exception {
+        confirm = PaymentConfirm.create(confirm);
+
+        String error_code = (String) confirm.get("error_code");
+        if (null != error_code) {
+            String errorMsg = (String) confirm.get("error_msg");
+            throw new ThirdpartyException(errorMsg);
+        }
+        return confirm;
+    }
+
+    /**
+     * 关闭一个支付交易
+     *
+     * @param paymentId 要关闭的支付id
+     * @return 关闭的支付对象
+     * @throws Exception 异常
+     */
+    public Map<String, Object> closePayment(String paymentId) throws Exception {
+        Map<String, Object> payment = new HashMap<>();
+        Map<String, Object> paymentParams = new HashMap<>(10);
+        paymentParams.put("payment_id", paymentId);
+        paymentParams.put("reason", "reason");
+        paymentParams.put("expend", "expend");
+        paymentParams.put("notify_url", "notify_url");
+        payment = com.huifu.adapay.model.Payment.close(paymentParams);
+
+        String error_code = (String) payment.get("error_code");
+        if (null != error_code) {
+            String errorMsg = (String) payment.get("error_msg");
+            throw new ThirdpartyException(errorMsg);
+        }
+        return payment;
+    }
+
+    /**
+     * 查询一个支付交易
+     *
+     * @param paymentId 要查询的支付id
+     * @return 查询的支付对象
+     * @throws Exception 异常
+     */
+    public Map<String, Object> queryPayment(String paymentId) throws Exception {
+        System.out.println("=======query payment begin=======");
+        //查询支付对象的参数,全部参数请参考 https://docs.adapay.tech/api/04-trade.html#id7
+        //调用sdk方法,查询支付交易,得到支付对象
+        Map<String, Object> payment = new HashMap<>();
+        try {
+            System.out.println("支付查询请求参数:" + JSON.toJSONString(paymentId));
+            payment = com.huifu.adapay.model.Payment.query(paymentId);
+        } catch (ThirdpartyException e) {
+            e.printStackTrace();
+        }
+
+        System.out.println("支付查询返回参数:" + JSON.toJSONString(payment));
+
+        String error_code = (String) payment.get("error_code");
+        if (null != error_code) {
+            String error_msg = (String) payment.get("error_msg");
+            System.out.println("error_code:" + error_code + "............." + error_msg);
+        }
+        System.out.println("=======query payment end=======");
+        return payment;
+    }
+    /***
+     * 获取openId
+     * @author liweifan
+     * @param: js_code
+     * @updateTime 2022/4/8 15:49
+     * @return: java.lang.Object
+     */
+    public HttpResponseResult<Map<String, String>> getOpenId(String js_code) {
+        log.info("微信[获取用户openId] Req:{}", js_code);
+        Map<String, Object> param = new HashMap<>();
+        param.put("appid", HuifuConfiguration.getHuifuProperties().getWxAppid());
+        param.put("secret", HuifuConfiguration.getHuifuProperties().getWxSecret());
+        param.put("js_code", js_code);
+        param.put("grant_type", CommonConstants.WECHAT_GRANT_TYPE);
+
+        try {
+            String res = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session", param);
+            JSONObject jsonObject = JSONObject.parseObject(res);
+            log.info("微信[获取用户openId] Res:{}", jsonObject.toJSONString());
+            String errcode = jsonObject.getString("errcode");
+            if(StringUtil.isEmpty(errcode) || "0".equals(errcode)){
+                Map<String, String> resMap = new HashMap<>();
+                resMap.put("openid", jsonObject.getString("openid"));
+                resMap.put("session_key", jsonObject.getString("session_key"));
+                return HttpResponseResult.succeed(resMap);
+            }else{
+                return HttpResponseResult.failed(jsonObject.getString("errmsg"));
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return HttpResponseResult.failed("请求失败");
+        }
+    }
+
+/*
+    public static Map<String, Object> queryList(Integer pageIndex, Long createdGte, Long createdLte) throws Exception {
+        Map<String, Object> paymentParams = new HashMap<>();
+        paymentParams.put("app_id", ConfigInit.appId);
+        paymentParams.put("page_index", pageIndex);
+        paymentParams.put("page_size", "20");
+        paymentParams.put("created_gte", createdGte);
+        paymentParams.put("created_lte", createdLte);
+        Map<String, Object> payment = com.huifu.adapay.model.Payment.queryList(paymentParams);
+        String error_code = (String) payment.get("error_code");
+        if (null != error_code) {
+            String errorMsg = (String) payment.get("error_msg");
+            throw new ThirdpartyException(errorMsg);
+        }
+        return payment;
+    }
+
+    public static Map<String, Object> queryConfirmList(String paymentId) throws Exception {
+        Map<String, Object> paymentParams = new HashMap<>();
+        paymentParams.put("app_id", ConfigInit.appId);
+        paymentParams.put("payment_id", paymentId);
+
+        Map<String, Object> payment = com.huifu.adapay.model.Payment.queryConfirmList(paymentParams);
+        String error_code = (String) payment.get("error_code");
+        if (null != error_code) {
+            String errorMsg = (String) payment.get("error_msg");
+            throw new ThirdpartyException(errorMsg);
+        }
+        return payment;
+    }
+
+
+    public static Map<String, Object> getPayMap(BigDecimal amount, String orderNo, String notifyUrl, String returnUrl, String orderSubject, String orderBody) throws Exception {
+        Map<String, Object> paymentParams = new LinkedHashMap<>();
+        paymentParams.put("appId", ConfigInit.appId);
+        paymentParams.put("amount", amount.setScale(2, BigDecimal.ROUND_HALF_UP));
+        paymentParams.put("orderNo", orderNo);
+//        paymentParams.put("notifyUrl", notifyUrl);
+//        paymentParams.put("returnUrl", returnUrl);
+        paymentParams.put("orderSubject", orderSubject);
+        paymentParams.put("orderBody", orderBody);
+        paymentParams.put("wxAppId", ConfigInit.wxAppId);
+
+        String originalStr = JSONObject.toJSONString(paymentParams);
+        String sign = DigestUtils.md5DigestAsHex(originalStr.getBytes());
+
+        paymentParams.put("sign", sign);
+        paymentParams.remove("appId");
+        return paymentParams;
+    }*/
+}

+ 27 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/DeviceInfo.java

@@ -0,0 +1,27 @@
+package com.yonge.cooleshow.sdk.req;
+
+import java.io.Serializable;
+
+/**
+ * 交易设备信息
+ * @Author: liweifan
+ * @Data: 2022/3/31 11:36
+ */
+public class DeviceInfo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /***
+     * 交易设备所在的公网 IP
+     * @author liweifan
+     * @updateTime 2022/3/31 11:07
+     */
+    private String device_ip;
+
+    public String getDevice_ip() {
+        return device_ip;
+    }
+
+    public void setDevice_ip(String device_ip) {
+        this.device_ip = device_ip;
+    }
+}

+ 55 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/DivMember.java

@@ -0,0 +1,55 @@
+package com.yonge.cooleshow.sdk.req;
+
+import java.io.Serializable;
+
+/**
+ * 分账对象
+ * @Author: liweifan
+ * @Data: 2022/3/31 11:26
+ */
+public class DivMember implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 分账用户 Member对象 的 id;若是商户本身时,传入0
+     * @author liweifan
+     * @updateTime 2022/3/31 11:27
+     */
+    private String member_id;
+    /**
+     * 分账金额,精确到分,如0.50,1.00等,分账总金额必须等于主交易金额,金额不能为0.00
+     * @author liweifan
+     * @updateTime 2022/3/31 11:28
+     */
+    private String amount;
+    /**
+     * 是否手续费承担方,N-否,Y-是,手续费承担方有且只能有一个
+     * @author liweifan
+     * @updateTime 2022/3/31 11:28
+     */
+    private String fee_flag;
+
+    public String getMember_id() {
+        return member_id;
+    }
+
+    public void setMember_id(String member_id) {
+        this.member_id = member_id;
+    }
+
+    public String getAmount() {
+        return amount;
+    }
+
+    public void setAmount(String amount) {
+        this.amount = amount;
+    }
+
+    public String getFee_flag() {
+        return fee_flag;
+    }
+
+    public void setFee_flag(String fee_flag) {
+        this.fee_flag = fee_flag;
+    }
+}

+ 147 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/OrderPayReq.java

@@ -0,0 +1,147 @@
+package com.yonge.cooleshow.sdk.req;
+
+import com.yonge.cooleshow.enums.OrderStatusEnum;
+import com.yonge.cooleshow.enums.PayChannelEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+import javax.validation.constraints.NotBlank;
+import javax.validation.constraints.NotNull;
+import java.math.BigDecimal;
+
+/**
+ * 下单支付请求
+ *
+ * @Author: liweifan
+ * @Data: 2022/3/31 14:55
+ */
+@ApiModel(value = "OrderPayReq对象", description = "下单支付请求")
+public class OrderPayReq {
+    @NotBlank(message = "订单号不能为空")
+    @ApiModelProperty(value = "订单号 ", required = true)
+    private String orderNo;
+    @NotNull(message = "支付渠道不能为空")
+    @ApiModelProperty(value = "支付渠道:  alipay 支付宝  wx_lite 微信 ", required = true)
+    private PayChannelEnum payChannel;
+    @ApiModelProperty(value = "用户id ")
+    private Long userId;
+    @ApiModelProperty(value = "用户端公网ip ")
+    private String ipAddress;
+    @ApiModelProperty(value = "微信用户openId(微信支付必传)")
+    private String openId;
+
+    @ApiModelProperty(value = "订单状态",hidden = true)
+    private OrderStatusEnum orderStatus;
+
+    @ApiModelProperty(value = "订单金额",hidden = true)
+    private BigDecimal orderPrice;
+
+    @ApiModelProperty(value = "商品标题",hidden = true)
+    private String goodTitle;
+
+    @ApiModelProperty(value = "商品描述",hidden = true)
+    private String goodDesc;
+
+    @ApiModelProperty("拉起支付信息")
+    private String payInfo;
+
+    public void orderStatus(Integer orderStatus) {
+        if (orderStatus == 0) {
+            this.orderStatus = OrderStatusEnum.WAIT_PAY;
+        } else if (orderStatus == 1) {
+            this.orderStatus = OrderStatusEnum.PAID;
+        }else if (orderStatus == 2) {
+            this.orderStatus = OrderStatusEnum.CLOSE;
+        }else if (orderStatus == 3) {
+            this.orderStatus = OrderStatusEnum.CLOSE;
+        }else if (orderStatus == 4) {
+            this.orderStatus = OrderStatusEnum.CLOSE;
+        }else if (orderStatus == 5) {
+            this.orderStatus = OrderStatusEnum.CLOSE;
+        }else if (orderStatus == 6) {
+            this.orderStatus = OrderStatusEnum.PAYING;
+        }else if (orderStatus == 7) {
+            this.orderStatus = OrderStatusEnum.FAIL;
+        }
+    }
+
+    public OrderStatusEnum getOrderStatus() {
+        return orderStatus;
+    }
+
+    public void setOrderStatus(OrderStatusEnum orderStatus) {
+        this.orderStatus = orderStatus;
+    }
+
+    public BigDecimal getOrderPrice() {
+        return orderPrice;
+    }
+
+    public void setOrderPrice(BigDecimal orderPrice) {
+        this.orderPrice = orderPrice;
+    }
+
+    public String getGoodTitle() {
+        return goodTitle;
+    }
+
+    public void setGoodTitle(String goodTitle) {
+        this.goodTitle = goodTitle;
+    }
+
+    public String getGoodDesc() {
+        return goodDesc;
+    }
+
+    public void setGoodDesc(String goodDesc) {
+        this.goodDesc = goodDesc;
+    }
+
+    public String getOrderNo() {
+        return orderNo;
+    }
+
+    public void setOrderNo(String orderNo) {
+        this.orderNo = orderNo;
+    }
+
+    public PayChannelEnum getPayChannel() {
+        return payChannel;
+    }
+
+    public void setPayChannel(PayChannelEnum payChannel) {
+        this.payChannel = payChannel;
+    }
+
+    public Long getUserId() {
+        return userId;
+    }
+
+    public void setUserId(Long userId) {
+        this.userId = userId;
+    }
+
+    public String getIpAddress() {
+        return ipAddress;
+    }
+
+    public void setIpAddress(String ipAddress) {
+        this.ipAddress = ipAddress;
+    }
+
+    public String getOpenId() {
+        return openId;
+    }
+
+    public void setOpenId(String openId) {
+        this.openId = openId;
+    }
+
+    public String getPayInfo() {
+        return payInfo;
+    }
+
+    public void setPayInfo(String payInfo) {
+        this.payInfo = payInfo;
+    }
+}

+ 73 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/PaymentConfirmParam.java

@@ -0,0 +1,73 @@
+package com.yonge.cooleshow.sdk.req;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * @Author: liweifan
+ * @Data: 2022/3/11 17:44
+ */
+public class PaymentConfirmParam implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    //Adapay生成的支付对象id
+    private String payment_id;
+    //请求订单号,只能为英文、数字或者下划线的一种或多种组合,保证在app_id下唯一
+    private String order_no;
+    //确认金额,必须大于0,保留两位小数点,如0.10、100.05等。必须小于等于原支付金额-已确认金额-已撤销金额。
+    private String confirm_amt;
+    //附加说明
+    private String description;
+    //分账对象信息列表,一次请求最多仅支持7个分账方
+    private List<DivMember> div_members;
+    //手续费收取模式:O-商户手续费账户扣取手续费,I-交易金额中扣取手续费;值为空时,默认值为I;若为O时,分账对象列表中不支持传入手续费承担方
+    private String fee_mode;
+
+    public String getPayment_id() {
+        return payment_id;
+    }
+
+    public void setPayment_id(String payment_id) {
+        this.payment_id = payment_id;
+    }
+
+    public String getOrder_no() {
+        return order_no;
+    }
+
+    public void setOrder_no(String order_no) {
+        this.order_no = order_no;
+    }
+
+    public String getConfirm_amt() {
+        return confirm_amt;
+    }
+
+    public void setConfirm_amt(String confirm_amt) {
+        this.confirm_amt = confirm_amt;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public List<DivMember> getDiv_members() {
+        return div_members;
+    }
+
+    public void setDiv_members(List<DivMember> div_members) {
+        this.div_members = div_members;
+    }
+
+    public String getFee_mode() {
+        return fee_mode;
+    }
+
+    public void setFee_mode(String fee_mode) {
+        this.fee_mode = fee_mode;
+    }
+}

+ 168 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/req/PaymentReq.java

@@ -0,0 +1,168 @@
+package com.yonge.cooleshow.sdk.req;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * 创建支付对象请求参数
+ * @Author: liweifan
+ * @Data: 2022/3/31 10:58
+ */
+public class PaymentReq implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    /***
+     * 请求订单号,只能为英文、数字或者下划线的一种或多种组合,保证在app_id下唯一
+     * @author liweifan
+     * @updateTime 2022/3/31 11:00
+     */
+    private String order_no;
+    /***
+     * 控制台 主页面应用的app_id
+     * @author liweifan
+     * @updateTime 2022/3/31 11:00
+     */
+    private String app_id;
+    /***
+     * 支付渠道,参见 支付渠道
+     * @author liweifan
+     * @updateTime 2022/3/31 11:01
+     */
+    private String pay_channel;
+    /***
+     * 交易金额,必须大于0,保留两位小数点,如0.10、100.05等
+     * @author liweifan
+     * @updateTime 2022/3/31 11:01
+     */
+    private String pay_amt;
+    /***
+     * 商品标题
+     * @author liweifan
+     * @updateTime 2022/3/31 11:01
+     */
+    private String goods_title;
+    /***
+     * 商品描述信息,微信小程序和微信公众号该字段最大长度42个字符
+     * @author liweifan
+     * @updateTime 2022/3/31 11:01
+     */
+    private String goods_desc;
+    /***
+     * 分账对象信息列表,最多仅支持7个分账方,json 数组形式,详见 分账对象信息列表
+     * @author liweifan
+     * @updateTime 2022/3/31 11:01
+     */
+    private String div_members;
+    /***
+     * 订单附加说明
+     * @author liweifan
+     * @updateTime 2022/3/31 11:01
+     */
+    private String description;
+    /***
+     * 前端设备信息,详见 设备信息
+     * @author liweifan
+     * @updateTime 2022/3/31 11:01
+     */
+    private DeviceInfo device_info;
+    /***
+     * 支付渠道额外参数,JSON格式,条件可输入,详见 支付渠道 expend参数
+     * @author liweifan
+     * @updateTime 2022/3/31 11:01
+     */
+    private Map<String,Object> expend;
+    /***
+     * 异步通知地址,url为http/https路径,服务器POST回调,URL 上请勿附带参数
+     * @author liweifan
+     * @updateTime 2022/3/31 11:01
+     */
+    private String notify_url;
+
+    public String getOrder_no() {
+        return order_no;
+    }
+
+    public void setOrder_no(String order_no) {
+        this.order_no = order_no;
+    }
+
+    public String getApp_id() {
+        return app_id;
+    }
+
+    public void setApp_id(String app_id) {
+        this.app_id = app_id;
+    }
+
+    public String getPay_amt() {
+        return pay_amt;
+    }
+
+    public void setPay_amt(String pay_amt) {
+        this.pay_amt = pay_amt;
+    }
+
+    public String getGoods_title() {
+        return goods_title;
+    }
+
+    public void setGoods_title(String goods_title) {
+        this.goods_title = goods_title;
+    }
+
+    public String getGoods_desc() {
+        return goods_desc;
+    }
+
+    public void setGoods_desc(String goods_desc) {
+        this.goods_desc = goods_desc;
+    }
+
+    public String getDiv_members() {
+        return div_members;
+    }
+
+    public void setDiv_members(String div_members) {
+        this.div_members = div_members;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public DeviceInfo getDevice_info() {
+        return device_info;
+    }
+
+    public void setDevice_info(DeviceInfo device_info) {
+        this.device_info = device_info;
+    }
+
+    public Map<String, Object> getExpend() {
+        return expend;
+    }
+
+    public void setExpend(Map<String, Object> expend) {
+        this.expend = expend;
+    }
+
+    public String getNotify_url() {
+        return notify_url;
+    }
+
+    public void setNotify_url(String notify_url) {
+        this.notify_url = notify_url;
+    }
+
+    public String getPay_channel() {
+        return pay_channel;
+    }
+
+    public void setPay_channel(String pay_channel) {
+        this.pay_channel = pay_channel;
+    }
+}

+ 100 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/sdk/res/OrderPayRes.java

@@ -0,0 +1,100 @@
+package com.yonge.cooleshow.sdk.res;
+
+import com.yonge.cooleshow.enums.OrderStatusEnum;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+
+/**
+ * @Author: liweifan
+ * @Data: 2022/4/1 15:35
+ */
+@ApiModel(value = "OrderPayRes", description = "订单支付请求返回对象")
+public class OrderPayRes {
+    @ApiModelProperty("支付金额")
+    private String pay_amt;
+    @ApiModelProperty("pay_info")
+    private String pay_info;
+
+    @ApiModelProperty("执行状态")
+    private boolean status = true;
+
+    @ApiModelProperty("订单状态")
+    private OrderStatusEnum orderStatus;
+
+    @ApiModelProperty("出错信息")
+    private String message;
+
+    @ApiModelProperty("订单编号")
+    private String orderNo;
+
+    @ApiModelProperty("支付方式")
+    private String payChannel;
+
+    @ApiModelProperty("交易流水号")
+    private String transNo;
+
+
+    public String getTransNo() {
+        return transNo;
+    }
+
+    public void setTransNo(String transNo) {
+        this.transNo = transNo;
+    }
+
+    public String getOrderNo() {
+        return orderNo;
+    }
+
+    public void setOrderNo(String orderNo) {
+        this.orderNo = orderNo;
+    }
+
+    public String getPayChannel() {
+        return payChannel;
+    }
+
+    public void setPayChannel(String payChannel) {
+        this.payChannel = payChannel;
+    }
+
+    public OrderStatusEnum getOrderStatus() {
+        return orderStatus;
+    }
+
+    public void setOrderStatus(OrderStatusEnum orderStatus) {
+        this.orderStatus = orderStatus;
+    }
+
+    public boolean isStatus() {
+        return status;
+    }
+
+    public void setStatus(boolean status) {
+        this.status = status;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public String getPay_amt() {
+        return pay_amt;
+    }
+
+    public void setPay_amt(String pay_amt) {
+        this.pay_amt = pay_amt;
+    }
+
+    public String getPay_info() {
+        return pay_info;
+    }
+
+    public void setPay_info(String pay_info) {
+        this.pay_info = pay_info;
+    }
+}

+ 27 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/service/PaymentService.java

@@ -0,0 +1,27 @@
+package com.yonge.cooleshow.service;
+
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.sdk.req.OrderPayReq;
+import com.yonge.cooleshow.sdk.res.OrderPayRes;
+
+/**
+ * Description 支付服务
+ *
+ * @author liujunchi
+ * @date 2022-04-21
+ */
+public interface PaymentService {
+
+    /**
+     * 调用支付
+     *
+     * @param payReq
+     * @return
+     */
+    OrderPayRes orderPay(OrderPayReq payReq);
+
+    OrderPayRes orderPayWaitPay(OrderPayReq payReq);
+
+
+    OrderPayRes orderPayPaying(OrderPayReq payReq);
+}

+ 109 - 0
cooleshow-mall/mall-pay/src/main/java/com/yonge/cooleshow/service/impl/AdapayPaymentServiceImpl.java

@@ -0,0 +1,109 @@
+package com.yonge.cooleshow.service.impl;
+
+import com.alibaba.fastjson.JSONObject;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.config.HuifuConfiguration;
+import com.yonge.cooleshow.enums.OrderStatusEnum;
+import com.yonge.cooleshow.enums.PayChannelEnum;
+import com.yonge.cooleshow.enums.PayStatusEnum;
+import com.yonge.cooleshow.sdk.PaymentSdk;
+import com.yonge.cooleshow.sdk.req.DeviceInfo;
+import com.yonge.cooleshow.sdk.req.OrderPayReq;
+import com.yonge.cooleshow.sdk.req.PaymentReq;
+import com.yonge.cooleshow.sdk.res.OrderPayRes;
+import com.yonge.cooleshow.service.PaymentService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-04-21
+ */
+@Service("adapayPaymentService")
+public class AdapayPaymentServiceImpl implements PaymentService {
+
+    @Autowired
+    private PaymentSdk paymentSdk;
+
+    @Override
+    public OrderPayRes orderPay(OrderPayReq payReq) {
+        if (OrderStatusEnum.WAIT_PAY.equals(payReq.getOrderStatus()) || OrderStatusEnum.FAIL.equals(payReq.getOrderStatus())) {
+            //处于待支付状态,需要调用汇付发起付款请求接口
+            return orderPayWaitPay(payReq);
+        } else if (OrderStatusEnum.PAYING.equals(payReq.getOrderStatus())) {
+            //处于付款中状态,需要拉起付款接口返回信息,并且去到汇付
+            return orderPayPaying(payReq);
+        }
+        OrderPayRes orderPayRes = new OrderPayRes();
+        orderPayRes.setStatus(false);
+        orderPayRes.setMessage("订单状态异常");
+        return orderPayRes;
+    }
+
+    @Override
+    public OrderPayRes orderPayWaitPay(OrderPayReq payReq) {
+        PaymentReq paymentReq = new PaymentReq();
+        paymentReq.setOrder_no(payReq.getOrderNo());
+        paymentReq.setPay_channel(payReq.getPayChannel().getCode());
+        paymentReq.setPay_amt(payReq.getOrderPrice().setScale(2, RoundingMode.HALF_UP).toString());
+        paymentReq.setGoods_title(payReq.getGoodTitle());
+        paymentReq.setGoods_desc(payReq.getGoodDesc());
+
+        DeviceInfo deviceInfo = new DeviceInfo();
+        deviceInfo.setDevice_ip(payReq.getIpAddress());
+
+        paymentReq.setDevice_info(deviceInfo);
+        //异步通知地址
+        paymentReq.setNotify_url(HuifuConfiguration.getHuifuProperties().getNotifyUrl());
+
+        if (PayChannelEnum.wx_lite.equals(payReq.getPayChannel())) {
+            Map<String, Object> expend = new HashMap<>();
+            expend.put("open_id", payReq.getOpenId());
+            paymentReq.setExpend(expend);
+        }
+        //付款请求
+        HttpResponseResult<Map<String, Object>> responseResult = paymentSdk.executePayment(paymentReq);
+        OrderPayRes orderPayRes = new OrderPayRes();
+        orderPayRes.setOrderNo(payReq.getOrderNo());
+        orderPayRes.setPayChannel(payReq.getPayChannel().getCode());
+
+        if (responseResult.getStatus()) {
+            Map<String, Object> res = responseResult.getData();
+            orderPayRes.setTransNo(res.get("id").toString());
+            orderPayRes.setPay_amt(
+                    new BigDecimal(res.get("pay_amt").toString()).setScale(2, RoundingMode.HALF_UP).toString()
+            );
+            String pay_info = ((JSONObject) res.get("expend")).getString("pay_info");
+            orderPayRes.setPay_info(pay_info);
+            orderPayRes.setOrderStatus(OrderStatusEnum.PAYING);
+            orderPayRes.setPay_amt(payReq.getOrderPrice().setScale(2, RoundingMode.HALF_UP).toString());
+            return orderPayRes;
+        } else {
+            //入订单付款表,同时修改订单状态
+            orderPayRes.setOrderStatus(OrderStatusEnum.FAIL);
+            orderPayRes.setStatus(false);
+            orderPayRes.setMessage(responseResult.getMsg());
+            return orderPayRes;
+        }
+    }
+
+    @Override
+    public OrderPayRes orderPayPaying(OrderPayReq payReq) {
+        OrderPayRes orderPayRes = new OrderPayRes();
+        if (OrderStatusEnum.PAYING.getCode().equals(payReq.getOrderStatus().getCode())) {
+            orderPayRes.setPay_info(payReq.getPayInfo());
+            orderPayRes.setPay_amt(payReq.getOrderPrice().toString());
+        } else {
+            orderPayRes.setStatus(false);
+            orderPayRes.setMessage("订单不处于支付状态中");
+        }
+        return orderPayRes;
+    }
+}

+ 7 - 1
cooleshow-mall/mall-portal/pom.xml

@@ -33,7 +33,7 @@
         </dependency>
         <dependency>
             <groupId>com.yonge.cooleshow</groupId>
-            <artifactId>mall-common</artifactId>
+            <artifactId>mall-pay</artifactId>
         </dependency>
         <dependency>
             <groupId>com.yonge.toolset</groupId>
@@ -69,6 +69,12 @@
             <version>20.0</version>
             <scope>compile</scope>
         </dependency>
+        <dependency>
+            <groupId>org.redisson</groupId>
+            <artifactId>redisson</artifactId>
+            <version>3.16.4</version>
+            <scope>compile</scope>
+        </dependency>
     </dependencies>
 
     <build>

+ 1 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/MallPortalApplication.java

@@ -10,7 +10,7 @@ import org.springframework.context.annotation.ComponentScan;
 
 @SpringBootApplication
 @MapperScan({"com.yonge.cooleshow.mbg.mapper", "com.yonge.cooleshow.portal.dao"})
-@ComponentScan(basePackages = {"com.yonge.cooleshow.portal","com.yonge.cooleshow.mbg", "com.yonge.cooleshow.mall.common", "com.yonge.cooleshow.common","com.yonge.toolset"})
+@ComponentScan(basePackages = {"com.yonge.cooleshow.portal","com.yonge.cooleshow.mbg", "com.yonge.cooleshow.mall.common", "com.yonge.cooleshow.common","com.yonge.toolset","com.yonge.cooleshow"})
 @EnableSwagger2Doc
 @EnableDiscoveryClient
 @EnableFeignClients("com.yonge.cooleshow")

+ 1 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/OmsPortalOrderController.java

@@ -44,7 +44,7 @@ public class OmsPortalOrderController {
     }
 
     @ApiOperation("用户支付成功的回调")
-    @RequestMapping(value = "/paySuccess", method = RequestMethod.POST)
+    // @RequestMapping(value = "/paySuccess", method = RequestMethod.POST)
     @ResponseBody
     public CommonResult paySuccess(@RequestParam Long orderId,@RequestParam Integer payType) {
         Integer count = portalOrderService.paySuccess(orderId,payType);

+ 129 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/controller/PaymentController.java

@@ -0,0 +1,129 @@
+package com.yonge.cooleshow.portal.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.huifu.adapay.core.AdapayCore;
+import com.huifu.adapay.core.util.AdapaySign;
+import com.yonge.cooleshow.auth.api.client.SysUserFeignService;
+import com.yonge.cooleshow.auth.api.entity.SysUser;
+import com.yonge.cooleshow.common.controller.BaseController;
+import com.yonge.cooleshow.common.entity.HttpResponseResult;
+import com.yonge.cooleshow.enums.OrdeerCacherEnmu;
+import com.yonge.cooleshow.portal.service.OmsPortalOrderService;
+import com.yonge.cooleshow.portal.util.DistributedLock;
+import com.yonge.cooleshow.sdk.PaymentSdk;
+import com.yonge.cooleshow.sdk.req.OrderPayReq;
+import com.yonge.cooleshow.sdk.res.OrderPayRes;
+import com.yonge.toolset.utils.web.WebUtil;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import org.redisson.api.RedissonClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.validation.Valid;
+import java.util.Map;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @Author: liweifan
+ * @Data: 2022/3/11 18:16
+ */
+@RestController
+@RequestMapping("/payment")
+@Api(value = "付款接口", tags = "付款接口")
+public class PaymentController extends BaseController {
+    private final static Logger log = LoggerFactory.getLogger(PaymentController.class);
+    @Autowired
+    private PaymentSdk paymentSdk;
+    @Autowired
+    private OmsPortalOrderService portalOrderService;
+    @Autowired
+    private SysUserFeignService sysUserFeignService;
+    @Autowired
+    private RedissonClient redissonClient;
+
+    @ApiOperation(value = "查询付款单")
+    @GetMapping("/queryPayment")
+    public HttpResponseResult<Map<String, Object>> queryPayment(String paymentId) throws Exception {
+        return HttpResponseResult.succeed(paymentSdk.queryPayment(paymentId));
+    }
+
+    @ApiOperation(value = "微信支付获取openid")
+    @GetMapping("/getOpenId")
+    public HttpResponseResult<Map<String, String>> getOpenId(String js_code) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        HttpResponseResult<Map<String, String>> responseResult = paymentSdk.getOpenId(js_code);
+        if (responseResult.getStatus()) {
+            Map<String, String> data = responseResult.getData();
+            //绑定到用户表
+            user.setWxOpenid(data.get("openid"));
+            log.info("绑定用户openid,param is {}", JSONObject.toJSONString(user));
+            sysUserFeignService.bindOpenId(user);
+        }
+        return responseResult;
+    }
+
+    /***
+     * 汇付回调
+     * 问题:1、成功失败需要回执什么信息 2、回调url地址是否需要加入白名单
+     * @author liweifan
+     * @param: request
+     * @updateTime 2022/3/11 18:35
+     */
+    @PostMapping("/callback")
+    public void callback(HttpServletRequest request) {
+        try {
+            //验签传参data
+            String data = request.getParameter("data");
+            //验签传参sign
+            String sign = request.getParameter("sign");
+            //验签传参publicKey
+            String publicKey = AdapayCore.PUBLIC_KEY;
+            //验签
+            boolean checkSign = AdapaySign.verifySign(data, sign, publicKey);
+            log.info("汇付回调,res is {}", data);
+            if (checkSign) {
+                //验签成功逻辑
+                log.info("验签成功");
+                portalOrderService.orderCallback(data);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @ApiOperation(value = "订单付款")
+    @PostMapping("/orderPay")
+    public HttpResponseResult<OrderPayRes> orderPay(@Valid @RequestBody OrderPayReq payReq, HttpServletRequest request) {
+        SysUser user = sysUserFeignService.queryUserInfo();
+        if (user == null || null == user.getId()) {
+            return failed(HttpStatus.FORBIDDEN, "请登录");
+        }
+        payReq.setUserId(user.getId());
+        payReq.setIpAddress(WebUtil.getRemoteIp(request));
+
+        Future<OrderPayRes> orderPayResFuture = DistributedLock.of(redissonClient)
+              .callIfLockCanGet(OrdeerCacherEnmu.LOCK_PAY_ORDER.getRedisKey(user.getId()),
+                                () -> portalOrderService.orderPay(payReq), 60L, TimeUnit.SECONDS);
+
+        try {
+            OrderPayRes orderPayRes = orderPayResFuture.get();
+            if (orderPayRes.isStatus()) {
+                return succeed(orderPayRes);
+            }  else {
+                return failed(orderPayRes.getMessage());
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return HttpResponseResult.failed("付款失败");
+        }
+    }
+}

+ 17 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/OmsPortalOrderService.java

@@ -4,10 +4,13 @@ import com.yonge.cooleshow.mall.common.api.CommonPage;
 import com.yonge.cooleshow.portal.domain.ConfirmOrderResult;
 import com.yonge.cooleshow.portal.domain.OmsOrderDetail;
 import com.yonge.cooleshow.portal.domain.OrderParam;
+import com.yonge.cooleshow.sdk.req.OrderPayReq;
+import com.yonge.cooleshow.sdk.res.OrderPayRes;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.Future;
 
 /**
  * 前台订单管理Service
@@ -68,4 +71,18 @@ public interface OmsPortalOrderService {
      * 用户根据订单ID删除订单
      */
     void deleteOrder(Long orderId);
+
+    /**
+     *
+     * @param data
+     */
+    void orderCallback(String data);
+
+    /**
+     * 订单拉起支付
+     *
+     * @param payReq 支付信息
+     * @return
+     */
+    OrderPayRes orderPay(OrderPayReq payReq);
 }

+ 29 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/UserOrderPaymentService.java

@@ -0,0 +1,29 @@
+package com.yonge.cooleshow.portal.service;
+
+import com.yonge.cooleshow.mbg.model.UserOrderPayment;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-04-24
+ */
+public interface UserOrderPaymentService {
+
+    /**
+     *  根据订单查询
+     *
+     * @param orderNo 订单id
+     * @return
+     */
+    UserOrderPayment getByOrderNo(String orderNo);
+
+    /**
+     * 保存订单记录
+     *
+     * @param userOrderPayment
+     */
+    void save(UserOrderPayment userOrderPayment);
+
+    void saveOrUpdate(UserOrderPayment userOrderPayment);
+}

+ 186 - 1
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/OmsPortalOrderServiceImpl.java

@@ -2,7 +2,11 @@ package com.yonge.cooleshow.portal.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollUtil;
+import com.alibaba.fastjson.JSONObject;
 import com.github.pagehelper.PageHelper;
+import com.yonge.cooleshow.common.exception.BizException;
+import com.yonge.cooleshow.enums.OrderStatusEnum;
+import com.yonge.cooleshow.enums.PayStatusEnum;
 import com.yonge.cooleshow.mall.common.api.CommonPage;
 import com.yonge.cooleshow.mall.common.exception.Asserts;
 import com.yonge.cooleshow.mall.common.service.RedisService;
@@ -14,15 +18,23 @@ import com.yonge.cooleshow.portal.dao.PortalOrderItemDao;
 import com.yonge.cooleshow.portal.dao.SmsCouponHistoryDao;
 import com.yonge.cooleshow.portal.domain.*;
 import com.yonge.cooleshow.portal.service.*;
+import com.yonge.cooleshow.sdk.PaymentSdk;
+import com.yonge.cooleshow.sdk.req.OrderPayReq;
+import com.yonge.cooleshow.sdk.res.OrderPayRes;
+import com.yonge.cooleshow.service.PaymentService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.function.Consumer;
 import java.util.stream.Collectors;
 
 /**
@@ -31,6 +43,8 @@ import java.util.stream.Collectors;
  */
 @Service
 public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
+
+    private static final Logger log = LoggerFactory.getLogger(OmsPortalOrderService.class);
     @Autowired
     private UmsMemberService memberService;
     @Autowired
@@ -64,6 +78,15 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
     @Autowired
     private CancelOrderSender cancelOrderSender;
 
+    @Autowired
+    private UserOrderPaymentService userOrderPaymentService;
+
+    @Autowired
+    private PaymentService adapayPaymentService;
+
+    @Autowired
+    private PaymentSdk paymentSdk;
+
     @Override
     public ConfirmOrderResult generateConfirmOrder(List<Long> cartIds) {
         ConfirmOrderResult result = new ConfirmOrderResult();
@@ -288,7 +311,10 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
     public void cancelOrder(Long orderId) {
         //查询未付款的取消订单
         OmsOrderExample example = new OmsOrderExample();
-        example.createCriteria().andIdEqualTo(orderId).andStatusEqualTo(0).andDeleteStatusEqualTo(0);
+        List<Integer> list = new ArrayList<>();
+        list.add(0);
+        list.add(6);
+        example.createCriteria().andIdEqualTo(orderId).andStatusIn(list).andDeleteStatusEqualTo(0);
         List<OmsOrder> cancelOrderList = orderMapper.selectByExample(example);
         if (CollectionUtils.isEmpty(cancelOrderList)) {
             return;
@@ -313,6 +339,14 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
                 memberService.updateIntegration(cancelOrder.getMemberId(), member.getIntegration() + cancelOrder.getUseIntegration());
             }
         }
+
+        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNo(cancelOrder.getOrderSn());
+        if (null != orderPayment) {
+            //更新付款单
+            orderPayment.setStatus(OrderStatusEnum.FAIL.getCode());
+            orderPayment.setPayFailMsg("交易取消");
+            userOrderPaymentService.saveOrUpdate(orderPayment);
+        }
     }
 
     @Override
@@ -395,6 +429,25 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         return orderDetail;
     }
 
+    public OmsOrderDetail detail(String orderSn) {
+        OmsOrderExample orderExample = new OmsOrderExample();
+        orderExample.createCriteria().andOrderSnEqualTo(orderSn);
+        List<OmsOrder> omsOrders = orderMapper.selectByExample(orderExample);
+        if (CollUtil.isEmpty(omsOrders)) {
+            throw new BizException("订单信息错误");
+        } else if (omsOrders.size() != 1) {
+            throw new BizException("订单号重复");
+        }
+        OmsOrder omsOrder = omsOrders.get(0);
+        OmsOrderItemExample example = new OmsOrderItemExample();
+        example.createCriteria().andOrderIdEqualTo(omsOrder.getId());
+        List<OmsOrderItem> orderItemList = orderItemMapper.selectByExample(example);
+        OmsOrderDetail orderDetail = new OmsOrderDetail();
+        BeanUtil.copyProperties(omsOrder,orderDetail);
+        orderDetail.setOrderItemList(orderItemList);
+        return orderDetail;
+    }
+
     @Override
     public void deleteOrder(Long orderId) {
         UmsMember member = memberService.getCurrentMember();
@@ -410,6 +463,138 @@ public class OmsPortalOrderServiceImpl implements OmsPortalOrderService {
         }
     }
 
+    @Override
+    @Transactional
+    public OrderPayRes orderPay(OrderPayReq payReq) {
+        OrderPayRes orderPayRes = new OrderPayRes();
+        OmsOrderDetail detail = detail(payReq.getOrderNo());
+        if (detail == null) {
+            orderPayRes.setStatus(false);
+            orderPayRes.setMessage("订单不存在");
+            return orderPayRes;
+        }
+        UserOrderPayment userOrderPayment = userOrderPaymentService.getByOrderNo(detail.getOrderSn());
+        payReq.orderStatus(detail.getStatus());
+        payReq.setOrderNo(detail.getOrderSn());
+        payReq.setOrderPrice(detail.getPayAmount());
+        payReq.setGoodTitle("");
+        payReq.setGoodDesc("");
+        if (userOrderPayment != null) {
+            payReq.setPayInfo(userOrderPayment.getPayInfo());
+        }
+        // 支付中的返回拉起信息
+        orderPayRes = adapayPaymentService.orderPay(payReq);
+        // 订单状态没变直接返回
+        if (payReq.getOrderStatus().getCode().equals(orderPayRes.getOrderStatus().getCode())) {
+            return orderPayRes;
+        }
+        // 订单状态变了, 改支付状态 和订单支付表
+        OmsOrder omsOrder = new OmsOrder();
+        omsOrder.setId(detail.getId());
+        if (orderPayRes.getOrderStatus().getCode().equals(OrderStatusEnum.PAYING.getCode())) {
+            omsOrder.setStatus(6);
+        }else {
+            omsOrder.setStatus(7);
+        }
+        orderMapper.updateByPrimaryKey(omsOrder);
+
+        // 保存订单支付表
+        if (userOrderPayment == null) {
+            userOrderPayment = new UserOrderPayment();
+        }
+        userOrderPayment.setOrderNo(orderPayRes.getOrderNo());
+        userOrderPayment.setPayChannel(orderPayRes.getPayChannel());
+        userOrderPayment.setTransNo(orderPayRes.getTransNo());
+        userOrderPayment.setPayAmt(new BigDecimal(orderPayRes.getPay_amt()));
+        userOrderPayment.setPayInfo(orderPayRes.getPay_info());
+        userOrderPayment.setStatus(orderPayRes.getOrderStatus().getCode());
+        userOrderPayment.setPayFailMsg(orderPayRes.getMessage());
+        userOrderPayment.setCreateTime(new Date());
+        userOrderPayment.setUpdateTime(new Date());
+        userOrderPaymentService.saveOrUpdate(userOrderPayment);
+
+        return orderPayRes;
+    }
+
+    @Override
+    public void orderCallback(String data) {
+        JSONObject hfRes = JSONObject.parseObject(data);
+        if (PayStatusEnum.succeeded.getCode().equals(hfRes.getString("status"))) {
+            //订单完成
+            OmsOrderDetail orderDetail = detail(hfRes.getString("order_no"));
+            if (null == orderDetail) {
+                log.error("汇付支付回调,订单未找到。 req is {}", data);
+                return;
+            }
+            if (orderDetail.getStatus() == 0
+                    && orderDetail.getStatus() == 6
+                    && orderDetail.getStatus() == 7) {
+                orderSuccess(orderDetail, hfRes);
+            } else {
+                log.error("汇付支付回调,订单状态异常。 req is {}", data);
+            }
+        }
+    }
+    /***
+     * 处理支付中订单
+     * @author liweifan
+     * @param: userOrder
+     * @updateTime 2022/4/13 16:51
+     */
+    @Transactional(rollbackFor = Exception.class)
+    void payingOrderHandle(OmsOrder userOrder) {
+        //判断汇付订单状态
+        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNo(userOrder.getOrderSn());
+        if (null == orderPayment) {
+            return;
+        }
+        try {
+            Map<String, Object> resMap = paymentSdk.queryPayment(orderPayment.getTransNo());
+            //支付失败
+            if (PayStatusEnum.failed.getCode().equals(resMap.get("status").toString())) {
+                cancelOrder(userOrder.getId());
+            }
+            //支付成功
+            if (PayStatusEnum.succeeded.getCode().equals(resMap.get("status").toString())) {
+                orderSuccess(userOrder,null);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("轮询处理支付中订单异常,异常参数: {}", JSONObject.toJSONString(userOrder));
+        }
+    }
+
+    /**
+     * 订单完成
+     *
+     * @author liweifan
+     * @param: detail
+     * @updateTime 2022/4/13 17:17
+     */
+    @Transactional(rollbackFor = Exception.class)
+    void orderSuccess(OmsOrder detail, JSONObject hfRes) {
+        //更新付款单
+        UserOrderPayment orderPayment = userOrderPaymentService.getByOrderNo(detail.getOrderSn());
+        if (orderPayment.getPayChannel().equals("alipay")) {
+            paySuccess(detail.getId(),1);
+        } else if (orderPayment.getPayChannel().equals("wx_lite")) {
+            paySuccess(detail.getId(),2);
+        }
+        orderPayment.setStatus(OrderStatusEnum.PAID.getCode());
+        orderPayment.setArrivalTime(new Date());
+        if (null != hfRes) {
+            try {
+                orderPayment.setPayAmt(new BigDecimal(hfRes.getString("pay_amt")));
+                orderPayment.setFeeAmt(new BigDecimal(hfRes.getString("fee_amt")));
+            } catch (Exception e) {
+                e.printStackTrace();
+                log.error("完成订单,付款单金额格式化失败,参数{}", hfRes.toJSONString());
+            }
+        }
+        userOrderPaymentService.saveOrUpdate(orderPayment);
+    }
+
+
     /**
      * 生成18位订单编号:8位日期+2位平台号码+2位支付方式+6位以上自增id
      */

+ 38 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/service/impl/UserOrderPaymentServiceImpl.java

@@ -0,0 +1,38 @@
+package com.yonge.cooleshow.portal.service.impl;
+
+import com.yonge.cooleshow.mbg.mapper.UserOrderPaymentMapper;
+import com.yonge.cooleshow.mbg.model.UserOrderPayment;
+import com.yonge.cooleshow.portal.service.UserOrderPaymentService;
+import org.springframework.stereotype.Service;
+
+/**
+ * Description
+ *
+ * @author liujunchi
+ * @date 2022-04-24
+ */
+@Service
+public class UserOrderPaymentServiceImpl implements UserOrderPaymentService {
+
+    @Override
+    private UserOrderPaymentMapper userOrderPaymentMapper;
+
+    @Override
+    public UserOrderPayment getByOrderNo(String orderNo) {
+        return userOrderPaymentMapper.selectByOrderNo(orderNo);
+    }
+
+    @Override
+    public void save(UserOrderPayment userOrderPayment) {
+        userOrderPaymentMapper.insert(userOrderPayment);
+    }
+
+    @Override
+    public void saveOrUpdate(UserOrderPayment userOrderPayment) {
+        if (userOrderPayment.getId() == null) {
+            userOrderPaymentMapper.insert(userOrderPayment);
+        } else {
+            userOrderPaymentMapper.updateByPrimaryKeySelective(userOrderPayment);
+        }
+    }
+}

+ 116 - 0
cooleshow-mall/mall-portal/src/main/java/com/yonge/cooleshow/portal/util/DistributedLock.java

@@ -0,0 +1,116 @@
+package com.yonge.cooleshow.portal.util;
+
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Objects;
+import java.util.concurrent.*;
+
+/**
+ * 分布式竞争锁
+ *
+ * @author hgw
+ */
+public class DistributedLock {
+    private final static Logger log = LoggerFactory.getLogger(DistributedLock.class);
+
+    private final RedissonClient redissonClient;
+
+    private static final long DEFAULT_TIMEOUT = 60L;// key过期时间默认1分钟后
+
+    private static final TimeUnit DEFAULT_TIME_UNIT = TimeUnit.SECONDS;//默认过期时间单位-秒钟
+
+    private DistributedLock(RedissonClient redissonClient) {
+        this.redissonClient = redissonClient;
+    }
+
+    public static DistributedLock of(RedissonClient redissonClient) {
+        return new DistributedLock(redissonClient);
+    }
+
+    /**
+     * 分布式锁-默认锁60秒
+     *
+     * @param lockName lockKey
+     * @param runnable 任务
+     * @return true 锁成功  false 锁失败
+     */
+    public boolean runIfLockCanGet(final String lockName, Runnable runnable) {
+        return runIfLockCanGet(lockName, runnable, DEFAULT_TIMEOUT, DEFAULT_TIME_UNIT);
+    }
+
+    /**
+     * 分布式锁
+     *
+     * @param lockName lockKey
+     * @param runnable 任务
+     * @param timeout  超时时间
+     * @param unit     超时时间单位
+     * @return true 锁成功  false 锁失败
+     */
+    public boolean runIfLockCanGet(final String lockName, Runnable runnable, final long timeout, TimeUnit unit) {
+        RLock lock = redissonClient.getLock(lockName);
+        if (Objects.isNull(lock)) {
+            log.info("runIfLockCanGet lock is null lockName : {}", lockName);
+            return false;
+        }
+        try {
+            if (lock.tryLock(0, timeout, unit)) {
+                if (Objects.nonNull(runnable)) {
+                    runnable.run();
+                }
+                return true;
+            } else {
+                return false;
+            }
+        } catch (Exception e) {
+            log.error("runIfLockCanGet error lockName : {}", lockName, e);
+            throw new RuntimeException("runIfLockCanGet error lockName :" + lockName, e);
+        } finally {
+            unlock(lock);
+        }
+    }
+
+    /**
+     * 分布式锁-异步
+     *
+     * @param lockName lockKey
+     * @param callable 任务
+     * @param timeout  超时时间
+     * @param unit     超时时间单位
+     * @return Future 异步任务
+     */
+    public <T> Future<T> callIfLockCanGet(final String lockName, Callable<T> callable, final long timeout, TimeUnit unit) {
+        RLock lock = redissonClient.getLock(lockName);
+        if (Objects.isNull(lock)) {
+            log.info("callIfLockCanGet lock is null lockName : {}", lockName);
+            return null;
+        }
+        ExecutorService executor = Executors.newCachedThreadPool();
+        try {
+            if (lock.tryLock(0, timeout, unit)) {
+                return executor.submit(callable);
+            } else {
+                return null;
+            }
+        } catch (Exception e) {
+            log.error("callIfLockCanGet error lockKey {}", lockName);
+            throw new RuntimeException("任务执行异常");
+        } finally {
+            executor.shutdown();
+            unlock(lock);
+        }
+    }
+
+    /**
+     * 解锁
+     */
+    public void unlock(RLock lock) {
+        if (lock.getHoldCount() != 0) {
+            lock.unlock();
+        }
+    }
+
+}

+ 1 - 0
cooleshow-mall/pom.xml

@@ -90,5 +90,6 @@
         <module>mall-admin</module>
         <module>mall-common</module>
         <module>mall-portal</module>
+        <module>mall-pay</module>
     </modules>
 </project>

+ 5 - 0
pom.xml

@@ -106,6 +106,11 @@
 				<artifactId>mall-common</artifactId>
 				<version>1.0</version>
 			</dependency>
+			<dependency>
+				<groupId>com.yonge.cooleshow</groupId>
+				<artifactId>mall-pay</artifactId>
+				<version>1.0</version>
+			</dependency>
 			<!--mall中MBG生成模块-->
 			<dependency>
 				<groupId>com.yonge.cooleshow</groupId>