소스 검색

银行mq加密,解密未完成

qzyReal 1 년 전
부모
커밋
19862c6bdf

+ 5 - 0
sp-service/payment-server/src/main/java/com/pj/bank_info/BankInfoController.java

@@ -2,6 +2,8 @@ package com.pj.bank_info;
 
 import java.util.List;
 
+import cn.hutool.crypto.digest.HMac;
+import cn.hutool.crypto.digest.HmacAlgorithm;
 import cn.hutool.log.StaticLog;
 import com.pj.rabbitmq.MessageSender;
 import com.pj.utils.so.SoMap;
@@ -88,6 +90,9 @@ public class BankInfoController {
 	public String test(@RequestBody String str){
 		StaticLog.info("info:{}",str);
 		messageSender.sendToLevelOneMQ(str);
+		byte[] key = "90003".getBytes();
+		HMac mac = new HMac(HmacAlgorithm.HmacSHA256, key);
+		System.out.println(mac.digestBase64("sw10002",false));
 		return "hello";
 	}
 

+ 3 - 3
sp-service/payment-server/src/main/java/com/pj/rabbitmq/MessageSender.java

@@ -39,11 +39,11 @@ public class MessageSender {
     }
 
     public void sendToLevelOneMQ(String message) {
-        levelTwoConnectionFactory.setMessageConverter(new Jackson2JsonMessageConverter());
-        levelOneConnectionFactory.convertAndSend(rabbitMQProperties.getLevelOneSendQueue(),message);
+//        levelTwoConnectionFactory.setMessageConverter(new Jackson2JsonMessageConverter());
+        levelOneConnectionFactory.convertAndSend(rabbitMQProperties.getLevelOneReceiveQueue(),message);
     }
     public void sendToLevelTwoMQ(String message) {
-        levelTwoConnectionFactory.setMessageConverter(new Jackson2JsonMessageConverter());
+//        levelTwoConnectionFactory.setMessageConverter(new Jackson2JsonMessageConverter());
         levelTwoConnectionFactory.convertAndSend(rabbitMQProperties.getLevelTwoSendQueue(),message);
     }
 

+ 74 - 0
sp-service/payment-server/src/main/java/com/pj/utils/CryptoUtil.java

@@ -0,0 +1,74 @@
+package com.pj.utils;
+
+
+import org.bouncycastle.jce.interfaces.ECPublicKey;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.nio.charset.StandardCharsets;
+import java.security.Security;
+
+//报文验签&解密
+public class CryptoUtil {
+    private final static String sm4Key="c9931a6c5219610179d7f6c6ec8fd328";
+
+    private static Logger logger = LoggerFactory.getLogger(CryptoUtil.class);
+    static{
+        Security.addProvider(new BouncyCastleProvider());
+    }
+
+    public static String getDecrypt(String m,String sm4Key,String sm2Key) throws Exception{
+        logger.info("原文: {}", m);
+        Encoder encoder = Encoder.Hex;
+        byte[] mtextByte = Encoder.Hex.decode(m);
+        // 签名
+        int siglen = (int) mtextByte[0];
+        byte[] signature = new byte[siglen];
+        System.arraycopy(mtextByte, 1, signature, 0, siglen);
+        //内容密文
+        byte[] mcontent = new byte[mtextByte.length - siglen - 1];
+        System.arraycopy(mtextByte, 1 + siglen, mcontent, 0, mtextByte.length - siglen - 1);
+
+        //SM4解密密文
+        SM4 SM4_key = SM4.recovery(sm4Key);
+        // SM4_key.getEncodedKeyStr(); // 交换编码密钥字符串 . Base64/Hex
+        byte[] keyBytes = encoder.decode(sm4Key); // 从交换编码密钥字符串还原为密钥字节码
+        byte[] plainBytesDecrypted = SM4.decrypt(keyBytes, mcontent, SM4_key.getTransformation()); // 解密后字节码
+        logger.info("解密出来的 明文:{}", new String(plainBytesDecrypted, "UTF-8"));
+
+        // SM2验签
+        ECPublicKey pub = SM2.recoveryPubKeyFromQ(encoder.decode(sm2Key));
+        logger.info("SM2 - 验签结果 - {}", SM2.verify(pub, null, plainBytesDecrypted, signature));
+        if(!SM2.verify(pub, null, plainBytesDecrypted, signature)){
+            throw new Exception("验签未通过!!");
+        }
+        return new String(plainBytesDecrypted, "UTF-8");
+    }
+
+    public static String encrypt(String m) {
+        return encrypt(m,sm4Key);
+    }
+
+    public static String encrypt(String m,String sm4Key) {
+        logger.info("原文: {}", m);
+        Encoder encoder = Encoder.Hex;
+        SM4 SM4_key = SM4.recovery(sm4Key);
+        byte[] keyBytes = encoder.decode(sm4Key); // 从交换编码密钥字符串还原为密钥字节码
+        byte[] plainBytesEncrypted = SM4.encrypt(keyBytes, m.getBytes(StandardCharsets.UTF_8), SM4_key.getTransformation());
+        String plainEncrypted = encoder.encode(plainBytesEncrypted);
+        logger.info("加密出来的 密文:{}", plainEncrypted);
+        return plainEncrypted;
+    }
+
+    public static String decrypt(String m,String sm4Key) {
+        logger.debug("原文: {}", m);
+        Encoder encoder = Encoder.Hex;
+        byte[] mtextByte = Encoder.Hex.decode(m);
+        SM4 SM4_key = SM4.recovery(sm4Key);
+        byte[] keyBytes = encoder.decode(sm4Key); // 从交换编码密钥字符串还原为密钥字节码
+        byte[] plainBytesDecrypted = SM4.decrypt(keyBytes, mtextByte, SM4_key.getTransformation()); // 解密后字节码
+        logger.debug("解密出来的 明文:{}", new String(plainBytesDecrypted, StandardCharsets.UTF_8));
+        return new String(plainBytesDecrypted, StandardCharsets.UTF_8);
+    }
+}

+ 91 - 0
sp-service/payment-server/src/main/java/com/pj/utils/Encoder.java

@@ -0,0 +1,91 @@
+package com.pj.utils;
+
+
+public enum Encoder implements EncoderInterface{
+    Hex("Hex"),Base64("Base64");
+    private String encoderName;
+    Encoder(String name){
+        encoderName = name;
+    }
+
+    @Override
+    public String encode(byte[] input) {
+
+        if ("Hex".equals(encoderName)){
+            return hexEncode(input);
+        }
+
+        if ("Base64".equals(encoderName)){
+            return base64Encode(input);
+        }
+
+        return null;
+    }
+
+    @Override
+    public byte[] decode(String input) {
+        if ("Hex".equals(encoderName)){
+            return hexDecode(input);
+        }
+
+        if("Base64".equals(encoderName)){
+            return base64Decode(input);
+        }
+
+        return null;
+    }
+    /*
+    *
+    * byte[] 转为hex字符串
+    *
+    * */
+    private String hexEncode(byte[] bytes){
+        String strHex = "";
+        StringBuilder sb = new StringBuilder("");
+        for (int n = 0; n < bytes.length; n++) {
+            strHex = Integer.toHexString(bytes[n] & 0xFF);
+            sb.append((strHex.length() == 1) ? "0" + strHex : strHex); // 每个字节由两个字符表示,位数不够,高位补0
+        }
+        return sb.toString().trim();
+    }
+
+
+    /*
+    *
+    *
+    * hex字符串转byte[]
+    *
+    *
+    * */
+    private byte[] hexDecode(String hex){
+
+        int m = 0, n = 0;
+        int byteLen = hex.length() / 2; // 每两个字符描述一个字节
+        byte[] ret = new byte[byteLen];
+        for (int i = 0; i < byteLen; i++) {
+            m = i * 2 + 1;
+            n = m + 1;
+            int intVal = Integer.decode("0x" + hex.substring(i * 2, m) + hex.substring(m, n));
+            ret[i] = Byte.valueOf((byte)intVal);
+        }
+        return ret;
+    }
+
+    private boolean isEmpty(String hex) {
+        return hex == null || "".equals(hex);
+    }
+
+    private String base64Encode(byte[] input){
+        return java.util.Base64.getEncoder().encodeToString(input);
+    }
+
+    private byte[] base64Decode(String base64Str){
+        return java.util.Base64.getDecoder().decode(base64Str);
+    }
+
+
+
+
+
+
+}

+ 6 - 0
sp-service/payment-server/src/main/java/com/pj/utils/EncoderInterface.java

@@ -0,0 +1,6 @@
+package com.pj.utils;
+
+public interface  EncoderInterface  {
+    public abstract String encode(byte[] input);
+    public abstract byte[] decode(String input);
+}

+ 1 - 0
sp-service/payment-server/src/main/java/com/pj/utils/Key.txt

@@ -0,0 +1 @@
+c9931a6c5219610179d7f6c6ec8fd328

+ 471 - 0
sp-service/payment-server/src/main/java/com/pj/utils/SM2.java

@@ -0,0 +1,471 @@
+package com.pj.utils;
+
+import org.bouncycastle.asn1.gm.GMNamedCurves;
+import org.bouncycastle.asn1.x9.X9ECParameters;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.CryptoException;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+import org.bouncycastle.crypto.engines.SM2Engine;
+import org.bouncycastle.crypto.params.*;
+import org.bouncycastle.crypto.signers.SM2Signer;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
+import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
+import org.bouncycastle.jce.interfaces.ECKey;
+import org.bouncycastle.jce.interfaces.ECPrivateKey;
+import org.bouncycastle.jce.interfaces.ECPublicKey;
+import org.bouncycastle.jce.spec.*;
+import org.bouncycastle.math.ec.ECCurve;
+import org.bouncycastle.math.ec.ECPoint;
+import org.bouncycastle.openssl.PEMParser;
+import org.bouncycastle.openssl.jcajce.JcaPEMWriter;
+import org.bouncycastle.openssl.jcajce.JcaPKCS8Generator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.math.BigInteger;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.security.*;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.nio.file.Files.newBufferedWriter;
+import static java.nio.file.Paths.get;
+import static java.util.Optional.of;
+import static org.bouncycastle.asn1.gm.GMObjectIdentifiers.sm2p256v1;
+import static org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME;
+
+/** BC标准实现国密SM2非对称加解密工具类,本工具类的功能包括:
+ * <ul>
+ * <li>密钥生成
+ * <li>密钥恢复
+ * </ul>
+ * <p>
+ * 具体用法,请参考本类对应的 SM2Tests 测试
+ * 
+ * @author benc.mai
+ * @see <a href='https://tools.ietf.org/html/draft-shen-sm2-ecdsa-02'>SM2 Digital Signature Algorithm</a> */
+public final class SM2 {
+
+    private static final Logger logger      = LoggerFactory.getLogger(SM2.class);
+    public final static String  algorithm   = "EC";
+    // private String transformation = Utils.transformation(algorithm, mode, padding);
+
+    public static final String  Pub_File    = SM4.class.getSimpleName() + "PubKey.txt";
+    public static final String  Pub_QFile   = SM4.class.getSimpleName() + "PubKeyQ.txt";
+    public static final String  Pri_File    = SM4.class.getSimpleName() + "PriKey.txt";
+    public static final String  Pri_DFile   = SM4.class.getSimpleName() + "PriKeyD.txt";
+    public static final String  Pri_PemFile = SM4.class.getSimpleName() + "PriKey.pem";
+
+    /** 密钥交换字符串编码方式. */
+    private Encoder encoder;
+    /** 明密文处理字符集. */
+    private Charset             charset;
+
+    /** 公钥 JCA/JCE 规范对象形态 */
+    private ECPublicKey         pub;
+    /** 公钥JCA/JCE 规范字节码形式 */
+    private byte[]              pubKeyBytes;
+    /** 公钥的 DERX509 编码字符串形式 */
+    private String              pubDERX509Str;
+    /***/
+    private String              pubQStr;
+
+    /** 私钥 JCA/JCE 规范对象形态 */
+    private ECPrivateKey        pri;
+    /** 私钥JCA/JCE 规范字节码形式 */
+    private byte[]              priKeyBytes;
+    /** 私钥的 DERPKCS8 编码字符串形式 */
+    private String              priDERPKCS8Str;
+    /***/
+    private String              priDStr;
+    /** 私钥的 PEM 编码字符串形式 */
+    private String              priPEMStr;
+
+    private SM2(Encoder encoder, Charset charset) {
+
+        this.encoder = of(encoder).get();
+        this.charset = of(charset).get();
+    }
+
+    //@formatter:off
+    public final Encoder getEncoder() { return encoder; }
+    public final Charset getCharset() { return charset; }
+    public final ECPublicKey getPub() { return pub; }
+    public final byte[] getPubKeyBytes() { return pubKeyBytes; }
+    public final String getPubDERX509Str() { return pubDERX509Str; }
+    public final String getPubQStr() { return pubQStr; }
+    public final ECPrivateKey getPri() { return pri; }
+    public final byte[] getPriKeyBytes() { return priKeyBytes; }
+    public final String getPriDERPKCS8Str() { return priDERPKCS8Str; }
+    public final String getPriDStr() { return priDStr; }
+    public final String getPriPEMStr() { return priPEMStr; }
+    //@formatter:on
+
+    /** 将编码后的密钥对以十六进字符串形式保存到指定目录
+     * 
+     * @param dir 密钥保存目录,不以 / 结尾
+     * @throws RuntimeException */
+    public void saveTo(String dir) {
+
+        try {
+
+            Path pDir = get(dir);
+
+            // 公钥
+            Path pubPath = pDir.resolve(Pub_File);
+            BufferedWriter pubBw = newBufferedWriter(pubPath, charset);
+            pubBw.write(pubDERX509Str);
+            pubBw.close();
+            logger.info("SM2公钥DER X509规范字节码({})保存于:{}", encoder, pubPath);
+
+            Path pubQPath = pDir.resolve(Pub_QFile);
+            BufferedWriter pubQBw = newBufferedWriter(pubQPath, charset);
+            pubQBw.write(pubQStr);
+            pubQBw.close();
+            logger.debug("SM2公钥 Q 参数({})保存于:{}", encoder, pubQPath);
+
+            // 私钥
+            Path priPath = pDir.resolve(Pri_File);
+            BufferedWriter priBw = newBufferedWriter(priPath, charset);
+            priBw.write(priDERPKCS8Str);
+            priBw.close();
+            logger.debug("SM2私钥DER PKCS8规范字节码({})保存于:{}", encoder, priPath);
+
+            Path priDPath = pDir.resolve(Pri_DFile);
+            BufferedWriter priDBw = newBufferedWriter(priDPath, charset);
+            priDBw.write(priDStr);
+            priDBw.close();
+            logger.debug("SM2私钥 D 参数({})保存于:{}", encoder, priDPath);
+
+            Path priPemPath = pDir.resolve(Pri_PemFile);
+            BufferedWriter PriPemBw = newBufferedWriter(priPemPath, charset);
+            PriPemBw.write(priPEMStr);
+            PriPemBw.close();
+            logger.debug("SM2私钥 PEM 规范编码保存于:{}", priPemPath);
+        } catch (Exception e) {
+            logger.warn("SM2 密钥保存失败.原因: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public String toString() {
+
+        return super.toString();
+        // return String.format("SM2封装对象 - Transformation: %s Key(%s %s byte):%s Charset:%s", transformation, encoder,
+        // keyBytes.length, encodedKeyStr, charset);
+    }
+
+    // 静态工具方法
+    // -----------------------------------------------------------------------------------------------------------------
+
+    public static SM2 genKeyPair() {
+
+        return genKeyPair(Encoder.Hex, UTF_8);
+    }
+
+    /** 生成SM2密钥对.密钥长度 应为 256
+     * 
+     * @param encoder 密钥、明/密文字节码编码器
+     * @param charset 字符集
+     * @return SM2 封装对象
+     * @throws RuntimeException */
+    public static SM2 genKeyPair(Encoder encoder, Charset charset) {
+
+        SM2 k = new SM2(encoder, charset);
+
+        try {
+            // 产生密钥对
+            KeyPairGenerator kpg = KeyPairGenerator.getInstance(algorithm, PROVIDER_NAME);
+            kpg.initialize(new ECNamedCurveGenParameterSpec(sm2p256v1.getId()));// ("sm2p256v1"));
+            KeyPair keyPair = kpg.generateKeyPair();
+
+            // 公钥
+            k.pub = (BCECPublicKey) keyPair.getPublic();
+            k.pubKeyBytes = encodePubKeyWithX509(k.pub);
+            k.pubDERX509Str = k.encoder.encode(k.pubKeyBytes);
+            k.pubQStr = k.encoder.encode(k.pub.getQ().getEncoded(Boolean.FALSE));
+
+            // 私钥
+            k.pri = (BCECPrivateKey) keyPair.getPrivate();
+            k.priKeyBytes = encodePriKeyWithPKCS8(k.pri);
+            k.priDERPKCS8Str = k.encoder.encode(k.priKeyBytes);
+            k.priDStr = k.encoder.encode(k.pri.getD().toByteArray());
+            k.priPEMStr = encodePriKey2PEM(k.pri);
+
+        } catch (Exception e) {
+            logger.warn("SM2 密钥对生成失败.原因: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+
+        return k;
+    }
+
+    // DER编码密钥对
+    //
+    // JCE本身是支持DER编码密钥对的解析的,可以参见PKCS8EncodedKeySpec和X509EncodedKeySpec
+    // DER编码是ASN.1编码规则中的一个子集,具体格式如何编排没有去了解,但最终呈现肯定的是一堆有规律的二进制组合而成
+    // PKCS#8定义了私钥信息语法和加密私钥语法,而X509定义证书规范,通常都会用DER和PEM进行编码存储,而在JAVA中则使用的DER
+    // ------------------------------------------------------------------------------------------------------------------
+    /** 生成公匙X509编码字节数组 */
+    public static byte[] encodePubKeyWithX509(PublicKey key) {
+
+        // key.getFormat();
+        // PublicKey pubKey = /* ( BCRSAPublicKey | RSAPublicKey) */key;
+        byte[] pubKeyBytes = key.getEncoded();// X509EncodedKeySpec
+        // RSAPublicKeySpec pubKeySpec = new RSAPublicKeySpec(pubKey.getModulus(), pubKey.getPublicExponent());
+        return pubKeyBytes;
+    }
+
+    /** 生成私匙PKCS#8编码字节数组
+     * 
+     * @throws IOException */
+    public static byte[] encodePriKeyWithPKCS8(PrivateKey key) {
+
+        // key.getFormat();
+        // PrivateKey priKey = /* ( BCRSAPrivateCrtKey | RSAPrivateKey) */key;
+        byte[] priKeyBytes = key.getEncoded();// PKCS8EncodedKeySpec
+        // logger.debug("RSAPrivateKey:{}", ByteUtilities.asHex(priKeyBytes));
+        return priKeyBytes;
+    }
+
+    /** 从X.509编码字节数组恢复公钥
+     * 
+     * @param x590Key DER编码公钥字节码
+     * @return 公钥
+     * @throws RuntimeException */
+    public static ECPublicKey recoveryPubKeyFromX509EncodedKeySpec(byte[] x590Key) {
+
+        try {
+            KeySpec keySpec = new X509EncodedKeySpec(x590Key);
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            ECPublicKey pubKey = (ECPublicKey) keyFactory.generatePublic(keySpec);
+            return pubKey;
+        } catch (GeneralSecurityException e) {
+            logger.warn("从X.509编码字节数组恢复  SM2 公钥失败.原因: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static ECPublicKey recoveryPubKeyFromQ(byte[] pubQbytes) {
+
+        // ECDomainParameters d_params = new ECDomainParameters(curve, G, BigInteger.ONE);
+        // ECPublicKeyParameters spec = new ECPublicKeyParameters(Q, d_params);
+
+        X9ECParameters x9 = GMNamedCurves.getByOID(sm2p256v1);
+        ECCurve curve = x9.getCurve();
+        ECPoint G = x9.getG();
+        BigInteger N = x9.getN();
+
+        ECPublicKey pubKey;
+        try {
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm, PROVIDER_NAME);
+            ECParameterSpec paramSpec = new ECNamedCurveParameterSpec(sm2p256v1.getId(), curve, G, N);
+            // byte[] Qbytes = encoder.decode(pub_Q_Str);
+            ECPoint Q = curve.decodePoint(pubQbytes);
+            KeySpec keySpec = new ECPublicKeySpec(Q, paramSpec);
+            pubKey = (ECPublicKey) keyFactory.generatePublic(keySpec);
+            return pubKey;
+        } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeySpecException e) {
+            logger.warn("从 Q 参数恢复 SM2 公钥失败.原因: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+
+    /** 从PKCS#8字节数组恢复私钥
+     * 
+     * @param pkcs8Key DER编码私钥字节码
+     * @return 私钥
+     * @throws RuntimeException */
+    public static ECPrivateKey recoveryPriKeyFromPKCS8EncodedKeySpec(byte[] pkcs8Key) {
+
+        try {
+            KeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8Key);
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            ECPrivateKey privKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec);
+            return privKey;
+        } catch (GeneralSecurityException e) {
+            logger.warn("从PKCS#8字节数组恢复 SM2 私钥失败.原因: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static ECPrivateKey recoveryPriKeyFromD(byte[] Dbytes) {
+
+        X9ECParameters x9 = GMNamedCurves.getByOID(sm2p256v1);
+        ECCurve curve = x9.getCurve();
+        ECPoint G = x9.getG();
+        BigInteger N = x9.getN();
+
+        ECPrivateKey priKey;
+        try {
+            KeyFactory keyFactory = KeyFactory.getInstance(algorithm, PROVIDER_NAME);
+            ECParameterSpec paramSpec = new ECNamedCurveParameterSpec(sm2p256v1.getId(), curve, G, N);
+
+            BigInteger D = new BigInteger(1, Dbytes);
+            KeySpec keySpec = new ECPrivateKeySpec(D, paramSpec);
+            priKey = (ECPrivateKey) keyFactory.generatePrivate(keySpec);
+            return priKey;
+        } catch (NoSuchAlgorithmException | NoSuchProviderException | InvalidKeySpecException e) {
+            logger.warn("从 D 参数恢复 SM2 私钥失败.原因: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+
+    }
+
+    // PEM编码密钥恢复
+    //
+    //
+    // ------------------------------------------------------------------------------------------------------------------
+    /** 将私钥转换成PEM字符串
+     * 
+     * @param key
+     * @return 私钥
+     * @throws RuntimeException */
+    public static String encodePriKey2PEM(PrivateKey key) {
+
+        try {
+            StringWriter sw = new StringWriter();
+            JcaPEMWriter pw = new JcaPEMWriter(sw);
+            pw.writeObject(new JcaPKCS8Generator(key, null));
+            // pw.writeObject(key);
+            pw.close();
+            String priKeyPEM = sw.toString();
+            return priKeyPEM;
+        } catch (IOException e) {
+            logger.warn("将 SM2 私钥编码成 PEM 格式字符串失败.原因: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+
+    /** 从PEM 字符串恢复出私钥
+     * 
+     * @param PEM
+     * @return 私钥
+     * @throws RuntimeException */
+    public static ECPrivateKey recoveryPriKeyFromPEM(String PEM) {
+
+        try {
+            PEMParser pr = new PEMParser(new StringReader(PEM));
+            PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pr.readPemObject().getContent());
+            final KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
+            ECPrivateKey privKey = (ECPrivateKey) keyFactory.generatePrivate(pkcs8KeySpec);
+            pr.close();
+            return privKey;
+        } catch (Exception e) {
+            logger.warn("从 PEM 格式字符串恢复 SM2 私钥失败.原因: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static byte[] encrypt(ECKey ecKey, byte[] plainBytes) {
+
+        ECKeyParameters key_param = getECKeyParameters(ecKey);
+
+        SM2Engine engine = new SM2Engine();
+        engine.init(true, new ParametersWithRandom(key_param, new SecureRandom()));
+        byte[] cipherBtyes;
+        try {
+            cipherBtyes = engine.processBlock(plainBytes, 0, plainBytes.length);
+            return cipherBtyes;
+        } catch (InvalidCipherTextException e) {
+            logger.warn("SM2 {} 加密失败.原因: {}", ecKey.getClass().getSimpleName(), e.getMessage());
+            throw new RuntimeException(e);
+        }
+
+    }
+
+    public static byte[] decrypt(ECKey ecKey, byte[] cipherBtyes) {
+
+        ECKeyParameters key_param = getECKeyParameters(ecKey);
+
+        SM2Engine engine = new SM2Engine();
+        engine.init(false, key_param);
+        byte[] plainBytes;
+        try {
+            plainBytes = engine.processBlock(cipherBtyes, 0, cipherBtyes.length);
+            return plainBytes;
+        } catch (InvalidCipherTextException e) {
+            logger.warn("SM2 {} 解密失败.原因: {}", ecKey.getClass().getSimpleName(), e.getMessage());
+            throw new RuntimeException(e);
+        }
+
+    }
+
+    /** ECC私钥签名
+     *
+     * @param ecKey ECC私钥
+     * @param withId 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes()
+     * @param srcData 源数据
+     * @return 签名
+     * @throws NoSuchAlgorithmException
+     * @throws NoSuchProviderException
+     * @throws CryptoException */
+    public static byte[] sign(ECKey ecKey, byte[] withId, byte[] srcData) {
+
+        ECKeyParameters key_param = getECKeyParameters(ecKey);
+
+        SM2Signer signer = new SM2Signer();
+        CipherParameters param = null;
+        ParametersWithRandom pwr = new ParametersWithRandom(key_param, new SecureRandom());
+        if (withId != null) {
+            param = new ParametersWithID(pwr, withId);
+        } else {
+            param = pwr;
+        }
+        signer.init(true, param);
+        signer.update(srcData, 0, srcData.length);
+        try {
+            return signer.generateSignature();
+        } catch (CryptoException e) {
+            logger.warn("SM2 {} 签名失败.原因: {}", ecKey.getClass().getSimpleName(), e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+
+    /** ECC公钥验签
+     *
+     * @param ecKey ECC公钥
+     * @param withId 可以为null,若为null,则默认withId为字节数组:"1234567812345678".getBytes()
+     * @param srcData 源数据
+     * @param sign 签名
+     * @return 验签成功返回true,失败返回false */
+    public static boolean verify(ECKey ecKey, byte[] withId, byte[] srcData, byte[] sign) {
+
+        ECKeyParameters key_param = getECKeyParameters(ecKey);
+
+        SM2Signer signer = new SM2Signer();
+        CipherParameters param = null;
+        if (withId != null) {
+            param = new ParametersWithID(key_param, withId);
+        } else {
+            param = key_param;
+        }
+        signer.init(false, param);
+        signer.update(srcData, 0, srcData.length);
+        return signer.verifySignature(sign);
+    }
+
+    private static ECKeyParameters getECKeyParameters(ECKey ecKey) {
+
+        ECParameterSpec param_spec = ecKey.getParameters();
+        ECDomainParameters domain_param = new ECDomainParameters(param_spec.getCurve(), param_spec.getG(),
+                param_spec.getN());
+
+        ECKeyParameters key_param = null;
+        if (ecKey instanceof ECPublicKey)
+            key_param = new ECPublicKeyParameters(((ECPublicKey) ecKey).getQ(), domain_param);
+        else if (ecKey instanceof ECPrivateKey)
+            key_param = new ECPrivateKeyParameters(((ECPrivateKey) ecKey).getD(), domain_param);
+
+        return key_param;
+    }
+}

+ 289 - 0
sp-service/payment-server/src/main/java/com/pj/utils/SM4.java

@@ -0,0 +1,289 @@
+package com.pj.utils;
+
+import cn.hutool.crypto.Mode;
+import cn.hutool.crypto.Padding;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.crypto.Cipher;
+import javax.crypto.KeyGenerator;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.IvParameterSpec;
+import javax.crypto.spec.SecretKeySpec;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.security.GeneralSecurityException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.nio.file.Files.newBufferedWriter;
+import static java.nio.file.Paths.get;
+import static java.util.Optional.of;
+import static org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME;
+
+/** BC标准实现国密SM4对称加解密工具类,本工具类的功能包括:
+ * <ul>
+ * <li>密钥生成
+ * <li>密钥恢复
+ * <li>加密.密文自动串联 iv长度、iv字节码 、密文字节码
+ * <li>解密.密文自动提取 iv长度、iv字节码 、密文字节码
+ * <li>支持全部SM4支持的区块工作模式和填充模式及扩展模式
+ * </ul>
+ * <p>
+ * 具体用法,请参考本类对应的 SM4Tests 测试
+ * 
+ * @author benc.mai
+ * @see <a href='https://tools.ietf.org/id/draft-ribose-cfrg-sm4-01.html'>The SM4 Block Cipher Algorithm And Its Modes
+ *      Of Operations</a> */
+public final class SM4 {
+
+    private static final Logger logger         = LoggerFactory.getLogger(SM4.class);
+    public static final String  Key_File_Name  = SM4.class.getSimpleName() + "Key.txt";
+    public static final String  algorithm      = "SM4";
+
+    /** 算法名 */
+
+    /** 使用何种区块加解密工作模式 .默认: CBC */
+    private Mode mode           = Mode.CBC;
+    /** 使用何种区块加解密填充方式.默认: PKCS5Padding */
+    private Padding padding        = Padding.PKCS5Padding;
+
+    /** 算法变种,用于 Cipher 加解密过程处理.
+     * <p>
+     * 格式为:
+     * 算法/模式/填充 (algorithm/mode/padding)
+     * <p>
+     * SM4 工作模式包含 ECB、CBC、CFBx、OFBx、CTR.(ECB、CBC 较为常用,除无工作模式和ECB外,其他模式都必须引入IV初始向量或额外变量)
+     * <p>
+     * SM4 在不同工作模式下支持的算法变种 :
+     * <li>SM4
+     * <li>SM4/ECB/PKCS5Padding、PKCS7Padding
+     * <li>SM4/CBC/PKCS5Padding、PKCS7Padding、ISO10126Padding
+     * <li>SM4/CFBx/NoPadding、PKCS5Padding、PKCS7Padding、ISO10126Padding
+     * <li>SM4/OFBx/NoPadding、PKCS5Padding、PKCS7Padding、ISO10126Padding
+     * <li>SM4/CTR/NoPadding、PKCS5Padding、PKCS7Padding、ISO10126Padding
+     * <li>SM4/EAX/NoPadding
+     * <li>SM4/GCM/NoPadding */
+    private String              transformation = Utils.transformation(algorithm, mode, padding);
+
+    /** 密钥交换字符串编码方式.默认:Hex */
+    private Encoder encoder;
+    /** 明密文处理字符集.默认: UTF-8 */
+    private Charset             charset;
+
+    /** 密钥JCA/JCE规范对象形态 */
+    private SecretKey           key;
+    /** 密钥JCA/JCE规范字节码形态 */
+    private byte[]              keyBytes;
+    /** 密钥编码字符串形态 */
+    private String              encodedKeyStr;
+
+    /** 构造SM4封装对象
+     * 
+     * @param encoder 密钥、明/密文字节码编码器
+     * @param charset 字符集
+     * @param mode 区块加解密工作模式
+     * @param padding 区块加解密填充方式 */
+    private SM4(Encoder encoder, Charset charset, Mode mode, Padding padding) {
+
+        this.encoder = of(encoder).get();
+        this.charset = of(charset).get();
+        this.mode = of(mode).get();
+        this.padding = of(padding).get();
+        this.transformation = Utils.transformation(algorithm, mode, padding);
+    }
+
+    //@formatter:off
+    public Encoder getEncoder() { return encoder; }
+    public Charset getCharset() { return charset; }
+    public Mode getMode() { return mode; }
+    public Padding getPadding() { return padding; }
+    public String getTransformation() { return transformation;}
+    public SecretKey getKey() { return key; }
+    public byte[] getKeyBytes() { return keyBytes; }
+    public String getEncodedKeyStr() { return encodedKeyStr; }
+    //@formatter:on
+
+    /** 将密钥以编码后的字符串形式保存到指定目录
+     * 
+     * @param dir 密钥保存目录,不以 / 结尾
+     * @throws RuntimeException */
+    public void saveTo(String dir) {
+
+        Path pDir = get(dir);
+
+        try {
+            BufferedWriter bw = newBufferedWriter(pDir.resolve(Key_File_Name), UTF_8);
+            bw.write(encodedKeyStr);
+            bw.close();
+            logger.info("保存 SM4密钥文件于:{}", pDir.resolve(Key_File_Name));
+
+        } catch (IOException e) {
+            logger.warn("SM4 密钥保存失败.原因: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+
+    @Override
+    public String toString() {
+
+        return String.format("SM4 - Transformation: %s Key(%s %s byte):%s Charset:%s", transformation, encoder,
+                keyBytes.length, encodedKeyStr, charset);
+    }
+
+    // 静态工具方法
+    // -----------------------------------------------------------------------------------------------------------------
+    public static SM4 genKey() {
+
+        return genKey(Encoder.Hex, UTF_8, Mode.CBC, Padding.PKCS5Padding);
+    }
+
+    /** 生成SM4封装对象
+     * 
+     * @param encoder 密钥、明/密文字节码编码器
+     * @param charset 字符集
+     * @param mode 区块加解密工作模式
+     * @param padding 区块加解密填充方式
+     * @return SM4 封装对象
+     * @throws RuntimeException */
+    public static SM4 genKey(Encoder encoder, Charset charset, Mode mode, Padding padding) {
+
+        SM4 k = new SM4(encoder, charset, mode, padding);
+
+        try {
+            KeyGenerator kg = KeyGenerator.getInstance(algorithm, PROVIDER_NAME);
+            SecureRandom rand = new SecureRandom();
+            // keyGenerator.init(128, rand);// SM4 标准实现密钥长度必须 128 bit
+            kg.init(rand);
+
+            k.key = kg.generateKey();
+            k.keyBytes = k.key.getEncoded();
+            k.encodedKeyStr = k.encoder.encode(k.keyBytes);
+            logger.info(k.toString());
+            return k;
+        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
+            logger.warn("SM4 Key Generation Fail.Reason: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+
+    }
+
+    public static SM4 recovery(String encodedKeyStr) {
+
+        return recovery(Encoder.Hex, UTF_8, encodedKeyStr, Mode.CBC, Padding.PKCS5Padding);
+    }
+
+    /** 还原密钥封装对象
+     * 
+     * @param encoder 密钥、明/密文字节码编码器
+     * @param charset 字符集
+     * @param encodedKeyStr JCA/JCE 规范字节码编码后的密钥字符串
+     * @param mode 区块加解密工作模式
+     * @param padding 区块加解密填充方式
+     * @return SM4 封装对象 */
+    public static SM4 recovery(Encoder encoder, Charset charset, String encodedKeyStr, Mode mode, Padding padding) {
+
+        SM4 k = new SM4(encoder, charset, mode, padding);
+
+        k.key = new SecretKeySpec(encoder.decode(encodedKeyStr), k.transformation);
+        k.keyBytes = k.key.getEncoded();
+        k.encodedKeyStr = encodedKeyStr;
+        logger.info(k.toString());
+        return k;
+    }
+
+    /** 只还原 JCA/JCE 密钥对象
+     * 
+     * @param keyBytes JCA/JCE 规范密钥字节码 */
+    public static SecretKey recovery(byte[] keyBytes) {
+
+        SecretKey key = new SecretKeySpec(keyBytes, algorithm);
+        return key;
+    }
+
+    /** SM4 加密
+     * 
+     * @param keyBytes 密钥字节码
+     * @param plainBytes 待加密原文字节码
+     * @param transformation 算法变种
+     * @return 密文字节码
+     * @throws RuntimeException */
+    public static byte[] encrypt(byte[] keyBytes, byte[] plainBytes, String transformation) {
+
+        try {
+            Cipher cipher = Cipher.getInstance(of(transformation).get(), PROVIDER_NAME);
+            cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(of(keyBytes).get(), transformation));
+
+            byte[] cipherBytes = cipher.doFinal(of(plainBytes).get());
+
+            // 特定的区块加密工作模式,除ECB外其他的一般都会产生初始向量(IV).IV的长度一般和区块长度一致
+            // 为便于传输,可以把IV作为前缀或后缀串联到密文字节码上,这里默认串联到密文数组前
+            // 解密时必须先分别提取IV和密文数组字节码
+            // SM4算法不同的区块工作模式IV长度由12-15-16字节不等,大部分都为16字节
+            // IV长度(1bit)+ IV字节码(12-16bit)+密文
+            byte[] ivBytes = cipher.getIV();
+            if (ivBytes != null) {
+                // IvParameterSpec iv_spec = new IvParameterSpec(iv);
+                // Mode.SHORT_IV_Okay.contains(mode);
+                // logger.info("加密方初始向量(IV {} bytes): {}", ivBytes.length, Encoder.Hex.encode(ivBytes));
+                byte[] combineIvlenghtAndIvAndCipher = new byte[1 + ivBytes.length + cipherBytes.length];
+                combineIvlenghtAndIvAndCipher[0] = (byte) ivBytes.length;
+                System.arraycopy(ivBytes, 0, combineIvlenghtAndIvAndCipher, 1, ivBytes.length);
+                System.arraycopy(cipherBytes, 0, combineIvlenghtAndIvAndCipher, ivBytes.length + 1, cipherBytes.length);
+                cipherBytes = combineIvlenghtAndIvAndCipher;
+            }
+            return cipherBytes;
+        } catch (GeneralSecurityException e) {
+            logger.warn("SM4 Encrypt.Reason: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+
+    /** SM4 解密
+     * 
+     * @param keyBytes 密钥字节码
+     * @param cipherBytes 密文字节码
+     * @param transformation 算法变种
+     * @param ivLength 初始向量长度.此值视不同的区块加解密模式而定,除默认SM4算法变种和ECB模式为0外,
+     *            其他的模式由长度为 12、15、16位不等,大部分为16位
+     * @return 原文字节码
+     * @throws RuntimeException */
+    public static byte[] decrypt(byte[] keyBytes, byte[] cipherBytes, String transformation) {
+
+        int index = of(transformation).get().indexOf('/');
+        int ivLength = 0;
+
+        // 排除 默认SM4算法变种和 ECB 工作模式没有 IV外,其他的 IV 长度等于密文的第一个字节
+        if ((index > 0)
+                && !(Mode.ECB.toString().equals(transformation.substring(index + 1, transformation.lastIndexOf('/')))))
+            ivLength = of(cipherBytes).get()[0];
+
+        try {
+            Cipher cipher = Cipher.getInstance(transformation, PROVIDER_NAME);
+
+            if (ivLength > 0) {
+                // logger.info("接收方收到密文:IV+Cipher({} bytes): {}", cipherBytes.length, Encoder.Hex.encode(cipherBytes));
+                byte[] ivBytes = new byte[ivLength];
+                System.arraycopy(cipherBytes, 1, ivBytes, 0, ivLength);
+                byte[] cipherBytesNoIvLenghtAndIv = new byte[cipherBytes.length - ivLength - 1];
+                System.arraycopy(cipherBytes, ivLength + 1, cipherBytesNoIvLenghtAndIv, 0,
+                        cipherBytes.length - ivLength - 1);
+                cipherBytes = cipherBytesNoIvLenghtAndIv;
+                // logger.info("接收方提取初始向量:(IV {} bytes): {}", ivBytes.length, Encoder.Hex.encode(ivBytes));
+                cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(of(keyBytes).get(), transformation),
+                        new IvParameterSpec(ivBytes));
+            } else {
+                cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(of(keyBytes).get(), transformation));
+            }
+
+            return cipher.doFinal(cipherBytes);
+        } catch (GeneralSecurityException e) {
+            logger.warn("SM4 Decrypt Fil.Reason: {}", e.getMessage());
+            throw new RuntimeException(e);
+        }
+    }
+}

+ 16 - 0
sp-service/payment-server/src/main/java/com/pj/utils/Utils.java

@@ -0,0 +1,16 @@
+package com.pj.utils;
+
+import cn.hutool.crypto.Mode;
+import cn.hutool.crypto.Padding;
+
+/*
+*
+* HouseYoung@20210508
+*
+* */
+public class Utils {
+    public static String transformation(String algorithm, Mode mode, Padding padding) {
+        if(mode == null || "".equals(mode)) return algorithm;
+        return String.format("%s/%s/%s", algorithm,mode,padding);
+    }
+}

+ 186 - 171
sp-service/payment-server/src/main/java/com/pj/xml/MessageXML.java

@@ -4,6 +4,7 @@ package com.pj.xml;
 import com.pj.api.dto.CompanyDto;
 import com.pj.api.dto.PaymentDto;
 import com.pj.api.dto.PaymentTwoDto;
+import com.pj.utils.CryptoUtil;
 
 import java.text.SimpleDateFormat;
 import java.util.Date;
@@ -13,7 +14,9 @@ import java.util.UUID;
 public class MessageXML {
     static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss sss");
 
-    /** 订单扣款:一级市场--->银行  */
+    /**
+     * 订单扣款:一级市场--->银行
+     */
     public static String SXB010(PaymentDto paymentDto) {
         String date = sdf.format(new Date());
         String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
@@ -21,15 +24,15 @@ public class MessageXML {
                 "<headers>\n" +
                 "        <item>\n" +
                 "               <key>sn</key>\n" +
-                "              <value>"+ UUID.randomUUID()+"</value>\n" +
+                "              <value>" + UUID.randomUUID() + "</value>\n" +
                 "       </item>\n" +
                 "        <item>\n" +
                 "               <key>date</key>\n" +
-                "              <value>"+date+"</value>\n" +
+                "              <value>" + date + "</value>\n" +
                 "       </item>\n" +
                 "        <item>\n" +
                 "               <key>organization</key>\n" +
-                "              <value>"+paymentDto.getFieldCode()+"</value>\n" +//互市点机构代码
+                "              <value>" + paymentDto.getFieldCode() + "</value>\n" +//互市点机构代码
                 "       </item>\n" +
                 "        <item>\n" +
                 "            <key>bankCode</key>\n" +
@@ -41,62 +44,98 @@ public class MessageXML {
                 "       </item>\n" +
                 "</headers>\n" +
                 " <payload xsi:type=\"orderDTO\">\n" +
-                "         <sn>"+paymentDto.getTradeNo()+"</sn>\n" +                         //订单号
+                "         <sn>" + paymentDto.getTradeNo() + "</sn>\n" +                         //订单号
                 "         <export>false</export>\n" +                                       //出口标识	true:出口,false:进口
-                "         <organization>"+paymentDto.getFieldCode()+"</organization>\n" +   //互市点机构代码
-                "         <currency>"+paymentDto.getCurrCode()+"</currency>\n" +            //币种
+                "         <organization>" + paymentDto.getFieldCode() + "</organization>\n" +   //互市点机构代码
+                "         <currency>" + paymentDto.getCurrCode() + "</currency>\n" +            //币种
                 "         <type>01</type>\n" +                                              //业务类型	01 代表扣款报文
-                "         <charging>"+paymentDto.getResalePrice()+"</charging>\n" +         //计费金额(二级市场转售总金额)
-                "         <total>"+paymentDto.getTotalPrice()+"</total>\n" +                //总金额8000.00(一级市场边民订单金额)
-                "         <date>"+paymentDto.getDeclTime()+"</date>\n" +                    //订单时间	YYYY-MM—DD HH:MM:DD SSS
+                "         <charging>" + paymentDto.getResalePrice() + "</charging>\n" +         //计费金额(二级市场转售总金额)
+                "         <total>" + paymentDto.getTotalPrice() + "</total>\n" +                //总金额8000.00(一级市场边民订单金额)
+                "         <date>" + paymentDto.getDeclTime() + "</date>\n" +                    //订单时间	YYYY-MM—DD HH:MM:DD SSS
                 "<vendee>\n" +
-                "         <name>"+paymentDto.getBorderName()+"</name>\n" +                 //边民姓名
+                "         <name>" + paymentDto.getBorderName() + "</name>\n" +                 //边民姓名
                 "         <paperType>0001</paperType>\n" +                                 //证件类型  0001 身份证
-                "         <paperNo>"+paymentDto.getBorderidno()+"</paperNo>\n" +           //边民证件号
+                "         <paperNo>" + paymentDto.getBorderidno() + "</paperNo>\n" +           //边民证件号
                 "         <nationality>中国</nationality>\n" +                             //国籍
-                "         <accountNo>"+paymentDto.getBankCode()+"</accountNo>\n" +         //银行账号
+                "         <accountNo>" + paymentDto.getBankCode() + "</accountNo>\n" +         //银行账号
                 "         <bankCode>ICBKCNBJYUN</bankCode>\n" +                            //开户行代码
-                "         <tel>"+paymentDto.getBorderTel()+"</tel>\n" +                    //联系电话
+                "         <tel>" + paymentDto.getBorderTel() + "</tel>\n" +                    //联系电话
                 "</vendee>\n" +
                 "<vendor>\n" +
-                "         <name>"+paymentDto.getOwnerName()+"</name>\n" +                  //商铺所属人姓名
-                "         <paperType>"+paymentDto.getOwnerIdtype()+"</paperType>\n" +      //所属人证件类型
+                "         <name>" + paymentDto.getOwnerName() + "</name>\n" +                  //商铺所属人姓名
+                "         <paperType>" + paymentDto.getOwnerIdtype() + "</paperType>\n" +      //所属人证件类型
                 "         <paperNo></paperNo>\n" +                                         //所属人证件号
                 "         <nationality></nationality>\n" +                                 //国籍
-                "         <accountNo>"+paymentDto.getBankAccount()+"</accountNo>\n" +      //银行账号
+                "         <accountNo>" + paymentDto.getBankAccount() + "</accountNo>\n" +      //银行账号
                 "         <bankCode>ICBKCNBJYUN</bankCode>\n" +                            //开户行代码
-                "         <tel>"+paymentDto.getOwnerTel()+"</tel>\n" +                     //联系电话
+                "         <tel>" + paymentDto.getOwnerTel() + "</tel>\n" +                     //联系电话
                 "<vendor>\n" +
                 "<items>\n" +
-                "         <name>"+paymentDto.getGoodsName()+"</name>\n" +                   //商品名称
-                "         <unit>"+paymentDto.getGoodsUnit()+"</unit>\n" +                   //商品单位
-                "         <price>"+paymentDto.getDeclPrice()+"</price>\n" +                 //商品单价
-                "         <quantity>"+paymentDto.getBuyQty()+"</quantity>\n" +              //商品数量
-                "         <weight>"+paymentDto.getGrossWt()+"</weight>\n" +                 //商品重量
-                "         <amount>"+paymentDto.getTotalPrice()+"</amount>\n" +              //金额
+                "         <name>" + paymentDto.getGoodsName() + "</name>\n" +                   //商品名称
+                "         <unit>" + paymentDto.getGoodsUnit() + "</unit>\n" +                   //商品单位
+                "         <price>" + paymentDto.getDeclPrice() + "</price>\n" +                 //商品单价
+                "         <quantity>" + paymentDto.getBuyQty() + "</quantity>\n" +              //商品数量
+                "         <weight>" + paymentDto.getGrossWt() + "</weight>\n" +                 //商品重量
+                "         <amount>" + paymentDto.getTotalPrice() + "</amount>\n" +              //金额
                 "</items>\n" +
                 "</payload>\n" +
                 "</message>\n";
         return xml;
     }
 
-    /** 订单退款:一级市场--->银行  */
+    /**
+     * 订单退款:一级市场--->银行
+     */
     public static String SXB013(PaymentDto paymentDto) {
         String date = sdf.format(new Date());
+        String payload = " <sn>" + paymentDto.getTradeNo() + "</sn>\n" +                         //订单号
+                "         <organization>" + paymentDto.getFieldCode() + "</organization>\n" +   //互市点机构代码
+                "         <currency>" + paymentDto.getCurrCode() + "</currency>\n" +            //币种
+                "         <type>02</type>\n" +                                              //业务类型	02代表退款报文
+                "         <charging>" + paymentDto.getResalePrice() + "</charging>\n" +         //计费金额(二级市场转售总金额)
+                "         <total>" + paymentDto.getTotalPrice() + "</total>\n" +                //总金额8000.00(一级市场边民订单金额)
+                "         <date>" + paymentDto.getDeclTime() + "</date>\n" +                    //订单时间	YYYY-MM—DD HH:MM:DD SSS
+                "<vendee>\n" +
+                "         <name>" + paymentDto.getBorderName() + "</name>\n" +                 //边民姓名
+                "         <paperType>0001</paperType>\n" +                                 //证件类型  0001 身份证
+                "         <paperNo>" + paymentDto.getBorderidno() + "</paperNo>\n" +           //边民证件号
+                "         <nationality>中国</nationality>\n" +                             //国籍
+                "         <accountNo>" + paymentDto.getBankCode() + "</accountNo>\n" +         //银行账号
+                "         <bankCode>ICBKCNBJYUN</bankCode>\n" +                            //开户行代码
+                "         <tel>" + paymentDto.getBorderTel() + "</tel>\n" +                    //联系电话
+                "</vendee>\n" +
+                "<vendor>\n" +
+                "         <name>" + paymentDto.getOwnerName() + "</name>\n" +                  //商铺所属人姓名
+                "         <paperType>" + paymentDto.getOwnerIdtype() + "</paperType>\n" +      //所属人证件类型
+                "         <paperNo></paperNo>\n" +                                         //所属人证件号
+                "         <nationality></nationality>\n" +                                 //国籍
+                "         <accountNo>" + paymentDto.getBankAccount() + "</accountNo>\n" +      //银行账号
+                "         <bankCode>ICBKCNBJYUN</bankCode>\n" +                            //开户行代码
+                "         <tel>" + paymentDto.getOwnerTel() + "</tel>\n" +                     //联系电话
+                "<vendor>\n" +
+                "<items>\n" +
+                "         <name>" + paymentDto.getGoodsName() + "</name>\n" +                   //商品名称
+                "         <unit>" + paymentDto.getGoodsUnit() + "</unit>\n" +                   //商品单位
+                "         <price>" + paymentDto.getDeclPrice() + "</price>\n" +                 //商品单价
+                "         <quantity>" + paymentDto.getBuyQty() + "</quantity>\n" +              //商品数量
+                "         <weight>" + paymentDto.getGrossWt() + "</weight>\n" +                 //商品重量
+                "         <amount>" + paymentDto.getTotalPrice() + "</amount>\n" +              //金额
+                "</items>\n";
+
         String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
                 "<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"\">\n" +
                 "<headers>\n" +
                 "        <item>\n" +
                 "               <key>sn</key>\n" +
-                "              <value>"+UUID.randomUUID()+"</value>\n" +
+                "              <value>" + UUID.randomUUID() + "</value>\n" +
                 "       </item>\n" +
                 "        <item>\n" +
                 "               <key>date</key>\n" +
-                "              <value>"+date+"</value>\n" +
+                "              <value>" + date + "</value>\n" +
                 "       </item>\n" +
                 "        <item>\n" +
                 "               <key>organization</key>\n" +
-                "              <value>"+paymentDto.getFieldCode()+"</value>\n" +//互市点机构代码
+                "              <value>" + paymentDto.getFieldCode() + "</value>\n" +//互市点机构代码
                 "       </item>\n" +
                 "        <item>\n" +
                 "            <key>bankCode</key>\n" +
@@ -108,61 +147,34 @@ public class MessageXML {
                 "       </item>\n" +
                 "</headers>\n" +
                 " <payload xsi:type=\"orderDTO\">\n" +
-                "         <sn>"+paymentDto.getTradeNo()+"</sn>\n" +                         //订单号
-                "         <organization>"+paymentDto.getFieldCode()+"</organization>\n" +   //互市点机构代码
-                "         <currency>"+paymentDto.getCurrCode()+"</currency>\n" +            //币种
-                "         <type>02</type>\n" +                                              //业务类型	02代表退款报文
-                "         <charging>"+paymentDto.getResalePrice()+"</charging>\n" +         //计费金额(二级市场转售总金额)
-                "         <total>"+paymentDto.getTotalPrice()+"</total>\n" +                //总金额8000.00(一级市场边民订单金额)
-                "         <date>"+paymentDto.getDeclTime()+"</date>\n" +                    //订单时间	YYYY-MM—DD HH:MM:DD SSS
-                "<vendee>\n" +
-                "         <name>"+paymentDto.getBorderName()+"</name>\n" +                 //边民姓名
-                "         <paperType>0001</paperType>\n" +                                 //证件类型  0001 身份证
-                "         <paperNo>"+paymentDto.getBorderidno()+"</paperNo>\n" +           //边民证件号
-                "         <nationality>中国</nationality>\n" +                             //国籍
-                "         <accountNo>"+paymentDto.getBankCode()+"</accountNo>\n" +         //银行账号
-                "         <bankCode>ICBKCNBJYUN</bankCode>\n" +                            //开户行代码
-                "         <tel>"+paymentDto.getBorderTel()+"</tel>\n" +                    //联系电话
-                "</vendee>\n" +
-                "<vendor>\n" +
-                "         <name>"+paymentDto.getOwnerName()+"</name>\n" +                  //商铺所属人姓名
-                "         <paperType>"+paymentDto.getOwnerIdtype()+"</paperType>\n" +      //所属人证件类型
-                "         <paperNo></paperNo>\n" +                                         //所属人证件号
-                "         <nationality></nationality>\n" +                                 //国籍
-                "         <accountNo>"+paymentDto.getBankAccount()+"</accountNo>\n" +      //银行账号
-                "         <bankCode>ICBKCNBJYUN</bankCode>\n" +                            //开户行代码
-                "         <tel>"+paymentDto.getOwnerTel()+"</tel>\n" +                     //联系电话
-                "<vendor>\n" +
-                "<items>\n" +
-                "         <name>"+paymentDto.getGoodsName()+"</name>\n" +                   //商品名称
-                "         <unit>"+paymentDto.getGoodsUnit()+"</unit>\n" +                   //商品单位
-                "         <price>"+paymentDto.getDeclPrice()+"</price>\n" +                 //商品单价
-                "         <quantity>"+paymentDto.getBuyQty()+"</quantity>\n" +              //商品数量
-                "         <weight>"+paymentDto.getGrossWt()+"</weight>\n" +                 //商品重量
-                "         <amount>"+paymentDto.getTotalPrice()+"</amount>\n" +              //金额
-                "</items>\n" +
+                CryptoUtil.encrypt(payload)+
                 "</payload>\n" +
                 "</message>\n";
         return xml;
     }
 
-    /** 通关车批信息同步(车出一级市场时):一级市场--->银行 */
+    /**
+     * 通关车批信息同步(车出一级市场时):一级市场--->银行
+     */
     public static String SXB023(PaymentDto paymentDto) {
         String date = sdf.format(new Date());
+        String payload= "<registration>" + paymentDto.getVoyageNo() + "</registration>\n" +  //车辆批号
+                "         <plateNumber>" + paymentDto.getVeNo() + "</plateNumber>\n" +        //车牌号
+                "         <Order>" + paymentDto.getTradeNo() + "</Order>\n" ;              //订单号	n个
         String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
                 "<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"\">\n" +
                 "<headers>\n" +
                 "        <item>\n" +
                 "               <key>sn</key>\n" +
-                "              <value>"+UUID.randomUUID()+"</value>\n" +
+                "              <value>" + UUID.randomUUID() + "</value>\n" +
                 "       </item>\n" +
                 "        <item>\n" +
                 "               <key>date</key>\n" +
-                "              <value>"+date+"</value>\n" +
+                "              <value>" + date + "</value>\n" +
                 "       </item>\n" +
                 "        <item>\n" +
                 "               <key>organization</key>\n" +
-                "              <value>"+paymentDto.getFieldCode()+"</value>\n" +//互市点机构代码
+                "              <value>" + paymentDto.getFieldCode() + "</value>\n" +//互市点机构代码
                 "       </item>\n" +
                 "        <item>\n" +
                 "            <key>bankCode</key>\n" +
@@ -174,140 +186,130 @@ public class MessageXML {
                 "       </item>\n" +
                 "</headers>\n" +
                 " <payload xsi:type=\"carDTO\">\n" +
-                "         <registration>"+paymentDto.getVoyageNo()+"</registration>\n" +  //车辆批号
-                "         <plateNumber>"+paymentDto.getVeNo()+"</plateNumber>\n" +        //车牌号
-                "         <Order>"+paymentDto.getTradeNo()+"</Order>\n" +                //订单号	n个
+                CryptoUtil.encrypt(payload)+
                 "</payload>\n" +
                 "</message>\n";
         return xml;
     }
 
-    /** 订单扣款(无手续费):二级市场--->银行  */
+    /**
+     * 订单扣款(无手续费):二级市场--->银行
+     */
     public static String MKT006_NoCommission(PaymentTwoDto paymentTwoDto) {
         String date = sdf.format(new Date());
+        String payload=  "         <sn>" + paymentTwoDto.getOrderNo() + "</sn>\n" +                         //订单号
+                "         <organization>" + paymentTwoDto.getFieldCode() + "</organization>\n" +   //互市点机构代码
+                "         <currency>" + paymentTwoDto.getCurrCode() + "</currency>\n" +            //币种
+                "         <type>001</type>\n" +                                                //业务类型	001 代表扣款订单
+                "         <total>" + paymentTwoDto.getResalePrice() + "</total>\n" +               //订单总金额 8150.00 【买方总支付金额】(转售金额)
+                "         <actualTotal></actualTotal>\n" +                                     //扣除手续费边民实际到账金额  actualTotal忽略
+                "         <dateTime>" + paymentTwoDto.getDeclTime() + "</dateTime>\n" +            //订单时间	YYYY-MM—DD HH:MM:DD SSS
+
+                "<vendee>\n" +//买方基本信息(采购企业)
+                "         <name>" + paymentTwoDto.getPcName() + "</name>\n" +                       //企业名称
+                "         <paperType>0008</paperType>\n" +                                      //证件类型  0008 社会统一信用代码(默认)
+                "         <paperNo>" + paymentTwoDto.getBusinessLicense() + "</paperNo>\n" +        //证件号
+                "         <nationality>中国</nationality>\n" +                                  //国籍
+                "         <accountNo>" + paymentTwoDto.getPcBankAccount() + "</accountNo>\n" +     //银行账号
+                "         <bankCode>KCCBCN2K</bankCode>\n" +                                   //开户行代码
+                "         <tel>" + paymentTwoDto.getPcContact() + "</tel>\n" +                     //联系电话
+                "</vendee>\n" +
+
+                "<vendee>\n" +//卖方基础信息(边民)
+                "         <name>" + paymentTwoDto.getBorderName() + "</name>\n" +                 //边民姓名
+                "         <paperType>0001</paperType>\n" +                                    //证件类型  0001 身份证
+                "         <paperNo>" + paymentTwoDto.getBorderidno() + "</paperNo>\n" +           //边民证件号
+                "         <nationality>中国</nationality>\n" +                                //国籍
+                "         <accountNo>" + paymentTwoDto.getBankCode() + "</accountNo>\n" +        //银行账号
+                "         <bankCode>KCCBCN2K</bankCode>\n" +                                 //开户行代码
+                "         <tel>" + paymentTwoDto.getBorderTel() + "</tel>\n" +                   //联系电话
+                "</vendee>\n" +
+
+                "<items>\n" +//商品明细
+                "         <code>" + paymentTwoDto.getCodeTs() + "</code>\n" +                      //商品编码
+                "         <name>" + paymentTwoDto.getGoodsName() + "</name>\n" +                   //商品名称
+                "         <unit>" + paymentTwoDto.getGoodsUnit() + "</unit>\n" +                   //商品单位
+                "         <price>" + paymentTwoDto.getDeclPrice() + "</price>\n" +                 //商品单价
+                "         <quantity>" + paymentTwoDto.getBuyQty() + "</quantity>\n" +              //商品数量
+                "         <weight>" + paymentTwoDto.getGrossWt() + "</weight>\n" +                 //商品重量
+                "         <amount>" + paymentTwoDto.getResalePrice() + "</amount>\n" +              //金额
+                "</items>\n" +
+                "<items>\n" +
+                "         <name>" + paymentTwoDto.getGoodsName() + "</name>\n" +                   //商品名称
+                "         <unit>" + paymentTwoDto.getGoodsUnit() + "</unit>\n" +                   //商品单位
+                "         <price>" + paymentTwoDto.getDeclPrice() + "</price>\n" +                 //商品单价
+                "         <quantity>" + paymentTwoDto.getBuyQty() + "</quantity>\n" +              //商品数量
+                "         <weight>" + paymentTwoDto.getGrossWt() + "</weight>\n" +                 //商品重量
+                "         <amount>" + paymentTwoDto.getResalePrice() + "</amount>\n" +              //金额
+                "</items>\n" ;
         String xml =
                 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
                         "<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"\" title=\"二级市场\">\n" +
                         "<headers>\n" +
-                        "         <sn>"+UUID.randomUUID()+"</sn>\n" +
-                        "         <date>"+date+"</date> \n" +
-                        "         <organization>"+paymentTwoDto.getFieldCode()+"</organization>\n" +
+                        "         <sn>" + UUID.randomUUID() + "</sn>\n" +
+                        "         <date>" + date + "</date> \n" +
+                        "         <organization>" + paymentTwoDto.getFieldCode() + "</organization>\n" +
                         "         <bankCode>KCCBCN2K</bankCode>\n" +
                         "         <operation>MKT006</operation>\n" +
                         "</headers>\n" +
 
                         " <payload xsi:type=\"orderDTO\">\n" +
-                        "         <sn>"+paymentTwoDto.getOrderNo()+"</sn>\n" +                         //订单号
-                        "         <organization>"+paymentTwoDto.getFieldCode()+"</organization>\n" +   //互市点机构代码
-                        "         <currency>"+paymentTwoDto.getCurrCode()+"</currency>\n" +            //币种
-                        "         <type>001</type>\n" +                                                //业务类型	001 代表扣款订单
-                        "         <total>"+paymentTwoDto.getResalePrice()+"</total>\n" +               //订单总金额 8150.00 【买方总支付金额】(转售金额)
-                        "         <actualTotal></actualTotal>\n" +                                     //扣除手续费边民实际到账金额  actualTotal忽略
-                        "         <dateTime>"+paymentTwoDto.getDeclTime()+"</dateTime>\n" +            //订单时间	YYYY-MM—DD HH:MM:DD SSS
-
-                        "<vendee>\n" +//买方基本信息(采购企业)
-                        "         <name>"+paymentTwoDto.getPcName()+"</name>\n" +                       //企业名称
-                        "         <paperType>0008</paperType>\n" +                                      //证件类型  0008 社会统一信用代码(默认)
-                        "         <paperNo>"+paymentTwoDto.getBusinessLicense()+"</paperNo>\n" +        //证件号
-                        "         <nationality>中国</nationality>\n" +                                  //国籍
-                        "         <accountNo>"+paymentTwoDto.getPcBankAccount()+"</accountNo>\n" +     //银行账号
-                        "         <bankCode>KCCBCN2K</bankCode>\n" +                                   //开户行代码
-                        "         <tel>"+paymentTwoDto.getPcContact()+"</tel>\n" +                     //联系电话
-                        "</vendee>\n" +
-
-                        "<vendee>\n" +//卖方基础信息(边民)
-                        "         <name>"+paymentTwoDto.getBorderName()+"</name>\n" +                 //边民姓名
-                        "         <paperType>0001</paperType>\n" +                                    //证件类型  0001 身份证
-                        "         <paperNo>"+paymentTwoDto.getBorderidno()+"</paperNo>\n" +           //边民证件号
-                        "         <nationality>中国</nationality>\n" +                                //国籍
-                        "         <accountNo>"+paymentTwoDto.getBankCode()+"</accountNo>\n" +        //银行账号
-                        "         <bankCode>KCCBCN2K</bankCode>\n" +                                 //开户行代码
-                        "         <tel>"+paymentTwoDto.getBorderTel()+"</tel>\n" +                   //联系电话
-                        "</vendee>\n" +
-
-                        "<items>\n" +//商品明细
-                        "         <code>"+paymentTwoDto.getCodeTs()+"</code>\n" +                      //商品编码
-                        "         <name>"+paymentTwoDto.getGoodsName()+"</name>\n" +                   //商品名称
-                        "         <unit>"+paymentTwoDto.getGoodsUnit()+"</unit>\n" +                   //商品单位
-                        "         <price>"+paymentTwoDto.getDeclPrice()+"</price>\n" +                 //商品单价
-                        "         <quantity>"+paymentTwoDto.getBuyQty()+"</quantity>\n" +              //商品数量
-                        "         <weight>"+paymentTwoDto.getGrossWt()+"</weight>\n" +                 //商品重量
-                        "         <amount>"+paymentTwoDto.getResalePrice()+"</amount>\n" +              //金额
-                        "</items>\n" +
-                        "<items>\n" +
-                        "         <name>"+paymentTwoDto.getGoodsName()+"</name>\n" +                   //商品名称
-                        "         <unit>"+paymentTwoDto.getGoodsUnit()+"</unit>\n" +                   //商品单位
-                        "         <price>"+paymentTwoDto.getDeclPrice()+"</price>\n" +                 //商品单价
-                        "         <quantity>"+paymentTwoDto.getBuyQty()+"</quantity>\n" +              //商品数量
-                        "         <weight>"+paymentTwoDto.getGrossWt()+"</weight>\n" +                 //商品重量
-                        "         <amount>"+paymentTwoDto.getResalePrice()+"</amount>\n" +              //金额
-                        "</items>\n" +
-
+                            CryptoUtil.encrypt(payload)+
                         "</payload>\n" +
                         "</message>\n";
         return xml;
     }
 
-    /** 订单扣款(+手续费):二级市场--->银行  */
+    /**
+     * 订单扣款(+手续费):二级市场--->银行
+     */
     public static String MKT006(PaymentTwoDto paymentTwoDto) {
         String date = sdf.format(new Date());
-        String chargesXml = chargesXml(paymentTwoDto.getCompanyDtoList(),paymentTwoDto.getOrderNo());
-        String xml =
-                "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
-                "<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"\" title=\"二级市场\">\n" +
-                "<headers>\n" +
-                "         <sn>"+UUID.randomUUID()+"</sn>\n" +
-                "         <date>"+date+"</date> \n" +
-                "         <organization>"+paymentTwoDto.getFieldCode()+"</organization>\n" +
-                "         <bankCode>KCCBCN2K</bankCode>\n" +
-                "         <operation>MKT006</operation>\n" +
-                "</headers>\n" +
-
-                " <payload xsi:type=\"orderDTO\">\n" +
-                "         <sn>"+paymentTwoDto.getOrderNo()+"</sn>\n" +                          //订单号
-                "         <organization>"+paymentTwoDto.getFieldCode()+"</organization>\n" +    //互市点机构代码
-                "         <currency>"+paymentTwoDto.getCurrCode()+"</currency>\n" +             //币种
+        String chargesXml = chargesXml(paymentTwoDto.getCompanyDtoList(), paymentTwoDto.getOrderNo());
+        String payload=                       "         <sn>" + paymentTwoDto.getOrderNo() + "</sn>\n" +                          //订单号
+                "         <organization>" + paymentTwoDto.getFieldCode() + "</organization>\n" +    //互市点机构代码
+                "         <currency>" + paymentTwoDto.getCurrCode() + "</currency>\n" +             //币种
                 "         <type>001</type>\n" +                                                 //业务类型	001 代表扣款订单
-                "         <total>"+paymentTwoDto.getResalePrice()+"</total>\n" +                //订单总金额 8150.00 【买方总支付金额】
-                "         <actualTotal>"+paymentTwoDto.getTotalPrice()+"</actualTotal>\n" +    //扣除手续费边民实际到账金额 8050
-                "         <dateTime>"+paymentTwoDto.getDeclTime()+"</dateTime>\n" +            //订单时间	YYYY-MM—DD HH:MM:DD SSS
+                "         <total>" + paymentTwoDto.getResalePrice() + "</total>\n" +                //订单总金额 8150.00 【买方总支付金额】
+                "         <actualTotal>" + paymentTwoDto.getTotalPrice() + "</actualTotal>\n" +    //扣除手续费边民实际到账金额 8050
+                "         <dateTime>" + paymentTwoDto.getDeclTime() + "</dateTime>\n" +            //订单时间	YYYY-MM—DD HH:MM:DD SSS
 
                 "<vendee>\n" +//买方基本信息(采购企业)
-                "         <name>"+paymentTwoDto.getPcName()+"</name>\n" +                       //企业名称
+                "         <name>" + paymentTwoDto.getPcName() + "</name>\n" +                       //企业名称
                 "         <paperType>0008</paperType>\n" +                                      //证件类型  0008 社会统一信用代码(默认)
-                "         <paperNo>"+paymentTwoDto.getBusinessLicense()+"</paperNo>\n" +        //证件号
+                "         <paperNo>" + paymentTwoDto.getBusinessLicense() + "</paperNo>\n" +        //证件号
                 "         <nationality>中国</nationality>\n" +                                  //国籍
-                "         <accountNo>"+paymentTwoDto.getPcBankAccount()+"</accountNo>\n" +     //银行账号
+                "         <accountNo>" + paymentTwoDto.getPcBankAccount() + "</accountNo>\n" +     //银行账号
                 "         <bankCode>KCCBCN2K</bankCode>\n" +                                   //开户行代码
-                "         <tel>"+paymentTwoDto.getPcContact()+"</tel>\n" +                     //联系电话
+                "         <tel>" + paymentTwoDto.getPcContact() + "</tel>\n" +                     //联系电话
                 "</vendee>\n" +
 
                 "<vendee>\n" +//卖方基础信息(边民)
-                "         <name>"+paymentTwoDto.getBorderName()+"</name>\n" +                 //边民姓名
+                "         <name>" + paymentTwoDto.getBorderName() + "</name>\n" +                 //边民姓名
                 "         <paperType>0001</paperType>\n" +                                    //证件类型  0001 身份证
-                "         <paperNo>"+paymentTwoDto.getBorderidno()+"</paperNo>\n" +           //边民证件号
+                "         <paperNo>" + paymentTwoDto.getBorderidno() + "</paperNo>\n" +           //边民证件号
                 "         <nationality>中国</nationality>\n" +                                //国籍
-                "         <accountNo>"+paymentTwoDto.getBankCode()+"</accountNo>\n" +        //银行账号
+                "         <accountNo>" + paymentTwoDto.getBankCode() + "</accountNo>\n" +        //银行账号
                 "         <bankCode>KCCBCN2K</bankCode>\n" +                                 //开户行代码
-                "         <tel>"+paymentTwoDto.getBorderTel()+"</tel>\n" +                   //联系电话
+                "         <tel>" + paymentTwoDto.getBorderTel() + "</tel>\n" +                   //联系电话
                 "</vendee>\n" +
 
                 "<items>\n" +//商品明细
-                "         <code>"+paymentTwoDto.getCodeTs()+"</code>\n" +                      //商品编码
-                "         <name>"+paymentTwoDto.getGoodsName()+"</name>\n" +                   //商品名称
-                "         <unit>"+paymentTwoDto.getGoodsUnit()+"</unit>\n" +                   //商品单位
-                "         <price>"+paymentTwoDto.getDeclPrice()+"</price>\n" +                 //商品单价
-                "         <quantity>"+paymentTwoDto.getBuyQty()+"</quantity>\n" +              //商品数量
-                "         <weight>"+paymentTwoDto.getGrossWt()+"</weight>\n" +                 //商品重量
-                "         <amount>"+paymentTwoDto.getResalePrice()+"</amount>\n" +              //金额
+                "         <code>" + paymentTwoDto.getCodeTs() + "</code>\n" +                      //商品编码
+                "         <name>" + paymentTwoDto.getGoodsName() + "</name>\n" +                   //商品名称
+                "         <unit>" + paymentTwoDto.getGoodsUnit() + "</unit>\n" +                   //商品单位
+                "         <price>" + paymentTwoDto.getDeclPrice() + "</price>\n" +                 //商品单价
+                "         <quantity>" + paymentTwoDto.getBuyQty() + "</quantity>\n" +              //商品数量
+                "         <weight>" + paymentTwoDto.getGrossWt() + "</weight>\n" +                 //商品重量
+                "         <amount>" + paymentTwoDto.getResalePrice() + "</amount>\n" +              //金额
                 "</items>\n" +
                 "<items>\n" +
-                "         <name>"+paymentTwoDto.getGoodsName()+"</name>\n" +                   //商品名称
-                "         <unit>"+paymentTwoDto.getGoodsUnit()+"</unit>\n" +                   //商品单位
-                "         <price>"+paymentTwoDto.getDeclPrice()+"</price>\n" +                 //商品单价
-                "         <quantity>"+paymentTwoDto.getBuyQty()+"</quantity>\n" +              //商品数量
-                "         <weight>"+paymentTwoDto.getGrossWt()+"</weight>\n" +                 //商品重量
-                "         <amount>"+paymentTwoDto.getResalePrice()+"</amount>\n" +              //金额
+                "         <name>" + paymentTwoDto.getGoodsName() + "</name>\n" +                   //商品名称
+                "         <unit>" + paymentTwoDto.getGoodsUnit() + "</unit>\n" +                   //商品单位
+                "         <price>" + paymentTwoDto.getDeclPrice() + "</price>\n" +                 //商品单价
+                "         <quantity>" + paymentTwoDto.getBuyQty() + "</quantity>\n" +              //商品数量
+                "         <weight>" + paymentTwoDto.getGrossWt() + "</weight>\n" +                 //商品重量
+                "         <amount>" + paymentTwoDto.getResalePrice() + "</amount>\n" +              //金额
                 "</items>\n" +
 
                 /*"<charges>\n" +//父级手续费(有子级手续费)
@@ -337,28 +339,41 @@ public class MessageXML {
                         "</childrenCharges>\n" +
                 "</charges>\n" +*/
 
-                 chargesXml +       //父级手续费(无子级手续费)
+                chargesXml ;      //父级手续费(无子级手续费);
+        String xml =
+                "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
+                        "<message xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"\" title=\"二级市场\">\n" +
+                        "<headers>\n" +
+                        "         <sn>" + UUID.randomUUID() + "</sn>\n" +
+                        "         <date>" + date + "</date> \n" +
+                        "         <organization>" + paymentTwoDto.getFieldCode() + "</organization>\n" +
+                        "         <bankCode>KCCBCN2K</bankCode>\n" +
+                        "         <operation>MKT006</operation>\n" +
+                        "</headers>\n" +
 
-                "</payload>\n" +
-                "</message>\n";
+                        " <payload xsi:type=\"orderDTO\">\n" +
+                        CryptoUtil.encrypt(payload)+
+                        "</payload>\n" +
+                        "</message>\n";
         return xml;
     }
-    private static String chargesXml(List<CompanyDto> companyDtoList, String orderNo){
+
+    private static String chargesXml(List<CompanyDto> companyDtoList, String orderNo) {
         String xml = "";
         for (CompanyDto companyDto : companyDtoList) {
-            xml +=  "<charges>\n" +//父级手续费(无子级手续费)
+            xml += "<charges>\n" +//父级手续费(无子级手续费)
                     "         <type></type>\n" +                                          //手续费类型	数据字典:ChargeType
-                    "         <sn>"+orderNo+"</sn>\n" +                                   //订单号
-                    "         <name>"+companyDto.getName()+"</name>\n" +                  //企业名称
+                    "         <sn>" + orderNo + "</sn>\n" +                                   //订单号
+                    "         <name>" + companyDto.getName() + "</name>\n" +                  //企业名称
                     "         <paperType>0008</paperType>\n" +                            //证件类型  0008 社会统一信用代码(默认)
-                    "         <paperNo>"+companyDto.getUsci()+"</paperNo>\n" +            //证件号
+                    "         <paperNo>" + companyDto.getUsci() + "</paperNo>\n" +            //证件号
                     "         <nationality>中国</nationality>\n" +                         //国籍
-                    "         <accountNo>"+companyDto.getBankAccount()+"</accountNo>\n" + //银行账号
+                    "         <accountNo>" + companyDto.getBankAccount() + "</accountNo>\n" + //银行账号
                     "         <bankCode>KCCBCN2K</bankCode>\n" +                          //开户行代码
                     "         <bankNo></bankNo>\n" +                                      //开户行行号	非必填
-                    "         <tel>"+companyDto.getContact()+"</tel>\n" +                 //联系电话
-                    "         <total>"+companyDto.getChargesPrice()+"</total>\n" +        //手续费金额
-                    "</charges>\n" ;
+                    "         <tel>" + companyDto.getContact() + "</tel>\n" +                 //联系电话
+                    "         <total>" + companyDto.getChargesPrice() + "</total>\n" +        //手续费金额
+                    "</charges>\n";
         }
         return xml;
     }