Browse Source

快捷支付

zhijiezhao 2 years ago
parent
commit
88ea052322
22 changed files with 1386 additions and 191 deletions
  1. 5 2
      pom.xml
  2. 18 0
      src/main/java/com/caimei365/order/annotation/FieldDes.java
  3. 18 0
      src/main/java/com/caimei365/order/annotation/FieldEncrypt.java
  4. 19 0
      src/main/java/com/caimei365/order/annotation/SignExclude.java
  5. 90 28
      src/main/java/com/caimei365/order/components/HeliPayUtil.java
  6. 24 15
      src/main/java/com/caimei365/order/constant/Constant.java
  7. 28 9
      src/main/java/com/caimei365/order/controller/HeliPayApi.java
  8. 2 0
      src/main/java/com/caimei365/order/mapper/PayOrderMapper.java
  9. 28 1
      src/main/java/com/caimei365/order/model/dto/HeliDto.java
  10. 4 3
      src/main/java/com/caimei365/order/model/enums/BizType.java
  11. 75 0
      src/main/java/com/caimei365/order/model/vo/FirstQuickPayVo.java
  12. 155 0
      src/main/java/com/caimei365/order/model/vo/QuickPayConfirmPayResponseVo.java
  13. 114 0
      src/main/java/com/caimei365/order/model/vo/QuickPayCreateOrderResponseVo.java
  14. 34 0
      src/main/java/com/caimei365/order/model/vo/QuickPayUserVo.java
  15. 5 0
      src/main/java/com/caimei365/order/service/HeliPayService.java
  16. 55 8
      src/main/java/com/caimei365/order/service/impl/HeliPayServiceImpl.java
  17. 73 0
      src/main/java/com/caimei365/order/utils/helipay/HeliPayCertConfig.java
  18. 81 0
      src/main/java/com/caimei365/order/utils/helipay/HeliPayCertUtils.java
  19. 117 0
      src/main/java/com/caimei365/order/utils/helipay/MessageHandle.java
  20. 94 0
      src/main/java/com/caimei365/order/utils/helipay/SM2Utils.java
  21. 100 0
      src/main/java/com/caimei365/order/utils/helipay/SM4Utils.java
  22. 247 125
      src/main/resources/mapper/PayOrderMapper.xml

+ 5 - 2
pom.xml

@@ -161,8 +161,11 @@
             <version>29.0-jre</version>
         </dependency>
 
-
-
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-crypto</artifactId>
+            <version>5.7.16</version>
+        </dependency>
 
 
 

+ 18 - 0
src/main/java/com/caimei365/order/annotation/FieldDes.java

@@ -0,0 +1,18 @@
+package com.caimei365.order.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Created by heli50 on 2018-06-25.
+ */
+@Target(FIELD)
+@Retention(RUNTIME)
+@Documented
+public @interface FieldDes {
+    String value() default "";
+}

+ 18 - 0
src/main/java/com/caimei365/order/annotation/FieldEncrypt.java

@@ -0,0 +1,18 @@
+package com.caimei365.order.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Created by heli50 on 2018-06-25.
+ */
+@Target(FIELD)
+@Retention(RUNTIME)
+@Documented
+public @interface FieldEncrypt {
+	String value() default "";
+}

+ 19 - 0
src/main/java/com/caimei365/order/annotation/SignExclude.java

@@ -0,0 +1,19 @@
+package com.caimei365.order.annotation;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import static java.lang.annotation.ElementType.FIELD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+/**
+ * Created by heli50 on 2018-06-25.
+ */
+
+@Target(FIELD)
+@Retention(RUNTIME)
+@Documented
+public @interface SignExclude {
+	String value() default "";
+}

+ 90 - 28
src/main/java/com/caimei365/order/components/HeliPayUtil.java

@@ -1,6 +1,5 @@
 package com.caimei365.order.components;
 
-import com.alibaba.fastjson.JSON;
 import com.caimei365.order.constant.Constant;
 import com.caimei365.order.mapper.OrderCommonMapper;
 import com.caimei365.order.mapper.PayOrderMapper;
@@ -8,7 +7,6 @@ import com.caimei365.order.model.bo.VipRecordBo;
 import com.caimei365.order.model.dto.HeliDto;
 import com.caimei365.order.model.enums.BizType;
 import com.caimei365.order.model.vo.*;
-import com.caimei365.order.utils.MathUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpHeaders;
@@ -18,8 +16,8 @@ import javax.annotation.Resource;
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
 import java.text.SimpleDateFormat;
-import java.util.ArrayList;
 import java.util.Date;
+import java.util.UUID;
 
 @Slf4j
 @Service
@@ -51,8 +49,10 @@ public class HeliPayUtil {
     private String couponUrl;
     @Value("${pay.coupon-union-url}")
     private String couponUnionPay;
+    @Value("${pay.quick-url}")
+    private String quickPayUrl;
 
-    private final String publicCode="wx91c4152b60ca91a3";
+    private final String publicCode = "wx91c4152b60ca91a3";
 
     //小程序/公众号线上公用方法 p8 openid在自己方法传
     public AppPayPublicCreateOrderVo setOnlineValue(AppPayPublicCreateOrderVo pay, HeliDto heliDto, String payFlag, HttpHeaders headers) {
@@ -115,14 +115,14 @@ public class HeliPayUtil {
             pay.setP18_desc(attach);
             //收款账号
             pay.setP3_customerNumber(Constant.CUSTOMERNUM);
-        }else if("coupon".equals(payFlag)){
+        } else if ("coupon".equals(payFlag)) {
             Double couponPrice = payOrderMapper.getCouponPrice(heliDto.getCouponRecordId());
             orderId = heliDto.getUserId() + "C" + heliDto.getCouponId() + "R" + heliDto.getCouponRecordId() + "T" + time + environment;
             pay.setP9_orderAmount(couponPrice.toString());
             pay.setP12_notifyUrl(couponUrl);
             String product = "采美订单" + orderId;
             pay.setP15_goodsName(product);
-            String attach = heliDto.getCouponId() + "," + heliDto.getUserId() + "," + heliDto.getCouponRecordId() + "," + BizType.getNumByType(heliDto.getPayType())+","+heliDto.getSource();
+            String attach = heliDto.getCouponId() + "," + heliDto.getUserId() + "," + heliDto.getCouponRecordId() + "," + BizType.getNumByType(heliDto.getPayType()) + "," + heliDto.getSource();
             pay.setP18_desc(attach);
             //收款账号
             pay.setP3_customerNumber(Constant.CUSTOMERNUM);
@@ -134,7 +134,7 @@ public class HeliPayUtil {
             pay.setP12_notifyUrl(notifyUrl);
             String product = "采美订单" + order.getOrderNo();
             pay.setP15_goodsName(product);
-            String attach = order.getOrderId() + "," + BizType.getNumByType(heliDto.getPayType())+","+heliDto.getShopOrderId();
+            String attach = order.getOrderId() + "," + BizType.getNumByType(heliDto.getPayType()) + "," + heliDto.getShopOrderId();
             pay.setP18_desc(attach);
         }
         pay.setP1_bizType(BizType.getP1ByType(heliDto.getPayType()));
@@ -175,7 +175,7 @@ public class HeliPayUtil {
             pay.setP14_desc(heliDto.getProductId().toString() + "," + BizType.getNumByType(heliDto.getPayType()));
             //网络收款,分账进信息
             pay.setP3_customerNumber(Constant.CUSTOMERNUM);
-        }else if ("vip".equals(payFlag)) {
+        } else if ("vip".equals(payFlag)) {
             VipRecordBo record = payOrderMapper.getVipPackageRecord(heliDto.getVipRecordId());
             Double price = payOrderMapper.getVipPackagePriceById(record.getPackageId());
             pay.setP5_orderAmount(price.toString());
@@ -187,7 +187,7 @@ public class HeliPayUtil {
             pay.setP14_desc(attach);
             //收款账号
             pay.setP3_customerNumber(Constant.CUSTOMERNUM);
-        }else if ("authVip".equals(payFlag)) {
+        } else if ("authVip".equals(payFlag)) {
             VipRecordBo record = payOrderMapper.getAuthVipRecord(heliDto.getVipRecordId());
             Double price = payOrderMapper.getAuthVipPackagePrice(record.getPackageId());
             pay.setP5_orderAmount(price.toString());
@@ -199,19 +199,18 @@ public class HeliPayUtil {
             pay.setP14_desc(attach);
             //收款账号
             pay.setP3_customerNumber(Constant.CUSTOMERNUM);
-        }else if("coupon".equals(payFlag)){
+        } else if ("coupon".equals(payFlag)) {
             Double couponPrice = payOrderMapper.getCouponPrice(heliDto.getCouponRecordId());
             orderId = heliDto.getUserId() + "C" + heliDto.getCouponId() + "R" + heliDto.getCouponRecordId() + "T" + time + environment;
             pay.setP5_orderAmount(couponPrice.toString());
             pay.setP9_notifyUrl(couponUrl);
             String product = "采美订单" + orderId;
             pay.setP12_goodsName(product);
-            String attach = heliDto.getCouponId() + "," + heliDto.getUserId() + "," + heliDto.getCouponRecordId() + "," + BizType.getNumByType(heliDto.getPayType())+","+heliDto.getSource();
+            String attach = heliDto.getCouponId() + "," + heliDto.getUserId() + "," + heliDto.getCouponRecordId() + "," + BizType.getNumByType(heliDto.getPayType()) + "," + heliDto.getSource();
             pay.setP14_desc(attach);
             //收款账号
             pay.setP3_customerNumber(Constant.CUSTOMERNUM);
-        }
-        else if ("order".equals(payFlag)) {
+        } else if ("order".equals(payFlag)) {
             //以子订单为单位付款,商户号为商品的分帐号
             OrderVo order = orderCommonMapper.getOrderByShopOrderId(heliDto.getShopOrderId());
             orderId = order.getOrderNo() + "T" + time + environment;
@@ -219,7 +218,8 @@ public class HeliPayUtil {
             pay.setP9_notifyUrl(notifyUrl);
             String product = "采美订单" + order.getOrderNo();
             pay.setP12_goodsName(product);
-            String attach = order.getOrderId() + "," + BizType.getNumByType(heliDto.getPayType())+","+heliDto.getShopOrderId();;
+            String attach = order.getOrderId() + "," + BizType.getNumByType(heliDto.getPayType()) + "," + heliDto.getShopOrderId();
+            ;
             pay.setP14_desc(attach);
         }
         pay.setP1_bizType(BizType.getP1ByType(heliDto.getPayType()));
@@ -228,7 +228,7 @@ public class HeliPayUtil {
         pay.setP6_currency("CNY");
         pay.setP7_authcode("1");
         //pc二维码apptype不是微信就是支付宝
-        String appType="WXEWM".equals(heliDto.getPayType())?"WXPAY":"ALIPAY";
+        String appType = "WXEWM".equals(heliDto.getPayType()) ? "WXPAY" : "ALIPAY";
         pay.setP8_appType(appType);
         pay.setP10_successToUrl(heliDto.getReturnUrl());
         pay.setP11_orderIp(headers.getFirst("X-CLIENT-IP"));
@@ -252,12 +252,12 @@ public class HeliPayUtil {
                 pay.setP12_serverCallback(secondUnionPay);
                 orderId = heliDto.getProductId() + "T" + time + environment;
                 String product = "采美订单" + orderId;
-                URLEncoder.encode(product,"UTF-8");
+                URLEncoder.encode(product, "UTF-8");
                 pay.setP8_goodsName(product);
-                String desc=heliDto.getProductId().toString() + "," + BizType.getNumByType(heliDto.getUserType());
-                URLEncoder.encode(desc,"UTF-8");
+                String desc = heliDto.getProductId().toString() + "," + BizType.getNumByType(heliDto.getUserType());
+                URLEncoder.encode(desc, "UTF-8");
                 pay.setP15_desc(desc);
-            }else if ("vip".equals(payFlag)) {
+            } else if ("vip".equals(payFlag)) {
                 pay.setP3_customerNumber(Constant.CUSTOMERNUM);
                 VipRecordBo record = payOrderMapper.getVipPackageRecord(heliDto.getVipRecordId());
                 Double price = payOrderMapper.getVipPackagePriceById(record.getPackageId());
@@ -265,22 +265,22 @@ public class HeliPayUtil {
                 pay.setP12_serverCallback(vipUnionPay);
                 orderId = record.getUserId() + "R" + heliDto.getVipRecordId() + "V" + record.getPackageId() + "T" + time + environment;
                 String product = "采美订单" + orderId;
-                URLEncoder.encode(product,"UTF-8");
+                URLEncoder.encode(product, "UTF-8");
                 pay.setP8_goodsName(product);
                 String attach = record.getPackageId() + "," + record.getUserId() + "," + heliDto.getVipRecordId() + "," + BizType.getNumByType(heliDto.getUserType());
-                URLEncoder.encode(attach,"UTF-8");
+                URLEncoder.encode(attach, "UTF-8");
                 pay.setP15_desc(attach);
-            }else if("coupon".equals(payFlag)){
+            } else if ("coupon".equals(payFlag)) {
                 pay.setP3_customerNumber(Constant.CUSTOMERNUM);
                 Double couponPrice = payOrderMapper.getCouponPrice(heliDto.getCouponRecordId());
                 pay.setP4_orderAmount(couponPrice.toString());
                 pay.setP12_serverCallback(couponUnionPay);
                 orderId = heliDto.getUserId() + "C" + heliDto.getCouponId() + "R" + heliDto.getCouponRecordId() + "T" + time + environment;
                 String product = "采美订单" + orderId;
-                URLEncoder.encode(product,"UTF-8");
+                URLEncoder.encode(product, "UTF-8");
                 pay.setP8_goodsName(product);
-                String attach = heliDto.getCouponId() + "," + heliDto.getUserId() + "," + heliDto.getCouponRecordId() + "," + BizType.getNumByType(heliDto.getPayType())+","+heliDto.getSource();
-                URLEncoder.encode(attach,"UTF-8");
+                String attach = heliDto.getCouponId() + "," + heliDto.getUserId() + "," + heliDto.getCouponRecordId() + "," + BizType.getNumByType(heliDto.getPayType()) + "," + heliDto.getSource();
+                URLEncoder.encode(attach, "UTF-8");
                 pay.setP15_desc(attach);
             } else if ("authVip".equals(payFlag)) {
                 pay.setP3_customerNumber(Constant.CUSTOMERNUM);
@@ -290,10 +290,10 @@ public class HeliPayUtil {
                 pay.setP12_serverCallback(authVipUnionPay);
                 orderId = record.getUserId() + "A" + heliDto.getVipRecordId() + "V" + record.getPackageId() + "T" + time + environment;
                 String product = "采美订单" + orderId;
-                URLEncoder.encode(product,"UTF-8");
+                URLEncoder.encode(product, "UTF-8");
                 pay.setP8_goodsName(product);
                 String attach = record.getPackageId() + "," + record.getUserId() + "," + heliDto.getVipRecordId() + "," + BizType.getNumByType(heliDto.getUserType());
-                URLEncoder.encode(attach,"UTF-8");
+                URLEncoder.encode(attach, "UTF-8");
                 pay.setP15_desc(attach);
             } else if ("order".equals(payFlag)) {
                 OrderVo order = orderCommonMapper.getOrderByShopOrderId(heliDto.getShopOrderId());
@@ -318,8 +318,70 @@ public class HeliPayUtil {
             pay.setP13_orderIp(headers.getFirst("X-CLIENT-IP"));
             pay.setP14_onlineCardType("DEBIT");
         } catch (UnsupportedEncodingException e) {
-            log.error("网银支付设值错误=================>"+e);
+            log.error("网银支付设值错误=================>" + e);
         }
         return pay;
     }
+
+    public void setQuickValue(HeliDto heliDto, FirstQuickPayVo firstQuickPayVo, HttpHeaders headers) {
+        firstQuickPayVo.setP1_bizType(BizType.getP1ByType(heliDto.getPayType()));
+        firstQuickPayVo.setP2_customerNumber(payOrderMapper.getSplitCodeByShopOrderId(heliDto.getShopOrderId()));
+        if (1 == heliDto.getQuickPayType()) {
+            //已绑卡
+            QuickPayUserVo quickPayUserInfo = payOrderMapper.getQuickPayUserInfo(heliDto.getUserId());
+            firstQuickPayVo.setP3_userId(quickPayUserInfo.getQuickPayUserId());
+            //姓名
+            firstQuickPayVo.setP6_payerName(quickPayUserInfo.getBankUserName());
+            //身份证号
+            firstQuickPayVo.setP8_idCardNo(quickPayUserInfo.getIdCard());
+            //银行卡号
+            firstQuickPayVo.setP9_cardNo(quickPayUserInfo.getBankNumber());
+            //银行绑定手机号
+            firstQuickPayVo.setP13_phone(quickPayUserInfo.getBindMobile());
+            if (2 == quickPayUserInfo.getBankType()) {
+                String[] split = quickPayUserInfo.getBankExpireTime().split("-");
+                firstQuickPayVo.setP10_year(split[0]);
+                firstQuickPayVo.setP11_month(split[1]);
+                firstQuickPayVo.setP12_cvv2(quickPayUserInfo.getBankCvvCode());
+            }
+        } else {
+            //未绑卡
+            firstQuickPayVo.setP3_userId("U" + heliDto.getUserId());
+            //姓名
+            firstQuickPayVo.setP6_payerName(heliDto.getQuickPayName());
+            //身份证号
+            firstQuickPayVo.setP8_idCardNo(heliDto.getIdCard());
+            //银行卡号
+            firstQuickPayVo.setP9_cardNo(heliDto.getQuickPayBankCode());
+            //银行绑定手机号
+            firstQuickPayVo.setP13_phone(heliDto.getQuickPayMobile());
+            //信用卡有效期年,月,cvv2 选择信用卡时必填,否则不填
+            if (2 == heliDto.getBankType()) {
+                String[] split = heliDto.getQuickPayBankExpireTime().split("-");
+                firstQuickPayVo.setP10_year(split[0]);
+                firstQuickPayVo.setP11_month(split[1]);
+                firstQuickPayVo.setP12_cvv2(heliDto.getCvvCode());
+            }
+        }
+        /**
+         *  订单id待定  快捷支付中回调参数不能带备注,无法在备注区传参,在快捷支付中订单id承担额外参数作用
+         *  (见其他支付方式desc参数)
+         */
+        //todo
+        firstQuickPayVo.setP4_orderId("");
+        String time = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
+        firstQuickPayVo.setP5_timestamp(time);
+        firstQuickPayVo.setP7_idCardType("IDCARD");
+        firstQuickPayVo.setP14_currency("CNY");
+        //目前设置0.1元起
+        firstQuickPayVo.setP15_orderAmount(heliDto.getPayAmount());
+        //名称
+        firstQuickPayVo.setP16_goodsName("采美订单");
+        firstQuickPayVo.setP18_terminalType("IMEI");
+        //终端唯一标识,如手机序列号
+        firstQuickPayVo.setP19_terminalId(UUID.randomUUID() + heliDto.getUserId().toString());
+        //回调地址
+        firstQuickPayVo.setP23_serverCallbackUrl(quickPayUrl);
+        firstQuickPayVo.setP20_orderIp(headers.getFirst("X-CLIENT-IP"));
+    }
 }

+ 24 - 15
src/main/java/com/caimei365/order/constant/Constant.java

@@ -3,47 +3,56 @@ package com.caimei365.order.constant;
 
 /**
  * 常量类
+ *
  * @author Administrator
  */
 public class Constant {
 
-
-
+    public static final String SIGNATURE_TYPE = "SM3WITHSM2";
     //专票 信息 测试佣金暂入信息  308785626@qq.com vip/二手暂入信息
     public static final String CUSTOMERNUM = "E1807059160";
     //信息的邮箱
-    public static final String XX_MAIL="308785626@qq.com";
+    public static final String XX_MAIL = "308785626@qq.com";
 
     //收款商编 网络   xun.zhang@caimei365.com
     public static final String CUSTOMERNUM2 = "E1807062884";
     //网络的邮箱
-    public static final String WL_MAIL="xun.zhang@caimei365.com";
+    public static final String WL_MAIL = "xun.zhang@caimei365.com";
 
     //普票 奥泰 测试私账暂进奥泰   caimei365@yeah.net
     public static final String CUSTOMERNUM3 = "E1807085606";
 
-    public static final String AT_MAIL="caimei365@yeah.net";
+    public static final String AT_MAIL = "caimei365@yeah.net";
 
     public static final String SPLIT = "&";
 
+    /**
+     * 快捷支付地址
+     */
+    public static final String REQUEST_URL_QUICKPAY = "http://quickpay.trx.helipay.com/trx/quickPayApi/interface.action";
+
     public static final String DOMAIN_NAME = "http://pay.trx.helipay.com/";
-    //网银地址http://pay.trx.helipay.com/trx/online/interface.action
-    public static final String YL="http://pay.trx.helipay.com/trx/online/interface.action";
-    //分账地址
-    public static final String FZ="http://pay.trx.helipay.com/trx/accountPay/interface.action";
+    /**
+     * 网银地址http://pay.trx.helipay.com/trx/online/interface.action
+     */
+    public static final String YL = "http://pay.trx.helipay.com/trx/online/interface.action";
+    /**
+     * 分账地址
+     */
+    public static final String FZ = "http://pay.trx.helipay.com/trx/accountPay/interface.action";
 
     //微信/支付宝扫码/小程序公众号支付
-    public static final String SAOMA="1iHnZaalUNAVcfcbKdh6n86Z0yUHtM6f";
+    public static final String SAOMA = "1iHnZaalUNAVcfcbKdh6n86Z0yUHtM6f";
     //网银
-    public static final String WANGYIN="CZiCbGrgFYQMldVkQnzbFQeQkn6mp25w";
+    public static final String WANGYIN = "CZiCbGrgFYQMldVkQnzbFQeQkn6mp25w";
     //虚拟账户支付
-    public static final String XUNI="8VmdRSXMIOfUo7aEq1iYs2XEWgGZpBQc";
+    public static final String XUNI = "8VmdRSXMIOfUo7aEq1iYs2XEWgGZpBQc";
     //分账
-    public static final String FENZHANG="2hATS0A4IoxdudGxNkGRNOt6aFSdOd8Q";
+    public static final String FENZHANG = "2hATS0A4IoxdudGxNkGRNOt6aFSdOd8Q";
     //公共产品
-    public static final String GONG="wrED4jYgKLQVsEwtgZ2eQmXrRgo7VHy4";
+    public static final String GONG = "wrED4jYgKLQVsEwtgZ2eQmXrRgo7VHy4";
     //结算
-    public static final String JIESUAN="fiweQU8igfuhBTcXLLDAQ3DScwIPEy2s";
+    public static final String JIESUAN = "fiweQU8igfuhBTcXLLDAQ3DScwIPEy2s";
     /**
      * 扫码接口地址
      */

+ 28 - 9
src/main/java/com/caimei365/order/controller/HeliPayApi.java

@@ -5,10 +5,7 @@ import com.caimei365.order.model.ResponseJson;
 import com.caimei365.order.model.dto.HeliDto;
 import com.caimei365.order.model.dto.PayDto;
 import com.caimei365.order.model.dto.PayLinkDto;
-import com.caimei365.order.model.vo.AccountResVo;
-import com.caimei365.order.model.vo.NotifyResponseVo;
-import com.caimei365.order.model.vo.ShopOrderVo;
-import com.caimei365.order.model.vo.UnionResVo;
+import com.caimei365.order.model.vo.*;
 import com.caimei365.order.service.HeliPayService;
 import com.caimei365.order.service.PayOrderService;
 import io.swagger.annotations.Api;
@@ -160,7 +157,7 @@ public class HeliPayApi {
     /**
      * 判断此次支付是否完成
      *
-     * @param shopOrderId           子订单id
+     * @param shopOrderId       子订单id
      * @param paySuccessCounter 付款次数
      */
     @ApiOperation("判断此次支付是否完成(旧:/PayOrder/payWhetherSuccess)")
@@ -191,14 +188,14 @@ public class HeliPayApi {
             @ApiImplicitParam(required = false, name = "shopOrderId", value = "子订单Id")
     })
     @GetMapping("/result/json")
-    public ResponseJson<JSONObject> getPayOrderResult(String mbOrderId,Integer orderFlag,Integer shopOrderId) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
+    public ResponseJson<JSONObject> getPayOrderResult(String mbOrderId, Integer orderFlag, Integer shopOrderId) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
         if (null == mbOrderId) {
             return ResponseJson.error("平台唯一流水号不能为空!", null);
         }
         if (null == orderFlag) {
             return ResponseJson.error("订单标识不能为空!", null);
         }
-        return heliPayService.getPayOrderResult(mbOrderId, orderFlag,shopOrderId);
+        return heliPayService.getPayOrderResult(mbOrderId, orderFlag, shopOrderId);
     }
 
     /**
@@ -213,15 +210,28 @@ public class HeliPayApi {
             @ApiImplicitParam(required = false, name = "shopOrderId", value = "子订单Id")
     })
     @GetMapping("/result/union")
-    public ResponseJson<JSONObject> getUnionResult(String mbOrderId,Integer orderFlag,Integer shopOrderId) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
+    public ResponseJson<JSONObject> getUnionResult(String mbOrderId, Integer orderFlag, Integer shopOrderId) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
         if (null == mbOrderId) {
             return ResponseJson.error("平台唯一流水号不能为空!", null);
         }
         if (null == orderFlag) {
             return ResponseJson.error("订单标识不能为空!", null);
         }
-        return heliPayService.getUnionResult(mbOrderId, orderFlag,shopOrderId);
+        return heliPayService.getUnionResult(mbOrderId, orderFlag, shopOrderId);
     }
+
+    @ApiOperation("合利宝快捷支付")
+    @PostMapping("/quick/pay")
+    public ResponseJson quickPay(HeliDto heliDto, @RequestHeader HttpHeaders headers) {
+        if (StringUtils.isBlank(heliDto.getPayType())) {
+            return ResponseJson.error("支付类型不能为空!", null);
+        }
+        if (null == heliDto.getShopOrderId()) {
+            return ResponseJson.error("子订单Id不能为空!", null);
+        }
+        return heliPayService.quickPay(heliDto, headers);
+    }
+
     /**
      * 合利宝pc支付宝二维码
      */
@@ -291,6 +301,15 @@ public class HeliPayApi {
         return heliPayService.paymentCallback(res);
     }
 
+    @ApiOperation("快捷支付异步通知回调")
+    @PostMapping("/quick/callback")
+    public String quickPayCallback(QuickPayConfirmPayResponseVo res) throws IntrospectionException, InvocationTargetException, IllegalAccessException {
+        if (res == null) {
+            return "回调参数失败";
+        }
+        return heliPayService.quickPayCallback(res);
+    }
+
     @ApiOperation("网银支付异步通知回调")
     @PostMapping("/union/callback")
     public String unionCallback(UnionResVo res) throws IntrospectionException, InvocationTargetException, IllegalAccessException {

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

@@ -255,4 +255,6 @@ public interface PayOrderMapper {
     String getSplitCodeByShopOrderId(Integer shopOrderId);
 
     void updateBySplitStatusByNo(String orderRequestNo);
+
+    QuickPayUserVo getQuickPayUserInfo(Integer userId);
 }

+ 28 - 1
src/main/java/com/caimei365/order/model/dto/HeliDto.java

@@ -50,7 +50,7 @@ public class HeliDto implements Serializable {
     private String userType;
 
 
-    @ApiModelProperty("支付类型 微信:WXEWM  支付宝:ZFBEWM 公众号:GZH 小程序:XCX 银联:YL")
+    @ApiModelProperty("支付类型 微信:WXEWM  支付宝:ZFBEWM 公众号:GZH 小程序:XCX 银联:YL 快捷:QUICK")
     private String payType;
 
     /**
@@ -89,5 +89,32 @@ public class HeliDto implements Serializable {
      */
     @ApiModelProperty("领取渠道1小程序 2网站")
     private Integer source;
+
+    /**
+     *  快捷支付方式 1已绑卡 2未绑卡
+     */
+    @ApiModelProperty("快捷支付方式 1已绑卡 2未绑卡")
+    private Integer quickPayType;
+
+    @ApiModelProperty("快捷支付方式 1借记卡 2信用卡")
+    private Integer bankType;
+
+    @ApiModelProperty("快捷支付用户姓名")
+    private String quickPayName;
+
+    @ApiModelProperty("快捷支付用户银行卡号/信用卡号")
+    private String quickPayBankCode;
+
+    @ApiModelProperty("快捷支付银行卡绑定手机号")
+    private String quickPayMobile;
+
+    @ApiModelProperty("快捷支付信用卡过期时间,只包含年月 yy-MM")
+    private String quickPayBankExpireTime;
+
+    @ApiModelProperty("身份证号")
+    private String idCard;
+
+    @ApiModelProperty("信用卡安全码")
+    private String cvvCode;
 }
 

+ 4 - 3
src/main/java/com/caimei365/order/model/enums/BizType.java

@@ -8,14 +8,15 @@ public enum BizType {
     // 企业网银  return "12";
     // 个人网银 "17";
 
-//    YL("YL", "AppPayPublic", "PUBLIC", "17"), //银联
-    B2B("B2B","","","12"),//企业网银
-    B2C("B2C","","","17"),//个人
+    //    YL("YL", "AppPayPublic", "PUBLIC", "17"), //银联
+    B2B("B2B", "", "", "12"),//企业网银
+    B2C("B2C", "", "", "17"),//个人
     XCX("XCX", "AppPayApplet", "APPLET", "15"),//小程序
     GZH("GZH", "AppPayPublic", "PUBLIC", "13"),//公众号
     ZFBEWM("ZFBEWM", "AppPay", "SCAN", "14"),//支付宝二维码
     //pc二维码跟公众号一样13
     WXEWM("WXEWM", "AppPay", "SCAN", "13"),//微信二维码
+    QUICK("QUICK", "QuickPayFirstPayPreOrder", "", "29")//快捷支付
     ;
 
     BizType(String type, String p1, String p4, String num) {

+ 75 - 0
src/main/java/com/caimei365/order/model/vo/FirstQuickPayVo.java

@@ -0,0 +1,75 @@
+package com.caimei365.order.model.vo;
+
+
+import com.caimei365.order.annotation.FieldEncrypt;
+import com.caimei365.order.annotation.SignExclude;
+import lombok.Data;
+
+/**
+ * Created by heli50 on 2017/4/14.
+ */
+@Data
+public class FirstQuickPayVo {
+    private String P1_bizType;
+
+    private String P2_customerNumber;
+
+    private String P3_userId;
+
+    private String P4_orderId;
+
+    private String P5_timestamp;
+
+    private String P6_payerName;
+
+    private String P7_idCardType;
+
+    @FieldEncrypt
+    private String P8_idCardNo;
+
+    @FieldEncrypt
+    private String P9_cardNo;
+
+    /**
+     * 当银行卡是信用卡时必输
+     * 信用卡有效期 年
+     */
+    @FieldEncrypt
+    private String P10_year;
+
+    /**
+     * 当银行卡是信用卡时必输
+     * 信用卡有效期 月
+     */
+    @FieldEncrypt
+    private String P11_month;
+
+    @FieldEncrypt
+    private String P12_cvv2;
+
+    @FieldEncrypt
+    private String P13_phone;
+
+    private String P14_currency;
+
+    private String P15_orderAmount;
+
+    private String P16_goodsName;
+
+    private String P17_goodsDesc;
+
+    private String P18_terminalType;
+
+    private String P19_terminalId;
+
+    private String P20_orderIp;
+
+    private String P21_period;
+
+    private String P22_periodUnit;
+
+    private String P23_serverCallbackUrl;
+
+    @SignExclude
+    private String signatureType;
+}

+ 155 - 0
src/main/java/com/caimei365/order/model/vo/QuickPayConfirmPayResponseVo.java

@@ -0,0 +1,155 @@
+package com.caimei365.order.model.vo;
+
+
+import com.caimei365.order.annotation.SignExclude;
+
+/**
+ * Created by heli50 on 2017/4/14.
+ */
+public class QuickPayConfirmPayResponseVo {
+    private String rt1_bizType;
+    private String rt2_retCode;
+    private String rt3_retMsg;
+    private String rt4_customerNumber;
+    private String rt5_orderId;
+    private String rt6_serialNumber;
+    private String rt7_completeDate;
+    private String rt8_orderAmount;
+    private String rt9_orderStatus;
+    private String rt10_bindId;
+    private String rt11_bankId;
+    private String rt12_onlineCardType;
+    private String rt13_cardAfterFour;
+    private String rt14_userId;
+    @SignExclude
+    private String sign;
+    @SignExclude
+    private String signatureType;
+
+    public String getRt1_bizType() {
+        return rt1_bizType;
+    }
+
+    public void setRt1_bizType(String rt1_bizType) {
+        this.rt1_bizType = rt1_bizType;
+    }
+
+    public String getRt2_retCode() {
+        return rt2_retCode;
+    }
+
+    public void setRt2_retCode(String rt2_retCode) {
+        this.rt2_retCode = rt2_retCode;
+    }
+
+    public String getRt3_retMsg() {
+        return rt3_retMsg;
+    }
+
+    public void setRt3_retMsg(String rt3_retMsg) {
+        this.rt3_retMsg = rt3_retMsg;
+    }
+
+    public String getRt4_customerNumber() {
+        return rt4_customerNumber;
+    }
+
+    public void setRt4_customerNumber(String rt4_customerNumber) {
+        this.rt4_customerNumber = rt4_customerNumber;
+    }
+
+    public String getRt5_orderId() {
+        return rt5_orderId;
+    }
+
+    public void setRt5_orderId(String rt5_orderId) {
+        this.rt5_orderId = rt5_orderId;
+    }
+
+    public String getRt6_serialNumber() {
+        return rt6_serialNumber;
+    }
+
+    public void setRt6_serialNumber(String rt6_serialNumber) {
+        this.rt6_serialNumber = rt6_serialNumber;
+    }
+
+    public String getRt7_completeDate() {
+        return rt7_completeDate;
+    }
+
+    public void setRt7_completeDate(String rt7_completeDate) {
+        this.rt7_completeDate = rt7_completeDate;
+    }
+
+    public String getRt8_orderAmount() {
+        return rt8_orderAmount;
+    }
+
+    public void setRt8_orderAmount(String rt8_orderAmount) {
+        this.rt8_orderAmount = rt8_orderAmount;
+    }
+
+    public String getRt9_orderStatus() {
+        return rt9_orderStatus;
+    }
+
+    public void setRt9_orderStatus(String rt9_orderStatus) {
+        this.rt9_orderStatus = rt9_orderStatus;
+    }
+
+    public String getRt10_bindId() {
+        return rt10_bindId;
+    }
+
+    public void setRt10_bindId(String rt10_bindId) {
+        this.rt10_bindId = rt10_bindId;
+    }
+
+    public String getRt11_bankId() {
+        return rt11_bankId;
+    }
+
+    public void setRt11_bankId(String rt11_bankId) {
+        this.rt11_bankId = rt11_bankId;
+    }
+
+    public String getRt12_onlineCardType() {
+        return rt12_onlineCardType;
+    }
+
+    public void setRt12_onlineCardType(String rt12_onlineCardType) {
+        this.rt12_onlineCardType = rt12_onlineCardType;
+    }
+
+    public String getRt13_cardAfterFour() {
+        return rt13_cardAfterFour;
+    }
+
+    public void setRt13_cardAfterFour(String rt13_cardAfterFour) {
+        this.rt13_cardAfterFour = rt13_cardAfterFour;
+    }
+
+    public String getRt14_userId() {
+        return rt14_userId;
+    }
+
+    public void setRt14_userId(String rt14_userId) {
+        this.rt14_userId = rt14_userId;
+    }
+
+    public String getSign() {
+        return sign;
+    }
+
+    public void setSign(String sign) {
+        this.sign = sign;
+    }
+    public String getSignatureType() {
+        return signatureType;
+    }
+
+    public void setSignatureType(String signatureType) {
+        this.signatureType = signatureType;
+    }
+}

+ 114 - 0
src/main/java/com/caimei365/order/model/vo/QuickPayCreateOrderResponseVo.java

@@ -0,0 +1,114 @@
+package com.caimei365.order.model.vo;
+
+
+import com.caimei365.order.annotation.SignExclude;
+
+/**
+ * Created by heli50 on 2017/4/14.
+ */
+public class QuickPayCreateOrderResponseVo {
+
+    private String rt1_bizType;
+
+    private String rt2_retCode;
+
+    private String rt3_retMsg;
+
+    private String rt4_customerNumber;
+
+    private String rt5_orderId;
+
+    @SignExclude
+    private String smsStatus;
+
+    @SignExclude
+    private String smsMsg;
+
+    @SignExclude
+    private String smsConfirm;
+
+    @SignExclude
+    private String sign;
+    @SignExclude
+    private String signatureType;
+
+    public String getRt1_bizType() {
+        return rt1_bizType;
+    }
+
+    public void setRt1_bizType(String rt1_bizType) {
+        this.rt1_bizType = rt1_bizType;
+    }
+
+    public String getRt2_retCode() {
+        return rt2_retCode;
+    }
+
+    public void setRt2_retCode(String rt2_retCode) {
+        this.rt2_retCode = rt2_retCode;
+    }
+
+    public String getRt3_retMsg() {
+        return rt3_retMsg;
+    }
+
+    public void setRt3_retMsg(String rt3_retMsg) {
+        this.rt3_retMsg = rt3_retMsg;
+    }
+
+    public String getRt4_customerNumber() {
+        return rt4_customerNumber;
+    }
+
+    public void setRt4_customerNumber(String rt4_customerNumber) {
+        this.rt4_customerNumber = rt4_customerNumber;
+    }
+
+    public String getRt5_orderId() {
+        return rt5_orderId;
+    }
+
+    public void setRt5_orderId(String rt5_orderId) {
+        this.rt5_orderId = rt5_orderId;
+    }
+
+    public String getSmsStatus() {
+        return smsStatus;
+    }
+
+    public void setSmsStatus(String smsStatus) {
+        this.smsStatus = smsStatus;
+    }
+
+    public String getSmsMsg() {
+        return smsMsg;
+    }
+
+    public void setSmsMsg(String smsMsg) {
+        this.smsMsg = smsMsg;
+    }
+
+    public String getSmsConfirm() {
+        return smsConfirm;
+    }
+
+    public void setSmsConfirm(String smsConfirm) {
+        this.smsConfirm = smsConfirm;
+    }
+
+    public String getSign() {
+        return sign;
+    }
+
+    public void setSign(String sign) {
+        this.sign = sign;
+    }
+
+    public String getSignatureType() {
+        return signatureType;
+    }
+
+    public void setSignatureType(String signatureType) {
+        this.signatureType = signatureType;
+    }
+}

+ 34 - 0
src/main/java/com/caimei365/order/model/vo/QuickPayUserVo.java

@@ -0,0 +1,34 @@
+package com.caimei365.order.model.vo;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author zzj
+ */
+@Data
+public class QuickPayUserVo implements Serializable {
+    private static final long serialVersionUID = 1L;
+    @ApiModelProperty("采美userId")
+    private Integer userId;
+    @ApiModelProperty("快捷支付绑定采美唯一userId")
+    private String quickPayUserId;
+    @ApiModelProperty("快捷支付绑定合利宝唯一Id")
+    private String quickPaybindId;
+    @ApiModelProperty("用户身份证号")
+    private String idCard;
+    @ApiModelProperty("用户银行卡/信用卡号")
+    private String bankNumber;
+    @ApiModelProperty("信用卡过期时间")
+    private String bankExpireTime;
+    @ApiModelProperty("信用卡安全码")
+    private String bankCvvCode;
+    @ApiModelProperty("用户绑定卡类型1借记卡2信用卡")
+    private Integer bankType;
+    @ApiModelProperty("用户银行预留手机号")
+    private String bindMobile;
+    @ApiModelProperty("用户银行绑定姓名")
+    private String bankUserName;
+}

+ 5 - 0
src/main/java/com/caimei365/order/service/HeliPayService.java

@@ -6,6 +6,7 @@ import com.caimei365.order.model.dto.HeliDto;
 import com.caimei365.order.model.dto.PayDto;
 import com.caimei365.order.model.vo.*;
 import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpRequest;
 
 import javax.servlet.http.HttpServletRequest;
 import java.beans.IntrospectionException;
@@ -52,4 +53,8 @@ public interface HeliPayService {
     ResponseJson<List<ShopOrderVo>> getShopOrders(Integer orderId);
 
     ResponseJson<JSONObject> getUnionResult(String mbOrderId, Integer orderFlag, Integer shopOrderId);
+
+    ResponseJson quickPay(HeliDto heliDto, HttpHeaders headers);
+
+    String quickPayCallback(QuickPayConfirmPayResponseVo res);
 }

+ 55 - 8
src/main/java/com/caimei365/order/service/impl/HeliPayServiceImpl.java

@@ -22,13 +22,11 @@ import com.caimei365.order.service.HeliPayService;
 import com.caimei365.order.service.RemoteCallService;
 import com.caimei365.order.utils.ImageUtil;
 import com.caimei365.order.utils.MathUtil;
-import com.caimei365.order.utils.PayUtil;
 import com.caimei365.order.utils.helipay.Disguiser;
 import com.caimei365.order.utils.helipay.HttpClientService;
+import com.caimei365.order.utils.helipay.MessageHandle;
 import com.caimei365.order.utils.helipay.MyBeanUtils;
-import com.caimei365.order.utils.pay.RSAUtil;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang.ArrayUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.http.HttpStatus;
 import org.springframework.beans.BeanUtils;
@@ -36,8 +34,6 @@ import org.springframework.beans.factory.annotation.Value;
 import org.springframework.http.HttpHeaders;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
-import org.springframework.web.servlet.ModelAndView;
-import springfox.documentation.spring.web.json.Json;
 
 import javax.annotation.Resource;
 import java.beans.IntrospectionException;
@@ -45,8 +41,6 @@ import java.io.IOException;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.math.BigDecimal;
-import java.security.NoSuchAlgorithmException;
-import java.security.spec.InvalidKeySpecException;
 import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
@@ -1161,7 +1155,7 @@ public class HeliPayServiceImpl implements HeliPayService {
                     if (null != promotions) {
                         if (1 == promotions.getType() && 1 == promotions.getMode()) {
                             //单品优惠价的时候取当前sku的touchprice
-                            promotions.setTouchPrice(baseMapper.getTouchPriceBySku(orderProduct.getSkuId(),promotions.getId()));
+                            promotions.setTouchPrice(baseMapper.getTouchPriceBySku(orderProduct.getSkuId(), promotions.getId()));
                         }
                         if (taxFlag && Integer.valueOf(1).equals(promotions.getType()) && Integer.valueOf(1).equals(promotions.getMode())) {
                             promotions.setTouchPrice(MathUtil.add(promotions.getTouchPrice(), MathUtil.div(MathUtil.mul(promotions.getTouchPrice(), orderProduct.getTaxRate()), 100)).doubleValue());
@@ -1242,6 +1236,59 @@ public class HeliPayServiceImpl implements HeliPayService {
         return null;
     }
 
+    @Override
+    public ResponseJson quickPay(HeliDto heliDto, HttpHeaders headers) {
+        FirstQuickPayVo firstQuickPayVo = new FirstQuickPayVo();
+        heliPayUtil.setQuickValue(heliDto, firstQuickPayVo, headers);
+        Map reqestMap = null;
+        try {
+            reqestMap = MessageHandle.getReqestMap(firstQuickPayVo);
+            log.info("请求参数:" + reqestMap);
+            Map<String, Object> resultMap = HttpClientService.getHttpResp(reqestMap, Constant.REQUEST_URL_QUICKPAY);
+            log.info("响应结果:" + resultMap);
+            String resultMsg = (String) resultMap.get("response");
+            if ((Integer) resultMap.get("statusCode") != org.apache.commons.httpclient.HttpStatus.SC_OK) {
+                //状态码不对请求失败
+                return ResponseJson.error("请求失败");
+            }
+            QuickPayCreateOrderResponseVo responseVo = JSONObject.parseObject(resultMsg, QuickPayCreateOrderResponseVo.class);
+            if (!MessageHandle.checkSign(responseVo)) {
+                return ResponseJson.error("验签失败");
+            }
+            if (!"0000".equals(responseVo.getRt2_retCode())) {
+                log.info(responseVo.getRt3_retMsg());
+                return ResponseJson.error(responseVo.getRt3_retMsg());
+            }
+            //验签没问题执行业务逻辑,保存身份证,银行卡,姓名,若已经存在,则不保存
+
+            //业务逻辑执行完请求发送短信
+            return ResponseJson.success();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public String quickPayCallback(QuickPayConfirmPayResponseVo res) {
+        try {
+            if (MessageHandle.checkSign(res)) {
+                if ("SUCCESS".equals(res.getRt9_orderStatus())) {
+                    /**
+                     * 验签通过 查看交易状态码是否成功,是则继续业务逻辑
+                     * rt10_bindId需要存入 cm_quickpay_info
+                     */
+
+
+                    return "SUCCESS";
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
     public static <T> T postForm(Map<String, String> params, String url, String sign, Class<T> clazz) {
         FormBody.Builder builder = new FormBody.Builder();
         for (Map.Entry<String, String> entry : params.entrySet()) {

+ 73 - 0
src/main/java/com/caimei365/order/utils/helipay/HeliPayCertConfig.java

@@ -0,0 +1,73 @@
+package com.caimei365.order.utils.helipay;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Security;
+
+
+public class HeliPayCertConfig {
+
+    /**
+     * 证书存储路径
+     */
+    private static final String CERT_PATH = "key\\dev\\";
+    //private static final String CERT_PATH = "D:\\certs\\key\\dev\\";
+
+    /**
+     * 商户SM2证书私钥路径
+     */
+    private static final String MERCHANT_PRIVATE_KEY_PATH = CERT_PATH + "C1800000002_dev.pfx";
+
+    /**
+     * 商户SM2证书私钥密码
+     */
+    private static final String MERCHANT_PRIVATE_KEY_PWD = "123456";
+
+    /**
+     *  商户SM2证书私钥字符串
+     */
+    private static final PrivateKey merchantPrivateKey;
+
+
+    /**
+     *  合利宝SM2证书公钥路径
+     */
+    private static final String HELIPAY_PUBLIC_KEY_PATH = CERT_PATH + "helipay_pub_dev.cer";//取决支付系统加载的合利宝私钥配对
+
+    //加密机公钥证书
+    //private static final String HELIPAY_PUBLIC_KEY_PATH = "D:\\certs\\hsm\\helipay-hsm.cer";
+
+    /**
+     * 合利宝SM2证书公钥对象
+     */
+    private static final PublicKey helipayPublicKey;
+
+    static {
+        if (Security.getProvider(BouncyCastleProvider.PROVIDER_NAME) == null) {
+            Security.addProvider(new BouncyCastleProvider());
+        }
+
+        try {
+            merchantPrivateKey = HeliPayCertUtils.getPrivateKeyByPfx("C:\\Users\\Administrator\\Desktop\\tmpCerts\\C1806995267_2303010060964109_privateKey.pfx","cm20230327");
+        } catch (Exception e) {
+            throw new RuntimeException("获取SM2证书私钥字符串异常:"+e.getMessage(),e) ;
+        }
+
+        try {
+            helipayPublicKey = HeliPayCertUtils.getPublicKey("C:\\Users\\Administrator\\Desktop\\tmpCerts\\helipayPublicKey.cer");
+        } catch (Exception e) {
+            throw new RuntimeException("加载合利宝SM2证书公钥异常异常:"+e.getMessage(),e) ;
+        }
+    }
+
+    public static PrivateKey getMerchantPrivateKey() {
+        return merchantPrivateKey;
+    }
+
+
+    public static PublicKey getHelipayPublicKey() {
+        return helipayPublicKey;
+    }
+}

+ 81 - 0
src/main/java/com/caimei365/order/utils/helipay/HeliPayCertUtils.java

@@ -0,0 +1,81 @@
+package com.caimei365.order.utils.helipay;
+
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+
+import java.io.ByteArrayInputStream;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.*;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Enumeration;
+
+/**
+ * 合利宝证书工具类
+ */
+public abstract class HeliPayCertUtils {
+
+    private HeliPayCertUtils() {}
+
+    public static PublicKey getPublicKey(String certFilePath) throws CertificateException, IOException, NoSuchProviderException {
+        return getX509Certificate(certFilePath).getPublicKey();
+    }
+
+    /**
+     * 获取证书
+     * @param certFilePath
+     * @return
+     * @throws CertificateException
+     * @throws NoSuchProviderException
+     * @throws IOException
+     */
+    public static X509Certificate getX509Certificate(String certFilePath) throws CertificateException,
+            NoSuchProviderException, IOException {
+        CertificateFactory cf = CertificateFactory.getInstance("X.509", BouncyCastleProvider.PROVIDER_NAME);
+        byte[] readAllBytes = Files.readAllBytes(Paths.get(certFilePath));
+        String fileContent = new String(readAllBytes);
+        if("-----BEGIN CERTIFICATE-----".indexOf(fileContent) < 0){
+            fileContent = "-----BEGIN CERTIFICATE-----\n" + fileContent  +
+                    "\n-----END CERTIFICATE-----";
+        }
+        InputStream is = new ByteArrayInputStream(fileContent.getBytes());
+        return (X509Certificate) cf.generateCertificate(is);
+    }
+
+    public static PrivateKey getPrivateKeyByPfx(String pfxPath, String pfxPassword) {
+        try {
+            KeyStore ks = KeyStore.getInstance("PKCS12",getProvider());
+            FileInputStream fis = new FileInputStream(pfxPath);
+            // If the keystore password is empty(""), then we have to set
+            // to null, otherwise it won't work!!!
+            char[] nPassword = null;
+            if ((pfxPassword == null) || pfxPassword.trim().equals("")) {
+                nPassword = null;
+            } else {
+                nPassword = pfxPassword.toCharArray();
+            }
+            ks.load(fis, nPassword);
+            fis.close();
+            Enumeration enumas = ks.aliases();
+            String keyAlias = null;
+            if (enumas.hasMoreElements())// we are readin just one certificate.
+            {
+                keyAlias = (String) enumas.nextElement();
+            }
+            PrivateKey prikey = (PrivateKey) ks.getKey(keyAlias, nPassword);
+            return prikey;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    private static Provider getProvider() {
+        return Security.getProvider(BouncyCastleProvider.PROVIDER_NAME);
+    }
+
+}

+ 117 - 0
src/main/java/com/caimei365/order/utils/helipay/MessageHandle.java

@@ -0,0 +1,117 @@
+package com.caimei365.order.utils.helipay;
+
+
+import com.caimei365.order.annotation.FieldEncrypt;
+import com.caimei365.order.annotation.SignExclude;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.lang.reflect.Field;
+import java.util.HashMap;
+import java.util.Map;
+
+
+public class MessageHandle {
+
+	private static Logger log = LoggerFactory.getLogger(MessageHandle.class);
+
+	private static final String ENCRYPTION_KEY = "encryptionKey";
+
+	private static final String SPLIT = "&";
+
+	private static final String SIGN = "sign"; 
+
+	/**
+	 * 获取map
+	 */
+	public static Map getReqestMap(Object bean) throws Exception {
+
+		Map retMap = new HashMap();
+
+		boolean isEncrypt = false;
+		String sm4Key = SM4Utils.generateRandomKey();
+		StringBuilder sb = new StringBuilder();
+
+		Class clazz = bean.getClass();
+		Field[] fields = clazz.getDeclaredFields();
+		for (Field field : fields) {
+			field.setAccessible(true);
+			String key = field.toString().substring(field.toString().lastIndexOf(".") + 1);
+			String value = (String) field.get(bean);
+			if (value == null) {
+				value = "";
+			}
+			//查看是否有需要SM4加密字段的注解,有则加密
+			//这部分是将需要SM4加密的字段先进行加密
+			if (field.isAnnotationPresent(FieldEncrypt.class) && StringUtils.isNotEmpty(value)) {
+				isEncrypt = true;
+				value = SM4Utils.encryptBase64(value , sm4Key);
+			}
+
+			//字段没有@SignExclude注解的拼签名串
+			//这部分是把需要参与签名的字段拼成一个待签名的字符串
+			if (!field.isAnnotationPresent(SignExclude.class)) {
+				sb.append(SPLIT);
+				sb.append(value);
+			}
+
+			retMap.put(key, value);
+		}
+
+		//请求参数中有需要加密的字段,使用合利宝的公钥的对SM4密钥KEY进行加密处理
+		if (isEncrypt) {
+			String encrytionKey = SM2Utils.encryptToBase64(HeliPayCertConfig.getHelipayPublicKey(), sm4Key);
+			retMap.put(ENCRYPTION_KEY, encrytionKey);
+		}
+
+		log.info("原签名串:" + sb.toString());
+		//使用商户的私钥进行签名
+		String sign = SM2Utils.sign(HeliPayCertConfig.getMerchantPrivateKey(), sb.toString());
+		retMap.put(SIGN, sign);
+		log.info("签名sign:" + sign);
+		return retMap;
+	}
+
+
+	public static boolean checkSign(Object bean) throws Exception {
+
+		boolean flag = false;
+		StringBuilder sb = new StringBuilder();
+
+		Class clazz = bean.getClass();
+		Field[] fields = clazz.getDeclaredFields();
+		String sign = "";
+		for (Field field : fields) {
+			field.setAccessible(true);
+			String key = field.toString().substring(field.toString().lastIndexOf(".") + 1);
+			String value = (String) field.get(bean);
+			if (value == null) {
+				value = "";
+			}
+
+			if (SIGN.equals(key)) {
+				sign = value;
+			}
+
+			//字段没有@SignExclude注解的拼签名串
+			//这部分是把需要参与签名的字段拼成一个待签名的字符串
+			if (!field.isAnnotationPresent(SignExclude.class)) {
+				sb.append(SPLIT);
+				sb.append(value);
+			}
+
+		}
+		log.info("response验签原签名串:" + sb.toString());
+
+		//使用合利宝的公钥进行验签
+		flag = SM2Utils.verify(HeliPayCertConfig.getHelipayPublicKey(), sb.toString(), sign);
+		if (flag) {
+			log.info("验签成功");
+		} else {
+			log.info("验签失败");
+		}
+		return flag;
+
+	}
+}

+ 94 - 0
src/main/java/com/caimei365/order/utils/helipay/SM2Utils.java

@@ -0,0 +1,94 @@
+package com.caimei365.order.utils.helipay;
+
+import cn.hutool.crypto.asymmetric.SM2;
+import org.apache.commons.lang3.StringUtils;
+import org.bouncycastle.crypto.engines.SM2Engine;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.charset.StandardCharsets;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.util.Base64;
+import java.util.Objects;
+
+/**
+ * 国密SM2算法工具类
+ * @description:
+ * @since:
+ */
+public class SM2Utils {
+
+    private static Logger logger = LoggerFactory.getLogger(SM2Utils.class);
+
+    private SM2Utils(){}
+
+    public static String sign(PrivateKey privateKey, String data) {
+        return sign(privateKey, data.getBytes(StandardCharsets.UTF_8), null);
+    }
+
+    public static String sign(PrivateKey privateKey, String data, byte[] id) {
+        return sign(privateKey, data.getBytes(StandardCharsets.UTF_8), id);
+    }
+
+    public static String sign(PrivateKey privateKey, byte[] data, byte[] id) {
+        SM2 sm2 = new SM2(privateKey, null);
+        return Base64.getEncoder().encodeToString(sm2.sign(data, id));
+    }
+
+    public static boolean verify(PublicKey publicKey, String plainText, String signText) {
+        Objects.requireNonNull(plainText, "plainText required");
+        Objects.requireNonNull(signText, "signText required");
+        return verify(publicKey, plainText.getBytes(StandardCharsets.UTF_8), Base64.getDecoder().decode(signText), null);
+    }
+
+    private static boolean verify(PublicKey publicKey, byte[] plainData, byte[] signature, byte[] id) {
+        SM2 sm2 = new SM2(null, publicKey);
+        return sm2.verify(plainData, signature, id);
+    }
+
+    public static String encryptToBase64(PublicKey publicKey, String plainText){
+        byte[] cipherData = encrypt(publicKey, plainText.getBytes(StandardCharsets.UTF_8));
+        return Base64.getEncoder().encodeToString(cipherData);
+    }
+
+    private static byte[] encrypt(PublicKey publicKey, byte[] message) {
+        SM2 sm2 = new SM2(null, publicKey);
+        sm2.setMode(SM2Engine.Mode.C1C3C2);
+        return sm2.encrypt(message);
+    }
+
+    public static String decryptBase64Message(PrivateKey privateKey,String cipherText){
+        byte[] base64Data = Base64.getDecoder().decode(cipherText);
+        byte[] bytes = decrypt(privateKey, base64Data);
+        return StringUtils.toEncodedString(bytes, StandardCharsets.UTF_8);
+    }
+
+    private static byte[] decrypt(PrivateKey privateKey, byte[] message) {
+        SM2 sm2 = new SM2(privateKey, null);
+        sm2.setMode(SM2Engine.Mode.C1C3C2);
+        return sm2.decrypt(message);
+    }
+
+    public static void main(String[] args)  {
+
+//        String plainText = "待签名串abc=123";
+//        // ===============  签名、验签 =================
+//
+//        String signText = sign(HeliPayCertConfig.getMerchantPrivateKey(), plainText);
+//        System.out.println("signText length:"+signText.length());
+//        System.out.println("signText:"+signText);
+//
+//        boolean b = verify(HeliPayCertConfig.getMerchantPublicKey(),plainText, signText);
+//        System.out.println("verify:"+b);
+//
+//        // ===============  加密、解密 =================
+//
+//        String cipherText = encryptToBase64(HeliPayCertConfig.getMerchantPublicKey(), plainText);
+//        System.out.println("cipherText:"+cipherText);
+//        System.out.println("cipherText length:"+cipherText.length());
+//
+//        String sourceText = decryptBase64Message(HeliPayCertConfig.getMerchantPrivateKey(), cipherText);
+//        System.out.println("sourceText:"+sourceText);
+    }
+}

+ 100 - 0
src/main/java/com/caimei365/order/utils/helipay/SM4Utils.java

@@ -0,0 +1,100 @@
+package com.caimei365.order.utils.helipay;
+
+import cn.hutool.crypto.symmetric.SM4;
+
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.nio.charset.StandardCharsets;
+import java.util.Base64;
+import java.util.Random;
+
+
+/**
+ * SM4对称加密工具类
+ */
+public class SM4Utils {
+
+    private static final int DEFAULT_KEY_LENGTH = 16;
+
+    private static final String ALL_CHAR = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+    private static final String ENCRYPTION_ALGORITHM = "SM4";
+
+    private static final String MODE_CBC ="CBC";
+
+    private static final String PKCS7PADDING = "PKCS7Padding";
+
+    private static final IvParameterSpec sm4IvSpec = new IvParameterSpec(Base64.getDecoder().decode(
+            "AQ4Zvt54xKn9QaW86ZzWdg=="));
+
+    private SM4Utils(){}
+
+    public static String generateRandomKey(){
+        StringBuffer sb = new StringBuffer();
+        Random random = new Random();
+        for (int i = 0; i < DEFAULT_KEY_LENGTH; i++) {
+            sb.append(ALL_CHAR.charAt(random.nextInt(ALL_CHAR.length())));
+        }
+        return sb.toString();
+    }
+
+    public static String decryptBase64(String message,String sm4Key){
+        return sm4DecryptBase64(message, toSecretKeySpec(sm4Key));
+    }
+
+    public static String encryptBase64(String message,String sm4Key){
+        return sm4EncryptBase64(message, toSecretKeySpec(sm4Key));
+    }
+
+    public static SecretKeySpec toSecretKeySpec(String sm4Key) {
+        return new SecretKeySpec(sm4Key.getBytes(StandardCharsets.UTF_8), ENCRYPTION_ALGORITHM);
+    }
+
+    public static String sm4DecryptBase64(String message, SecretKeySpec keySpec) {
+        byte[] bytes = Base64.getDecoder().decode(message);
+        byte[] decrypted = SM4Utils.decrypt(keySpec, sm4IvSpec, bytes);
+        return new String(decrypted, StandardCharsets.UTF_8);
+    }
+
+    public static String sm4EncryptBase64(String message, SecretKeySpec keySpec) {
+        return encryptBase64(keySpec, sm4IvSpec, message.getBytes(StandardCharsets.UTF_8));
+    }
+
+
+    public static String encryptBase64(SecretKey key, IvParameterSpec iv, byte[] data) {
+        byte[] bytes = encrypt(key, iv, data);
+        return Base64.getEncoder().encodeToString(bytes);
+    }
+
+    public static byte[] encrypt(SecretKey key, IvParameterSpec iv, byte[] data) {
+        SM4 sm4 = new SM4(MODE_CBC, PKCS7PADDING, key, iv);
+        return sm4.encrypt(data);
+    }
+
+    public static byte[] decrypt(SecretKey key, IvParameterSpec iv, byte[] data) {
+        SM4 sm4 = new SM4(MODE_CBC, PKCS7PADDING, key, iv);
+        return sm4.decrypt(data);
+    }
+
+
+    public static void main(String[] args) {
+//        Stopwatch stopwatch = Stopwatch.createStarted();
+//        String sm4Key = generateRandomKey();
+//        System.out.println("执行时长1:"+stopwatch.elapsed(TimeUnit.MILLISECONDS));
+//        String content ="12345678";
+//        System.out.println("content length:"+content.length());
+//        SecretKeySpec encryptSecretKey = toSecretKeySpec(sm4Key);
+//        System.out.println("执行时长2:"+stopwatch.elapsed(TimeUnit.MILLISECONDS));
+//        String sm4EncryptBase64 = sm4EncryptBase64(content,encryptSecretKey);
+//        System.out.println("执行时长3:"+stopwatch.elapsed(TimeUnit.MILLISECONDS));
+//        System.out.println("sm4EncryptBase64:"+sm4EncryptBase64);
+//        String encryptSm4Key = SM2Utils.encryptToBase64(HeliPayCertConfig.getMerchantPublicKey(),sm4Key);
+//        System.out.println("执行时长4:"+stopwatch.elapsed(TimeUnit.MILLISECONDS));
+//        String decryptSm4Key = SM2Utils.decryptBase64Message(HeliPayCertConfig.getMerchantPrivateKey(),encryptSm4Key);
+//        System.out.println("执行时长5:"+stopwatch.elapsed(TimeUnit.MILLISECONDS));
+//        String sm4DecryptBase64 = decryptBase64(sm4EncryptBase64,decryptSm4Key);
+//        System.out.println("执行时长6:"+stopwatch.elapsed(TimeUnit.MILLISECONDS));
+//        System.out.println("sm4DecryptBase64:"+sm4DecryptBase64);
+    }
+}

+ 247 - 125
src/main/resources/mapper/PayOrderMapper.xml

@@ -37,33 +37,47 @@
         WHERE userID = #{userId}
     </update>
     <delete id="deleteAuthVipRoleRelation">
-        DELETE FROM auth_role_user WHERE user_id = #{userId}
+        DELETE
+        FROM auth_role_user
+        WHERE user_id = #{userId}
     </delete>
-    <insert id="insertOrderPayLink" keyColumn="id" keyProperty="id"  parameterType="com.caimei365.order.model.vo.OrderPayLinkVo" useGeneratedKeys="true">
+    <insert id="insertOrderPayLink" keyColumn="id" keyProperty="id"
+            parameterType="com.caimei365.order.model.vo.OrderPayLinkVo" useGeneratedKeys="true">
         INSERT INTO cm_order_pay_link (orderId, vipRecordId, authVipRecordId, vipMonth, linkLogo, unpaidAmount,
                                        generateTime, effectiveTime, payStatus, payType, delFlag, shopOrderId)
         VALUES (#{orderId}, #{vipRecordId}, #{authVipRecordId}, #{vipMonth}, #{linkLogo}, #{unpaidAmount},
                 #{generateTime}, #{effectiveTime}, #{payStatus}, #{payType}, #{delFlag}, #{shopOrderId})
     </insert>
-    <insert id="insertSplitAccount" keyColumn="id" keyProperty="id"  parameterType="com.caimei365.order.model.po.SplitAccountPo" useGeneratedKeys="true">
-        INSERT INTO cm_split_account (orderId, productId, orderProductId, shopId, couponRecordId,vipRecordId, authVipRecordId, type, subUserNo, splitAccount,
-                                        mbOrderId, orderRequestNo,payStatus, productType, splitTime)
-        VALUES (#{orderId}, #{productId}, #{orderProductId}, #{shopId},#{couponRecordId},#{vipRecordId}, #{authVipRecordId}, #{type}, #{subUserNo}, #{splitAccount},
+    <insert id="insertSplitAccount" keyColumn="id" keyProperty="id"
+            parameterType="com.caimei365.order.model.po.SplitAccountPo" useGeneratedKeys="true">
+        INSERT INTO cm_split_account (orderId, productId, orderProductId, shopId, couponRecordId, vipRecordId,
+                                      authVipRecordId, type, subUserNo, splitAccount,
+                                      mbOrderId, orderRequestNo, payStatus, productType, splitTime)
+        VALUES (#{orderId}, #{productId}, #{orderProductId}, #{shopId}, #{couponRecordId}, #{vipRecordId},
+                #{authVipRecordId}, #{type}, #{subUserNo}, #{splitAccount},
                 #{mbOrderId}, #{orderRequestNo}, #{payStatus}, #{productType}, NOW());
     </insert>
-    <insert id="insertPayShop" keyColumn="id" keyProperty="id" parameterType="com.caimei365.order.model.po.PayShopPo" useGeneratedKeys="true">
+    <insert id="insertPayShop" keyColumn="id" keyProperty="id" parameterType="com.caimei365.order.model.po.PayShopPo"
+            useGeneratedKeys="true">
         INSERT INTO cm_pay_shop (shopID, name, bankAccountName, bankAccount, bankName, type, totalAmount, balancePayFee,
-                                 transferPayFee, payType, wipePayment, wipeRemarks, wipeRemarkImages, wipeTime, applicant,
+                                 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},
+        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" keyColumn="id" keyProperty="id" parameterType="com.caimei365.order.model.po.PayShopRecordPo" useGeneratedKeys="true">
-        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 id="insertPayShopRecord" keyColumn="id" keyProperty="id"
+            parameterType="com.caimei365.order.model.po.PayShopRecordPo" useGeneratedKeys="true">
+        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>
-    <insert id="insertUserVipInfo" keyColumn="id" keyProperty="id" parameterType="com.caimei365.order.model.po.UserVipPo">
+    <insert id="insertUserVipInfo" keyColumn="id" keyProperty="id"
+            parameterType="com.caimei365.order.model.po.UserVipPo">
         INSERT INTO cm_svip_user(userId, beginTime, endTime, delFlag, updateTime)
         VALUES (#{userId}, #{beginTime}, #{endTime}, #{delFlag}, #{updateTime})
     </insert>
@@ -71,55 +85,89 @@
         INSERT INTO auth_vip_user(authUserId, beginTime, endTime, delFlag, updateTime)
         VALUES (#{userId}, #{beginTime}, #{endTime}, #{delFlag}, #{updateTime})
     </insert>
-    <insert id="insertCouponRecord" keyColumn="id" keyProperty="id" parameterType="com.caimei365.order.model.po.CouponRecordPo" useGeneratedKeys="true">
-        INSERT INTO cm_coupon_buyrecord (couponId, userId) VALUES (#{couponId},#{userId})
+    <insert id="insertCouponRecord" keyColumn="id" keyProperty="id"
+            parameterType="com.caimei365.order.model.po.CouponRecordPo" useGeneratedKeys="true">
+        INSERT INTO cm_coupon_buyrecord (couponId, userId)
+        VALUES (#{couponId}, #{userId})
     </insert>
     <insert id="insertAuthVipRoleRelation">
-        INSERT INTO auth_role_user(user_id, role_id) VALUES(#{userId}, #{roleId})
+        INSERT INTO auth_role_user(user_id, role_id)
+        VALUES (#{userId}, #{roleId})
     </insert>
     <update id="updateUserVipInfo">
-        UPDATE cm_svip_user set userId=#{userId}, beginTime=#{beginTime}, endTime=#{endTime}, delFlag=#{delFlag}, updateTime=#{updateTime}
+        UPDATE cm_svip_user
+        set userId=#{userId},
+            beginTime=#{beginTime},
+            endTime=#{endTime},
+            delFlag=#{delFlag},
+            updateTime=#{updateTime}
         WHERE userId = #{userId}
     </update>
     <update id="updateVipPackageRecord">
-        UPDATE cm_svip_history set payStatus=#{payStatus},payWay=#{payWay},payType=#{payType},beginTime=#{beginTime},endTime=#{endTime},payTime=#{payTime}
+        UPDATE cm_svip_history
+        set payStatus=#{payStatus},
+            payWay=#{payWay},
+            payType=#{payType},
+            beginTime=#{beginTime},
+            endTime=#{endTime},
+            payTime=#{payTime}
         WHERE id = #{id}
     </update>
     <update id="updateOrderPayLink">
-        UPDATE cm_order_pay_link SET
-            orderId = #{orderId}, vipRecordId = #{vipRecordId}, authVipRecordId = #{authVipRecordId}, vipMonth = #{vipMonth}, linkLogo = #{linkLogo}, unpaidAmount = #{unpaidAmount}, generateTime = #{generateTime},
-            effectiveTime = #{effectiveTime}, payStatus = #{payStatus}, payType = #{payType}, delFlag = #{delFlag} , shopOrderId = #{shopOrderId}
+        UPDATE cm_order_pay_link
+        SET orderId         = #{orderId},
+            vipRecordId     = #{vipRecordId},
+            authVipRecordId = #{authVipRecordId},
+            vipMonth        = #{vipMonth},
+            linkLogo        = #{linkLogo},
+            unpaidAmount    = #{unpaidAmount},
+            generateTime    = #{generateTime},
+            effectiveTime   = #{effectiveTime},
+            payStatus       = #{payStatus},
+            payType         = #{payType},
+            delFlag         = #{delFlag},
+            shopOrderId     = #{shopOrderId}
         WHERE id = #{id}
     </update>
     <update id="updateOrderPayLinkStatus">
-        UPDATE cm_order_pay_link SET payStatus = #{payStatus}
+        UPDATE cm_order_pay_link
+        SET payStatus = #{payStatus}
         WHERE id = #{id}
     </update>
     <update id="updateSeconHandDetail">
         UPDATE cm_second_hand_detail
-        SET payType = #{payType}, payAmount = #{payAmount}, payFormData = #{payFormData}, payStatus = '2',payDate = NOW()
+        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 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 cm_receipt_order_relation
+        SET splitStatus = 1
+        WHERE mbOrderId = #{mbOrderId}
     </update>
     <update id="updateShopOrderByPayStatus">
-        UPDATE cm_shop_order SET
-        payStatus = #{payStatus}, payedShopAmount = #{paidShop}
+        UPDATE cm_shop_order
+        SET payStatus       = #{payStatus},
+            payedShopAmount = #{paidShop}
         WHERE shopOrderID = #{shopOrderId}
     </update>
     <update id="updateOrderByPayStatus">
-        UPDATE cm_order SET
-        payStatus = #{payStatus}
+        UPDATE cm_order
+        SET payStatus = #{payStatus}
         WHERE orderID = #{orderId}
     </update>
     <update id="updateUserMoney">
         UPDATE USER
         SET userMoney     = #{userMoney},
-        ableUserMoney = #{ableUserMoney}
+            ableUserMoney = #{ableUserMoney}
         WHERE userID = #{userId}
     </update>
     <update id="updateCouponRecord">
@@ -128,11 +176,22 @@
         where id = #{recordId}
     </update>
     <update id="updateAuthVipInfo">
-        UPDATE auth_vip_user set authUserId=#{userId}, beginTime=#{beginTime}, endTime=#{endTime}, delFlag=#{delFlag}, updateTime=#{updateTime}
+        UPDATE auth_vip_user
+        set authUserId=#{userId},
+            beginTime=#{beginTime},
+            endTime=#{endTime},
+            delFlag=#{delFlag},
+            updateTime=#{updateTime}
         WHERE authUserId = #{userId}
     </update>
     <update id="updateAuthVipRecord">
-        UPDATE auth_vip_history set payStatus=#{payStatus},payWay=#{payWay},payType=#{payType},beginTime=#{beginTime},endTime=#{endTime},payTime=#{payTime}
+        UPDATE auth_vip_history
+        set payStatus=#{payStatus},
+            payWay=#{payWay},
+            payType=#{payType},
+            beginTime=#{beginTime},
+            endTime=#{endTime},
+            payTime=#{payTime}
         WHERE id = #{id}
     </update>
     <update id="updateSplitAccount">
@@ -142,33 +201,41 @@
         WHERE orderRequestNo = #{orderRequestNo}
     </update>
     <update id="updateShopOrder">
-        UPDATE cm_shop_order SET
-        receiptStatus = #{receiptStatus}, receiptAmount = #{receiptAmount},paySuccessCounter =#{paySuccessCounter}
+        UPDATE cm_shop_order
+        SET receiptStatus     = #{receiptStatus},
+            receiptAmount     = #{receiptAmount},
+            paySuccessCounter =#{paySuccessCounter}
         WHERE shopOrderID = #{shopOrderId}
     </update>
     <update id="updateBySplitStatusByNo">
-        UPDATE cm_receipt_order_relation SET splitStatus = 1 WHERE orderRequestNo = #{orderRequestNo}
+        UPDATE cm_receipt_order_relation
+        SET splitStatus = 1
+        WHERE orderRequestNo = #{orderRequestNo}
     </update>
     <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 id="getRefundCount" resultType="java.lang.Integer">
         SELECT COUNT(*)
         FROM cm_returned_purchase
-        WHERE orderID = #{orderId} AND STATUS = '1' AND delFlag = '0'
+        WHERE orderID = #{orderId}
+          AND STATUS = '1'
+          AND delFlag = '0'
     </select>
     <select id="getOrderPayLink" resultType="com.caimei365.order.model.vo.OrderPayLinkVo">
         SELECT
-            id,
-            orderId,
-            vipRecordId,
-            linkLogo,
-            unpaidAmount,
-            generateTime,
-            effectiveTime,
-            payStatus,
-            payType,
-            delFlag
+        id,
+        orderId,
+        vipRecordId,
+        linkLogo,
+        unpaidAmount,
+        generateTime,
+        effectiveTime,
+        payStatus,
+        payType,
+        delFlag
         FROM
         cm_order_pay_link
         WHERE shopOrderId = #{orderId}
@@ -200,110 +267,134 @@
         ORDER BY id DESC LIMIT 1
     </select>
     <select id="getPayLinkByLinkLogo" resultType="com.caimei365.order.model.vo.OrderPayLinkVo">
-        SELECT
-            id,
-            shopOrderId,
-            orderId,
-            vipRecordId,
-            authVipRecordId,
-            vipMonth,
-            linkLogo,
-            unpaidAmount,
-            generateTime,
-            effectiveTime,
-            payStatus,
-            payType,
-            delFlag
-        FROM
-        cm_order_pay_link
+        SELECT id,
+               shopOrderId,
+               orderId,
+               vipRecordId,
+               authVipRecordId,
+               vipMonth,
+               linkLogo,
+               unpaidAmount,
+               generateTime,
+               effectiveTime,
+               payStatus,
+               payType,
+               delFlag
+        FROM cm_order_pay_link
         WHERE linkLogo = #{linkLogo}
-        AND delFlag = '0'
+          AND delFlag = '0'
     </select>
     <select id="getOrderPromotionsId" resultType="java.lang.Integer">
-        SELECT id FROM cm_promotions_order WHERE orderId = #{orderId} LIMIT 1
+        SELECT id
+        FROM cm_promotions_order
+        WHERE orderId = #{orderId}
+        LIMIT 1
     </select>
     <select id="getDbPaySuccessCounter" resultType="java.lang.Integer">
-        SELECT ifnull(paySuccessCounter,0) FROM cm_shop_order
-        WHERE shopOrderID = #{shopOrderId} AND delFlag = '0'
+        SELECT ifnull(paySuccessCounter, 0)
+        FROM cm_shop_order
+        WHERE shopOrderID = #{shopOrderId}
+          AND delFlag = '0'
     </select>
 
     <select id="getOpenidListByPermission" resultType="java.lang.String">
-        SELECT openid FROM `wechat_user` WHERE unionId= #{unionid}
+        SELECT openid
+        FROM `wechat_user`
+        WHERE unionId = #{unionid}
     </select>
 
     <select id="getSplitAccountList" resultType="com.caimei365.order.model.po.SplitAccountPo">
-        SELECT
-            id,
-            orderId,
-            productId,
-            orderProductId,
-            shopId,
-            type,
-            subUserNo,
-            SUM(splitAccount) AS splitAccount,
-            mbOrderId,
-            orderRequestNo,
-            payStatus,
-            productType
+        SELECT id,
+               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}
+        WHERE type = 4
+          AND payStatus = 1
+          AND splitAccount > 0
+          AND mbOrderId = #{mbOrderId}
         GROUP BY shopId
     </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}
+        WHERE STATUS = 1
+          AND delFlag = 0
+          AND shopOrderID = #{shopOrderId}
     </select>
     <select id="getUndividedPaidReceipt" resultType="com.caimei365.order.model.po.OrderReceiptRelationPo">
-        SELECT
-            cror.id,
-            cror.relationType,
-            cror.receiptId,
-            cror.associateAmount,
-            cror.orderId,
-            cror.delFlag,
-            cror.mbOrderId,
-            cror.orderRequestNo,
-            cror.splitStatus,
-            cdr.payType
+        SELECT cror.id,
+               cror.relationType,
+               cror.receiptId,
+               cror.associateAmount,
+               cror.orderId,
+               cror.delFlag,
+               cror.mbOrderId,
+               cror.orderRequestNo,
+               cror.splitStatus,
+               cdr.payType
         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 cror.delFlag = 0 AND cror.mbOrderId IS NOT NULL AND cror.splitStatus = 0
-        AND cdr.payWay = 1 AND cdr.receiptDate <![CDATA[  <=  ]]> #{currentTime}
-        AND co.organizeID = 0 AND co.orderType != 2 AND co.refundType != 2
+                 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 cror.delFlag = 0
+          AND cror.mbOrderId IS NOT NULL
+          AND cror.splitStatus = 0
+          AND cdr.payWay = 1
+          AND cdr.receiptDate <![CDATA[  <=  ]]> #{currentTime}
+          AND co.organizeID = 0
+          AND co.orderType != 2
+          AND co.refundType != 2
     </select>
     <select id="getOrderProductPaidAmount" resultType="java.lang.Double">
         SELECT SUM(splitAccount)
         FROM cm_split_account
         WHERE orderProductId = #{orderProductId}
-        AND payStatus = 1 AND productType = 1
+          AND payStatus = 1
+          AND productType = 1
     </select>
     <select id="getShopCommercialCode" resultType="java.lang.String">
-        SELECT commercialCode FROM cm_shop_splitcode WHERE shopID = #{shopId}
+        SELECT commercialCode
+        FROM cm_shop_splitcode
+        WHERE shopID = #{shopId}
         limit 1
     </select>
     <select id="getPaidShipping" resultType="java.lang.Double">
         SELECT SUM(splitAccount)
         FROM cm_split_account
         WHERE orderId = #{orderId}
-        AND shopId = #{shopId}
-        AND productType = 2 AND payStatus = 1
+          AND shopId = #{shopId}
+          AND productType = 2
+          AND payStatus = 1
     </select>
     <select id="getVipPackagePriceById" resultType="java.lang.Double">
-        SELECT price FROM cm_svip_package WHERE id = #{id};
+        SELECT price
+        FROM cm_svip_package
+        WHERE id = #{id};
     </select>
     <select id="getVipPackageDurationById" resultType="java.lang.Integer">
-        SELECT duration FROM cm_svip_package WHERE id = #{id};
+        SELECT duration
+        FROM cm_svip_package
+        WHERE id = #{id};
     </select>
     <select id="getVipPackageRecord" resultType="com.caimei365.order.model.bo.VipRecordBo">
-        SELECT id, userId, packageId, price, payStatus FROM cm_svip_history WHERE id = #{id};
+        SELECT id, userId, packageId, price, payStatus
+        FROM cm_svip_history
+        WHERE id = #{id};
     </select>
     <select id="getUserVipInfo" resultType="com.caimei365.order.model.po.UserVipPo">
-        SELECT id,userId, beginTime, endTime, updateTime, delFlag
+        SELECT id, userId, beginTime, endTime, updateTime, delFlag
         FROM cm_svip_user
-        WHERE userId = #{#userId} and endTime > now()
+        WHERE userId = #{#userId}
+          and endTime > now()
     </select>
     <select id="findBankCode" resultType="com.caimei365.order.model.vo.BankCodeVo">
         select id, bankName, B2C, B2B, bankLogo, delFlag
@@ -311,39 +402,49 @@
     </select>
     <select id="getCouponPrice" resultType="java.lang.Double">
         SELECT cc.moneyCouponPrice
-        FROM  cm_coupon cc
-        LEFT JOIN cm_coupon_buyrecord ccb ON cc.id=ccb.couponId
+        FROM cm_coupon cc
+                 LEFT JOIN cm_coupon_buyrecord ccb ON cc.id = ccb.couponId
         WHERE ccb.id = #{recordId}
     </select>
     <select id="findPayStatus" resultType="java.lang.Integer">
-        select payStatus from cm_coupon_buyrecord where id = #{recordId}
+        select payStatus
+        from cm_coupon_buyrecord
+        where id = #{recordId}
     </select>
     <select id="findClubType" resultType="java.lang.Integer">
-        SELECT firstClubType FROM club WHERE userId = #{userId}
+        SELECT firstClubType
+        FROM club
+        WHERE userId = #{userId}
     </select>
     <select id="findCouponOrder" resultType="com.caimei365.order.model.vo.CouponCheckVo">
-        SELECT cop.num,co.userId,cop.orderId,cop.productId
+        SELECT cop.num, co.userId, cop.orderId, cop.productId
         FROM cm_order_product cop
-        LEFT JOIN cm_order co ON cop.orderId = co.orderId
-        LEFT JOIN cm_coupon_buyrecord ccb ON ccb.orderId = co.orderId
-        WHERE cop.productId IN (7619,7620)
+                 LEFT JOIN cm_order co ON cop.orderId = co.orderId
+                 LEFT JOIN cm_coupon_buyrecord ccb ON ccb.orderId = co.orderId
+        WHERE cop.productId IN (7619, 7620)
           AND co.receiptStatus = 3
           AND co.delflag = 0
           AND cop.orderId NOT IN (SELECT orderId FROM cm_coupon_buyrecord WHERE orderId IS NOT NULL)
     </select>
     <select id="getAuthVipRecord" resultType="com.caimei365.order.model.bo.VipRecordBo">
-        SELECT id, authUserId as userId, packageId, price, payStatus FROM auth_vip_history WHERE id = #{authVipRecordId};
+        SELECT id, authUserId as userId, packageId, price, payStatus
+        FROM auth_vip_history
+        WHERE id = #{authVipRecordId};
     </select>
     <select id="getAuthVipPackagePrice" resultType="java.lang.Double">
-        SELECT price FROM auth_vip_package WHERE id = #{packageId};
+        SELECT price
+        FROM auth_vip_package
+        WHERE id = #{packageId};
     </select>
     <select id="getAuthVipInfo" resultType="com.caimei365.order.model.po.UserVipPo">
-        SELECT id,authUserId as userId, beginTime, endTime, updateTime, delFlag
+        SELECT id, authUserId as userId, beginTime, endTime, updateTime, delFlag
         FROM auth_vip_user
         WHERE authUserId = #{#userId}
     </select>
     <select id="getAuthVipPackageById" resultType="com.caimei365.order.model.po.AuthVipPackagePo">
-        select duration,unit,price from auth_vip_package where id =#{vipId}
+        select duration, unit, price
+        from auth_vip_package
+        where id = #{vipId}
     </select>
     <select id="getAuthVipPayLink" resultType="com.caimei365.order.model.vo.OrderPayLinkVo">
         SELECT
@@ -367,10 +468,14 @@
         ORDER BY id DESC LIMIT 1
     </select>
     <select id="findShopOrderSplitCode" resultType="java.lang.String">
-        select splitCode from cm_shop_order where shopOrderID = #{shopOrderId}
+        select splitCode
+        from cm_shop_order
+        where shopOrderID = #{shopOrderId}
     </select>
     <select id="getOrderId" resultType="java.lang.Integer">
-        select orderId from cm_shop_order where shopOrderID = #{shopOrderId}
+        select orderId
+        from cm_shop_order
+        where shopOrderID = #{shopOrderId}
     </select>
     <select id="findB2BBankCode" resultType="com.caimei365.order.model.vo.BankCodeVo">
         select id, bankName, B2B, bankLogo, delFlag
@@ -387,6 +492,23 @@
           and delFlag = 0
     </select>
     <select id="getSplitCodeByShopOrderId" resultType="java.lang.String">
-        select splitCode from cm_shop_order where shopOrderID = #{shopOrderId}
+        select splitCode
+        from cm_shop_order
+        where shopOrderID = #{shopOrderId}
+    </select>
+
+    <select id="getQuickPayUserInfo" resultType="com.caimei365.order.model.vo.QuickPayUserVo">
+        select userId,
+               quickPayUserId,
+               quickPaybindId,
+               idCard,
+               bankNumber,
+               bankExpireTime,
+               bankCvvCode,
+               bankType,
+               bindMobile,
+               bankUserName
+        from cm_quickpay_info
+        where userId = #{userId}
     </select>
 </mapper>