Browse Source

Merge remote-tracking branch 'origin/dev' into dev

lazhaoqian 3 years ago
parent
commit
078fe52796

+ 2 - 0
blade-service-api/blade-purchase-sales-api/src/main/java/org/springblade/purchase/sales/vo/OrderItemBillNoVO.java

@@ -16,5 +16,7 @@ public class OrderItemBillNoVO
 
   private Long itemId;
 
+  private String cntrNo;
+
   private List<Map<String,Object>> itemName;
 }

+ 4 - 4
blade-service/blade-check/src/main/java/org/springblade/check/controller/AuditProecessController.java

@@ -149,14 +149,14 @@ public class AuditProecessController extends BladeController {
 	public  R operationFinanceProcess(@RequestBody AuditProecess auditProecess)
 	{
 		auditProecessService.operationFinanceProcess(auditProecess);
-		return R.success("操作成功");
+		return R.data(auditProecess);
 	}
 
 	@PostMapping("batchOperation")
 	@ApiOperationSupport(order = 2)
 	@ApiOperation(value = "批量审批", notes = "传入auditProecessDTOList")
 	public R batchOperation(@ApiParam(value = "主键集合", required = true) @RequestParam String ids,
-							@ApiParam(value = "操作状态", required = true) @RequestParam String auditStatus)
+							@ApiParam(value = "操作状态", required = true) @RequestParam Integer operate)
 	{
               LambdaQueryWrapper<AuditProecess> auditProecessLambdaQueryWrapper=new LambdaQueryWrapper<>();
 		      auditProecessLambdaQueryWrapper.in(AuditProecess::getId, Func.toLongList(ids));
@@ -165,8 +165,8 @@ public class AuditProecessController extends BladeController {
 		      {
 		      	throw new SecurityException("未查询相关数据,禁止操作");
 			  }
-		     auditProecessService.batchOperation(proecessList,auditStatus);
-		     return R.success("操作成功");
+		      auditProecessService.batchOperation(proecessList,operate);
+		      return R.success("操作成功");
 	}
 
 

+ 1 - 1
blade-service/blade-check/src/main/java/org/springblade/check/service/IAuditProecessService.java

@@ -45,6 +45,6 @@ public interface IAuditProecessService extends IService<AuditProecess> {
 
 	void operationFinanceProcess(AuditProecess auditProecess);
 
-	void batchOperation(List<AuditProecess> processLis,String auditStatus);
+	void batchOperation(List<AuditProecess> processLis,Integer operate);
 
 }

+ 2 - 2
blade-service/blade-check/src/main/java/org/springblade/check/service/impl/AuditProecessServiceImpl.java

@@ -239,10 +239,10 @@ public class AuditProecessServiceImpl extends ServiceImpl<AuditProecessMapper, A
 	@Override
 	@Transactional
 	@GlobalTransactional
-	public void batchOperation(List<AuditProecess> processLis, String auditStatus)
+	public void batchOperation(List<AuditProecess> processLis, Integer operate)
 	{
 		processLis.forEach(e->{
-			e.setAuditStatus(auditStatus);
+			e.setOperate(operate);
 			this.operationFinanceProcess(e);
 		});
 	}

+ 2 - 2
blade-service/blade-deliver-goods/src/main/java/org/springblade/deliver/goods/service/impl/DeliveryServiceImpl.java

@@ -291,7 +291,7 @@ public class DeliveryServiceImpl extends ServiceImpl<DeliveryMapper, Delivery> i
 				R r = iOrderItemsClient.updateActualQuantity(e.getSrcId(), inventoryNumber, 1);
 				if(!r.isSuccess())
 				{
-					throw new SecurityException("更新采购明细失败->已发数量");
+					throw new SecurityException("操作已发数量失败:"+r.getMsg());
 				}
 				if(delivery.getTradeType().equals("JK"))
 				{
@@ -299,7 +299,7 @@ public class DeliveryServiceImpl extends ServiceImpl<DeliveryMapper, Delivery> i
 					R weightR = iOrderItemsClient.updateActualWeight(e.getSrcId(), invoiceWeight, 1);
 					if(!weightR.isSuccess())
 					{
-						throw new SecurityException("更新采购明细失败->已发发票重量");
+						throw new SecurityException("操作发票重量失败:"+weightR.getMsg());
 					}
 				}
 

+ 2 - 2
blade-service/blade-purchase-sales/src/main/java/org/springblade/purchase/sales/feign/OrderItemsClient.java

@@ -45,7 +45,7 @@ public class OrderItemsClient implements IOrderItemsClient{
 			//判断 已发货数量 或者 已收货数量 ,不能大于(订货数量-已收数量)
 			if(actualQuantity.compareTo(orderItems.getOrderQuantity().subtract(orderItems.getActualQuantity()))>0)
 			{
-				throw  new RuntimeException("操作数量禁止大于订货数量");
+				throw  new RuntimeException("操作数量大于件数,无法出入库");
 			}
 
 			items.setActualQuantity(orderItems.getActualQuantity().add(actualQuantity));
@@ -77,7 +77,7 @@ public class OrderItemsClient implements IOrderItemsClient{
 			//判断 已发货数量 或者 已收货数量 ,不能大于(订货数量-已收数量)
 			if(actualWeight.compareTo(orderItems.getInvoiceWeight().subtract(orderItems.getActualWeight()))>0)
 			{
-				throw  new RuntimeException("操作数量禁止大于订货数量");
+				throw  new RuntimeException("操作重量大于发票重量,无法出入库");
 			}
 
 			items.setActualWeight(orderItems.getActualWeight().add(actualWeight));

+ 1 - 0
blade-service/blade-purchase-sales/src/main/java/org/springblade/purchase/sales/mapper/OrderMapper.xml

@@ -372,6 +372,7 @@
 
     <select id="findContractNoByBillNo" resultType="org.springblade.purchase.sales.vo.OrderItemBillNoVO">
         SELECT
+        b.cntr_no as cntrNo,
         a.order_no as orderNo,
         b.bill_no as billNo,
         b.item_id as itemId

+ 1 - 0
blade-service/pom.xml

@@ -31,6 +31,7 @@
         <module>trade-finance</module>
         <module>store-goods</module>
         <module>blade-check</module>
+        <module>blade-rocket-mq</module>
     </modules>
 
     <dependencies>

+ 888 - 0
blade-service/trade-finance/src/main/java/org/springblade/finance/tool/CertificateUtils.java

@@ -0,0 +1,888 @@
+package org.springblade.finance.tool;
+
+import javax.crypto.Cipher;
+import java.io.*;
+import java.nio.MappedByteBuffer;
+import java.nio.channels.FileChannel;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.Signature;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateException;
+import java.security.cert.CertificateFactory;
+import java.security.cert.X509Certificate;
+import java.util.Base64;
+import java.util.Date;
+
+/**
+ * <p>
+ * 数字签名/加密解密工具包
+ * </p>
+ */
+public class CertificateUtils {
+
+    /**
+     * Java密钥库(Java 密钥库,JKS)KEY_STORE
+     */
+    public static final String KEY_STORE = "JKS";
+
+    public static final String X509 = "X.509";
+
+    /**
+     * 文件读取缓冲区大小
+     */
+    private static final int CACHE_SIZE = 2048;
+
+    /**
+     * 最大文件加密块
+     */
+    private static final int MAX_ENCRYPT_BLOCK = 117;
+
+    /**
+     * 最大文件解密块
+     */
+    private static final int MAX_DECRYPT_BLOCK = 128;
+
+    /**
+     * <p>
+     * 根据密钥库获得私钥
+     * </p>
+     *
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    static PrivateKey getPrivateKey(String keyStorePath, String alias, String password)
+            throws Exception {
+        KeyStore keyStore = getKeyStore(keyStorePath, password);
+        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
+        return privateKey;
+    }
+
+    /**
+     * <p>
+     * 获得密钥库
+     * </p>
+     *
+     * @param keyStorePath 密钥库存储路径
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    private static KeyStore getKeyStore(String keyStorePath, String password)
+            throws Exception {
+        FileInputStream in = new FileInputStream(keyStorePath);
+        KeyStore keyStore = KeyStore.getInstance(KEY_STORE);
+        keyStore.load(in, password.toCharArray());
+        in.close();
+        return keyStore;
+    }
+
+    /**
+     * <p>
+     * 根据证书获得公钥
+     * </p>
+     *
+     * @param certificatePath 证书存储路径
+     * @return
+     * @throws Exception
+     */
+    static PublicKey getPublicKey(String certificatePath) throws CertificateException, IOException {
+        Certificate certificate = getCertificate(certificatePath);
+        PublicKey publicKey = certificate.getPublicKey();
+        return publicKey;
+    }
+
+    /**
+     * <p>
+     * 根据证书获得公钥
+     * </p>
+     *
+     * @param certificateInStream 证书输入流
+     * @return
+     * @throws Exception
+     */
+    static PublicKey getPublicKey(InputStream certificateInStream) throws CertificateException, IOException {
+        Certificate certificate = getCertificate(certificateInStream);
+        PublicKey publicKey = certificate.getPublicKey();
+        return publicKey;
+    }
+
+    /**
+     * <p>
+     * 获得证书
+     * </p>
+     *
+     * @param certificatePath 证书存储路径
+     * @return
+     * @throws Exception
+     */
+    private static Certificate getCertificate(String certificatePath) throws CertificateException, IOException {
+        CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
+        FileInputStream in = new FileInputStream(certificatePath);
+        Certificate certificate = certificateFactory.generateCertificate(in);
+        in.close();
+        return certificate;
+    }
+
+    /**
+     * <p>
+     * 获得证书
+     * </p>
+     *
+     * @param certificateInStream 证书输入流
+     * @return
+     * @throws Exception
+     */
+    private static Certificate getCertificate(InputStream certificateInStream) throws CertificateException, IOException {
+        CertificateFactory certificateFactory = CertificateFactory.getInstance(X509);
+        Certificate certificate = certificateFactory.generateCertificate(certificateInStream);
+        certificateInStream.close();
+        return certificate;
+    }
+
+    /**
+     * <p>
+     * 根据密钥库获得证书
+     * </p>
+     *
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    private static Certificate getCertificate(String keyStorePath, String alias, String password)
+            throws Exception {
+        KeyStore keyStore = getKeyStore(keyStorePath, password);
+        Certificate certificate = keyStore.getCertificate(alias);
+        return certificate;
+    }
+
+    /**
+     * <p>
+     * 私钥加密
+     * </p>
+     *
+     * @param data 源数据
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    public static byte[] encryptByPrivateKey(byte[] data, String keyStorePath, String alias, String password)
+            throws Exception {
+        // 取得私钥
+        PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
+        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
+        System.out.print("\n=========="+privateKey.getAlgorithm()+"\n==========");
+        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+        int inputLen = data.length;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int offSet = 0;
+        byte[] cache;
+        int i = 0;
+        // 对数据分段加密
+        while (inputLen - offSet > 0) {
+            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
+                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
+            } else {
+                cache = cipher.doFinal(data, offSet, inputLen - offSet);
+            }
+            out.write(cache, 0, cache.length);
+            i++;
+            offSet = i * MAX_ENCRYPT_BLOCK;
+        }
+        byte[] encryptedData = out.toByteArray();
+        out.close();
+        return encryptedData;
+    }
+
+    /**
+     * <p>
+     * 文件私钥加密
+     * </p>
+     * <p>
+     * 过大的文件可能会导致内存溢出
+     * </>
+     *
+     * @param filePath 文件路径
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    public static byte[] encryptFileByPrivateKey(String filePath, String keyStorePath, String alias, String password)
+            throws Exception {
+        byte[] data = fileToByte(filePath);
+        return encryptByPrivateKey(data, keyStorePath, alias, password);
+    }
+
+    /**
+     * <p>
+     * 文件加密
+     * </p>
+     *
+     * @param srcFilePath 源文件
+     * @param destFilePath 加密后文件
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @throws Exception
+     */
+    public static void encryptFileByPrivateKey(String srcFilePath, String destFilePath, String keyStorePath, String alias, String password)
+            throws Exception {
+        // 取得私钥
+        PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
+        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
+        cipher.init(Cipher.ENCRYPT_MODE, privateKey);
+        File srcFile = new File(srcFilePath);
+        FileInputStream in = new FileInputStream(srcFile);
+        File destFile = new File(destFilePath);
+        if (!destFile.getParentFile().exists()) {
+            destFile.getParentFile().mkdirs();
+        }
+        destFile.createNewFile();
+        OutputStream out = new FileOutputStream(destFile);
+        byte[] data = new byte[MAX_ENCRYPT_BLOCK];
+        byte[] encryptedData;    // 加密块
+        while (in.read(data) != -1) {
+            encryptedData = cipher.doFinal(data);
+            out.write(encryptedData, 0, encryptedData.length);
+            out.flush();
+        }
+        out.close();
+        in.close();
+    }
+
+    /**
+     * <p>
+     * 文件加密成BASE64编码的字符串
+     * </p>
+     *
+     * @param filePath 文件路径
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+//    public static String encryptFileToBase64ByPrivateKey(String filePath, String keyStorePath, String alias, String password)
+//            throws Exception {
+//        byte[] encryptedData = encryptFileByPrivateKey(filePath, keyStorePath, alias, password);
+//        return Base64Utils.encode(encryptedData);
+//    }
+
+    /**
+     * <p>
+     * 私钥解密
+     * </p>
+     *
+     * @param encryptedData 已加密数据
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    public static byte[] decryptByPrivateKey(byte[] encryptedData, String keyStorePath, String alias, String password)
+            throws Exception {
+        // 取得私钥
+        PrivateKey privateKey = getPrivateKey(keyStorePath, alias, password);
+        Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
+        cipher.init(Cipher.DECRYPT_MODE, privateKey);
+        // 解密byte数组最大长度限制: 128
+        int inputLen = encryptedData.length;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int offSet = 0;
+        byte[] cache;
+        int i = 0;
+        // 对数据分段解密
+        while (inputLen - offSet > 0) {
+            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
+                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
+            } else {
+                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
+            }
+            out.write(cache, 0, cache.length);
+            i++;
+            offSet = i * MAX_DECRYPT_BLOCK;
+        }
+        byte[] decryptedData = out.toByteArray();
+        out.close();
+        return decryptedData;
+    }
+
+    /**
+     * <p>
+     * 公钥加密
+     * </p>
+     *
+     * @param data 源数据
+     * @param certificatePath 证书存储路径
+     * @return
+     * @throws Exception
+     */
+    public static byte[] encryptByPublicKey(byte[] data, String certificatePath)
+            throws Exception {
+        // 取得公钥
+        PublicKey publicKey = getPublicKey(certificatePath);
+        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
+        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
+        int inputLen = data.length;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int offSet = 0;
+        byte[] cache;
+        int i = 0;
+        // 对数据分段加密
+        while (inputLen - offSet > 0) {
+            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
+                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
+            } else {
+                cache = cipher.doFinal(data, offSet, inputLen - offSet);
+            }
+            out.write(cache, 0, cache.length);
+            i++;
+            offSet = i * MAX_ENCRYPT_BLOCK;
+        }
+        byte[] encryptedData = out.toByteArray();
+        out.close();
+        return encryptedData;
+    }
+
+    /**
+     * <p>
+     * 公钥解密
+     * </p>
+     *
+     * @param encryptedData 已加密数据
+     * @param certificatePath 证书存储路径
+     * @return
+     * @throws Exception
+     */
+    public static byte[] decryptByPublicKey(byte[] encryptedData, String certificatePath)
+            throws Exception {
+        PublicKey publicKey = getPublicKey(certificatePath);
+        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
+        cipher.init(Cipher.DECRYPT_MODE, publicKey);
+        int inputLen = encryptedData.length;
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        int offSet = 0;
+        byte[] cache;
+        int i = 0;
+        // 对数据分段解密
+        while (inputLen - offSet > 0) {
+            if (inputLen - offSet > MAX_DECRYPT_BLOCK) {
+                cache = cipher.doFinal(encryptedData, offSet, MAX_DECRYPT_BLOCK);
+            } else {
+                cache = cipher.doFinal(encryptedData, offSet, inputLen - offSet);
+            }
+            out.write(cache, 0, cache.length);
+            i++;
+            offSet = i * MAX_DECRYPT_BLOCK;
+        }
+        byte[] decryptedData = out.toByteArray();
+        out.close();
+        return decryptedData;
+    }
+
+    /**
+     * <p>
+     * 文件解密
+     * </p>
+     *
+     * @param srcFilePath 源文件
+     * @param destFilePath 目标文件
+     * @param certificatePath 证书存储路径
+     * @throws Exception
+     */
+    public static void decryptFileByPublicKey(String srcFilePath, String destFilePath, String certificatePath)
+            throws Exception {
+        PublicKey publicKey = getPublicKey(certificatePath);
+        Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
+        cipher.init(Cipher.DECRYPT_MODE, publicKey);
+        File srcFile = new File(srcFilePath);
+        FileInputStream in = new FileInputStream(srcFile);
+        File destFile = new File(destFilePath);
+        if (!destFile.getParentFile().exists()) {
+            destFile.getParentFile().mkdirs();
+        }
+        destFile.createNewFile();
+        OutputStream out = new FileOutputStream(destFile);
+        byte[] data = new byte[MAX_DECRYPT_BLOCK];
+        byte[] decryptedData;    // 解密块
+        while (in.read(data) != -1) {
+            decryptedData = cipher.doFinal(data);
+            out.write(decryptedData, 0, decryptedData.length);
+            out.flush();
+        }
+        out.close();
+        in.close();
+    }
+
+    /**
+     * <p>
+     * 生成数据签名
+     * </p>
+     *
+     * @param data 源数据
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    public static byte[] sign(byte[] data, String keyStorePath, String alias, String password)
+            throws Exception {
+        // 获得证书
+        X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath, alias, password);
+        // 获取私钥
+        KeyStore keyStore = getKeyStore(keyStorePath, password);
+        // 取得私钥
+        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
+        // 构建签名
+        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
+        signature.initSign(privateKey);
+        signature.update(data);
+        return signature.sign();
+    }
+
+    /**
+     * <p>
+     * 生成数据签名并以BASE64编码
+     * </p>
+     *
+     * @param data 源数据
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    public static String signToBase64(byte[] data, String keyStorePath, String alias, String password)
+            throws Exception {
+        return Base64.getEncoder().encodeToString(sign(data, keyStorePath, alias, password));
+    }
+
+    /**
+     * <p>
+     * 生成文件数据签名(BASE64)
+     * </p>
+     * <p>
+     * 需要先将文件私钥加密,再根据加密后的数据生成签名(BASE64),适用于小文件
+     * </p>
+     *
+     * @param filePath 源文件
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    public static String signFileToBase64WithEncrypt(String filePath, String keyStorePath, String alias, String password)
+            throws Exception {
+        byte[] encryptedData = encryptFileByPrivateKey(filePath, keyStorePath, alias, password);
+        return signToBase64(encryptedData, keyStorePath, alias, password);
+    }
+
+    /**
+     * <p>
+     * 生成文件签名
+     * </p>
+     * <p>
+     * 注意:<br>
+     * 方法中使用了FileChannel,其巨大Bug就是不会释放文件句柄,导致签名的文件无法操作(移动或删除等)<br>
+     * 该方法已被generateFileSign取代
+     * </p>
+     *
+     * @param filePath 文件路径
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     * @throws Exception
+     */
+    @Deprecated
+    public static byte[] signFile(String filePath, String keyStorePath, String alias, String password)
+            throws Exception {
+        byte[] sign = new byte[0];
+        // 获得证书
+        X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath, alias, password);
+        // 获取私钥
+        KeyStore keyStore = getKeyStore(keyStorePath, password);
+        // 取得私钥
+        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
+        // 构建签名
+        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
+        signature.initSign(privateKey);
+        File file = new File(filePath);
+        if (file.exists()) {
+            FileInputStream in = new FileInputStream(file);
+            FileChannel fileChannel = in.getChannel();
+            MappedByteBuffer byteBuffer = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0, file.length());
+            signature.update(byteBuffer);
+            fileChannel.close();
+            in.close();
+            sign = signature.sign();
+         }
+        return sign;
+    }
+
+    /**
+     * <p>
+     * 生成文件数字签名
+     * </p>
+     *
+     * @param filePath
+     * @param keyStorePath
+     * @param alias
+     * @param password
+     * @return
+     * @throws Exception
+     */
+    public static byte[] generateFileSign(String filePath, String keyStorePath, String alias, String password)
+            throws Exception {
+        byte[] sign = new byte[0];
+        // 获得证书
+        X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath, alias, password);
+        // 获取私钥
+        KeyStore keyStore = getKeyStore(keyStorePath, password);
+        // 取得私钥
+        PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, password.toCharArray());
+        // 构建签名
+        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
+        signature.initSign(privateKey);
+        File file = new File(filePath);
+        if (file.exists()) {
+            FileInputStream in = new FileInputStream(file);
+            byte[] cache = new byte[CACHE_SIZE];
+            int nRead = 0;
+            while ((nRead = in.read(cache)) != -1) {
+                signature.update(cache, 0, nRead);
+            }
+            in.close();
+            sign = signature.sign();
+         }
+        return sign;
+
+    }
+
+    /**
+     * <p>
+     * 文件签名成BASE64编码字符串
+     * </p>
+     *
+     * @param filePath
+     * @param keyStorePath
+     * @param alias
+     * @param password
+     * @return
+     * @throws Exception
+     */
+    public static String signFileToBase64(String filePath, String keyStorePath, String alias, String password)
+            throws Exception {
+        return Base64.getEncoder().encodeToString(generateFileSign(filePath, keyStorePath, alias, password));
+    }
+
+    /**
+     * <p>
+     * 验证签名
+     * </p>
+     *
+     * @param data 已加密数据
+     * @param sign 数据签名[BASE64]
+     * @param certificatePath 证书存储路径
+     * @return
+     * @throws Exception
+     */
+    public static boolean verifySign(byte[] data, String sign, String certificatePath)
+            throws Exception {
+        // 获得证书
+        X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
+        // 获得公钥
+        PublicKey publicKey = x509Certificate.getPublicKey();
+        // 构建签名
+        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
+        signature.initVerify(publicKey);
+        signature.update(data);
+        return signature.verify(Base64.getDecoder().decode(sign));
+    }
+
+    /**
+     * <p>
+     * 验证签名
+     * </p>
+     *
+     * @param data 已加密数据
+     * @param sign 数据签名[BASE64]
+     * @param certificate 证书
+     * @return
+     * @throws Exception
+     */
+    public static boolean verifySign(byte[] data, String sign, byte[] certificate)
+            throws Exception {
+        // 获得证书
+        X509Certificate x509Certificate = (X509Certificate) getCertificate(new ByteArrayInputStream(certificate));
+        // 获得公钥
+        PublicKey publicKey = x509Certificate.getPublicKey();
+        // 构建签名
+        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
+        signature.initVerify(publicKey);
+        signature.update(data);
+        return signature.verify(Base64.getDecoder().decode(sign));
+    }
+
+    /**
+     * <p>
+     * 校验文件签名
+     * </p>
+     *
+     * @param filePath
+     * @param sign
+     * @param certificatePath
+     * @return
+     * @throws Exception
+     */
+//    public static boolean validateFileSign(String filePath, String sign, String certificatePath)
+//            throws Exception {
+//        boolean result = false;
+//        // 获得证书
+//        X509Certificate x509Certificate = (X509Certificate) getCertificate(certificatePath);
+//        // 获得公钥
+//        PublicKey publicKey = x509Certificate.getPublicKey();
+////        System.out.print("测试私钥");
+////        System.out.print(publicKey);
+////        System.out.print("测试私钥");
+////        System.out.print("\n");
+//
+//        // 构建签名
+//        Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
+//        signature.initVerify(publicKey);
+//        File file = new File(filePath);
+//        if (file.exists()) {
+//            byte[] decodedSign = Base64Utils.decode(sign);
+//            FileInputStream in = new FileInputStream(file);
+//            byte[] cache = new byte[CACHE_SIZE];
+//            int nRead = 0;
+//            while ((nRead = in.read(cache)) != -1) {
+//                signature.update(cache, 0, nRead);
+//            }
+//            in.close();
+//            result = signature.verify(decodedSign);
+//         }
+//        return result;
+//    }
+
+    /**
+     * <p>
+     * BASE64解码->签名校验
+     * </p>
+     *
+     * @param base64String BASE64编码字符串
+     * @param sign 数据签名[BASE64]
+     * @param certificatePath 证书存储路径
+     * @return
+     * @throws Exception
+     */
+//    public static boolean verifyBase64Sign(String base64String, String sign, String certificatePath)
+//            throws Exception {
+//        byte[] data = Base64Utils.decode(base64String);
+//        return verifySign(data, sign, certificatePath);
+//    }
+
+    /**
+     * <p>
+     * BASE64解码->公钥解密-签名校验
+     * </p>
+     *
+     *
+     * @param base64String BASE64编码字符串
+     * @param sign 数据签名[BASE64]
+     * @param certificatePath 证书存储路径
+     * @return
+     * @throws Exception
+     */
+//    public static boolean verifyBase64SignWithDecrypt(String base64String, String sign, String certificatePath)
+//            throws Exception {
+//        byte[] encryptedData = Base64Utils.decode(base64String);
+//        byte[] data = decryptByPublicKey(encryptedData, certificatePath);
+//        return verifySign(data, sign, certificatePath);
+//    }
+
+    /**
+     * <p>
+     * 文件公钥解密->签名校验
+     * </p>
+     *
+     * @param encryptedFilePath 加密文件路径
+     * @param sign 数字证书[BASE64]
+     * @param certificatePath
+     * @return
+     * @throws Exception
+     */
+//    public static boolean verifyFileSignWithDecrypt(String encryptedFilePath, String sign, String certificatePath)
+//            throws Exception {
+//        byte[] encryptedData = fileToByte(encryptedFilePath);
+//        byte[] data =  decryptByPublicKey(encryptedData, certificatePath);
+//        return verifySign(data, sign, certificatePath);
+//    }
+
+    /**
+     * <p>
+     * 校验证书当前是否有效
+     * </p>
+     *
+     * @param certificate 证书
+     * @return
+     */
+    public static boolean verifyCertificate(Certificate certificate) {
+        return verifyCertificate(new Date(), certificate);
+    }
+
+    /**
+     * <p>
+     * 验证证书是否过期或无效
+     * </p>
+     *
+     * @param date 日期
+     * @param certificate 证书
+     * @return
+     */
+    public static boolean verifyCertificate(Date date, Certificate certificate) {
+        boolean isValid = true;
+        try {
+            X509Certificate x509Certificate = (X509Certificate) certificate;
+            x509Certificate.checkValidity(date);
+        } catch (Exception e) {
+            isValid = false;
+        }
+        return isValid;
+    }
+
+    /**
+     * <p>
+     * 验证数字证书是在给定的日期是否有效
+     * </p>
+     *
+     * @param date 日期
+     * @param certificatePath 证书存储路径
+     * @return
+     */
+    public static boolean verifyCertificate(Date date, String certificatePath) {
+        Certificate certificate;
+        try {
+            certificate = getCertificate(certificatePath);
+            return verifyCertificate(certificate);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * <p>
+     * 验证数字证书是在给定的日期是否有效
+     * </p>
+     *
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     */
+    public static boolean verifyCertificate(Date date, String keyStorePath, String alias, String password) {
+        Certificate certificate;
+        try {
+            certificate = getCertificate(keyStorePath, alias, password);
+            return verifyCertificate(certificate);
+        } catch (Exception e) {
+            e.printStackTrace();
+            return false;
+        }
+    }
+
+    /**
+     * <p>
+     * 验证数字证书当前是否有效
+     * </p>
+     *
+     * @param keyStorePath 密钥库存储路径
+     * @param alias 密钥库别名
+     * @param password 密钥库密码
+     * @return
+     */
+    public static boolean verifyCertificate(String keyStorePath, String alias, String password) {
+        return verifyCertificate(new Date(), keyStorePath, alias, password);
+    }
+
+    /**
+     * <p>
+     * 验证数字证书当前是否有效
+     * </p>
+     *
+     * @param certificatePath 证书存储路径
+     * @return
+     */
+    public static boolean verifyCertificate(String certificatePath) {
+        return verifyCertificate(new Date(), certificatePath);
+    }
+
+    /**
+     * <p>
+     * 文件转换为byte数组
+     * </p>
+     *
+     * @param filePath 文件路径
+     * @return
+     * @throws Exception
+     */
+    public static byte[] fileToByte(String filePath) throws Exception {
+        byte[] data = new byte[0];
+        File file = new File(filePath);
+        if (file.exists()) {
+            FileInputStream in = new FileInputStream(file);
+            ByteArrayOutputStream out = new ByteArrayOutputStream(2048);
+            byte[] cache = new byte[CACHE_SIZE];
+            int nRead = 0;
+            while ((nRead = in.read(cache)) != -1) {
+                out.write(cache, 0, nRead);
+                out.flush();
+            }
+            out.close();
+            in.close();
+            data = out.toByteArray();
+         }
+        return data;
+    }
+
+    /**
+     * <p>
+     * 二进制数据写文件
+     * </p>
+     *
+     * @param bytes 二进制数据
+     * @param filePath 文件生成目录
+     */
+    public static void byteArrayToFile(byte[] bytes, String filePath) throws Exception {
+        InputStream in = new ByteArrayInputStream(bytes);
+        File destFile = new File(filePath);
+        if (!destFile.getParentFile().exists()) {
+            destFile.getParentFile().mkdirs();
+        }
+        destFile.createNewFile();
+        OutputStream out = new FileOutputStream(destFile);
+        byte[] cache = new byte[CACHE_SIZE];
+        int nRead = 0;
+        while ((nRead = in.read(cache)) != -1) {
+            out.write(cache, 0, nRead);
+            out.flush();
+        }
+        out.close();
+        in.close();
+    }
+
+}

+ 223 - 0
blade-service/trade-finance/src/main/java/org/springblade/finance/tool/HttpUtil.java

@@ -0,0 +1,223 @@
+package org.springblade.finance.tool;
+
+import javax.net.ssl.*;
+import java.io.*;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.Map;
+import java.util.Map.Entry;
+
+/**
+ * 进行http访问的基本类
+ */
+public class HttpUtil {
+
+    private static final String DEFAULT_CHARSET = "UTF-8";
+
+    private static final String METHOD_POST = "POST";
+
+    private static final String METHOD_GET = "GET";
+
+    private static final int CONNECTTIMEOUT = 5000;
+
+    private static final int READTIMEOUT = 5000;
+
+    private static class DefaultTrustManager implements X509TrustManager {
+
+        public X509Certificate[] getAcceptedIssuers() {
+            return null;
+        }
+
+        public void checkClientTrusted(X509Certificate[] cert, String oauthType)
+                throws java.security.cert.CertificateException {
+        }
+
+        public void checkServerTrusted(X509Certificate[] cert, String oauthType)
+                throws java.security.cert.CertificateException {
+        }
+    }
+
+    private static HttpURLConnection getConnection(URL url, String method)
+            throws IOException {
+
+        HttpURLConnection conn;
+        if ("https".equals(url.getProtocol())) {
+            SSLContext ctx;
+            try {
+                ctx = SSLContext.getInstance("TLS");
+                ctx.init(new KeyManager[0], new TrustManager[] { new DefaultTrustManager() },
+                        new SecureRandom());
+            } catch (Exception e) {
+                throw new IOException(e);
+            }
+            HttpsURLConnection connHttps = (HttpsURLConnection) url.openConnection();
+            connHttps.setSSLSocketFactory(ctx.getSocketFactory());
+            connHttps.setHostnameVerifier(new HostnameVerifier() {
+
+                public boolean verify(String hostname, SSLSession session) {
+                    return true;// 默认都认证通过
+                }
+            });
+            conn = connHttps;
+        } else {
+            conn = (HttpURLConnection) url.openConnection();
+        }
+        conn.setRequestMethod(method);
+        conn.setDoInput(true);
+        conn.setDoOutput(true);
+        conn.setRequestProperty("Content-Type", "application/json;charset=UTF-8");
+        conn.setRequestProperty("Connection", "Keep-Alive");
+        return conn;
+
+    }
+
+    /**
+     * 通过get方法访问
+     *
+     * @param url 访问的url地址
+     * @param urlParams 请求需要的参数
+     * @return 返回请求响应的数据
+     * @throws IOException
+     */
+    public static String doGet(String url, Map<String, String> urlParams)
+            throws IOException {
+        if (isEmpty(url)) {
+            throw new IllegalArgumentException("The parameter 'url' can not be null or blank.");
+        }
+        url += buildQuery(urlParams, DEFAULT_CHARSET);
+        HttpURLConnection conn = getConnection(new URL(url), METHOD_GET);
+        String s = getResponseAsString(conn);
+        return s;
+    }
+
+    /**
+     *
+     * @param url api请求的权路径url地址
+     * @param urlParams 请求的参数
+     * @param requestJson 请求报文
+     * @return 请求响应
+     * @throws IOException
+     */
+    public static String doPost(String url, Map<String, String> urlParams, String requestJson) throws IOException {
+        return doPost(url, urlParams, requestJson, CONNECTTIMEOUT, READTIMEOUT);
+    }
+
+    /**
+     *
+     * 通过post方法请求数据
+     *
+     * @param url 请求的url地址
+     * @param urlParams 请求的参数
+     * @param requestJson 请求报文
+     * @param connectTimeOut 请求连接过期时间
+     * @param readTimeOut 请求读取过期时间
+     * @return 请求响应
+     * @throws IOException
+     */
+    public static String doPost(String url, Map<String, String> urlParams, String requestJson,
+            int connectTimeOut, int readTimeOut) throws IOException {
+        if (isEmpty(url)) {
+            throw new IllegalArgumentException("The parameter 'url' can not be null or blank.");
+        }
+        url += buildQuery(urlParams, DEFAULT_CHARSET);
+        HttpURLConnection conn = getConnection(new URL(url), METHOD_POST);
+        conn.setConnectTimeout(connectTimeOut);
+        conn.setReadTimeout(readTimeOut);
+        conn.getOutputStream().write(requestJson.getBytes(DEFAULT_CHARSET));
+        String s = getResponseAsString(conn);
+        return s;
+    }
+
+    /**
+     *
+     * @param params 请求参数
+     * @return 构建query
+     */
+    public static String buildQuery(Map<String, String> params, String charset) throws UnsupportedEncodingException {
+        if (params == null || params.isEmpty()) {
+            return "";
+        }
+        StringBuilder sb = new StringBuilder();
+        boolean first = true;
+        for (Entry<String, String> entry : params.entrySet()) {
+            if (first) {
+                sb.append("?");
+                first = false;
+            } else {
+                sb.append("&");
+            }
+            String key = entry.getKey();
+            String value = entry.getValue();
+            if (areNotEmpty(key, value)) {
+                sb.append(key).append("=").append(URLEncoder.encode(value, charset));
+            }
+        }
+        return sb.toString();
+
+    }
+
+    private static String getResponseAsString(HttpURLConnection conn) throws IOException {
+        InputStream es = conn.getErrorStream();
+        if (es == null) {
+            return getStreamAsString(conn.getInputStream(), DEFAULT_CHARSET);
+        } else {
+            String msg = getStreamAsString(es, DEFAULT_CHARSET);
+            if (isEmpty(msg)) {
+                throw new IOException(conn.getResponseCode() + " : " + conn.getResponseMessage());
+            } else {
+                throw new IOException(msg);
+            }
+        }
+
+    }
+
+    private static String getStreamAsString(InputStream input, String charset) throws IOException {
+        StringBuilder sb = new StringBuilder();
+        BufferedReader bf = null;
+        try {
+            bf = new BufferedReader(new InputStreamReader(input, charset));
+            String str;
+            while ((str = bf.readLine()) != null) {
+                sb.append(str);
+            }
+            return sb.toString();
+        } finally {
+            if (bf != null) {
+                bf.close();
+            }
+        }
+
+    }
+
+    /**
+     * 判断字符串为空
+     *
+     * @param str 字符串信息
+     * @return true or false
+     */
+    private static boolean isEmpty(String str) {
+        return str == null || str.trim().length() == 0;
+    }
+
+    /**
+     * 判断字符数组,不为空
+     *
+     * @param values 字符数组
+     * @return true or false
+     */
+    public static boolean areNotEmpty(String... values) {
+        if (values == null || values.length == 0) {
+            return false;
+        }
+
+        for (String value : values) {
+            if (isEmpty(value)) {
+                return false;
+            }
+        }
+        return true;
+    }
+}