Explorar o código

二手发布支付 及 延时分账

chao %!s(int64=3) %!d(string=hai) anos
pai
achega
78e32237bc

+ 89 - 3
src/main/java/com/caimei365/order/controller/PayOrderApi.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.caimei365.order.model.ResponseJson;
 import com.caimei365.order.model.ResponseJson;
 import com.caimei365.order.model.dto.PayDto;
 import com.caimei365.order.model.dto.PayDto;
 import com.caimei365.order.model.dto.PayLinkDto;
 import com.caimei365.order.model.dto.PayLinkDto;
+import com.caimei365.order.model.dto.SecondPayDto;
 import com.caimei365.order.service.PayOrderService;
 import com.caimei365.order.service.PayOrderService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiImplicitParam;
 import io.swagger.annotations.ApiImplicitParam;
@@ -19,12 +20,12 @@ import java.security.spec.InvalidKeySpecException;
 import java.util.Map;
 import java.util.Map;
 
 
 /**
 /**
- * 支付API
+ * 订单支付API
  *
  *
  * @author : Charles
  * @author : Charles
  * @date : 2021/7/29
  * @date : 2021/7/29
  */
  */
-@Api(tags="支付API")
+@Api(tags="订单支付API")
 @RestController
 @RestController
 @RequiredArgsConstructor
 @RequiredArgsConstructor
 @RequestMapping("/order/pay")
 @RequestMapping("/order/pay")
@@ -246,10 +247,95 @@ public class PayOrderApi {
         return payOrderService.getPayOrderResult(mbOrderId);
         return payOrderService.getPayOrderResult(mbOrderId);
     }
     }
 
 
+    /**
+     * 二手发布微信线上支付
+     * @param secondPayDto {
+     *               productId      二手发布商品id
+     *               returnUrl     页面回调地址
+     *               code          微信小程序code
+     *               state         微信公众号state参数
+     * }
+     */
+    @ApiOperation("二手发布微信线上支付(旧:/PayOrder/appletsSecondHandPay)(/PayOrder/secondHandPay[WEIXIN])")
+    @PostMapping("/second/wechat")
+    public ResponseJson<JSONObject> paySecondByWeChat(SecondPayDto secondPayDto, @RequestHeader HttpHeaders headers){
+        if (null == secondPayDto.getProductId()) {
+            return ResponseJson.error("二手商品Id不能为空!", null);
+        }
+        if (StringUtils.isEmpty(secondPayDto.getCode())) {
+            return ResponseJson.error("微信code不能为空!", null);
+        }
+        return payOrderService.paySecondByWeChat(secondPayDto, headers);
+    }
 
 
+    /**
+     * 二手发布支付宝线上支付
+     * @param secondPayDto {
+     *               productId      二手发布商品id
+     *               returnUrl     页面回调地址
+     * }
+     */
+    @ApiOperation("二手发布支付宝线上支付(旧:/PayOrder/secondHandPay[ALIPAY])")
+    @PostMapping("/second/alipay")
+    public ResponseJson<JSONObject> paySecondByAlipay(SecondPayDto secondPayDto, @RequestHeader HttpHeaders headers){
+        if (null == secondPayDto.getProductId()) {
+            return ResponseJson.error("二手商品Id不能为空!", null);
+        }
+        if (StringUtils.isEmpty(secondPayDto.getReturnUrl())) {
+            return ResponseJson.error("回调地址不能为空!", null);
+        }
+        return payOrderService.paySecondByAlipay(secondPayDto, headers);
+    }
 
 
+    /**
+     * 二手发布银联线上支付
+     * @param secondPayDto {
+     *               productId       二手发布商品id
+     *               returnUrl     页面回调地址
+     *               bankCode      银行编码(银联支付使用)
+     *               userType      用户类型(银联支付使用)企业:ENTERPRISE,个人:USER
+     * }
+     */
+    @ApiOperation("二手发布银联线上支付(旧:/PayOrder/secondHandPay[UNIONPAY])")
+    @PostMapping("/second/union")
+    public ResponseJson<JSONObject> paySecondByUnionPay(SecondPayDto secondPayDto, @RequestHeader HttpHeaders headers){
+        if (null == secondPayDto.getProductId()) {
+            return ResponseJson.error("二手商品Id不能为空!", null);
+        }
+        if (StringUtils.isEmpty(secondPayDto.getReturnUrl())) {
+            return ResponseJson.error("回调地址不能为空!", null);
+        }
+        if (StringUtils.isEmpty(secondPayDto.getBankCode())) {
+            return ResponseJson.error("银行编码不能为空!", null);
+        }
+        if (StringUtils.isEmpty(secondPayDto.getUserType())) {
+            return ResponseJson.error("银行用户类型不能为空!", null);
+        }
+        return payOrderService.paySecondByUnionPay(secondPayDto, headers);
+    }
 
 
+    /**
+     * 二手发布支付回调
+     */
+    @ApiOperation("二手发布支付回调(旧:/PayOrder/secondHandPayCallBack)")
+    @GetMapping("/second/callback")
+    public String paymentSecondCallback(String data) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        if (StringUtils.isBlank(data)) {
+            return "回调参数失败";
+        }
+        return payOrderService.paymentSecondCallback(data);
+    }
 
 
-
+    /**
+     * 延时分账异步通知回调
+     */
+    @ApiOperation("延时分账异步通知回调(旧:/PayOrder/delayedSplittingCallback)")
+    @GetMapping("/delay/split/callback")
+    public String delayedSplittingCallback(String data) {
+        if (StringUtils.isBlank(data)) {
+            return "回调参数失败";
+        }
+        return payOrderService.delayedSplittingCallback(data);
+    }
 
 
 }
 }

+ 51 - 0
src/main/java/com/caimei365/order/mapper/PayOrderMapper.java

@@ -1,10 +1,15 @@
 package com.caimei365.order.mapper;
 package com.caimei365.order.mapper;
 
 
+import com.caimei365.order.model.po.PayShopPo;
+import com.caimei365.order.model.po.PayShopRecordPo;
+import com.caimei365.order.model.po.SplitAccountPo;
 import com.caimei365.order.model.vo.OrderPayLinkVo;
 import com.caimei365.order.model.vo.OrderPayLinkVo;
 import com.caimei365.order.model.vo.OrderVo;
 import com.caimei365.order.model.vo.OrderVo;
+import com.caimei365.order.model.vo.ShopOrderVo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Mapper;
 
 
 import java.math.BigDecimal;
 import java.math.BigDecimal;
+import java.util.List;
 
 
 /**
 /**
  * Description
  * Description
@@ -73,4 +78,50 @@ public interface PayOrderMapper {
      * @param orderId 订单Id
      * @param orderId 订单Id
      */
      */
     Integer getDbPaySuccessCounter(Integer orderId);
     Integer getDbPaySuccessCounter(Integer orderId);
+    /**
+     * 保存分账详情
+     */
+    void insertSplitAccount(SplitAccountPo splitAccount);
+    /**
+     * 更新二手详情
+     */
+    void updateSeconHandDetail(Integer productId, String payType, double payAmount, String payFormData);
+    /**
+     * 修改分账付款状态
+     */
+    void updateSplitAccountByPay(String mbOrderId);
+    /**
+     * 修改收款分账状态
+     * @param mbOrderId
+     */
+    void updateBySplitStatus(String mbOrderId);
+    /**
+     * 查询分账给子商户号
+     */
+    List<SplitAccountPo> getSplitAccountList(String mbOrderId);
+    /**
+     * 根据订单Id获取子订单列表
+     */
+    List<ShopOrderVo> getShopOrderListByOrderId(Integer orderId);
+    /**
+     * 查询已付供应商金额
+     */
+    Double getPaidShopAmount(Integer shopOrderId);
+    /**
+     * 修改子订单付款状态及付款金额
+     */
+    void updateShopOrderByPayStatus(Integer shopOrderId, Double paidShop, Integer payStatus);
+    /**
+     * 修改主订单付款状态
+     */
+    void updateOrderByPayStatus(Integer orderId, Integer payStatus);
+    /**
+     * 保存付款单表
+     */
+    void insertPayShop(PayShopPo payShop);
+    /**
+     * 保存付供应商记录
+     */
+    void insertPayShopRecord(PayShopRecordPo shopRecord);
+
 }
 }

+ 4 - 0
src/main/java/com/caimei365/order/model/bo/PayParamBo.java

@@ -19,6 +19,10 @@ public class PayParamBo implements Serializable {
      * 订单Id
      * 订单Id
      */
      */
     private Integer orderId;
     private Integer orderId;
+    /**
+     * 二手发布商品id
+     */
+    private Integer productId;
     /**
     /**
      * 支付金额,单位分,必须大于2
      * 支付金额,单位分,必须大于2
      */
      */

+ 47 - 0
src/main/java/com/caimei365/order/model/dto/SecondPayDto.java

@@ -0,0 +1,47 @@
+package com.caimei365.order.model.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/7/30
+ */
+@Data
+public class SecondPayDto {
+    private static final long serialVersionUID = 1L;
+    /**
+     * 二手发布商品id
+     */
+    @ApiModelProperty("二手发布商品id")
+    private Integer productId;
+    /**
+     * 页面回调地址
+     */
+    @ApiModelProperty("页面回调地址")
+    private String returnUrl;
+    /**
+     * 微信小程序code,微信小程序支付使用
+     */
+    @ApiModelProperty("微信小程序code")
+    private String code;
+    /**
+     * 微信公众号state参数
+     */
+    @ApiModelProperty("微信公众号state参数")
+    private String state;
+    /**
+     * 银行编码(银联支付使用)
+     */
+    @ApiModelProperty("银行编码(银联支付使用)")
+    private String bankCode;
+    /**
+     * 用户类型(银联支付使用)
+     * 企业:ENTERPRISE
+     * 个人:USER
+     */
+    @ApiModelProperty("用户类型(银联支付使用)企业:ENTERPRISE,个人:USER")
+    private String userType;
+}

+ 129 - 0
src/main/java/com/caimei365/order/model/po/PayShopPo.java

@@ -0,0 +1,129 @@
+package com.caimei365.order.model.po;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/8/3
+ */
+@Data
+public class PayShopPo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Integer id;
+
+    /**
+     * 供应商Id
+     */
+    private Integer shopId;
+
+    /**
+     * 付款单名称
+     */
+    private String name;
+
+    /**
+     * 付款账号的户名
+     */
+    private String bankAccountName;
+
+    /**
+     * 付款账号
+     */
+    private String bankAccount;
+
+    /**
+     * 付款账号的开户行
+     */
+    private String bankName;
+
+    /**
+     *  付款账号的类型 0公账, 1私账
+     */
+    private Integer type;
+
+    /**
+     * 付供应商总金额
+     */
+    private Double totalAmount;
+
+    /**
+     * 余额支付
+     */
+    private Double balancePayFee;
+
+    /**
+     * 转账支付
+     */
+    private Double transferPayFee;
+
+    /**
+     * 付款方式 1建设银行7297, 2中信银行0897, 3中信银行7172, 4广发银行0115, 5广发银行5461
+     */
+    private Integer payType;
+
+    /**
+     * 付款抹平金额(总)
+     */
+    private Double wipePayment;
+
+    /**
+     * 付款抹平备注(文字)
+     */
+    private String wipeRemarks;
+
+    /**
+     * 付款抹平备注(图片),以"##"隔开
+     */
+    private String wipeRemarkImages;
+
+    /**
+     * 抹平申请时间
+     */
+    private String wipeTime;
+
+    /**
+     * 申请人ID
+     */
+    private Integer applicant;
+
+    /**
+     * 申请时间
+     */
+    private String applyTime;
+
+    /**
+     * 审核人ID
+     */
+    private Integer reviewer;
+
+    /**
+     * 审核时间
+     */
+    private String reviewTime;
+
+    /**
+     * 付款时间
+     */
+    private String payTime;
+
+    /**
+     * 审核状态  0待审核,  1审核通过  2审核不通过
+     */
+    private Integer status;
+
+    /**
+     * 审核不通过原因
+     */
+    private String reason;
+
+    /**
+     * 删除标记 0 否,其余是
+     */
+    private Integer delFlag;
+
+}

+ 58 - 0
src/main/java/com/caimei365/order/model/po/PayShopRecordPo.java

@@ -0,0 +1,58 @@
+package com.caimei365.order.model.po;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/8/3
+ */
+@Data
+public class PayShopRecordPo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Integer id;
+    /**
+     * 供应商Id
+     */
+    private Integer shopId;
+    /**
+     * 子订单ID
+     */
+    private Integer shopOrderId;
+    /**
+     * 子订单编号
+     */
+    private String shopOrderNo;
+    /**
+     * 付款金额
+     */
+    private Double payAmount;
+    /**
+     * 付款抹平金额
+     */
+    private Double wipePayment;
+    /**
+     * 付款方式 1建设银行7297, 2中信银行0897, 3中信银行7172, 4广发银行0115, 5广发银行5461
+     */
+    private Integer payType;
+    /**
+     * 付款时间
+     */
+    private String payTime;
+    /**
+     * 付款单表id
+     */
+    private Integer payShopId;
+    /**
+     * 0待审核, 1审核通过, 2审核不通过
+     */
+    private Integer status;
+    /**
+     * 删除标记 0 否,其余是
+     */
+    private Integer delFlag;
+}

+ 67 - 0
src/main/java/com/caimei365/order/model/po/SplitAccountPo.java

@@ -0,0 +1,67 @@
+package com.caimei365.order.model.po;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * Description
+ *
+ * @author : Charles
+ * @date : 2021/8/3
+ */
+@Data
+public class SplitAccountPo implements Serializable {
+    private static final long serialVersionUID = 1L;
+
+    private Integer id;
+    /**
+     * 主订单id
+     */
+    private Integer orderId;
+    /**
+     * 商品id,仅对二手发布商品
+     */
+    private Integer productId;
+    /**
+     * 订单商品id
+     */
+    private Integer orderProductId;
+    /**
+     * 供应商id
+     */
+    private Integer shopId;
+    /**
+     * 分账类型:1公账-专票,2私账-无票,3公账-普票,4供应商子商户
+     */
+    private Integer type;
+    /**
+     * 子商户商编
+     */
+    private String subUserNo;
+    /**
+     * 分账金额
+     */
+    private Double splitAccount;
+    /**
+     * 米花科技平台唯一流水号
+     */
+    private String mbOrderId;
+    /**
+     * 商户唯一订单请求号(订单编号#随机时间戳)
+     */
+    private String orderRequestNo;
+    /**
+     * 付款状态,0待付,1付款成功
+     */
+    private Integer payStatus;
+    /**
+     * 商品类型:1商品成本,2供应商运费,3佣金,4二手发布
+     */
+    private Integer productType;
+    /**
+     * 分账时间
+     */
+    private Date splitTime;
+}

+ 9 - 1
src/main/java/com/caimei365/order/model/vo/ShopOrderVo.java

@@ -3,6 +3,7 @@ package com.caimei365.order.model.vo;
 import lombok.Data;
 import lombok.Data;
 
 
 import java.io.Serializable;
 import java.io.Serializable;
+import java.math.BigDecimal;
 import java.util.List;
 import java.util.List;
 
 
 /**
 /**
@@ -66,7 +67,14 @@ public class ShopOrderVo implements Serializable {
      * 促销满减优惠(店铺促销)
      * 促销满减优惠(店铺促销)
      */
      */
     private Double promotionFullReduction;
     private Double promotionFullReduction;
-
+    /**
+     * (付款供应商)付款状态:1待付款、2部分付款、3已付款
+     */
+    private Integer payStatus;
+    /**
+     * 已付款金额
+     */
+    private Double payedShopAmount;
     /**
     /**
      * 佣金 =  应付采美
      * 佣金 =  应付采美
      */
      */

+ 38 - 0
src/main/java/com/caimei365/order/service/PayOrderService.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.caimei365.order.model.ResponseJson;
 import com.caimei365.order.model.ResponseJson;
 import com.caimei365.order.model.dto.PayDto;
 import com.caimei365.order.model.dto.PayDto;
 import com.caimei365.order.model.dto.PayLinkDto;
 import com.caimei365.order.model.dto.PayLinkDto;
+import com.caimei365.order.model.dto.SecondPayDto;
 import org.springframework.http.HttpHeaders;
 import org.springframework.http.HttpHeaders;
 
 
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchAlgorithmException;
@@ -100,4 +101,41 @@ public interface PayOrderService {
      * @param mbOrderId 平台唯一流水号
      * @param mbOrderId 平台唯一流水号
      */
      */
     ResponseJson<JSONObject> getPayOrderResult(String mbOrderId);
     ResponseJson<JSONObject> getPayOrderResult(String mbOrderId);
+
+    /**
+     * 二手发布微信线上支付
+     * @param secondPayDto {
+     *               productId      二手发布商品id
+     *               returnUrl     页面回调地址
+     *               code          微信小程序code
+     *               state         微信公众号state参数
+     * }
+     */
+    ResponseJson<JSONObject> paySecondByWeChat(SecondPayDto secondPayDto, HttpHeaders headers);
+    /**
+     * 二手发布支付宝线上支付
+     * @param secondPayDto {
+     *               productId      二手发布商品id
+     *               returnUrl     页面回调地址
+     * }
+     */
+    ResponseJson<JSONObject> paySecondByAlipay(SecondPayDto secondPayDto, HttpHeaders headers);
+    /**
+     * 二手发布银联线上支付
+     * @param secondPayDto {
+     *               productId       二手发布商品id
+     *               returnUrl     页面回调地址
+     *               bankCode      银行编码(银联支付使用)
+     *               userType      用户类型(银联支付使用)企业:ENTERPRISE,个人:USER
+     * }
+     */
+    ResponseJson<JSONObject> paySecondByUnionPay(SecondPayDto secondPayDto, HttpHeaders headers);
+    /**
+     * 二手发布支付回调
+     */
+    String paymentSecondCallback(String data) throws NoSuchAlgorithmException, InvalidKeySpecException;
+    /**
+     * 延时分账异步通知回调
+     */
+    String delayedSplittingCallback(String data);
 }
 }

+ 360 - 15
src/main/java/com/caimei365/order/service/impl/PayOrderServiceImpl.java

@@ -11,14 +11,9 @@ import com.caimei365.order.model.ResponseJson;
 import com.caimei365.order.model.bo.PayParamBo;
 import com.caimei365.order.model.bo.PayParamBo;
 import com.caimei365.order.model.dto.PayDto;
 import com.caimei365.order.model.dto.PayDto;
 import com.caimei365.order.model.dto.PayLinkDto;
 import com.caimei365.order.model.dto.PayLinkDto;
-import com.caimei365.order.model.po.BalanceRecordPo;
-import com.caimei365.order.model.po.DiscernReceiptPo;
-import com.caimei365.order.model.po.OrderReceiptRelationPo;
-import com.caimei365.order.model.po.UserBeansHistoryPo;
-import com.caimei365.order.model.vo.DiscernReceiptVo;
-import com.caimei365.order.model.vo.OrderPayLinkVo;
-import com.caimei365.order.model.vo.OrderProductVo;
-import com.caimei365.order.model.vo.OrderVo;
+import com.caimei365.order.model.dto.SecondPayDto;
+import com.caimei365.order.model.po.*;
+import com.caimei365.order.model.vo.*;
 import com.caimei365.order.service.PayOrderService;
 import com.caimei365.order.service.PayOrderService;
 import com.caimei365.order.service.RemoteCallService;
 import com.caimei365.order.service.RemoteCallService;
 import com.caimei365.order.utils.CodeUtil;
 import com.caimei365.order.utils.CodeUtil;
@@ -36,6 +31,7 @@ import org.springframework.http.HttpHeaders;
 import org.springframework.stereotype.Service;
 import org.springframework.stereotype.Service;
 
 
 import javax.annotation.Resource;
 import javax.annotation.Resource;
+import java.math.BigDecimal;
 import java.security.NoSuchAlgorithmException;
 import java.security.NoSuchAlgorithmException;
 import java.security.spec.InvalidKeySpecException;
 import java.security.spec.InvalidKeySpecException;
 import java.text.SimpleDateFormat;
 import java.text.SimpleDateFormat;
@@ -65,12 +61,14 @@ public class PayOrderServiceImpl implements PayOrderService {
     private WeChatService weChatService;
     private WeChatService weChatService;
     @Resource
     @Resource
     private RemoteCallService remoteCallService;
     private RemoteCallService remoteCallService;
-    @Value("${caimei.notifyUrl}")
-    private String notifyUrl;
     @Value("${caimei.redirectLink}")
     @Value("${caimei.redirectLink}")
     private String redirectLink;
     private String redirectLink;
     @Value("${caimei.linkPage}")
     @Value("${caimei.linkPage}")
     private String linkPage;
     private String linkPage;
+    @Value("${caimei.notifyUrl}")
+    private String notifyUrl;
+    @Value("${caimei.secondHandUrl}")
+    private String secondHandUrl;
 
 
     /**
     /**
      * 订单支付前效验付款规则
      * 订单支付前效验付款规则
@@ -390,6 +388,8 @@ public class PayOrderServiceImpl implements PayOrderService {
         PayParamBo payParam = new PayParamBo();
         PayParamBo payParam = new PayParamBo();
         // payDto -> payParam
         // payDto -> payParam
         BeanUtils.copyProperties(payDto, payParam);
         BeanUtils.copyProperties(payDto, payParam);
+        // 微信线上支付
+        payParam.setPayWay("WEIXIN");
         String openId = null;
         String openId = null;
         if (null == payParam.getState()) {
         if (null == payParam.getState()) {
             // 小程序微信授权获取登录信息
             // 小程序微信授权获取登录信息
@@ -421,7 +421,7 @@ public class PayOrderServiceImpl implements PayOrderService {
         payParam.setOpenId(openId);
         payParam.setOpenId(openId);
         payParam.setNotifyUrl(notifyUrl);
         payParam.setNotifyUrl(notifyUrl);
         log.info("【微信支付】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>获取openId:" + openId);
         log.info("【微信支付】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>获取openId:" + openId);
-        return toPay(payParam, headers);
+        return toPayOrder(payParam, headers);
     }
     }
 
 
     /**
     /**
@@ -444,7 +444,7 @@ public class PayOrderServiceImpl implements PayOrderService {
         payParam.setPayType("ALIPAY_H5");
         payParam.setPayType("ALIPAY_H5");
         payParam.setNotifyUrl(notifyUrl);
         payParam.setNotifyUrl(notifyUrl);
         log.info("【支付宝支付】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>orderId:" + payParam.getOrderId());
         log.info("【支付宝支付】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>orderId:" + payParam.getOrderId());
-        return toPay(payParam, headers);
+        return toPayOrder(payParam, headers);
     }
     }
 
 
     /**
     /**
@@ -469,13 +469,13 @@ public class PayOrderServiceImpl implements PayOrderService {
         payParam.setPayType("GATEWAY_UNIONPAY");
         payParam.setPayType("GATEWAY_UNIONPAY");
         payParam.setNotifyUrl(notifyUrl);
         payParam.setNotifyUrl(notifyUrl);
         log.info("【银联支付】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>orderId:" + payParam.getOrderId());
         log.info("【银联支付】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>orderId:" + payParam.getOrderId());
-        return toPay(payParam, headers);
+        return toPayOrder(payParam, headers);
     }
     }
 
 
     /**
     /**
-     * 线上支付
+     * 订单线上支付
      */
      */
-    private ResponseJson<JSONObject> toPay(PayParamBo payParam, HttpHeaders headers) {
+    private ResponseJson<JSONObject> toPayOrder(PayParamBo payParam, HttpHeaders headers) {
         // 订单信息
         // 订单信息
         OrderVo order = payOrderMapper.getOrderByOrderId(payParam.getOrderId());
         OrderVo order = payOrderMapper.getOrderByOrderId(payParam.getOrderId());
         if (null == order) {
         if (null == order) {
@@ -856,4 +856,349 @@ public class PayOrderServiceImpl implements PayOrderService {
         }
         }
         return ResponseJson.success(result);
         return ResponseJson.success(result);
     }
     }
+
+    /**
+     * 二手发布微信线上支付
+     *
+     * @param secondPayDto {
+     *                     productId      二手发布商品id
+     *                     returnUrl     页面回调地址
+     *                     code          微信小程序code
+     *                     state         微信公众号state参数
+     *                     }
+     * @param headers
+     */
+    @Override
+    public ResponseJson<JSONObject> paySecondByWeChat(SecondPayDto secondPayDto, HttpHeaders headers) {
+        PayParamBo payParam = new PayParamBo();
+        // payDto -> payParam
+        BeanUtils.copyProperties(secondPayDto, payParam);
+        // 微信线上支付
+        payParam.setPayWay("WEIXIN");
+        String openId = null;
+        if (null == payParam.getState()) {
+            // 小程序微信授权获取登录信息
+            ResponseJson<Map<String, Object>> appletsInfo = weChatService.getInfoMapByApplets(payParam.getCode(), headers, 1);
+            if (appletsInfo.getCode() == -1) {
+                return ResponseJson.error(appletsInfo.getMsg(), null);
+            }
+            Map<String, Object> infoData = appletsInfo.getData();
+            openId = (String) infoData.get(WeChatService.Keys.OPEN_ID);
+            if (StringUtils.isEmpty(openId)) {
+                return ResponseJson.error("微信小程序获取openId失败!", null);
+            }
+            //小程序微信快捷支付
+            payParam.setPayType("MINIAPP_WEIXIN");
+        } else {
+            try {
+                // 微信公众号,通过code获取微信用户信息
+                Map<String, Object> map = weChatService.getInfoMapByWeb(payParam.getCode(), "crm");
+                openId = (String) map.get(WeChatService.Keys.OPEN_ID);
+            } catch (Exception e) {
+                log.error("try-catch:",e);
+            }
+            if (StringUtils.isEmpty(openId)) {
+                return ResponseJson.error("微信公众号获取openId失败!", null);
+            }
+            //pc微信扫码支付,微信公众号支付
+            payParam.setPayType("JSAPI_WEIXIN");
+        }
+        payParam.setOpenId(openId);
+        // 二手发布默认100元
+        payParam.setPayAmount(10000);
+        payParam.setNotifyUrl(secondHandUrl);
+        log.info("【二手发布微信支付】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>获取openId:" + openId);
+        return toPaySecond(payParam, headers);
+    }
+
+    /**
+     * 二手发布支付宝线上支付
+     *
+     * @param secondPayDto {
+     *                     productId      二手发布商品id
+     *                     returnUrl     页面回调地址
+     *                     }
+     * @param headers
+     */
+    @Override
+    public ResponseJson<JSONObject> paySecondByAlipay(SecondPayDto secondPayDto, HttpHeaders headers) {
+        PayParamBo payParam = new PayParamBo();
+        // payDto -> payParam
+        BeanUtils.copyProperties(secondPayDto, payParam);
+        //支付宝支付
+        payParam.setPayWay("ALIPAY");
+        payParam.setPayType("ALIPAY_H5");
+        // 二手发布默认100元
+        payParam.setPayAmount(10000);
+        payParam.setNotifyUrl(secondHandUrl);
+        log.info("【二手发布支付宝支付】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>productId:" + payParam.getProductId());
+        return toPaySecond(payParam, headers);
+    }
+
+    /**
+     * 二手发布银联线上支付
+     *
+     * @param secondPayDto {
+     *                     productId       二手发布商品id
+     *                     returnUrl     页面回调地址
+     *                     bankCode      银行编码(银联支付使用)
+     *                     userType      用户类型(银联支付使用)企业:ENTERPRISE,个人:USER
+     *                     }
+     * @param headers
+     */
+    @Override
+    public ResponseJson<JSONObject> paySecondByUnionPay(SecondPayDto secondPayDto, HttpHeaders headers) {
+        PayParamBo payParam = new PayParamBo();
+        // payDto -> payParam
+        BeanUtils.copyProperties(secondPayDto, payParam);
+        //支付宝支付
+        payParam.setPayWay("UNIONPAY");
+        payParam.setPayType("GATEWAY_UNIONPAY");
+        // 二手发布默认100元
+        payParam.setPayAmount(10000);
+        payParam.setNotifyUrl(secondHandUrl);
+        log.info("【二手发布银联支付】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>productId:" + payParam.getProductId());
+        return toPaySecond(payParam, headers);
+    }
+
+    /**
+     * 二手发布支付
+     */
+    private ResponseJson<JSONObject> toPaySecond(PayParamBo payParam, HttpHeaders headers) {
+        // 定义支付请求结果
+        JSONObject result = null;
+        try {
+            // 时间戳
+            long time = System.currentTimeMillis() / 1000;
+            // 用户IP地址
+            String userIp = headers.getFirst("X-CLIENT-IP");
+            JSONObject json = new JSONObject();
+            json.put("merAccount", PayUtil.merAccount);
+            json.put("merNo", PayUtil.merNo);
+            json.put("time", time);
+            //支付金额
+            json.put("amount", payParam.getPayAmount());
+            json.put("payWay", payParam.getPayWay());
+            json.put("payType", payParam.getPayType());
+            json.put("userIp", userIp);
+            json.put("returnUrl", payParam.getReturnUrl());
+            json.put("notifyUrl", payParam.getNotifyUrl());
+            if (StringUtils.isNotBlank(payParam.getBankCode())) {
+                json.put("bankCode", payParam.getBankCode());
+            }
+            if (StringUtils.isNotBlank(payParam.getUserType())) {
+                json.put("userType", payParam.getUserType());
+            }
+            if (StringUtils.isNotBlank(payParam.getOpenId())) {
+                json.put("openId", payParam.getOpenId());
+            }
+            String environment = "";
+            if (payParam.getNotifyUrl().contains("8008")) {
+                environment = "DEV";
+            } else if (payParam.getNotifyUrl().contains("spi-b")) {
+                environment = "BETA";
+            }
+            // 商户订单号
+            String orderId = payParam.getProductId() + "T" + time + environment;
+            json.put("orderId", orderId);
+            //商品名称
+            String product = "采美订单" + payParam.getProductId();
+            json.put("product", product);
+            String attach = payParam.getProductId() + "," + payParam.getPayType();
+            json.put("attach", attach);
+            String sign = PayUtil.getPaySign(json, PayUtil.merKey);
+            json.put("sign", sign);
+            // 二手发布默认100元,默认私账
+            List<Map<String, String>> list = new ArrayList<>();
+            Map<String, String> map = new HashMap<>(3);
+            map.put("subUserNo", PayUtil.privateAccountNo);
+            map.put("splitBillType", "1");
+            map.put("splitBillValue", "1");
+            list.add(map);
+            String splitBillDetail = JSONObject.toJSONString(list);
+            json.put("splitBillDetail", splitBillDetail);
+            // 私钥加密
+            String data = RSAUtil.privateEncrypt(json.toJSONString(), PayUtil.merKey);
+            // 提交
+            result = PayUtil.httpGet("https://platform.mhxxkj.com/paygateway/mbpay/order/v1", PayUtil.merAccount, data);
+        } catch (Exception e) {
+            log.error("错误信息", e);
+            return ResponseJson.error("支付失败!", null);
+        }
+        String code = result.getString("code");
+        if (!"000000".equals(code)) {
+            String msg = result.getString("msg");
+            log.info("第三方支付失败>>>>>>>msg:" + msg);
+            return ResponseJson.error(msg, null);
+        }
+        // 保存二手发布分账参数
+        SplitAccountPo splitAccount = new SplitAccountPo();
+        splitAccount.setOrderId(payParam.getOrderId());
+        splitAccount.setProductId(payParam.getProductId());
+        // 二手交易供应商
+        splitAccount.setShopId(1252);
+        splitAccount.setProductType(4);
+        splitAccount.setType(2);
+        if ("UNIONPAY".equals(payParam.getPayWay())) {
+            splitAccount.setSplitAccount(92.00);
+        } else {
+            splitAccount.setSplitAccount(99.62);
+        }
+        JSONObject data = result.getJSONObject("data");
+        splitAccount.setMbOrderId(data.getString("mbOrderId"));
+        splitAccount.setOrderRequestNo(data.getString("orderId"));
+        splitAccount.setPayStatus(0);
+        // 保存分账详情
+        payOrderMapper.insertSplitAccount(splitAccount);
+
+        return ResponseJson.success(result);
+    }
+
+    /**
+     * 二手发布支付回调
+     *
+     * @param data
+     */
+    @Override
+    public String paymentSecondCallback(String data) throws NoSuchAlgorithmException, InvalidKeySpecException {
+        log.info("******************** 二手发布支付异步回调 start *******************");
+        // 公钥解密
+        JSONObject json = PayUtil.publicKeyDecrypt(data, PayUtil.publicKey);
+        log.info("公钥解密>>>>>>" + json);
+        // 公钥验签
+        String signaa = json.getString("sign");
+        json.remove("sign");
+        String signbb = PayUtil.getPaySign(json, PayUtil.publicKey);
+        if (!signaa.equals(signbb)) {
+            return "验签失败";
+        }
+        // 订单状态
+        String orderStatus = json.getString("orderStatus");
+        // 平台唯一流水号
+        String mbOrderId = json.getString("mbOrderId");
+        // 附加数据,下单时若有传输则原样返回,下单时为空,则不返回该数据
+        String attach = json.getString("attach");
+        // 订单金额,以元为单位
+        BigDecimal amount = json.getBigDecimal("amount");
+        log.info("订单状态>>>>>>" + orderStatus);
+        if ("FAILED".equals(orderStatus)) {
+            return "支付失败";
+        }
+        String[] split = attach.split(",");
+        // 订单id
+        Integer productId = Integer.valueOf(split[0]);
+        // 支付类型
+        String payType = split[1];
+        double payAmount = amount.doubleValue();
+        String payFormData = json.toJSONString();
+        payOrderMapper.updateSeconHandDetail(productId, payType, payAmount, payFormData);
+        //修改分账付款状态
+        payOrderMapper.updateSplitAccountByPay(mbOrderId);
+        return "SUCCESS";
+    }
+
+    /**
+     * 延时分账异步通知回调
+     */
+    @Override
+    public String delayedSplittingCallback(String data) {
+        try {
+            log.info("******************** 延时分账异步通知回调 start *******************");
+            // 公钥解密
+            JSONObject json = PayUtil.publicKeyDecrypt(data, PayUtil.publicKey);
+            log.info("公钥解密>>>>>>" + json);
+            // 公钥验签
+            String signaa = json.getString("sign");
+            json.remove("sign");
+            String signbb = PayUtil.getPaySign(json, PayUtil.publicKey);
+            if (!signaa.equals(signbb)) {
+                return "验签失败";
+            }
+            String mbOrderId = json.getString("mbOrderId");
+            String status = json.getString("status");
+            log.info("【延时分账回调】>>>>>>>>>>分账状态:" + status);
+            if ("FAILED".equals(status)) {
+                return "分账失败";
+            }
+            // 修改收款分账状态
+            payOrderMapper.updateBySplitStatus(mbOrderId);
+
+            List<SplitAccountPo> splitAccountList = payOrderMapper.getSplitAccountList(mbOrderId);
+            if (splitAccountList != null && splitAccountList.size() > 0) {
+                Integer orderId = splitAccountList.get(0).getOrderId();
+                List<ShopOrderVo> shopOrderList = payOrderMapper.getShopOrderListByOrderId(orderId);
+                Integer shopOrderId = null;
+                String shopOrderNo = "";
+                for (SplitAccountPo account : splitAccountList) {
+                    log.info("【延时分账回调】>>>>>>>>>>保存应付付供应商:" + account.getShopId());
+                    // 本次付供应商金额(分账金额)
+                    Double splitAmount = account.getSplitAccount();
+                    orderId = account.getOrderId();
+                    Integer shopId = account.getShopId();
+                    for (ShopOrderVo shopOrder : shopOrderList) {
+                        if (shopId.equals(shopOrder.getShopId())) {
+                            shopOrderId = shopOrder.getShopOrderId();
+                            shopOrderNo = shopOrder.getShopOrderNo();
+                            // 已付供应商金额
+                            Double paidAmount = payOrderMapper.getPaidShopAmount(shopOrderId);
+                            Double paidShop = MathUtil.add(paidAmount, splitAmount).doubleValue();
+                            shopOrder.setPayedShopAmount(paidShop);
+                            if (MathUtil.compare(shopOrder.getShouldPayShopAmount(), paidShop) == 0) {
+                                shopOrder.setPayStatus(3);
+                            } else {
+                                shopOrder.setPayStatus(2);
+                            }
+                            // 修改子订单付款状态及付款金额
+                            payOrderMapper.updateShopOrderByPayStatus(shopOrderId, paidShop, shopOrder.getPayStatus());
+                        }
+                    }
+                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                    String currentTime = format.format(new Date());
+                    // 保存付款单表
+                    PayShopPo payShop = new PayShopPo();
+                    payShop.setShopId(shopId);
+                    payShop.setName("线上支付分账");
+                    payShop.setTotalAmount(splitAmount);
+                    payShop.setWipePayment(0d);
+                    payShop.setPayType(6);
+                    payShop.setStatus(1);
+                    payShop.setDelFlag(0);
+                    payShop.setApplyTime(currentTime);
+                    payShop.setReviewTime(currentTime);
+                    payShop.setPayTime(currentTime);
+                    payOrderMapper.insertPayShop(payShop);
+                    // 保存 付供应商记录
+                    PayShopRecordPo shopRecord = new PayShopRecordPo();
+                    shopRecord.setShopId(shopId);
+                    shopRecord.setShopOrderId(shopOrderId);
+                    shopRecord.setShopOrderNo(shopOrderNo);
+                    shopRecord.setPayAmount(splitAmount);
+                    shopRecord.setWipePayment(0d);
+                    shopRecord.setPayType(6);
+                    shopRecord.setPayTime(currentTime);
+                    shopRecord.setPayShopId(payShop.getId());
+                    shopRecord.setStatus(1);
+                    shopRecord.setDelFlag(0);
+                    payOrderMapper.insertPayShopRecord(shopRecord);
+                }
+                //子订单是否全部付款
+                boolean isPay = true;
+                for (ShopOrderVo shopOrder : shopOrderList) {
+                    if (3 != shopOrder.getPayStatus()) {
+                        isPay = false;
+                    }
+                }
+                // 修改主订单付款状态
+                if (isPay) {
+                    payOrderMapper.updateOrderByPayStatus(orderId, 3);
+                } else {
+                    payOrderMapper.updateOrderByPayStatus(orderId, 2);
+                }
+            }
+        } catch (Exception e) {
+            log.error("【延时分账回调】>>>>>>>>>>分账异步通知异常", e);
+            return "分账失败";
+        }
+        return "SUCCESS";
+    }
 }
 }

+ 93 - 0
src/main/resources/mapper/PayOrderMapper.xml

@@ -33,6 +33,24 @@
         INSERT INTO (orderId, linkLogo, unpaidAmount, generateTime, effectiveTime, payStatus, payType, delFlag)
         INSERT INTO (orderId, linkLogo, unpaidAmount, generateTime, effectiveTime, payStatus, payType, delFlag)
         VALUES (#{orderId}, #{linkLogo}, #{unpaidAmount}, #{generateTime}, #{effectiveTime}, #{payStatus}, #{payType}, #{delFlag})
         VALUES (#{orderId}, #{linkLogo}, #{unpaidAmount}, #{generateTime}, #{effectiveTime}, #{payStatus}, #{payType}, #{delFlag})
     </insert>
     </insert>
+    <insert id="insertSplitAccount" keyColumn="id" keyProperty="id"  parameterType="com.caimei365.order.model.po.SplitAccountPo">
+        INSERT INTO cm_split_account (orderId, productId, orderProductId,shopId, type, subUserNo, splitAccount,
+                                        mbOrderId, orderRequestNo,payStatus, productType, splitTime)
+        VALUES (#{orderId}, #{productId}, #{orderProductId}, #{shopId}, #{type}, #{subUserNo}, #{splitAccount},
+                #{mbOrderId}, #{orderRequestNo}, #{payStatus}, #{productType}, NOW());
+    </insert>
+    <insert id="insertPayShop">
+        INSERT INTO cm_pay_shop (shopID, name, bankAccountName, bankAccount, bankName, type, totalAmount, balancePayFee,
+                                 transferPayFee, payType, wipePayment, wipeRemarks, wipeRemarkImages, wipeTime, applicant,
+                                 applyTime, reviewer, reviewTime, payTime, status, reason, delFlag)
+        VALUES (#{shopId}, #{name}, #{bankAccountName}, #{bankAccount}, #{bankName}, #{type}, #{totalAmount}, #{balancePayFee},
+                #{transferPayFee}, #{payType}, #{wipePayment}, #{wipeRemarks}, #{wipeRemarkImages}, #{wipeTime}, #{applicant},
+                #{applyTime}, #{reviewer}, #{reviewTime}, #{payTime}, #{status}, #{reason}, #{delFlag})
+    </insert>
+    <insert id="insertPayShopRecord">
+        INSERT INTO cm_pay_shop_record (shopID, shopOrderID, shopOrderNo, payAmount, wipePayment, payType, payTime, payShopID, status, delFlag)
+        VALUES (#{shopId}, #{shopOrderId}, #{shopOrderNo}, #{payAmount}, #{wipePayment}, #{payType}, #{payTime}, #{payShopId}, #{status}, #{delFlag})
+    </insert>
     <update id="updateOrderPayLink">
     <update id="updateOrderPayLink">
         UPDATE cm_order_pay_link SET
         UPDATE cm_order_pay_link SET
             orderId = #{orderId}, linkLogo = #{linkLogo}, unpaidAmount = #{unpaidAmount}, generateTime = #{generateTime},
             orderId = #{orderId}, linkLogo = #{linkLogo}, unpaidAmount = #{unpaidAmount}, generateTime = #{generateTime},
@@ -43,6 +61,27 @@
         UPDATE cm_order_pay_link SET payStatus = #{payStatus}
         UPDATE cm_order_pay_link SET payStatus = #{payStatus}
         WHERE id = #{id}
         WHERE id = #{id}
     </update>
     </update>
+    <update id="updateSeconHandDetail">
+        UPDATE cm_second_hand_detail
+        SET payType = #{payType}, payAmount = #{payAmount}, payFormData = #{payFormData}, payStatus = '2',payDate = NOW()
+        WHERE productID = #{productId}
+    </update>
+    <update id="updateSplitAccountByPay">
+        UPDATE cm_split_account SET payStatus = '1' WHERE mbOrderId = #{mbOrderId}
+    </update>
+    <update id="updateBySplitStatus">
+        UPDATE cm_receipt_order_relation SET splitStatus = 1 WHERE mbOrderId = #{mbOrderId}
+    </update>
+    <update id="updateShopOrderByPayStatus">
+        UPDATE cm_shop_order SET
+        payStatus = #{payStatus}, payedShopAmount = #{paidShop}
+        WHERE shopOrderID = #{shopOrderId}
+    </update>
+    <update id="updateOrderByPayStatus">
+        UPDATE cm_order SET
+        payStatus = #{payStatus}
+        WHERE orderID = #{orderId}
+    </update>
     <select id="getPayOnLineSwitch" resultType="java.lang.Integer">
     <select id="getPayOnLineSwitch" resultType="java.lang.Integer">
         SELECT STATUS FROM cm_pay_online_switch WHERE id=1
         SELECT STATUS FROM cm_pay_online_switch WHERE id=1
     </select>
     </select>
@@ -143,5 +182,59 @@
         SELECT paySuccessCounter FROM cm_order
         SELECT paySuccessCounter FROM cm_order
         WHERE orderID = #{orderId} AND delFlag = '0'
         WHERE orderID = #{orderId} AND delFlag = '0'
     </select>
     </select>
+    <select id="getSplitAccountList" resultType="com.caimei365.order.model.po.SplitAccountPo">
+        SELECT
+            orderId,
+            productId,
+            orderProductId,
+            shopId,
+            type,
+            subUserNo,
+            SUM(splitAccount) AS splitAccount,
+            mbOrderId,
+            orderRequestNo,
+            payStatus,
+            productType
+        FROM cm_split_account
+        WHERE type = 4 AND payStatus = 1 AND splitAccount > 0
+        AND mbOrderId = #{mbOrderId}
+        GROUP BY shopId
+    </select>
+    <select id="getShopOrderListByOrderId" resultType="com.caimei365.order.model.vo.ShopOrderVo">
+        SELECT
+            shopOrderNo,
+            orderID AS orderId,
+            orderNo,
+            shopID AS shopId,
+            shopName,
+            note,
+            userID AS userId,
+            clubID AS clubId,
+            spID AS spId,
+            orderPromotionsId,
+            promotionFullReduction,
+            brokerage,
+            canRefundAmount,
+            itemCount,
+            totalAmount,
+            productAmount,
+            needPayAmount,
+            shopProductAmount,
+            shopPostFee,
+            shopTaxFee,
+            shouldPayShopAmount,
+            orderTime,
+            orderSubmitType,
+            payStatus,
+            splitFlag
+        FROM cm_shop_order
+        WHERE cso.delFlag = 0
+        AND orderID = #{orderId}
+    </select>
+    <select id="getPaidShopAmount" resultType="java.lang.Double">
+        SELECT SUM(payAmount)
+        FROM cm_pay_shop_record
+        WHERE STATUS = 1 AND delFlag = 0 AND shopOrderID = #{shopOrderId}
+    </select>
 
 
 </mapper>
 </mapper>