import Ignore_ReadUTF8File as ReadUTF8File import com.dySweetFishPlugin.tool.crypto.encoder.BASE64Decoder import com.sweetfish.convert.json.JsonConvert import com.sweetfish.service.RetResult import com.yinjie.heating.common.api.BusinessExecutor import com.yinjie.heating.common.datas.ERPModule import com.yinjie.heating.common.entity.base.ProcessMapItem import com.yinjie.heating.common.entity.callthird.DownloadBillResponse import com.yinjie.heating.common.entity.heating.HeatingApp import com.yinjie.heating.common.tool.PaySignatureUtil import org.apache.commons.lang3.StringUtils import org.apache.logging.log4j.LogManager import org.apache.logging.log4j.Logger import org.rex.RMap import javax.annotation.Resource import javax.crypto.Cipher import javax.crypto.KeyGenerator import javax.crypto.SecretKey import javax.crypto.spec.IvParameterSpec import java.nio.file.Files import java.nio.file.Path import java.nio.file.Paths import java.security.KeyFactory import java.security.PublicKey import java.security.SecureRandom import java.security.spec.X509EncodedKeySpec import java.time.LocalDateTime class BE_Call_DownloadBillFile implements BusinessExecutor { private final Logger logger = LogManager.getLogger(this.getClass().getSimpleName()) @Resource private JsonConvert jsonConvert @Resource(name = "property.downloadBillRoot") private String downloadBillRoot @Override String scriptName() { return "外部热力服务商调用-下载对账单,需加密" } @Override ERPModule module() { return ERPModule.CALL_THIRD } private static byte[] encryptFile(SecretKey aesKey, byte[] fileData) throws Exception { // 生成随机的16字节初始化向量 (IV) byte[] iv = new byte[16]; new SecureRandom().nextBytes(iv); IvParameterSpec ivSpec = new IvParameterSpec(iv); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, aesKey, ivSpec); // 将IV和加密后的数据一起返回,IV不需要保密,但需要用于解密 byte[] encryptedData = cipher.doFinal(fileData); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); outputStream.write(iv); outputStream.write(encryptedData); return outputStream.toByteArray(); } private static byte[] encryptAESKey(String publicKeyStr, SecretKey aesKey) throws Exception { byte[] keyBytes = (new BASE64Decoder()).decodeBuffer(publicKeyStr); X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); PublicKey publicKey = keyFactory.generatePublic(keySpec); Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); return cipher.doFinal(aesKey.getEncoded()); } RetResult execute(ProcessMapItem source) { long currentTime = LocalDateTime.now().toDate().time RMap params = source.itemData String dataSourceId = source.dataSourceId long supplierCode = source.supplierCode String payDate = params.getString("payDate") HeatingApp app = params.get("app") as HeatingApp params.remove("app")//避免影响下面验签 //接口均返回正确,错误放在result里 if (app == null) { logger.error("下载对账单传入app为空") return RetResult. successT().result(new DownloadBillResponse.Builder() .respCode("DEF0010") .respMsg("用户不存在") .timeStamp((new Date()).time as String) .build()) } if (StringUtils.isBlank(payDate)) { logger.error("下载对账单传入参数不正确") return RetResult. successT().result(new DownloadBillResponse.Builder() .respCode("DEF0006") .respMsg("系统错误") .timeStamp((new Date()).time as String) .build()) } //签名 String sign = params.getString("sign") if (PaySignatureUtil.verifySign(sign, "RSA_1_256", params, app.supplyPublicKey, "")) { logger.info("下载对账单验签成功") //查找对应日期的文件夹是否存在 Path dirPath = Paths.get(downloadBillRoot + File.separator + payDate) if (Files.exists(dirPath) && (Files.isDirectory(dirPath))) { Path filePath = Paths.get(downloadBillRoot + File.separator + payDate + File.separator + "GD_" + payDate + "_" + app.upperChannelAppId + ".txt") if (Files.exists(filePath)) { //读取文件内容并加密 KeyGenerator keyGenerator = KeyGenerator.getInstance("AES") keyGenerator.init(128) // 使用128位密钥长度 SecretKey aesKey = keyGenerator.generateKey() String fileStr = ReadUTF8File.execute(filePath, false, logger) byte[] fileData = fileStr.getBytes("UTF-8") byte[] encryptedFileData = encryptFile(aesKey, fileData) //加密的文件 byte[] encryptedAESKey = encryptAESKey(app.supplyPublicKey, aesKey) //加密的密钥 return RetResult. successT().result(new DownloadBillResponse.Builder() .respCode("00000") .respMsg("success") .appId(app.appId) .fileKey(encryptedAESKey) .fileContent(encryptedFileData) .timeStamp((new Date()).time as String) .build()) } else { logger.error("找不到对账单" + filePath.toString()) return RetResult. successT().result(new DownloadBillResponse.Builder() .respCode("DEF0020") .respMsg("该日期账单文件暂未生成") .timeStamp((new Date()).time as String) .build()) } } else { logger.error("找不到对账单日期" + payDate + "的目录") return RetResult. successT().result(new DownloadBillResponse.Builder() .respCode("DEF0020") .respMsg("该日期账单文件暂未生成") .timeStamp((new Date()).time as String) .build()) } } else { logger.error("下载对账单验签失败") return RetResult. successT().result(new DownloadBillResponse.Builder() .respCode("DEF0030") .respMsg("验签失败") .timeStamp((new Date()).time as String) .build()) } } }