Procházet zdrojové kódy

快捷支付退款

zhijiezhao před 2 roky
rodič
revize
2cc6ff561a

+ 12 - 0
pom.xml

@@ -105,6 +105,18 @@
 	</pluginRepositories>
 	<!-- 依赖项定义 -->
 	<dependencies>
+		<dependency>
+			<groupId>cn.hutool</groupId>
+			<artifactId>hutool-crypto</artifactId>
+			<version>5.7.16</version>
+		</dependency>
+
+		<dependency>
+			<groupId>org.bouncycastle</groupId>
+			<artifactId>bcprov-jdk15to18</artifactId>
+			<version>1.69</version>
+		</dependency>
+
 		<dependency>
 			<groupId>org.projectlombok</groupId>
 			<artifactId>lombok</artifactId>

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

@@ -0,0 +1,18 @@
+package com.caimei.modules.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 "";
+}

+ 16 - 0
src/main/java/com/caimei/modules/order/annotation/FieldEncrypt.java

@@ -0,0 +1,16 @@
+package com.caimei.modules.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;
+
+
+@Target(FIELD)
+@Retention(RUNTIME)
+@Documented
+public @interface FieldEncrypt {
+	String value() default "";
+}

+ 16 - 0
src/main/java/com/caimei/modules/order/annotation/SignExclude.java

@@ -0,0 +1,16 @@
+package com.caimei.modules.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;
+
+
+@Target(FIELD)
+@Retention(RUNTIME)
+@Documented
+public @interface SignExclude {
+	String value() default "";
+}

+ 2 - 0
src/main/java/com/caimei/modules/order/dao/CmReturnedPurchaseDao.java

@@ -51,4 +51,6 @@ public interface CmReturnedPurchaseDao extends CrudDao<CmReturnedPurchase> {
     Integer findRefundType(Integer orderID);
 
     Double findShopOrderPaid(Integer shopOrderID);
+
+    String findSplitCodeEmail(String splitCode);
 }

+ 3 - 0
src/main/java/com/caimei/modules/order/entity/Constant.java

@@ -12,6 +12,9 @@ public class Constant {
 
     public static final String betaSplit = "https://core-b.caimei365.com/order/pay/delay/split/callback";
 
+    //快捷支付请求地址
+    public static final String REQUEST_URL_QUICKPAY = "http://quickpay.trx.helipay.com/trx/quickPayApi/interface.action";
+
     /**
      * 专票 信息 测试佣金暂入信息  308785626@qq.com vip/二手暂入信息
      */

+ 23 - 0
src/main/java/com/caimei/modules/order/entity/QuickPaySpRefundResponseVo.java

@@ -0,0 +1,23 @@
+package com.caimei.modules.order.entity;
+
+
+import com.caimei.modules.order.annotation.SignExclude;
+import lombok.Data;
+
+@Data
+public class QuickPaySpRefundResponseVo {
+
+    private String rt1_bizType;
+    private String rt2_retCode;
+    private String rt3_retMsg;
+    private String rt4_customerNumber;
+    private String rt5_orderId;
+    private String rt6_refundOrderId;
+    private String rt7_amount;
+    private String rt8_orderStatus;
+    @SignExclude
+    private String sign;
+    @SignExclude
+    private String signatureType;
+
+}

+ 26 - 0
src/main/java/com/caimei/modules/order/entity/QuickPaySpRefundVo.java

@@ -0,0 +1,26 @@
+package com.caimei.modules.order.entity;
+
+import com.caimei.modules.order.annotation.FieldEncrypt;
+import com.caimei.modules.order.annotation.SignExclude;
+import lombok.Data;
+
+@Data
+public class QuickPaySpRefundVo {
+
+    private String P1_bizType;
+
+    private String P2_orderId;
+
+    private String P3_customerNumber;
+
+    private String P4_refundOrderId;
+
+    @FieldEncrypt
+    private String P5_ruleJson;
+
+    private String P6_callbackUrl;
+
+    @SignExclude
+    private String signatureType;
+
+}

+ 46 - 11
src/main/java/com/caimei/modules/order/service/CmReturnedPurchaseService.java

@@ -108,7 +108,6 @@ public class CmReturnedPurchaseService extends CrudService<CmReturnedPurchaseDao
     private MessageCenterDao messageCenterDao;
 
 
-
     public CmReturnedPurchase get(String id) {
         return super.get(id);
     }
@@ -185,7 +184,7 @@ public class CmReturnedPurchaseService extends CrudService<CmReturnedPurchaseDao
         if (num <= 0) {
             return "请填写退货/取消数量";
         }
-        if(null!=cmReturnedPurchase.getRefundType()&&2==cmReturnedPurchase.getRefundType()){
+        if (null != cmReturnedPurchase.getRefundType() && 2 == cmReturnedPurchase.getRefundType()) {
             cmReturnedPurchase.setRefundFee(cmReturnedPurchase.getFreeRefundFee());
         }
         String id = cmReturnedPurchase.getId();//存在Id则是重申或者再次申请
@@ -579,7 +578,7 @@ public class CmReturnedPurchaseService extends CrudService<CmReturnedPurchaseDao
             }
             newOrderService.update(newOrder);
             //判断是否选择退回余额
-            if ((StringUtils.isNotBlank(returnedPurchase.getReturnedWay())&&"1".equals(returnedPurchase.getReturnedWay()) && returnedPurchase.getRefundBalanceFee() > 0d) || (null!=newOrder.getRechargeGoods()&&(1 == newOrder.getRechargeGoods() || 2 == newOrder.getRechargeGoods()))) {
+            if ((StringUtils.isNotBlank(returnedPurchase.getReturnedWay()) && "1".equals(returnedPurchase.getReturnedWay()) && returnedPurchase.getRefundBalanceFee() > 0d) || (null != newOrder.getRechargeGoods() && (1 == newOrder.getRechargeGoods() || 2 == newOrder.getRechargeGoods()))) {
                 Double userMoney = user.getUserMoney();
                 Double ableUserMoney = user.getAbleUserMoney();
                 Double refundBalanceFee = returnedPurchase.getRefundBalanceFee();
@@ -708,8 +707,8 @@ public class CmReturnedPurchaseService extends CrudService<CmReturnedPurchaseDao
                         Date date = new Date();
                         String curDateStr = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(date);
                         //推送信息中心-交易物流
-                       Integer clubId= messageCenterDao.clubIdCule(newOrder.getUserID());
-                        MessageCenter messageCenter=new MessageCenter();
+                        Integer clubId = messageCenterDao.clubIdCule(newOrder.getUserID());
+                        MessageCenter messageCenter = new MessageCenter();
                         messageCenter.setShopId(null);
                         messageCenter.setClubId(clubId);
                         messageCenter.setUserType(1);
@@ -720,21 +719,21 @@ public class CmReturnedPurchaseService extends CrudService<CmReturnedPurchaseDao
                         messageCenter.setTime(curDateStr);
                         messageCenterDao.addMessageCenter(messageCenter);
                         //部分退
-                        String name=newOrder.getProductName();
+                        String name = newOrder.getProductName();
                         if (name.length() > 10) {
                             name = StringUtils.strip(name.substring(0, 11));
                             name += "...";
                         }
                         String shortLink = newOrderService.getShortLink(8, 9, wwwServer + "user/order/detail.html?orderId=" + newOrder.getOrderID());
-                        String content = "【采美365】订单("+name+"等"+productCount+"件商品)已全部退款成功,退款金额¥"+returnedPurchase.getRefundFee()+"。您可点击采美网址www.caimei.com 或使用微信小程序“采美采购商城”查看订单。";
+                        String content = "【采美365】订单(" + name + "等" + productCount + "件商品)已全部退款成功,退款金额¥" + returnedPurchase.getRefundFee() + "。您可点击采美网址www.caimei.com 或使用微信小程序“采美采购商城”查看订单。";
                         sendSms = newOrderService.getSendSms(9, user.getBindMobile(), content);
                     } else if ("2".equals(newOrder.getRefundType())) {
 
                         Date date = new Date();
                         String curDateStr = (new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")).format(date);
                         //推送信息中心-交易物流
-                        Integer clubId= messageCenterDao.clubIdCule(newOrder.getUserID());
-                        MessageCenter messageCenter=new MessageCenter();
+                        Integer clubId = messageCenterDao.clubIdCule(newOrder.getUserID());
+                        MessageCenter messageCenter = new MessageCenter();
                         messageCenter.setShopId(null);
                         messageCenter.setClubId(clubId);
                         messageCenter.setUserType(1);
@@ -745,13 +744,13 @@ public class CmReturnedPurchaseService extends CrudService<CmReturnedPurchaseDao
                         messageCenter.setTime(curDateStr);
                         messageCenterDao.addMessageCenter(messageCenter);
                         //全部退
-                        String name=newOrder.getProductName();
+                        String name = newOrder.getProductName();
                         if (name.length() > 10) {
                             name = StringUtils.strip(name.substring(0, 11));
                             name += "...";
                         }
                         String shortLink = newOrderService.getShortLink(8, 10, wwwServer + "user/order/detail.html?orderId=" + newOrder.getOrderID());
-                        String content = "【采美365】订单("+name+"等"+productCount+"件商品)已部份退款成功,退款金额¥"+returnedPurchase.getRefundFee()+"。您可点击采美网址www.caimei.com 或使用微信小程序“采美采购商城”查看订单。";
+                        String content = "【采美365】订单(" + name + "等" + productCount + "件商品)已部份退款成功,退款金额¥" + returnedPurchase.getRefundFee() + "。您可点击采美网址www.caimei.com 或使用微信小程序“采美采购商城”查看订单。";
                         sendSms = newOrderService.getSendSms(10, user.getBindMobile(), content);
                     }
                     if (!sendSms) {
@@ -852,6 +851,42 @@ public class CmReturnedPurchaseService extends CrudService<CmReturnedPurchaseDao
                         }
                         //网银
                         unionRefund(orderRelation.getOrderRequestNo(), value, orderRelation.getShopOrderId());
+                    } else if ("28".equals(orderRelation.getPayType()) || "29".equals(orderRelation.getPayType())) {
+                        //快捷支付
+                        QuickPaySpRefundVo quickPaySpRefundVo = new QuickPaySpRefundVo();
+                        quickPaySpRefundVo.setP1_bizType("QuickPaySpRefund");
+                        quickPaySpRefundVo.setP2_orderId(orderRelation.getOrderRequestNo());
+                        String splitCode = cmReturnedPurchaseDao.findSplitCode(orderRelation.getShopOrderId());
+                        quickPaySpRefundVo.setP3_customerNumber(splitCode);
+                        quickPaySpRefundVo.setP4_refundOrderId("ref" + orderRelation.getOrderRequestNo());
+                        /**
+                         * [{ 'splitBillMerchantEmail': 'xun.zhang@caimei365.com','refundAmount': 0.12}]
+                         */
+                        String email = cmReturnedPurchaseDao.findSplitCodeEmail(splitCode);
+                        String refundJson = "[{ 'splitBillMerchantEmail': " + email + ",'refundAmount': " + value + "}]";
+                        quickPaySpRefundVo.setP5_ruleJson(refundJson);
+                        quickPaySpRefundVo.setP6_callbackUrl("");
+                        quickPaySpRefundVo.setSignatureType("SM3WITHSM2");
+                        Map reqestMap = MessageHandle.getReqestMap(quickPaySpRefundVo);
+                        Map<String, Object> resultMap = HttpClientService.getHttpResp(reqestMap, Constant.REQUEST_URL_QUICKPAY);
+                        if ((Integer) resultMap.get("statusCode") != HttpStatus.SC_OK) {
+                            logger.info("-------------------快捷支付退款请求失败---------------");
+                        } else {
+                            String resultMsg = (String) resultMap.get("response");
+                            QuickPaySpRefundResponseVo responseVo = JSONObject.parseObject(resultMsg, QuickPaySpRefundResponseVo.class);
+                            logger.info("--------------------->快捷支付退款json: " + JSONObject.toJSON(responseVo));
+                            if (!MessageHandle.checkSign(responseVo)) {
+                                logger.info("---------------快捷支付退款验签失败------------------");
+                            } else {
+                                if ("0000".equals(responseVo.getRt2_retCode())) {
+                                    CmRefundRecord cmRefundRecord = new CmRefundRecord();
+                                    cmRefundRecord.setRefundAmount(Double.parseDouble(value));
+                                    cmRefundRecord.setOrderRequestNo(orderRelation.getOrderRequestNo());
+                                    cmRefundRecord.setShopOrderId(orderRelation.getShopOrderId());
+                                    cmReturnedPurchaseDao.insertCmRefundRecord(cmRefundRecord);
+                                }
+                            }
+                        }
                     } else {
                         // 已分帐应该先转回佣金
                         if (1 == orderRelation.getSplitStatus()) {

+ 72 - 0
src/main/java/com/caimei/modules/order/utils/HeliPayCertConfig.java

@@ -0,0 +1,72 @@
+package com.caimei.modules.order.utils;
+
+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/caimei/modules/order/utils/HeliPayCertUtils.java

@@ -0,0 +1,81 @@
+package com.caimei.modules.order.utils;
+
+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);
+    }
+
+}

+ 118 - 0
src/main/java/com/caimei/modules/order/utils/MessageHandle.java

@@ -0,0 +1,118 @@
+package com.caimei.modules.order.utils;
+
+
+
+import com.caimei.modules.order.annotation.FieldEncrypt;
+import com.caimei.modules.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/caimei/modules/order/utils/SM2Utils.java

@@ -0,0 +1,94 @@
+package com.caimei.modules.order.utils;
+
+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/caimei/modules/order/utils/SM4Utils.java

@@ -0,0 +1,100 @@
+package com.caimei.modules.order.utils;
+
+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);
+    }
+}

+ 382 - 364
src/main/resources/mappings/modules/order/CmReturnedPurchaseMapper.xml

@@ -2,8 +2,8 @@
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
 <mapper namespace="com.caimei.modules.order.dao.CmReturnedPurchaseDao">
 
-	<sql id="cmReturnedPurchaseColumns">
-		a.id AS "id",
+    <sql id="cmReturnedPurchaseColumns">
+        a.id AS "id",
 		a.returnedNo AS "returnedNo",
 		a.orderID AS "orderID",
 		a.userID AS "userID",
@@ -42,431 +42,449 @@
 		c.name as "name",
 		c.userOrganizeID as "userOrganizeId",
 		ifnull(a.refundType,1) as "refundType"
-	</sql>
+    </sql>
 
-	<sql id="cmReturnedPurchaseJoins">
-		left join cm_order as b on a.orderID = b.orderID
+    <sql id="cmReturnedPurchaseJoins">
+        left join cm_order as b on a.orderID = b.orderID
 		left join user as c on a.userID = c.userID
-	</sql>
+    </sql>
 
-	<select id="get" resultType="CmReturnedPurchase">
-		SELECT
-			<include refid="cmReturnedPurchaseColumns"/>
-		FROM cm_returned_purchase a
-		<include refid="cmReturnedPurchaseJoins"/>
-		WHERE a.id = #{id}
+    <select id="get" resultType="CmReturnedPurchase">
+        SELECT
+        <include refid="cmReturnedPurchaseColumns"/>
+        FROM cm_returned_purchase a
+        <include refid="cmReturnedPurchaseJoins"/>
+        WHERE a.id = #{id}
         and a.delFlag = 0
-	</select>
+    </select>
 
-	<!--查询排除当前撤销的退货退款记录-->
-	<select id="findReturnedPurchaseRecord" resultType="CmReturnedPurchase">
-		SELECT
-		a.*
-		FROM cm_returned_purchase a
-		<where>
-			<if test="id != null and id != ''">
-				AND a.id != #{id}
-			</if>
-			<if test="orderID != null and orderID != ''">
-				AND a.orderID = #{orderID}
-			</if>
-			<if test="status != null and status != ''">
-				AND a.status = #{status}
-			</if>
-			and a.delFlag = 0
-		</where>
-	</select>
+    <!--查询排除当前撤销的退货退款记录-->
+    <select id="findReturnedPurchaseRecord" resultType="CmReturnedPurchase">
+        SELECT
+        a.*
+        FROM cm_returned_purchase a
+        <where>
+            <if test="id != null and id != ''">
+                AND a.id != #{id}
+            </if>
+            <if test="orderID != null and orderID != ''">
+                AND a.orderID = #{orderID}
+            </if>
+            <if test="status != null and status != ''">
+                AND a.status = #{status}
+            </if>
+            and a.delFlag = 0
+        </where>
+    </select>
 
-	<!--只查询审核通过的数据-->
-	<select id="findListBuySuccess" resultType="CmReturnedPurchase">
-		SELECT
-		a.*
-		FROM cm_returned_purchase a
-		<where>
-			<if test="id != null and id != ''">
-				AND a.id = #{id}
-			</if>
-			<if test="orderID != null and orderID != ''">
-				AND a.orderID = #{orderID}
-			</if>
-			AND a.status = 2
-			and a.delFlag = 0
-		</where>
-	</select>
+    <!--只查询审核通过的数据-->
+    <select id="findListBuySuccess" resultType="CmReturnedPurchase">
+        SELECT
+        a.*
+        FROM cm_returned_purchase a
+        <where>
+            <if test="id != null and id != ''">
+                AND a.id = #{id}
+            </if>
+            <if test="orderID != null and orderID != ''">
+                AND a.orderID = #{orderID}
+            </if>
+            AND a.status = 2
+            and a.delFlag = 0
+        </where>
+    </select>
 
 
-	<select id="findList" resultType="CmReturnedPurchase">
-		SELECT
-			<include refid="cmReturnedPurchaseColumns"/>
-		,s.name AS "applicationUserName",
-		s1.name AS "reviewUserName",
-		co.organizeID AS "organizeID",
-		f.bankAccount as bankNameType
-		FROM cm_returned_purchase a
-		LEFT JOIN sys_user s on s.id = a.applicationUserID
-		LEFT JOIN sys_user s1 on s1.id = a.reviewUserID
-		LEFT JOIN cm_order co ON a.orderID=co.orderID
-		LEFT JOIN cm_offline_collection f ON a.payType = f.type
-		<include refid="cmReturnedPurchaseJoins"/>
-		<where>
-			<if test="organizeID != null and organizeID != ''">
-				AND co.organizeID = #{organizeID}
-			</if>
-			<if test="orderType == 2">
-				AND co.orderType = 2
-			</if>
+    <select id="findList" resultType="CmReturnedPurchase">
+        SELECT
+        <include refid="cmReturnedPurchaseColumns"/>
+        ,s.name AS "applicationUserName",
+        s1.name AS "reviewUserName",
+        co.organizeID AS "organizeID",
+        f.bankAccount as bankNameType
+        FROM cm_returned_purchase a
+        LEFT JOIN sys_user s on s.id = a.applicationUserID
+        LEFT JOIN sys_user s1 on s1.id = a.reviewUserID
+        LEFT JOIN cm_order co ON a.orderID=co.orderID
+        LEFT JOIN cm_offline_collection f ON a.payType = f.type
+        <include refid="cmReturnedPurchaseJoins"/>
+        <where>
+            <if test="organizeID != null and organizeID != ''">
+                AND co.organizeID = #{organizeID}
+            </if>
+            <if test="orderType == 2">
+                AND co.orderType = 2
+            </if>
             <if test="id != null and id != ''">
                 AND a.id = #{id}
             </if>
-			<if test="returnedNo != null and returnedNo != ''">
-				AND a.returnedNo = #{returnedNo}
-			</if>
-			<if test="orderID != null and orderID != ''">
-				AND a.orderID = #{orderID}
-			</if>
-			<if test="userID != null and userID != ''">
-				AND a.userID = #{userID}
-			</if>
-			<if test="status != null and status != ''">
-				AND a.status = #{status}
-			</if>
-			<if test="returnTime != null and returnTime != ''">
-				AND a.returnTime = #{returnTime}
-			</if>
-			<if test="confirmReturnTime != null and confirmReturnTime != ''">
-				AND a.confirmReturnTime = #{confirmReturnTime}
-			</if>
-			<if test="beginTime != null and beginTime != ''">
-				AND returnTime <![CDATA[  >=  ]]> #{beginTime}
-			</if>
-			<if test="endTime != null and endTime != ''">
-				AND returnTime <![CDATA[  <=  ]]> #{endTime}
-			</if>
-			<if test="beginConfirmReturnTime != null and beginConfirmReturnTime != ''">
-				AND STR_TO_DATE(confirmReturnTime,'%Y-%m-%d %H:%i') <![CDATA[  >  ]]> STR_TO_DATE(#{beginConfirmReturnTime},'%Y-%m-%d %H:%i')
-			</if>
-			<if test="endConfirmReturnTime != null and endConfirmReturnTime != ''">
-				AND STR_TO_DATE(confirmReturnTime,'%Y-%m-%d %H:%i') <![CDATA[  <  ]]> STR_TO_DATE(#{endConfirmReturnTime},'%Y-%m-%d %H:%i')
-			</if>
-			<if test="name != null and name != ''">
-				AND c.name like
-				<if test="dbName == 'oracle'">'%'||#{name}||'%'</if>
-				<if test="dbName == 'mssql'">'%'+#{name}+'%'</if>
-				<if test="dbName == 'mysql'">concat('%',#{name},'%')</if>
-			</if>
-			<if test="orderNo != null and orderNo != ''">
-				AND b.orderNo = #{orderNo}
-			</if>
+            <if test="returnedNo != null and returnedNo != ''">
+                AND a.returnedNo = #{returnedNo}
+            </if>
+            <if test="orderID != null and orderID != ''">
+                AND a.orderID = #{orderID}
+            </if>
+            <if test="userID != null and userID != ''">
+                AND a.userID = #{userID}
+            </if>
+            <if test="status != null and status != ''">
+                AND a.status = #{status}
+            </if>
+            <if test="returnTime != null and returnTime != ''">
+                AND a.returnTime = #{returnTime}
+            </if>
+            <if test="confirmReturnTime != null and confirmReturnTime != ''">
+                AND a.confirmReturnTime = #{confirmReturnTime}
+            </if>
+            <if test="beginTime != null and beginTime != ''">
+                AND returnTime <![CDATA[  >=  ]]> #{beginTime}
+            </if>
+            <if test="endTime != null and endTime != ''">
+                AND returnTime <![CDATA[  <=  ]]> #{endTime}
+            </if>
+            <if test="beginConfirmReturnTime != null and beginConfirmReturnTime != ''">
+                AND STR_TO_DATE(confirmReturnTime,'%Y-%m-%d %H:%i') <![CDATA[  >  ]]>
+                STR_TO_DATE(#{beginConfirmReturnTime},'%Y-%m-%d %H:%i')
+            </if>
+            <if test="endConfirmReturnTime != null and endConfirmReturnTime != ''">
+                AND STR_TO_DATE(confirmReturnTime,'%Y-%m-%d %H:%i') <![CDATA[  <  ]]>
+                STR_TO_DATE(#{endConfirmReturnTime},'%Y-%m-%d %H:%i')
+            </if>
+            <if test="name != null and name != ''">
+                AND c.name like
+                <if test="dbName == 'oracle'">'%'||#{name}||'%'</if>
+                <if test="dbName == 'mssql'">'%'+#{name}+'%'</if>
+                <if test="dbName == 'mysql'">concat('%',#{name},'%')</if>
+            </if>
+            <if test="orderNo != null and orderNo != ''">
+                AND b.orderNo = #{orderNo}
+            </if>
             and a.delFlag = 0
-		</where>
-		<choose>
-			<when test="page !=null and page.orderBy != null and page.orderBy != ''">
-				ORDER BY ${page.orderBy}
-			</when>
-			<otherwise>
-				order by a.returnTime desc
-			</otherwise>
-		</choose>
-	</select>
+        </where>
+        <choose>
+            <when test="page !=null and page.orderBy != null and page.orderBy != ''">
+                ORDER BY ${page.orderBy}
+            </when>
+            <otherwise>
+                order by a.returnTime desc
+            </otherwise>
+        </choose>
+    </select>
 
-	<select id="findAllList" resultType="CmReturnedPurchase">
-		SELECT
-			<include refid="cmReturnedPurchaseColumns"/>
-		FROM cm_returned_purchase a
-		<include refid="cmReturnedPurchaseJoins"/>
-		<where>
-             a.delFlag = 0
-		</where>
-		<choose>
-			<when test="page !=null and page.orderBy != null and page.orderBy != ''">
-				ORDER BY ${page.orderBy}
-			</when>
-			<otherwise>
-			</otherwise>
-		</choose>
-	</select>
+    <select id="findAllList" resultType="CmReturnedPurchase">
+        SELECT
+        <include refid="cmReturnedPurchaseColumns"/>
+        FROM cm_returned_purchase a
+        <include refid="cmReturnedPurchaseJoins"/>
+        <where>
+            a.delFlag = 0
+        </where>
+        <choose>
+            <when test="page !=null and page.orderBy != null and page.orderBy != ''">
+                ORDER BY ${page.orderBy}
+            </when>
+            <otherwise>
+            </otherwise>
+        </choose>
+    </select>
 
-	<insert id="insert" parameterType="CmReturnedPurchase"  keyProperty="id" useGeneratedKeys="true">
-		INSERT INTO cm_returned_purchase(
-			returnedNo,
-			orderID,
-			userID,
-			status,
-			returnedWay,
-			payType,
-			operatingOrderStatus,
-			bankAccountName,
-			bankAccountNo,
-			openBank,
-			bankAccountType,
-			returnedPurchaseFee,
-			refundFee,
-			refundBalanceFee,
-			refundOnlineFee,
-			refundOfflineFee,
-			image1,
-			image2,
-			image3,
-			image4,
-			image5,
-			remarks,
-			reviewRemarks,
-			applicationUserID,
-			returnTime,
-			reviewUserID,
-			confirmReturnTime,
-            refundType
-		) VALUES (
-			#{returnedNo},
-			#{orderID},
-			#{userID},
-			#{status},
-			#{returnedWay},
-			#{payType},
-			#{operatingOrderStatus},
-			#{bankAccountName},
-			#{bankAccountNo},
-			#{openBank},
-			#{bankAccountType},
-			#{returnedPurchaseFee},
-			#{refundFee},
-			#{refundBalanceFee},
-			#{refundOnlineFee},
-			#{refundOfflineFee},
-			#{image1},
-			#{image2},
-			#{image3},
-			#{image4},
-			#{image5},
-			#{remarks},
-			#{reviewRemarks},
-			#{applicationUserID},
-			#{returnTime},
-			#{reviewUserID},
-			#{confirmReturnTime},
-		    #{refundType}
-		)
-	</insert>
-	<insert id="insertCmRefundRecord">
-		insert into cm_refundmoney_record
-		(refundAmount,orderRequestNo,shopOrderId)
-		values(#{refundAmount},#{orderRequestNo},#{shopOrderId})
-	</insert>
+    <insert id="insert" parameterType="CmReturnedPurchase" keyProperty="id" useGeneratedKeys="true">
+        INSERT INTO cm_returned_purchase(returnedNo,
+                                         orderID,
+                                         userID,
+                                         status,
+                                         returnedWay,
+                                         payType,
+                                         operatingOrderStatus,
+                                         bankAccountName,
+                                         bankAccountNo,
+                                         openBank,
+                                         bankAccountType,
+                                         returnedPurchaseFee,
+                                         refundFee,
+                                         refundBalanceFee,
+                                         refundOnlineFee,
+                                         refundOfflineFee,
+                                         image1,
+                                         image2,
+                                         image3,
+                                         image4,
+                                         image5,
+                                         remarks,
+                                         reviewRemarks,
+                                         applicationUserID,
+                                         returnTime,
+                                         reviewUserID,
+                                         confirmReturnTime,
+                                         refundType)
+        VALUES (#{returnedNo},
+                #{orderID},
+                #{userID},
+                #{status},
+                #{returnedWay},
+                #{payType},
+                #{operatingOrderStatus},
+                #{bankAccountName},
+                #{bankAccountNo},
+                #{openBank},
+                #{bankAccountType},
+                #{returnedPurchaseFee},
+                #{refundFee},
+                #{refundBalanceFee},
+                #{refundOnlineFee},
+                #{refundOfflineFee},
+                #{image1},
+                #{image2},
+                #{image3},
+                #{image4},
+                #{image5},
+                #{remarks},
+                #{reviewRemarks},
+                #{applicationUserID},
+                #{returnTime},
+                #{reviewUserID},
+                #{confirmReturnTime},
+                #{refundType})
+    </insert>
+    <insert id="insertCmRefundRecord">
+        insert into cm_refundmoney_record
+            (refundAmount, orderRequestNo, shopOrderId)
+        values (#{refundAmount}, #{orderRequestNo}, #{shopOrderId})
+    </insert>
 
-	<update id="updateRevokeApply">
-		UPDATE cm_returned_purchase
-		<set>
-			status = #{status},
-			reviewImage1 = #{reviewImage1},
-			reviewImage1 = #{reviewImage2},
-			reviewImage1 = #{reviewImage3},
-			reviewImage1 = #{reviewImage4},
-			reviewImage1 = #{reviewImage5},
-			reviewRemarks = #{reviewRemarks},
-			applicationUserID = #{applicationUserID},
-			confirmReturnTime = #{confirmReturnTime},
-			reviewUserID = #{reviewUserID},
-		</set>
-		WHERE id = #{id}
-	</update>
+    <update id="updateRevokeApply">
+        UPDATE cm_returned_purchase
+        <set>
+            status = #{status},
+            reviewImage1 = #{reviewImage1},
+            reviewImage1 = #{reviewImage2},
+            reviewImage1 = #{reviewImage3},
+            reviewImage1 = #{reviewImage4},
+            reviewImage1 = #{reviewImage5},
+            reviewRemarks = #{reviewRemarks},
+            applicationUserID = #{applicationUserID},
+            confirmReturnTime = #{confirmReturnTime},
+            reviewUserID = #{reviewUserID},
+        </set>
+        WHERE id = #{id}
+    </update>
 
 
-	<update id="update">
-		UPDATE cm_returned_purchase
+    <update id="update">
+        UPDATE cm_returned_purchase
         <set>
-            <if test="returnedNo != null and returnedNo != ''" >
+            <if test="returnedNo != null and returnedNo != ''">
                 returnedNo = #{returnedNo},
             </if>
-            <if test="orderID != null and orderID != ''" >
+            <if test="orderID != null and orderID != ''">
                 orderID = #{orderID},
             </if>
-            <if test="userID != null and userID != ''" >
+            <if test="userID != null and userID != ''">
                 userID = #{userID},
             </if>
-            <if test="status != null and status != ''" >
+            <if test="status != null and status != ''">
                 status = #{status},
             </if>
-            <if test="returnedWay != null and returnedWay != ''" >
+            <if test="returnedWay != null and returnedWay != ''">
                 returnedWay = #{returnedWay},
             </if>
-			<if test="payType != null and payType != ''" >
-				payType = #{payType},
-			</if>
-			<if test="operatingOrderStatus != null and operatingOrderStatus != ''" >
-				operatingOrderStatus = #{operatingOrderStatus},
-			</if>
-			<if test="bankAccountName != null and bankAccountName != ''" >
-				bankAccountName = #{bankAccountName},
-			</if>
-			<if test="bankAccountNo != null and bankAccountNo != ''" >
-				bankAccountNo = #{bankAccountNo},
-			</if>
-			<if test="openBank != null and openBank != ''" >
-				openBank = #{openBank},
-			</if>
-			<if test="bankAccountType != null and bankAccountType != ''" >
-				bankAccountType = #{bankAccountType},
-			</if>
-            <if test="returnedPurchaseFee != null " >
+            <if test="payType != null and payType != ''">
+                payType = #{payType},
+            </if>
+            <if test="operatingOrderStatus != null and operatingOrderStatus != ''">
+                operatingOrderStatus = #{operatingOrderStatus},
+            </if>
+            <if test="bankAccountName != null and bankAccountName != ''">
+                bankAccountName = #{bankAccountName},
+            </if>
+            <if test="bankAccountNo != null and bankAccountNo != ''">
+                bankAccountNo = #{bankAccountNo},
+            </if>
+            <if test="openBank != null and openBank != ''">
+                openBank = #{openBank},
+            </if>
+            <if test="bankAccountType != null and bankAccountType != ''">
+                bankAccountType = #{bankAccountType},
+            </if>
+            <if test="returnedPurchaseFee != null ">
                 returnedPurchaseFee = #{returnedPurchaseFee},
             </if>
-            <if test="refundFee != null" >
+            <if test="refundFee != null">
                 refundFee = #{refundFee},
             </if>
-			<if test="refundBalanceFee != null" >
-				refundBalanceFee = #{refundBalanceFee},
-			</if>
-			<if test="refundOnlineFee != null" >
-				refundOnlineFee = #{refundOnlineFee},
-			</if>
-			<if test="refundOfflineFee != null" >
-				refundOfflineFee = #{refundOfflineFee},
-			</if>
-            <if test="image1 != null and image1 != ''" >
+            <if test="refundBalanceFee != null">
+                refundBalanceFee = #{refundBalanceFee},
+            </if>
+            <if test="refundOnlineFee != null">
+                refundOnlineFee = #{refundOnlineFee},
+            </if>
+            <if test="refundOfflineFee != null">
+                refundOfflineFee = #{refundOfflineFee},
+            </if>
+            <if test="image1 != null and image1 != ''">
                 image1 = #{image1},
             </if>
-            <if test="image2 != null and image2 != ''" >
+            <if test="image2 != null and image2 != ''">
                 image2 = #{image2},
             </if>
-            <if test="image3 != null and image3 != ''" >
+            <if test="image3 != null and image3 != ''">
                 image3 = #{image3},
             </if>
-            <if test="image4 != null and image4 != ''" >
+            <if test="image4 != null and image4 != ''">
                 image4 = #{image4},
             </if>
-            <if test="image5 != null and image5 != ''" >
+            <if test="image5 != null and image5 != ''">
                 image5 = #{image5},
             </if>
-            <if test="remarks != null and remarks != ''" >
+            <if test="remarks != null and remarks != ''">
                 remarks = #{remarks},
             </if>
-			<if test="reviewRemarks != null and reviewRemarks != ''" >
-				reviewRemarks = #{reviewRemarks},
-			</if>
-			<if test="applicationUserID != null and applicationUserID != ''" >
-				applicationUserID = #{applicationUserID},
-			</if>
-			<if test="reviewUserID != null and reviewUserID != ''" >
-				reviewUserID = #{reviewUserID},
-			</if>
-            <if test="reviewImage1 != null and reviewImage1 != ''" >
+            <if test="reviewRemarks != null and reviewRemarks != ''">
+                reviewRemarks = #{reviewRemarks},
+            </if>
+            <if test="applicationUserID != null and applicationUserID != ''">
+                applicationUserID = #{applicationUserID},
+            </if>
+            <if test="reviewUserID != null and reviewUserID != ''">
+                reviewUserID = #{reviewUserID},
+            </if>
+            <if test="reviewImage1 != null and reviewImage1 != ''">
                 reviewImage1 = #{reviewImage1},
             </if>
-            <if test="reviewImage2 != null and reviewImage2 != ''" >
+            <if test="reviewImage2 != null and reviewImage2 != ''">
                 reviewImage2 = #{reviewImage2},
             </if>
-            <if test="reviewImage3 != null and reviewImage3 != ''" >
+            <if test="reviewImage3 != null and reviewImage3 != ''">
                 reviewImage3 = #{reviewImage3},
             </if>
-            <if test="reviewImage4 != null and reviewImage4 != ''" >
+            <if test="reviewImage4 != null and reviewImage4 != ''">
                 reviewImage4 = #{reviewImage4},
             </if>
-            <if test="reviewImage5 != null and reviewImage5 != ''" >
+            <if test="reviewImage5 != null and reviewImage5 != ''">
                 reviewImage5 = #{reviewImage5},
             </if>
-            <if test="returnTime != null and returnTime != ''" >
+            <if test="returnTime != null and returnTime != ''">
                 returnTime = #{returnTime},
             </if>
-            <if test="confirmReturnTime != null and confirmReturnTime != ''" >
+            <if test="confirmReturnTime != null and confirmReturnTime != ''">
                 confirmReturnTime = #{confirmReturnTime},
             </if>
-			<if test="delFlag != null and delFlag != ''" >
-				delFlag = #{delFlag},
-			</if>
-		    <if test="refundType != null">
-				refundType = #{refundType},
-			</if>
+            <if test="delFlag != null and delFlag != ''">
+                delFlag = #{delFlag},
+            </if>
+            <if test="refundType != null">
+                refundType = #{refundType},
+            </if>
         </set>
 
-		WHERE id = #{id}
-	</update>
+        WHERE id = #{id}
+    </update>
 
-	<delete id="delete">
-		DELETE FROM cm_returned_purchase
-		WHERE id = #{id}
-	</delete>
+    <delete id="delete">
+        DELETE
+        FROM cm_returned_purchase
+        WHERE id = #{id}
+    </delete>
 
-	<select id="findOrderIDInReturnPurchase" resultType="integer">
-		select orderID from cm_returned_purchase where status = '1'
-		and orderID in
-		<foreach collection="orderIds" open="(" close=")" item="oId" separator=",">
-			#{oId}
-		</foreach>
-		and delFlag = 0
-	</select>
+    <select id="findOrderIDInReturnPurchase" resultType="integer">
+        select orderID from cm_returned_purchase where status = '1'
+        and orderID in
+        <foreach collection="orderIds" open="(" close=")" item="oId" separator=",">
+            #{oId}
+        </foreach>
+        and delFlag = 0
+    </select>
 
-	<select id="findOrderIDsInApplyReturnFlag" resultType="integer">
-		select orderID from cm_returned_purchase where status in (1,3)
-		and orderID in
-		<foreach collection="orderIds" open="(" close=")" item="oId" separator=",">
-			#{oId}
-		</foreach>
-		and delFlag = 0
-	</select>
+    <select id="findOrderIDsInApplyReturnFlag" resultType="integer">
+        select orderID from cm_returned_purchase where status in (1,3)
+        and orderID in
+        <foreach collection="orderIds" open="(" close=")" item="oId" separator=",">
+            #{oId}
+        </foreach>
+        and delFlag = 0
+    </select>
 
-	<select id="refundTotalMoney" resultType="double">
-		SELECT SUM(IFNULL(returnedPurchaseFee,0)) FROM cm_returned_purchase
-		WHERE orderID=#{orderID} AND delFlag='0' AND status='2'
-	</select>
-	<select id="findReturnedShopOrder" resultType="java.lang.Integer">
-		SELECT shopOrderId FROM cm_returned_purchase_product crpp
-		LEFT JOIN cm_returned_purchase crp ON crp.id=crpp.returnedID
-		WHERE crp.orderId=#{orderID}
-		  AND crp.status=2
-		  AND crp.returnedWay =1
-		  AND crp.delflag=0
-	</select>
+    <select id="refundTotalMoney" resultType="double">
+        SELECT SUM(IFNULL(returnedPurchaseFee, 0))
+        FROM cm_returned_purchase
+        WHERE orderID = #{orderID}
+          AND delFlag = '0'
+          AND status = '2'
+    </select>
+    <select id="findReturnedShopOrder" resultType="java.lang.Integer">
+        SELECT shopOrderId
+        FROM cm_returned_purchase_product crpp
+                 LEFT JOIN cm_returned_purchase crp ON crp.id = crpp.returnedID
+        WHERE crp.orderId = #{orderID}
+          AND crp.status = 2
+          AND crp.returnedWay = 1
+          AND crp.delflag = 0
+    </select>
     <select id="findSplitCode" resultType="java.lang.String">
-		select splitCode from cm_shop_order where shopOrderID = #{shopOrderId}
-	</select>
-	<select id="getReturnShopOrder" resultType="java.lang.Integer">
-		SELECT shopOrderId FROM cm_returned_purchase_product crpp
-		LEFT JOIN cm_returned_purchase crp ON crp.id=crpp.returnedID
-		WHERE crp.id=#{id}
-		  AND crp.status=2
-		  AND crp.returnedWay =1
-		  AND crp.delflag=0
-	</select>
-	<select id="findBrokerage" resultType="java.lang.Double">
-		SELECT SUM(splitAccount)
-		FROM cm_split_account
-		WHERE productType = 3
-		  AND TYPE=5
-		  AND orderRequestNo= #{orderRequestNo}
-	</select>
-	<select id="findRefundTransfer" resultType="java.lang.Double">
-		SELECT SUM(transferAmount) FROM cm_refund_transfer
-		WHERE transferType=2
-		  AND orderRequestNo=#{orderRequestNo}
-	</select>
-	<select id="findRefundCharge" resultType="java.lang.Double">
-		SELECT SUM(transferAmount) FROM cm_refund_transfer
-		WHERE transferType=1
-		  AND orderRequestNo=#{orderRequestNo}
-	</select>
-	<select id="findPayAmount" resultType="java.lang.Double">
-		select associateAmount from cm_receipt_order_relation
-		where orderRequestNo = #{orderRequestNo}
-	</select>
-	<select id="findOnlinePay" resultType="java.lang.Double">
-		SELECT SUM(receiptAmount) FROM
-		cm_discern_receipt cdr
-		LEFT JOIN cm_receipt_order_relation cror ON cror.receiptID=cdr.Id
-		WHERE shopOrderId=#{shopOrderId}
-	</select>
-	<select id="findShopOrderSettleStatus" resultType="java.lang.String">
-		select settleStatus from cm_shop_order where shopOrderID = #{onlineShopOrderId}
-	</select>
-	<select id="findRefundType" resultType="java.lang.Integer">
-		SELECT COUNT(*) FROM cm_returned_purchase
-		WHERE orderId=#{orderID}
-		  AND delflag = 0
-		  AND refundtype=2
-	</select>
-	<select id="findShopOrderPaid" resultType="java.lang.Double">
-		SELECT SUM(associateAmount)
-		FROM cm_receipt_order_relation
-		WHERE shopOrderId=#{shopOrderID}
-		AND delflag=0
-	</select>
+        select splitCode
+        from cm_shop_order
+        where shopOrderID = #{shopOrderId}
+    </select>
+    <select id="getReturnShopOrder" resultType="java.lang.Integer">
+        SELECT shopOrderId
+        FROM cm_returned_purchase_product crpp
+                 LEFT JOIN cm_returned_purchase crp ON crp.id = crpp.returnedID
+        WHERE crp.id = #{id}
+          AND crp.status = 2
+          AND crp.returnedWay = 1
+          AND crp.delflag = 0
+    </select>
+    <select id="findBrokerage" resultType="java.lang.Double">
+        SELECT SUM(splitAccount)
+        FROM cm_split_account
+        WHERE productType = 3
+          AND TYPE = 5
+          AND orderRequestNo = #{orderRequestNo}
+    </select>
+    <select id="findRefundTransfer" resultType="java.lang.Double">
+        SELECT SUM(transferAmount)
+        FROM cm_refund_transfer
+        WHERE transferType = 2
+          AND orderRequestNo = #{orderRequestNo}
+    </select>
+    <select id="findRefundCharge" resultType="java.lang.Double">
+        SELECT SUM(transferAmount)
+        FROM cm_refund_transfer
+        WHERE transferType = 1
+          AND orderRequestNo = #{orderRequestNo}
+    </select>
+    <select id="findPayAmount" resultType="java.lang.Double">
+        select associateAmount
+        from cm_receipt_order_relation
+        where orderRequestNo = #{orderRequestNo}
+    </select>
+    <select id="findOnlinePay" resultType="java.lang.Double">
+        SELECT SUM(receiptAmount)
+        FROM cm_discern_receipt cdr
+                 LEFT JOIN cm_receipt_order_relation cror ON cror.receiptID = cdr.Id
+        WHERE shopOrderId = #{shopOrderId}
+    </select>
+    <select id="findShopOrderSettleStatus" resultType="java.lang.String">
+        select settleStatus
+        from cm_shop_order
+        where shopOrderID = #{onlineShopOrderId}
+    </select>
+    <select id="findRefundType" resultType="java.lang.Integer">
+        SELECT COUNT(*)
+        FROM cm_returned_purchase
+        WHERE orderId = #{orderID}
+          AND delflag = 0
+          AND refundtype = 2
+    </select>
+    <select id="findShopOrderPaid" resultType="java.lang.Double">
+        SELECT SUM(associateAmount)
+        FROM cm_receipt_order_relation
+        WHERE shopOrderId = #{shopOrderID}
+          AND delflag = 0
+    </select>
+    <select id="findSplitCodeEmail" resultType="java.lang.String">
+        select email
+        from cm_shop_email
+        where splitCode = #{splitCode}
+    </select>
 </mapper>