瀏覽代碼

呵呵支付

plf 4 年之前
父節點
當前提交
04b140132a

+ 21 - 3
src/main/java/com/caimei/controller/PayOrderApi.java

@@ -37,15 +37,21 @@ public class PayOrderApi {
     @Value("${caimei.notifyUrl}")
     private String notifyUrl;
 
-    @Value("${caimei.redirectLink}")
-    private String redirectLink;
-
     @Value("${wx.AppId}")
     private String appId;
 
     @Value("${wx.AppSecret}")
     private String appSecret;
 
+    /**
+     * 获取线上支付开关状态
+     */
+    @ApiOperation("获取线上支付开关状态")
+    @GetMapping("/onLineSwitch")
+    public ResponseJson<Integer> onLineSwitch() {
+        return payOrderService.getPayOnLineSwitch();
+    }
+
     /**
      * 微信线上支付
      */
@@ -133,4 +139,16 @@ public class PayOrderApi {
         }
         return payOrderService.findOrderStatus(mbOrderId);
     }
+
+    /**
+     * 延时分账异步通知回调
+     */
+    @GetMapping("/delayedSplittingCallback")
+    public String delayedSplittingCallback(String data) {
+        log.info("延时分账异步通知>>>>>>>start");
+        if (StringUtils.isBlank(data)) {
+            return "回调参数失败";
+        }
+        return payOrderService.delayedSplittingCallback(data);
+    }
 }

+ 104 - 0
src/main/java/com/caimei/mapper/PayOrderMapper.java

@@ -1,10 +1,13 @@
 package com.caimei.mapper;
 
 import com.caimei.model.po.CmDiscernReceiptPo;
+import com.caimei.model.po.CmPayShopPo;
+import com.caimei.model.po.CmPayShopRecordPo;
 import com.caimei.model.po.CmReceiptOrderRelationPo;
 import com.caimei.model.vo.DiscernReceiptVo;
 import com.caimei.model.vo.OrderProductVo;
 import com.caimei.model.vo.OrderVo;
+import com.caimei.model.vo.SplitAccountVo;
 import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
@@ -19,6 +22,13 @@ import java.util.List;
  */
 @Mapper
 public interface PayOrderMapper {
+    /**
+     * 获取线上支付开关状态
+     *
+     * @return
+     */
+    Integer getPayOnLineSwitch();
+
     /**
      * 查询支付记录
      *
@@ -55,4 +65,98 @@ public interface PayOrderMapper {
      * @return
      */
     List<OrderProductVo> findAllOrderProduct(Integer orderId);
+
+    /**
+     * 查询未分账已支付收款
+     *
+     * @param currentTime 延迟时间
+     * @return
+     */
+    List<CmReceiptOrderRelationPo> findUnallocatedAccount(String currentTime);
+
+    /**
+     * 保存分账信息
+     *
+     * @param splitAccount
+     */
+    void insertSplitAccount(SplitAccountVo splitAccount);
+
+    /**
+     * 查询已支付金额
+     *
+     * @param orderProductId
+     * @return
+     */
+    BigDecimal findPaidAmount(Integer orderProductId);
+
+    /**
+     * 查询子商户商编
+     *
+     * @param shopId
+     * @return
+     */
+    String findCommercialCode(Long shopId);
+
+    /**
+     * 查询已支付运费
+     *
+     * @param orderId
+     * @param shopId
+     * @return
+     */
+    BigDecimal findShipping(@Param("orderId") Integer orderId, @Param("shopId") Integer shopId);
+
+    /**
+     * 修改收款分账状态
+     *
+     * @param mbOrderId
+     */
+    void updateBySplitStatus(String mbOrderId);
+
+    /**
+     * 查询分账信息
+     *
+     * @param mbOrderId 米花平台交易流水号
+     * @return
+     */
+    List<SplitAccountVo> findByMbOrderId(String mbOrderId);
+
+    /**
+     * 查询已付供应商金额
+     *
+     * @param shopOrderId
+     * @return
+     */
+    BigDecimal findPaidShop(Integer shopOrderId);
+
+    /**
+     * 修改子订单付款状态及付款金额
+     *
+     * @param shopOrderId
+     * @param paidShop
+     * @param payStatus
+     */
+    void updateShopOrderByPayStatus(@Param("shopOrderId") Integer shopOrderId, @Param("paidShop") BigDecimal paidShop, @Param("payStatus") String payStatus);
+
+    /**
+     * 保存付款单
+     *
+     * @param payShop
+     */
+    void insertPayShop(CmPayShopPo payShop);
+
+    /**
+     * 保存付款记录
+     *
+     * @param shopRecord
+     */
+    void insertPayShopRecord(CmPayShopRecordPo shopRecord);
+
+    /**
+     * 修改主订单付款状态
+     *
+     * @param orderId
+     * @param payStatus
+     */
+    void updateOrderByPayStatus(@Param("orderId") Integer orderId, @Param("payStatus") String payStatus);
 }

+ 127 - 0
src/main/java/com/caimei/model/po/CmPayShopPo.java

@@ -0,0 +1,127 @@
+package com.caimei.model.po;
+
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * cm_pay_shop
+ * @author 
+ */
+@Data
+public class CmPayShopPo implements Serializable {
+    private Long id;
+
+    /**
+     * 供应商Id
+     */
+    private Integer shopID;
+
+    /**
+     * 付款单名称
+     */
+    private String name;
+
+    /**
+     * 付款账号的户名
+     */
+    private String bankAccountName;
+
+    /**
+     * 付款账号
+     */
+    private String bankAccount;
+
+    /**
+     * 付款账号的开户行
+     */
+    private String bankName;
+
+    /**
+     *  付款账号的类型 0公账, 1私账
+     */
+    private String type;
+
+    /**
+     * 付供应商总金额
+     */
+    private BigDecimal totalAmount;
+
+    /**
+     * 余额支付
+     */
+    private BigDecimal balancePayFee;
+
+    /**
+     * 转账支付
+     */
+    private BigDecimal transferPayFee;
+
+    /**
+     * 付款方式 1建设银行7297, 2中信银行0897, 3中信银行7172, 4广发银行0115, 5广发银行5461, 6线上分账
+     */
+    private String payType;
+
+    /**
+     * 付款抹平金额(总)
+     */
+    private BigDecimal 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 String status;
+
+    /**
+     * 审核不通过原因
+     */
+    private String reason;
+
+    /**
+     * 删除标记 0 否,其余是
+     */
+    private String delFlag;
+
+    private static final long serialVersionUID = 1L;
+}

+ 79 - 0
src/main/java/com/caimei/model/vo/SplitAccountVo.java

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

+ 19 - 0
src/main/java/com/caimei/service/PayOrderService.java

@@ -11,6 +11,12 @@ import com.caimei.model.dto.PaymentDto;
  * @date : 2020/5/9
  */
 public interface PayOrderService {
+    /**
+     * 获取线上支付开关状态
+     *
+     * @return
+     */
+    ResponseJson<Integer> getPayOnLineSwitch();
 
     /**
      * 线上支付
@@ -41,4 +47,17 @@ public interface PayOrderService {
      * @return
      */
     ResponseJson<JSONObject> findOrderStatus(String mbOrderId);
+
+    /**
+     * 延时分账
+     */
+    void delayedSplitting();
+
+    /**
+     * 分账异步通知
+     *
+     * @param data
+     * @return
+     */
+    String delayedSplittingCallback(String data);
 }

+ 372 - 19
src/main/java/com/caimei/service/impl/PayOrderServiceImpl.java

@@ -1,26 +1,29 @@
 package com.caimei.service.impl;
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.caimei.mapper.OrderMapper;
 import com.caimei.mapper.PayOrderMapper;
 import com.caimei.model.ResponseJson;
 import com.caimei.model.dto.PaymentDto;
 import com.caimei.model.po.CmDiscernReceiptPo;
+import com.caimei.model.po.CmPayShopPo;
+import com.caimei.model.po.CmPayShopRecordPo;
 import com.caimei.model.po.CmReceiptOrderRelationPo;
-import com.caimei.model.vo.DiscernReceiptVo;
-import com.caimei.model.vo.OrderVo;
+import com.caimei.model.vo.*;
 import com.caimei.service.PayOrderService;
 import com.caimei.util.MathUtil;
 import com.caimei.util.PayUtils;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.List;
+import java.util.*;
 
 /**
  * Description
@@ -36,22 +39,48 @@ public class PayOrderServiceImpl implements PayOrderService {
     @Resource
     private OrderMapper orderMapper;
 
+    @Value("${caimei.delayedSplittingUrl}")
+    private String delayedSplittingUrl;
+
     /**
      * 商户标识
      */
-    String merAccount = "aa9aee6a148843a6a9e4ea117df4454b";
+    String merAccount = "150a5459416b4046b9153c1cd442e397";
     /**
      * 私钥,商户密钥
      */
-    String merKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAM0qCTZFdi1I59/Jeis+8KVhzSNhsRrKiOlHazIVyxNLzUQvFpWN5PlfVKlnJToorURTStfjAv01HD0Z4ZvMauuHhDT0bptiDln928Ld6SzX889X2nsCxl0Q+WzrkFsnT6gotvGnTeQGUgbBV3SQD3IUOwRwxoWYbrZqxtqHFxqRAgMBAAECgYEAvsHx9MMbAToDVmEXtXP8/lh0Cwy/RgDA0d30voni2pslTNtXbVCUcIUBy8y6oVvG1nt3YEmTsuiZy/nvehPT6GV1Gqj8T6lqWQ8KQKsDGlubvh23tzNM90me2TLZEPdNqC5CPRrwYrjght4BXgzu7s2+5FpeYCob1gVNi+w0Jz0CQQD0dXb9Oez+Ybnxb3rCghGWM6cxi8fsqk6MuKaleg53qfXrkgAVH78faeWzRaeSbVOh5+Z9kX5HUeynfM7E/f4nAkEA1tmnvJp4JQaouO1Trzbnkhowjea5daK/tDE8K0hIMHUjAw+c1QTteGOVGBFBHWPkUwkSCd2HKmk4URkp/snMhwJAO32+qF+Jclq8EqqLmHxo5UHKxX7793d2yD5Dp++tR6fgBiUwyfNA4tc1pEwmPLdIbBVwfUyEC70/N39jHoOlbwI/dX6SPJI9IgKCQp+HJEriWQP5iaCjy7E1JVXHkeP1lop4mzPukJAhTbUn1AGbmncGZmKPetWrFYZ1ReR9EtlJAkEA2kBmARWyOTt8fbikImuHr65M+BDgD+2fkuDb5+tqJljNmSqAIRRwcXj1Je6vkzlDJuSw3wlG6iliFtwe0cq7+w==";
+    String merKey = "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIggpVq2S1JLH0szxurEgVTz4JTpoyO6/YreVP3xl2bcVj8ekVU+GBwLXNhokxOavgY116XxScinFPa/VoWhaVzyLTbvKz5B6yytuRc3OkSqdDj83jCk+mpmJ5UuCRQ3jesaZAxRpPLzLc99sPtD7xnzEd9UWG8Hlnm6ATmmEQhDAgMBAAECgYBPX+nLGRyWYaNfsFM+tVJMfN/pNMqhnPkWLkoUwPhtS/EmYOaRc+GPCLkcnu2Tstk2udKCuk0xqOs6bZs/1DygxzifYUltWFpqQ2gfmDMoOL4GOflXEHIpoSzSinXz8rjjlQU0wgkbNn6wV6Ao4Jxm5Rzmr9mvTKrAwsnY2eZnYQJBAP+Gj3rrJ7s5778jCramS7yLei2ljkHa/7P0MQsJ+B02/V5CFCh6qKZ2aaAQdk6Z7og5f641TrKX76QetDItSgsCQQCIYVdOdkC3+P6r7WYKXEJ8fdIrf2xyhcCAt9I4q+rcID+ZQ+UqzPoBuib/xpgBZVukDpj9BbIyObyStkvQsNWpAkBd6ADQ5pz6ZKdkMiecym6pAwVKwz4Nm8M/Si2/5dEGQ5BH1Lb9zV4vlvLofURNTKrp61+uES8z2TybryEAE77TAkAD8YSbwTGX4DxE7mVf8VD+1oiIN3QET7fEQQx0FQyCdvA/10W+GhU0jZRpGu30RGEE+mMUFeEUMLUyLNE+ZI6ZAkEA2t0rz4UpljOPms3yfxvzFnShBdshFZOy8kZRG/+OL9entaSOJ0gDmfeFBE9oWXwTj8aVasgbrBV1HjNfyb8WfA==";
     /**
      * 公钥
      */
-    String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDNKgk2RXYtSOffyXorPvClYc0jYbEayojpR2syFcsTS81ELxaVjeT5X1SpZyU6KK1EU0rX4wL9NRw9GeGbzGrrh4Q09G6bYg5Z/dvC3eks1/PPV9p7AsZdEPls65BbJ0+oKLbxp03kBlIGwVd0kA9yFDsEcMaFmG62asbahxcakQIDAQAB";
+    String publicKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCIIKVatktSSx9LM8bqxIFU8+CU6aMjuv2K3lT98Zdm3FY/HpFVPhgcC1zYaJMTmr4GNdel8UnIpxT2v1aFoWlc8i027ys+QessrbkXNzpEqnQ4/N4wpPpqZieVLgkUN43rGmQMUaTy8y3PfbD7Q+8Z8xHfVFhvB5Z5ugE5phEIQwIDAQAB";
     /**
      * 用户编号
      */
-    String merNo = "10001720";
+    String merNo = "10002106";
+    /**
+     * 公账-专票,子商户商编
+     */
+    String publicAccountNo = "20001793";
+    /**
+     * 公账-普票,子商户商编
+     */
+    String commonInvoiceNo = "20001754";
+    /**
+     * 私账-无票,子商户商编
+     */
+    String privateAccountNo = "20001924";
+
+    /**
+     * 获取线上支付开关状态
+     *
+     * @return
+     */
+    @Override
+    public ResponseJson<Integer> getPayOnLineSwitch() {
+        Integer status = payOrderMapper.getPayOnLineSwitch();
+        return ResponseJson.success(status);
+    }
 
     @Override
     public synchronized ResponseJson<JSONObject> pay(PaymentDto payment) {
@@ -102,8 +131,7 @@ public class PayOrderServiceImpl implements PayOrderService {
     /**
      * 设置第三方支付参数
      */
-    private JSONObject getPayParameter(PaymentDto payment, long time) throws Exception {
-        String userType = "ENTERPRISE";
+    private JSONObject getPayParameter(PaymentDto payment, long time) {
         JSONObject json = new JSONObject();
         json.put("merAccount", merAccount);
         json.put("merNo", merNo);
@@ -115,11 +143,10 @@ public class PayOrderServiceImpl implements PayOrderService {
         json.put("userIp", payment.getClientIp());
         json.put("returnUrl", payment.getReturnUrl());
         json.put("notifyUrl", payment.getNotifyUrl());
-        if (null != payment.getBankCode()) {
+        if (StringUtils.isNotBlank(payment.getBankCode())) {
             json.put("bankCode", payment.getBankCode());
         }
-        json.put("userType", userType);
-        if (null != payment.getOrderId()) {
+        if (StringUtils.isNotBlank(payment.getOpenid())) {
             json.put("openId", payment.getOpenid());
         }
         return json;
@@ -203,12 +230,6 @@ public class PayOrderServiceImpl implements PayOrderService {
         //更新付款次数
         order.setPaySuccessCounter(order.getPaySuccessCounter() + 1);
         payOrderMapper.updateSelective(order);
-        /*//修改支付链接状态
-        OrderPayLinkVo orderPayLink = payOrderMapper.findOrderPayLink(order.getOrderId(), amount);
-        if (null != orderPayLink && ("12".equals(payType) || "17".equals(payType))) {
-            orderPayLink.setPayStatus("1");
-            payOrderMapper.updateOrderPayLink(orderPayLink);
-        }*/
         //保存收款记录
         String curDateStr = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(new Date());
         CmDiscernReceiptPo discernReceipt = new CmDiscernReceiptPo();
@@ -300,4 +321,336 @@ public class PayOrderServiceImpl implements PayOrderService {
         }
         return ResponseJson.success(result);
     }
+
+    @Override
+    public void delayedSplitting() {
+        log.info("延时分账,每一小时执行一次");
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(new Date());
+        calendar.add(Calendar.DAY_OF_MONTH, -1);
+        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+        String currentTime = format.format(calendar.getTime());
+        List<CmReceiptOrderRelationPo> orderRelations = payOrderMapper.findUnallocatedAccount(currentTime);
+        if (orderRelations != null && orderRelations.size() > 0) {
+            for (CmReceiptOrderRelationPo orderRelation : orderRelations) {
+                log.info("订单id" + orderRelation.getOrderID() + ">>>进入延时分账");
+                OrderVo order = orderMapper.findOrder(orderRelation.getOrderID());
+                PaymentDto payment = new PaymentDto();
+                payment.setPayAmount(MathUtil.mul(orderRelation.getAssociateAmount(), 100).intValue());
+                List<SplitAccountVo> splitBillDetail = splitBillDetail(order, payment);
+                String parameters = ledgerParameters(splitBillDetail, order.getOrderId());
+                log.info("分账参数: " + parameters);
+
+                //第三方分账接口
+                JSONObject result = null;
+                try {
+                    // 时间戳
+                    long time = System.currentTimeMillis() / 1000;
+                    JSONObject json = new JSONObject();
+                    json.put("merAccount", merAccount);
+                    json.put("orderId", orderRelation.getOrderRequestNo());
+                    json.put("requestNo", orderRelation.getOrderRequestNo());
+                    json.put("mbOrderId", orderRelation.getMbOrderId());
+                    json.put("time", time);
+                    json.put("splitBillDetail", parameters);
+                    json.put("notifyUrl", delayedSplittingUrl);
+                    log.info("回调接口>>>" + delayedSplittingUrl);
+                    String sign = PayUtils.buildSign(json, merKey);
+                    json.put("sign", sign);
+                    String data = PayUtils.buildDataPrivate(json, merKey);
+                    result = PayUtils.httpGet("https://platform.mhxxkj.com/paygateway/mbpay/splitOrder/v1", merAccount, data);
+                } catch (Exception e) {
+                    log.error("错误信息", e);
+                }
+                if (result != null) {
+                    String code = result.getString("code");
+                    if (!"000000".equals(code)) {
+                        String msg = result.getString("msg");
+                        log.info("第三方延迟分账失败>>>>>>>msg:" + msg);
+                    } else {
+                        //保存分账记录
+                        for (SplitAccountVo splitAccount : splitBillDetail) {
+                            splitAccount.setMbOrderId(orderRelation.getMbOrderId());
+                            splitAccount.setOrderRequestNo(orderRelation.getOrderRequestNo());
+                            splitAccount.setPayStatus("1");
+                            payOrderMapper.insertSplitAccount(splitAccount);
+                        }
+                        log.info("此订单分账结束");
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public String delayedSplittingCallback(String data) {
+        try {
+            //公钥解密
+            JSONObject json = PayUtils.decryptDataPublic(data, publicKey);
+            log.info("公钥解密>>>>>>" + json);
+            //公钥验签
+            String signaa = json.getString("sign");
+            json.remove("sign");
+            String signbb = PayUtils.buildSign(json, 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);
+
+            Integer orderId = null;
+            List<SplitAccountVo> splitAccountList = payOrderMapper.findByMbOrderId(mbOrderId);
+            if (splitAccountList != null && splitAccountList.size() > 0) {
+                Integer shopOrderId = null;
+                String shopOrderNo = "";
+                for (SplitAccountVo account : splitAccountList) {
+                    log.info("保存应付付供应商>>>>" + account.getShopId());
+                    //本次付供应商金额(分账金额)
+                    BigDecimal splitAmount = account.getSplitAccount();
+                    orderId = account.getOrderId();
+                    Integer shopId = account.getShopId();
+                    List<ShopOrderVo> shopOrderList = orderMapper.findAllShopOrder(orderId);
+                    String payStatus = "";
+                    for (ShopOrderVo shopOrder : shopOrderList) {
+                        if (shopId.equals(shopOrder.getShopId())) {
+                            shopOrderId = shopOrder.getShopOrderId();
+                            shopOrderNo = shopOrder.getShopOrderNo();
+                            //已付供应商金额
+                            BigDecimal paidAmount = payOrderMapper.findPaidShop(shopOrderId);
+                            BigDecimal paidShop = MathUtil.add(paidAmount, splitAmount);
+                            if (MathUtil.compare(shopOrder.getShouldPayShopAmount(), paidShop) == 0) {
+                                payStatus = "3";
+                            } else {
+                                payStatus = "2";
+                            }
+                            //修改子订单付款状态及付款金额
+                            payOrderMapper.updateShopOrderByPayStatus(shopOrderId, paidShop, payStatus);
+                        }
+                    }
+
+                    SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+                    String currentTime = format.format(new Date());
+                    //保存付供应商记录
+                    CmPayShopPo payShop = new CmPayShopPo();
+                    payShop.setShopID(shopId);
+                    payShop.setName("线上支付分账");
+                    payShop.setTotalAmount(splitAmount);
+                    payShop.setWipePayment(BigDecimal.ZERO);
+                    payShop.setPayType("6");
+                    payShop.setStatus("1");
+                    payShop.setDelFlag("0");
+                    payShop.setApplyTime(currentTime);
+                    payShop.setReviewTime(currentTime);
+                    payShop.setPayTime(currentTime);
+                    payOrderMapper.insertPayShop(payShop);
+
+                    CmPayShopRecordPo shopRecord = new CmPayShopRecordPo();
+                    shopRecord.setShopID(shopId);
+                    shopRecord.setShopOrderID(shopOrderId);
+                    shopRecord.setShopOrderNo(shopOrderNo);
+                    shopRecord.setPayAmount(splitAmount);
+                    shopRecord.setWipePayment(BigDecimal.ZERO);
+                    shopRecord.setPayType("6");
+                    shopRecord.setPayTime(currentTime);
+                    shopRecord.setPayShopID(payShop.getId().intValue());
+                    shopRecord.setStatus("1");
+                    shopRecord.setDelFlag("0");
+                    payOrderMapper.insertPayShopRecord(shopRecord);
+                }
+
+                //修改主订单付款状态
+                List<ShopOrderVo> shopOrderList = orderMapper.findAllShopOrder(orderId);
+                //子订单是否全部付款
+                boolean isPay = true;
+                for (ShopOrderVo shopOrder : shopOrderList) {
+                    if (!"3".equals(shopOrder.getPayStatus())) {
+                        isPay = false;
+                    }
+                }
+                if (isPay) {
+                    payOrderMapper.updateOrderByPayStatus(orderId, "3");
+                } else {
+                    payOrderMapper.updateOrderByPayStatus(orderId, "2");
+                }
+            }
+        } catch (Exception e) {
+            log.error("分账异步通知异常", e);
+            return "分账失败";
+        }
+        return "SUCCESS";
+    }
+
+    /**
+     * 分账详情
+     */
+    private List<SplitAccountVo> splitBillDetail(OrderVo order, PaymentDto payment) {
+        List<SplitAccountVo> list = new ArrayList<>();
+        //本次支付金额,单位/元
+        BigDecimal payAmount = MathUtil.div(payment.getPayAmount(), 100);
+        //待分账总金额
+        BigDecimal splitAmount = payAmount;
+        //总手续费
+        BigDecimal procedureFee = BigDecimal.ZERO;
+        //手续费
+        procedureFee = MathUtil.mul(payAmount, 0.0038, 2);
+        if (MathUtil.compare(procedureFee, 0) == 0) {
+            procedureFee = new BigDecimal("0.01");
+        }
+        splitAmount = MathUtil.sub(splitAmount, procedureFee);
+        List<OrderProductVo> orderProductList = payOrderMapper.findAllOrderProduct(order.getOrderId());
+        for (OrderProductVo orderProduct : orderProductList) {
+            BigDecimal costPrice = MathUtil.mul(orderProduct.getCostPrice(), orderProduct.getNum());
+            //不含税能开发票
+            if ("0".equals(orderProduct.getIncludedTax()) && !"3".equals(orderProduct.getInvoiceType())) {
+                //应付总税费
+                BigDecimal payableTax = MathUtil.mul(orderProduct.getSingleShouldPayTotalTax(), orderProduct.getNum());
+                costPrice = MathUtil.add(costPrice, payableTax);
+            }
+            //判断是否支付过
+            BigDecimal paidAmount = payOrderMapper.findPaidAmount(orderProduct.getOrderProductId());
+            if (paidAmount == null || MathUtil.compare(paidAmount, costPrice) < 0) {
+                if (paidAmount != null && MathUtil.compare(paidAmount, 0) > 0) {
+                    costPrice = MathUtil.sub(costPrice, paidAmount);
+                }
+                //待分账金额>=本次待分账金额
+                if (MathUtil.compare(splitAmount, costPrice) > -1) {
+                    splitAmount = MathUtil.sub(splitAmount, costPrice);
+                } else {
+                    costPrice = splitAmount;
+                    splitAmount = BigDecimal.ZERO;
+                }
+                String commercialCode = payOrderMapper.findCommercialCode(orderProduct.getShopId());
+                SplitAccountVo splitAccount = new SplitAccountVo();
+                splitAccount.setOrderId(order.getOrderId());
+                splitAccount.setOrderProductId(orderProduct.getOrderProductId());
+                splitAccount.setShopId(orderProduct.getShopId().intValue());
+                splitAccount.setSplitAccount(costPrice);
+                splitAccount.setProductType("1");
+                if (StringUtils.isNotBlank(commercialCode)) {
+                    //供应商拥有子商户号
+                    splitAccount.setType("4");
+                    splitAccount.setSubUserNo(commercialCode);
+                } else {
+                    if ("3".equals(orderProduct.getInvoiceType())) {
+                        //不能开票,则分账到私账-无票
+                        splitAccount.setType("2");
+                        splitAccount.setSubUserNo(privateAccountNo);
+                    } else if ("1".equals(orderProduct.getInvoiceType())) {
+                        //开增值税发票,则分账到公账-专票
+                        splitAccount.setType("1");
+                        splitAccount.setSubUserNo(publicAccountNo);
+                    } else if ("2".equals(orderProduct.getInvoiceType())) {
+                        //开普通发票,则分账到公账-普票
+                        splitAccount.setType("3");
+                        splitAccount.setSubUserNo(commonInvoiceNo);
+                    }
+                }
+                list.add(splitAccount);
+                if (MathUtil.compare(splitAmount, 0) == 0) {
+                    break;
+                }
+            }
+        }
+
+        //付供应商运费,是以供应商为单位的
+        if (MathUtil.compare(splitAmount, 0) > 0) {
+            List<ShopOrderVo> shopOrderList = orderMapper.findAllShopOrder(order.getOrderId());
+            for (ShopOrderVo shopOrder : shopOrderList) {
+                //运费
+                BigDecimal shopPostFee = shopOrder.getShopPostFee();
+                if (MathUtil.compare(shopPostFee, 0) > 0) {
+                    BigDecimal shipping = payOrderMapper.findShipping(order.getOrderId(), shopOrder.getShopId());
+                    shopPostFee = MathUtil.sub(shopPostFee, shipping);
+                    if (MathUtil.compare(splitAmount, shopPostFee) > -1) {
+                        splitAmount = MathUtil.sub(splitAmount, shipping);
+                    } else {
+                        shopPostFee = splitAmount;
+                        splitAmount = BigDecimal.ZERO;
+                    }
+                    String commercialCode = payOrderMapper.findCommercialCode(Long.valueOf(shopOrder.getShopId()));
+                    SplitAccountVo splitAccount = new SplitAccountVo();
+                    splitAccount.setOrderId(order.getOrderId());
+                    splitAccount.setShopId(shopOrder.getShopId());
+                    splitAccount.setSplitAccount(shopPostFee);
+                    splitAccount.setProductType("2");
+                    if (StringUtils.isNotBlank(commercialCode)) {
+                        //供应商拥有子商户号
+                        splitAccount.setType("4");
+                        splitAccount.setSubUserNo(commercialCode);
+                    } else {
+                        //私账
+                        splitAccount.setType("2");
+                        splitAccount.setSubUserNo(privateAccountNo);
+                    }
+                    list.add(splitAccount);
+                }
+            }
+        }
+
+        //佣金,公账
+        if (MathUtil.compare(splitAmount, 0) > 0) {
+            SplitAccountVo splitAccount = new SplitAccountVo();
+            splitAccount.setOrderId(order.getOrderId());
+            splitAccount.setSplitAccount(splitAmount);
+            splitAccount.setProductType("3");
+            splitAccount.setType("1");
+            splitAccount.setSubUserNo(publicAccountNo);
+            list.add(splitAccount);
+        }
+        return list;
+    }
+
+    /**
+     * 整理第三方支付详情参数
+     */
+    private String ledgerParameters(List<SplitAccountVo> splitBillDetail, Integer orderId) {
+        List<Map<String, String>> maps = new ArrayList<>();
+        List<ShopOrderVo> shopOrderList = orderMapper.findAllShopOrder(orderId);
+        //供应商子商户总金额
+        for (ShopOrderVo shopOrder : shopOrderList) {
+            BigDecimal shopTotalAmount = BigDecimal.ZERO;
+            String subUserNo = "";
+            for (SplitAccountVo account : splitBillDetail) {
+                if ("4".equals(account.getType()) && shopOrder.getShopId().equals(account.getShopId())) {
+                    shopTotalAmount = MathUtil.add(shopTotalAmount, account.getSplitAccount());
+                    subUserNo = account.getSubUserNo();
+                }
+            }
+            addMaps(maps, shopTotalAmount, subUserNo);
+        }
+        //公账-专票总金额,私账-无票总金额,公账-普票总金额
+        BigDecimal totalAmount1 = BigDecimal.ZERO;
+        BigDecimal totalAmount2 = BigDecimal.ZERO;
+        BigDecimal totalAmount3 = BigDecimal.ZERO;
+        for (SplitAccountVo account : splitBillDetail) {
+            if ("1".equals(account.getType())) {
+                totalAmount1 = MathUtil.add(totalAmount1, account.getSplitAccount());
+            } else if ("2".equals(account.getType())) {
+                totalAmount2 = MathUtil.add(totalAmount2, account.getSplitAccount());
+            } else if ("3".equals(account.getType())) {
+                totalAmount3 = MathUtil.add(totalAmount3, account.getSplitAccount());
+            }
+        }
+        addMaps(maps, totalAmount1, publicAccountNo);
+        addMaps(maps, totalAmount2, privateAccountNo);
+        addMaps(maps, totalAmount3, commonInvoiceNo);
+        return JSON.toJSONString(maps);
+    }
+
+    private void addMaps(List<Map<String, String>> maps, BigDecimal shopTotalAmount, String subUserNo) {
+        if (MathUtil.compare(shopTotalAmount, 0) > 0) {
+            Map<String, String> map = new HashMap<>(3);
+            map.put("subUserNo", subUserNo);
+            map.put("splitBillType", "2");
+            map.put("splitBillValue", MathUtil.mul(shopTotalAmount, 100).toString());
+            maps.add(map);
+        }
+    }
 }

+ 31 - 0
src/main/java/com/caimei/task/SplitAccountTask.java

@@ -0,0 +1,31 @@
+package com.caimei.task;
+
+import com.caimei.service.PayOrderService;
+import org.springframework.scheduling.annotation.EnableScheduling;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.Resource;
+
+/**
+ * Description
+ * 延时分账定时器
+ *
+ * @author : plf
+ * @date : 2021/3/3
+ */
+@Component
+@EnableScheduling
+public class SplitAccountTask {
+    @Resource
+    private PayOrderService payOrderService;
+
+    /**
+     * 延时分账,每一小时执行一次
+     */
+    @Scheduled(cron = "0 0 * * * ?")
+    //@Scheduled(cron = "0 */1 * * * ?")
+    public void delayedSplitting() {
+        payOrderService.delayedSplitting();
+    }
+}

+ 4 - 2
src/main/resources/config/beta/application-beta.yml

@@ -43,8 +43,10 @@ wx:
 caimei:
   oldapi: https://www-b.caimei365.com
   #支付异步回调地址
-  notifyUrl: https://spi-b.caimei365.com/PayOrder/paymentCallback
+  notifyUrl: https://mall2c-b.caimei365.com/PayOrder/paymentCallback
   #支付链接重定向地址
-  redirectLink: https://spi-b.caimei365.com/PayOrder/jumpPage
+  redirectLink: https://mall2c-b.caimei365.com/PayOrder/jumpPage
   #微服务网关地址
   userUrl: https://core-b.caimei365.com
+  #延时分账异步回调地址
+  delayedSplittingUrl: https://mall2c-b.caimei365.com/PayOrder/delayedSplittingCallback

+ 5 - 3
src/main/resources/config/dev/application-dev.yml

@@ -42,8 +42,10 @@ wx:
 caimei:
   oldapi: http://localhost:8100
   #支付异步回调地址
-  notifyUrl: https://spi-b.caimei365.com/PayOrder/paymentCallback
+  notifyUrl: https://mall2c-b.caimei365.com/PayOrder/paymentCallback
   #支付链接重定向地址
-  redirectLink: https://spi-b.caimei365.com/PayOrder/jumpPage
+  redirectLink: https://mall2c-b.caimei365.com/PayOrder/jumpPage
   #微服务网关地址
-  userUrl: http://localhost:18002
+  userUrl: http://localhost:18002
+  #延时分账异步回调地址
+  delayedSplittingUrl: https://mall2c-b.caimei365.com/PayOrder/delayedSplittingCallback

+ 4 - 2
src/main/resources/config/prod/application-prod.yml

@@ -44,8 +44,10 @@ wx:
 caimei:
   oldapi: https://www.caimei365.com
   #支付异步回调地址
-  notifyUrl: https://spi.caimei365.com/PayOrder/paymentCallback
+  notifyUrl: https://mall2c.caimei365.com/PayOrder/paymentCallback
   #支付链接重定向地址
-  redirectLink: https://spi.caimei365.com/PayOrder/jumpPage
+  redirectLink: https://mall2c.caimei365.com/PayOrder/jumpPage
   #微服务网关地址
   userUrl: https://core.caimei365.com
+  #延时分账异步回调地址
+  delayedSplittingUrl: https://mall2c.caimei365.com/PayOrder/delayedSplittingCallback

+ 1 - 0
src/main/resources/mapper/OrderMapper.xml

@@ -88,6 +88,7 @@
         cso.itemCount,
         cso.totalAmount,
         cso.note,
+        cso.shopPostFee,
         s.name AS shopName,
         s.logo AS shopLogo
         FROM

+ 175 - 138
src/main/resources/mapper/PayOrderMapper.xml

@@ -3,6 +3,10 @@
         PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.caimei.mapper.PayOrderMapper">
+    <select id="getPayOnLineSwitch" resultType="java.lang.Integer">
+        select status from cm_pay_online_switch where id=1
+    </select>
+
     <select id="getDiscernReceipt" resultType="com.caimei.model.vo.DiscernReceiptVo">
         SELECT
           cdr.*,
@@ -29,44 +33,20 @@
     <update id="updateSelective">
         update cm_order
         <set>
-            <if test="orderNo != null">
-                orderNo = #{orderNo,jdbcType=VARCHAR},
-            </if>
-            <if test="userID != null">
-                userID = #{userID,jdbcType=BIGINT},
-            </if>
-            <if test="buyUserID != null">
-                buyUserID = #{buyUserID,jdbcType=INTEGER},
-            </if>
-            <if test="shopOrderIDs != null">
-                shopOrderIDs = #{shopOrderIDs,jdbcType=VARCHAR},
-            </if>
-            <if test="orderSubmitType != null">
-                orderSubmitType = #{orderSubmitType,jdbcType=INTEGER},
-            </if>
-            <if test="orderType != null">
-                orderType = #{orderType,jdbcType=INTEGER},
-            </if>
-            <if test="hasActProduct != null">
-                hasActProduct = #{hasActProduct,jdbcType=CHAR},
-            </if>
-            <if test="autoCloseTimeMills != null">
-                autoCloseTimeMills = #{autoCloseTimeMills,jdbcType=DECIMAL},
-            </if>
             <if test="status != null">
-                `status` = #{status,jdbcType=CHAR},
+                `status` = #{status},
             </if>
             <if test="receiptStatus != null">
-                receiptStatus = #{receiptStatus,jdbcType=CHAR},
+                receiptStatus = #{receiptStatus},
             </if>
             <if test="payStatus != null">
-                payStatus = #{payStatus,jdbcType=CHAR},
+                payStatus = #{payStatus},
             </if>
             <if test="sendOutStatus != null">
-                sendOutStatus = #{sendOutStatus,jdbcType=CHAR},
+                sendOutStatus = #{sendOutStatus},
             </if>
             <if test="refundType != null">
-                refundType = #{refundType,jdbcType=CHAR},
+                refundType = #{refundType},
             </if>
             <if test="paySuccessCounter != null">
                 paySuccessCounter = #{paySuccessCounter},
@@ -75,115 +55,7 @@
                 payFlag = #{payFlag,jdbcType=CHAR},
             </if>
             <if test="onlinePayFlag != null">
-                onlinePayFlag = #{onlinePayFlag,jdbcType=CHAR},
-            </if>
-            <if test="productTotalFee != null">
-                productTotalFee = #{productTotalFee,jdbcType=DECIMAL},
-            </if>
-            <if test="orderTotalFee != null">
-                orderTotalFee = #{orderTotalFee,jdbcType=DECIMAL},
-            </if>
-            <if test="payTotalFee != null">
-                payTotalFee = #{payTotalFee,jdbcType=DECIMAL},
-            </if>
-            <if test="payableAmount != null">
-                payableAmount = #{payableAmount,jdbcType=DECIMAL},
-            </if>
-            <if test="balancePayFee != null">
-                balancePayFee = #{balancePayFee,jdbcType=DECIMAL},
-            </if>
-            <if test="preferential != null">
-                preferential = #{preferential,jdbcType=DECIMAL},
-            </if>
-            <if test="discountFee != null">
-                discountFee = #{discountFee,jdbcType=DECIMAL},
-            </if>
-            <if test="spID != null">
-                spID = #{spID,jdbcType=BIGINT},
-            </if>
-            <if test="mainSpID != null">
-                mainSpID = #{mainSpID,jdbcType=BIGINT},
-            </if>
-            <if test="note != null">
-                note = #{note,jdbcType=VARCHAR},
-            </if>
-            <if test="clubID != null">
-                clubID = #{clubID,jdbcType=BIGINT},
-            </if>
-            <if test="clubScanTime != null">
-                clubScanTime = #{clubScanTime,jdbcType=VARCHAR},
-            </if>
-            <if test="payWay != null">
-                payWay = #{payWay,jdbcType=VARCHAR},
-            </if>
-            <if test="orderSource != null">
-                orderSource = #{orderSource,jdbcType=CHAR},
-            </if>
-            <if test="closeTime != null">
-                closeTime = #{closeTime,jdbcType=VARCHAR},
-            </if>
-            <if test="confirmTime != null">
-                confirmTime = #{confirmTime,jdbcType=VARCHAR},
-            </if>
-            <if test="payTime != null">
-                payTime = #{payTime,jdbcType=VARCHAR},
-            </if>
-            <if test="orderTime != null">
-                orderTime = #{orderTime,jdbcType=VARCHAR},
-            </if>
-            <if test="productCount != null">
-                productCount = #{productCount,jdbcType=INTEGER},
-            </if>
-            <if test="presentCount != null">
-                presentCount = #{presentCount,jdbcType=INTEGER},
-            </if>
-            <if test="cooFreeFlag != null">
-                cooFreeFlag = #{cooFreeFlag,jdbcType=CHAR},
-            </if>
-            <if test="cooFreeRate != null">
-                cooFreeRate = #{cooFreeRate,jdbcType=INTEGER},
-            </if>
-            <if test="cooFreeAmount != null">
-                cooFreeAmount = #{cooFreeAmount,jdbcType=DECIMAL},
-            </if>
-            <if test="invoiceFlag != null">
-                invoiceFlag = #{invoiceFlag,jdbcType=CHAR},
-            </if>
-            <if test="confirmFlag != null">
-                confirmFlag = #{confirmFlag,jdbcType=CHAR},
-            </if>
-            <if test="clauseID != null">
-                clauseID = #{clauseID,jdbcType=BIGINT},
-            </if>
-            <if test="clauseContent != null">
-                clauseContent = #{clauseContent,jdbcType=VARCHAR},
-            </if>
-            <if test="clauseName != null">
-                clauseName = #{clauseName,jdbcType=VARCHAR},
-            </if>
-            <if test="updateDate != null">
-                updateDate = #{updateDate,jdbcType=VARCHAR},
-            </if>
-            <if test="freePostFlag != null">
-                freePostFlag = #{freePostFlag,jdbcType=CHAR},
-            </if>
-            <if test="freight != null">
-                freight = #{freight,jdbcType=DECIMAL},
-            </if>
-            <if test="delFlag != null">
-                delFlag = #{delFlag,jdbcType=CHAR},
-            </if>
-            <if test="freePostageTicketID != null">
-                freePostageTicketID = #{freePostageTicketID,jdbcType=INTEGER},
-            </if>
-            <if test="splitFlag != null">
-                splitFlag = #{splitFlag,jdbcType=CHAR},
-            </if>
-            <if test="closeReason != null">
-                closeReason = #{closeReason,jdbcType=VARCHAR},
-            </if>
-            <if test="postageOrderFlag != null">
-                postageOrderFlag = #{postageOrderFlag,jdbcType=CHAR},
+                onlinePayFlag = #{onlinePayFlag},
             </if>
         </set>
         where orderID = #{orderID,jdbcType=BIGINT}
@@ -275,4 +147,169 @@
           shopID ASC,
           productID ASC
     </select>
+
+    <select id="findUnallocatedAccount" resultType="com.caimei.model.po.CmReceiptOrderRelationPo">
+        SELECT
+          cror.id,
+          cror.relationType,
+          cror.receiptID,
+          cror.orderID,
+          cror.mbOrderId,
+          cror.orderRequestNo,
+          cror.splitStatus,
+          cror.associateAmount
+        FROM
+          cm_receipt_order_relation cror
+          LEFT JOIN cm_discern_receipt cdr ON cror.receiptID = cdr.id
+          LEFT JOIN cm_order co ON cror.orderID = co.orderID
+        WHERE
+          cror.relationType = 2
+          AND cdr.payWay = 1
+          AND cror.delFlag = 0
+          AND cror.mbOrderId IS NOT NULL
+          AND cror.splitStatus = 0
+          AND cdr.receiptDate <![CDATA[  <=  ]]> #{currentTime}
+          AND co.orderType = 2
+    </select>
+
+    <insert id="insertSplitAccount" keyColumn="id" keyProperty="id" parameterType="com.caimei.model.vo.SplitAccountVo" useGeneratedKeys="true">
+        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>
+
+    <select id="findPaidAmount" resultType="java.math.BigDecimal">
+        SELECT
+          SUM(splitAccount)
+        FROM
+          cm_split_account
+        WHERE
+          orderProductId = #{orderProductId}
+          AND payStatus = 1
+          AND productType = 1
+    </select>
+
+    <select id="findCommercialCode" resultType="string">
+        SELECT commercialCode FROM shop WHERE shopID = #{shopId}
+    </select>
+
+    <select id="findShipping" resultType="java.math.BigDecimal">
+        SELECT
+          SUM(splitAccount)
+        FROM
+          cm_split_account
+        WHERE
+          orderId = #{orderId}
+          AND shopId = #{shopId}
+          AND productType = 2
+          AND payStatus = 1
+    </select>
+
+    <update id="updateBySplitStatus">
+        UPDATE cm_receipt_order_relation SET splitStatus = 1 WHERE mbOrderId = #{mbOrderId}
+    </update>
+
+    <select id="findByMbOrderId" resultType="com.caimei.model.vo.SplitAccountVo">
+        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="findPaidShop" resultType="java.math.BigDecimal">
+        SELECT
+          SUM(payAmount)
+        FROM
+          cm_pay_shop_record
+        WHERE
+          STATUS = 1
+          AND delFlag = 0
+          AND shopOrderID = #{shopOrderId}
+    </select>
+
+    <update id="updateShopOrderByPayStatus">
+        UPDATE
+          cm_shop_order
+        SET
+          payStatus = #{payStatus},
+          payedShopAmount = #{paidShop}
+        WHERE
+          shopOrderID = #{shopOrderId}
+    </update>
+
+    <insert id="insertPayShop" useGeneratedKeys="true" keyProperty="id" keyColumn="id" parameterType="com.caimei.model.po.CmPayShopPo">
+        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="updateOrderByPayStatus">
+        UPDATE
+          cm_order
+        SET
+          payStatus = #{payStatus}
+        WHERE
+          orderID = #{orderId}
+    </update>
 </mapper>