From 8eb9cf3ce6499a5486a38e3dfe7bb8b0a4b66955 Mon Sep 17 00:00:00 2001 From: Jack <46790855@qq.com> Date: Thu, 15 May 2025 15:53:29 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8B=89=E5=8D=A1=E6=8B=89=20=E5=85=A5?= =?UTF-8?q?=E7=BD=91=E7=94=B5=E5=AD=90=E5=90=88=E5=90=8C=E7=94=B3=E8=AF=B7?= =?UTF-8?q?=20=E7=9B=B8=E5=85=B3=E4=B8=9A=E5=8A=A1=E9=80=BB=E8=BE=91?= =?UTF-8?q?=EF=BC=8C=E4=BF=AE=E6=94=B9=E5=8A=A0=E5=AF=86=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/modules/lakala/LklLedgerEc.java | 1 + .../suisung/mall/common/utils/JiebaUtils.java | 3 + .../suisung/mall/common/utils/RSAUtil.java | 159 +++++++++++++++ .../suisung/mall/pay/utils/LakalaUtil.java | 14 +- .../impl/EsignContractServiceImpl.java | 11 +- .../controller/mobile/LakalaController.java | 6 + .../controller/mobile/LklTkController.java | 3 +- .../service/impl/LakalaApiServiceImpl.java | 76 ++++++- .../impl/LklLedgerReceiverServiceImpl.java | 5 + .../lakala/service/impl/LklTkServiceImpl.java | 117 +---------- .../mall/shop/lakala/utils/LakalaUtil.java | 188 ++++++++++++++++-- .../src/main/resources/bootstrap-dev.yml | 2 +- .../src/main/resources/bootstrap-local.yml | 4 +- .../src/main/resources/bootstrap-prod.yml | 2 +- .../src/main/resources/bootstrap-test.yml | 2 +- .../src/main/resources/bootstrap-uat.yml | 2 +- 16 files changed, 439 insertions(+), 156 deletions(-) create mode 100644 mall-common/src/main/java/com/suisung/mall/common/utils/RSAUtil.java diff --git a/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklLedgerEc.java b/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklLedgerEc.java index 6347f1f4..3aa80583 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklLedgerEc.java +++ b/mall-common/src/main/java/com/suisung/mall/common/modules/lakala/LklLedgerEc.java @@ -41,6 +41,7 @@ public class LklLedgerEc implements Serializable { private String ec_status; private Long ec_apply_id; private String result_url; + private String notify_url; private Integer status; private Date created_at; private Date updated_at; diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/JiebaUtils.java b/mall-common/src/main/java/com/suisung/mall/common/utils/JiebaUtils.java index 531a3ad5..6308bca5 100644 --- a/mall-common/src/main/java/com/suisung/mall/common/utils/JiebaUtils.java +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/JiebaUtils.java @@ -14,6 +14,9 @@ import org.springframework.stereotype.Component; import java.util.List; import java.util.stream.Collectors; +/** + * 结巴分词工具类 + */ @Component public class JiebaUtils { diff --git a/mall-common/src/main/java/com/suisung/mall/common/utils/RSAUtil.java b/mall-common/src/main/java/com/suisung/mall/common/utils/RSAUtil.java new file mode 100644 index 00000000..ff063c95 --- /dev/null +++ b/mall-common/src/main/java/com/suisung/mall/common/utils/RSAUtil.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2025. Lorem ipsum dolor sit amet, consectetur adipiscing elit. + * Morbi non lorem porttitor neque feugiat blandit. Ut vitae ipsum eget quam lacinia accumsan. + * Etiam sed turpis ac ipsum condimentum fringilla. Maecenas magna. + * Proin dapibus sapien vel ante. Aliquam erat volutpat. Pellentesque sagittis ligula eget metus. + * Vestibulum commodo. Ut rhoncus gravida arcu. + */ + +package com.suisung.mall.common.utils; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; +import java.util.Base64; + +public class RSAUtil { + + private static final Logger logger = LoggerFactory.getLogger(RSAUtil.class); + + /** + * 使用私钥对数据进行 SHA256withRSA 签名 + * + * @param data 待签名的数据 + * @param privateKey 私钥(Base64编码) + * @return 签名结果(Base64编码) + */ + public static String signSHA256withRSA(String data, String privateKey) { + try { + // 解码私钥 + byte[] keyBytes = Base64.getDecoder().decode(privateKey); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + + // 生成私钥对象 + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PrivateKey priKey = keyFactory.generatePrivate(keySpec); + + // 初始化签名 + Signature signature = Signature.getInstance("SHA256withRSA"); + signature.initSign(priKey); + signature.update(data.getBytes(StandardCharsets.UTF_8)); + + // 生成签名并编码为Base64 + byte[] signBytes = signature.sign(); + return Base64.getEncoder().encodeToString(signBytes); + } catch (NoSuchAlgorithmException e) { + logger.error("不支持的加密算法: {}", e.getMessage(), e); + } catch (InvalidKeySpecException e) { + logger.error("私钥格式错误: {}", e.getMessage(), e); + } catch (InvalidKeyException e) { + logger.error("无效的私钥: {}", e.getMessage(), e); + } catch (SignatureException e) { + logger.error("签名处理异常: {}", e.getMessage(), e); + } catch (Exception e) { + logger.error("签名过程发生未知异常: {}", e.getMessage(), e); + } + return null; + } + + /** + * 使用公钥验证 SHA256withRSA 签名 + * + * @param data 原始数据 + * @param sign 签名结果(Base64编码) + * @param publicKey 公钥(Base64编码) + * @return 验证结果 + */ + public static boolean verifySHA256withRSA(String data, String sign, String publicKey) { + try { + // 解码公钥 + byte[] keyBytes = Base64.getDecoder().decode(publicKey); + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + + // 生成公钥对象 + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + PublicKey pubKey = keyFactory.generatePublic(keySpec); + + // 初始化签名验证 + Signature signature = Signature.getInstance("SHA256withRSA"); + signature.initVerify(pubKey); + signature.update(data.getBytes(StandardCharsets.UTF_8)); + + // 验证签名 + byte[] signBytes = Base64.getDecoder().decode(sign); + return signature.verify(signBytes); + } catch (NoSuchAlgorithmException e) { + logger.error("不支持的加密算法: {}", e.getMessage(), e); + } catch (InvalidKeySpecException e) { + logger.error("公钥格式错误: {}", e.getMessage(), e); + } catch (InvalidKeyException e) { + logger.error("无效的公钥: {}", e.getMessage(), e); + } catch (SignatureException e) { + logger.error("签名验证异常: {}", e.getMessage(), e); + } catch (Exception e) { + logger.error("验证过程发生未知异常: {}", e.getMessage(), e); + } + return false; + } + + /** + * 生成 RSA 密钥对 + * + * @param keySize 密钥长度,推荐 2048 + * @return 密钥对 + */ + public static KeyPair generateKeyPair(int keySize) { + KeyPairGenerator keyPairGen = null; + try { + keyPairGen = KeyPairGenerator.getInstance("RSA"); + } catch (NoSuchAlgorithmException e) { + throw new RuntimeException(e); + } + keyPairGen.initialize(keySize); + return keyPairGen.generateKeyPair(); + } + + /** + * 获取公钥的 Base64 编码字符串 + */ + public static String getPublicKeyString(KeyPair keyPair) { + PublicKey publicKey = keyPair.getPublic(); + return Base64.getEncoder().encodeToString(publicKey.getEncoded()); + } + + /** + * 获取私钥的 Base64 编码字符串 + */ + public static String getPrivateKeyString(KeyPair keyPair) { + PrivateKey privateKey = keyPair.getPrivate(); + return Base64.getEncoder().encodeToString(privateKey.getEncoded()); + } + + // 示例用法 + public static void main(String[] args) { + try { + // 生成密钥对 + KeyPair keyPair = generateKeyPair(2048); + String publicKey = getPublicKeyString(keyPair); + String privateKey = getPrivateKeyString(keyPair); + + // 待签名数据 + String data = "Hello, RSA Signature!"; + + // 签名 + String signature = signSHA256withRSA(data, privateKey); + System.out.println("签名结果: " + signature); + + // 验证 + boolean isValid = verifySHA256withRSA(data, signature, publicKey); + System.out.println("验证结果: " + isValid); + } catch (Exception e) { + e.printStackTrace(); + } + } +} \ No newline at end of file diff --git a/mall-pay/src/main/java/com/suisung/mall/pay/utils/LakalaUtil.java b/mall-pay/src/main/java/com/suisung/mall/pay/utils/LakalaUtil.java index 0347ebb3..00ffa9d7 100644 --- a/mall-pay/src/main/java/com/suisung/mall/pay/utils/LakalaUtil.java +++ b/mall-pay/src/main/java/com/suisung/mall/pay/utils/LakalaUtil.java @@ -11,7 +11,6 @@ package com.suisung.mall.pay.utils; import cn.hutool.core.util.StrUtil; import com.lkl.laop.sdk.Config2; import com.lkl.laop.sdk.LKLSDK; -import com.lkl.laop.sdk.auth.PrivateKeySigner; import com.suisung.mall.common.exception.ApiException; import com.suisung.mall.common.utils.I18nUtil; import lombok.extern.slf4j.Slf4j; @@ -76,6 +75,7 @@ public class LakalaUtil { } } + /** * 获取 body 请求数据 * @@ -130,7 +130,6 @@ public class LakalaUtil { } } - /** * 签名验证 * @@ -155,9 +154,9 @@ public class LakalaUtil { } } - /** * 签名校验 + * * @param authorization * @param reqBody * @param lklNotifyCerPath @@ -176,11 +175,9 @@ public class LakalaUtil { return false; } - StringBuilder preSignData = new StringBuilder(); - preSignData.append(timestamp).append("\n") - .append(nonceStr).append("\n") - .append(reqBody).append("\n"); - String preSignDataStr = preSignData.toString(); + String preSignDataStr = timestamp + "\n" + + nonceStr + "\n" + + reqBody + "\n"; log.debug("拉卡拉签名明文内容:{}", preSignDataStr); if (verify(lklNotifyCer, preSignDataStr.getBytes(StandardCharsets.UTF_8), signature)) { log.debug("验签成功"); @@ -237,4 +234,5 @@ public class LakalaUtil { return map; } + } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java index d3abac9a..03c51055 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/esign/service/impl/EsignContractServiceImpl.java @@ -211,9 +211,14 @@ public class EsignContractServiceImpl extends BaseServiceImpl response = RestTemplateHttpUtil.sendPostBodyBackEntity(reqUrl, header, reqBody, JSONObject.class); + if (ObjectUtil.isEmpty(response) || response.getStatusCode() != HttpStatus.OK) { + return Pair.of(false, "商家入网申请电子合同:请求失败"); + } + + JSONObject respBody = response.getBody(); + if (ObjectUtil.isNotEmpty(respBody) && !lklSuccessCode.equals(respBody.getStr("code"))) { + String errMsg = StrUtil.isBlank(respBody.getStr("msg")) ? "返回状态有误" : respBody.getStr("msg"); + return Pair.of(false, "商家入网申请电子合同失败:" + errMsg); + } + + JSONObject respData = respBody.getJSONObject("resp_data"); + if (respBody.getJSONObject("resp_data") == null) { + return Pair.of(false, "商家入网申请电子合同失败:返回数据有误"); + } + + // 商家入网申请电子合同处理数据 + // 先写入本地数据库表中 + LklLedgerEc record = new LklLedgerEc(); + record.setMch_id(shopMchEntry.getId()); + record.setMch_mobile(shopMchEntry.getLogin_mobile()); + record.setReq_params(reqBody.toString()); + record.setNotify_url(retUrl); + record.setEc_apply_id(respData.getLong("ec_apply_id")); + record.setResult_url(respData.getStr("result_url")); + record.setResp_body(respBody.toString()); + Boolean success = lklLedgerEcService.saveOrUpdateByMchId(record); + if (!success) { + return Pair.of(false, "商家入网申请电子合同失败:本地数据保存失败"); + } + + + return Pair.of(true, "商家入网申请电子合同成功"); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerReceiverServiceImpl.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerReceiverServiceImpl.java index ab9d14c2..59720908 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerReceiverServiceImpl.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/service/impl/LklLedgerReceiverServiceImpl.java @@ -24,6 +24,7 @@ import com.suisung.mall.shop.lakala.mapper.LklLedgerReceiverMapper; import com.suisung.mall.shop.lakala.service.LakalaApiService; import com.suisung.mall.shop.lakala.service.LklLedgerMemberService; import com.suisung.mall.shop.lakala.service.LklLedgerReceiverService; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; @@ -31,6 +32,7 @@ import javax.annotation.Resource; import java.util.ArrayList; import java.util.List; +@Slf4j @Service public class LklLedgerReceiverServiceImpl extends BaseServiceImpl implements LklLedgerReceiverService { @@ -207,13 +209,16 @@ public class LklLedgerReceiverServiceImpl extends BaseServiceImpl 0; i++, offset = i * 128) { - if (length - offset > 128) { - cache = cipher.doFinal(dataBytes, offset, 128); - } else { - cache = cipher.doFinal(dataBytes, offset, length - offset); - } - out.write(cache, 0, cache.length); - } - - String decodedDataStr = out.toString("UTF-8"); - logger.debug("拉卡拉tk数据解密结果:{}", decodedDataStr); - - return decodedDataStr; - } catch (IllegalArgumentException e) { - logger.error("Base64解码失败: {}", e.getMessage(), e); - } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { - logger.error("RSA算法初始化失败: {}", e.getMessage(), e); - } catch (InvalidKeySpecException | InvalidKeyException e) { - logger.error("私钥格式或类型错误: {}", e.getMessage(), e); - } catch (BadPaddingException | IllegalBlockSizeException e) { - logger.error("解密数据块大小或填充错误: {}", e.getMessage(), e); - } catch (Exception e) { - logger.error("解密过程中出现未知异常: {}", e.getMessage(), e); - } finally { - closeQuietly(out); - } - - return null; - } protected String buildLklTkUrl(String urlPath) { return tkServerUrl + urlPath; @@ -610,8 +497,8 @@ public class LklTkServiceImpl { } // 公钥解密出来的数据 - String notifyPubKey = LakalaUtil.getResourceFileWithEndSeq(notifyPubKeyPath, false); - String data = decryptNotifyData(notifyPubKey, srcData); + String notifyPubKey = LakalaUtil.getResourceFile(notifyPubKeyPath, false, false); + String data = LakalaUtil.decryptNotifyData(notifyPubKey, srcData); if (StrUtil.isBlank(data)) { return new JSONObject().set("code", "500").set("message", "密文解密出错!"); } diff --git a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/utils/LakalaUtil.java b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/utils/LakalaUtil.java index d9cbb2a3..1f9e943d 100644 --- a/mall-shop/src/main/java/com/suisung/mall/shop/lakala/utils/LakalaUtil.java +++ b/mall-shop/src/main/java/com/suisung/mall/shop/lakala/utils/LakalaUtil.java @@ -13,23 +13,28 @@ import com.lkl.laop.sdk.Config2; import com.lkl.laop.sdk.LKLSDK; import com.suisung.mall.common.exception.ApiException; import com.suisung.mall.common.utils.I18nUtil; +import com.suisung.mall.common.utils.RSAUtil; +import com.suisung.mall.common.utils.StringUtils; import lombok.extern.slf4j.Slf4j; import org.apache.commons.codec.binary.Base64; import org.springframework.core.io.ClassPathResource; +import javax.crypto.BadPaddingException; +import javax.crypto.Cipher; +import javax.crypto.IllegalBlockSizeException; +import javax.crypto.NoSuchPaddingException; import javax.servlet.http.HttpServletRequest; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; +import java.io.*; import java.nio.charset.StandardCharsets; -import java.security.InvalidKeyException; -import java.security.NoSuchAlgorithmException; -import java.security.Signature; -import java.security.SignatureException; +import java.security.*; import java.security.cert.*; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.security.spec.X509EncodedKeySpec; import java.util.HashMap; import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; @Slf4j public class LakalaUtil { @@ -58,10 +63,17 @@ public class LakalaUtil { * @return */ public static String getResourceFile(String fileName) { - return getResourceFileWithEndSeq(fileName, true); + return getResourceFile(fileName, true, false); } - public static String getResourceFileWithEndSeq(String fileName, boolean keepLineBreaks) { + /** + * 获取配置文件内容 + * + * @param fileName recource 文件夹下的路径,如:palyKey/wx/lakala_public_key.cer + * @param keepLineBreaks 保留换行符 + * @return + */ + public static String getResourceFile(String fileName, boolean keepLineBreaks, boolean stripPemHeaders) { StringBuilder stringBuilder = new StringBuilder(); try (InputStream inputStream = new ClassPathResource(fileName).getInputStream(); InputStreamReader inputStreamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8); @@ -71,6 +83,9 @@ public class LakalaUtil { while ((line = bufferedReader.readLine()) != null) { stringBuilder.append(line).append(endSeq); } + if (stripPemHeaders) { + return stripPemHeaders(stringBuilder.toString()); + } return stringBuilder.toString(); } catch (IOException e) { // 记录异常信息 @@ -79,6 +94,76 @@ public class LakalaUtil { } } + /** + * 拉卡拉使用私钥加密数据 + */ + public static String encryptNotifyData(String priKey, String data) { + ByteArrayOutputStream out = null; + try { + log.debug("拉卡拉tk加密私钥:{}", priKey); + log.debug("拉卡拉tk待加密data数据:{}", data); + + // 解码私钥 + byte[] keyBytes = java.util.Base64.getDecoder().decode(priKey); + + // 生成私钥对象 + PrivateKey privateKey = KeyFactory.getInstance("RSA") + .generatePrivate(new PKCS8EncodedKeySpec(keyBytes)); + + // 初始化加密器 + Cipher cipher = Cipher.getInstance("RSA"); + cipher.init(Cipher.ENCRYPT_MODE, privateKey); + + // 分段加密 + byte[] dataBytes = data.getBytes(StandardCharsets.UTF_8); + out = new ByteArrayOutputStream(); + for (int offset = 0; offset < dataBytes.length; offset += 117) { + int blockSize = Math.min(117, dataBytes.length - offset); + byte[] encryptedBlock = cipher.doFinal(dataBytes, offset, blockSize); + out.write(encryptedBlock); + } + + // 编码为Base64字符串 + String encryptDataStr = java.util.Base64.getEncoder().encodeToString(out.toByteArray()); + log.debug("拉卡拉tk数据加密结果:{}", encryptDataStr); + return encryptDataStr; + } catch (Exception e) { + throw new RuntimeException("私钥加密失败", e); + } finally { + closeQuietly(out); + } + } + + /** + * 安全关闭流 + */ + private static void closeQuietly(ByteArrayOutputStream out) { + if (out != null) { + try { + out.close(); + } catch (Exception e) { + // 忽略异常 + } + } + } + + public static String stripPemHeaders(String key) { + if (key == null || key.isEmpty()) { + return key; + } + + // 定义正则表达式:匹配标签行、任意数量连字符和空白字符 + // 1. 包含BEGIN或END的标签行(无论连字符数量) + // 2. 单独的连字符(不在标签行中的) + // 3. 空白字符(空格、制表符、换行等) + Pattern pattern = Pattern.compile( + "-*BEGIN[^-]*-*|-*END[^-]*-*|-|\\s"); + + // 执行替换 + Matcher matcher = pattern.matcher(key); + return matcher.replaceAll(""); + } + /** * 获取 body 请求数据 * @@ -133,7 +218,6 @@ public class LakalaUtil { } } - /** * 签名验证 * @@ -158,7 +242,6 @@ public class LakalaUtil { } } - /** * 签名校验 * @@ -239,4 +322,85 @@ public class LakalaUtil { return map; } + + /** + * 拼接拉卡拉header中的Authorization字段 + * 参考文档:https://o.lakala.com/#/home/document/detail?id=33 + * + * @param privateKey + * @param appId + * @param serialNo + * @param reqBody + * @return + */ + public static String genAuthorization(String privateKey, String appId, String serialNo, String reqBody) { + if (StrUtil.isBlank(privateKey) || StrUtil.isBlank(appId) || StrUtil.isBlank(serialNo) || StrUtil.isBlank(reqBody)) { + log.error("生产拉卡拉签名时缺少参数"); + return ""; + } + + //待签字符串格式:${appid}\n+${serialNo}\n+${timeStamp}\n+${nonceStr}\n+${body}\n + String timestamp = String.valueOf(System.currentTimeMillis() / 1000); + String nonceStr = StringUtils.genRandomNumber(12); + String builder = appId + "\n" + + serialNo + "\n" + + timestamp + "\n" + + nonceStr + "\n" + + reqBody + "\n"; + + String signature = RSAUtil.signSHA256withRSA(builder, privateKey); + + return String.format("LKLAPI-SHA256withRSA appid=\"%s\",serial_no=\"%s\",timestamp=\"%s\",nonce_str=\"%s\",signature=\"%s\"", + appId, serialNo, timestamp, nonceStr, signature); + } + + /** + * 拉卡拉异步通知数据公钥解密 + * + * @param pubKey Base64公钥 + * @param data Base64数据 + * @return 解密字符串 + */ + public static String decryptNotifyData(String pubKey, String data) { + ByteArrayOutputStream out = null; + try { + log.debug("拉卡拉tk解密公钥:{}", pubKey); + log.debug("拉卡拉tk待解密data数据:{}", data); + java.util.Base64.Decoder decoder = java.util.Base64.getDecoder(); + byte[] keyBytes = decoder.decode(pubKey.getBytes(StandardCharsets.UTF_8)); + byte[] dataBytes = decoder.decode(data.getBytes(StandardCharsets.UTF_8)); + Cipher cipher = Cipher.getInstance("RSA"); + PublicKey publicKey = KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(keyBytes)); + cipher.init(Cipher.DECRYPT_MODE, publicKey); + out = new ByteArrayOutputStream(); + byte[] cache; + for (int i = 0, offset = 0, length = dataBytes.length; length - offset > 0; i++, offset = i * 128) { + if (length - offset > 128) { + cache = cipher.doFinal(dataBytes, offset, 128); + } else { + cache = cipher.doFinal(dataBytes, offset, length - offset); + } + out.write(cache, 0, cache.length); + } + + String decodedDataStr = out.toString("UTF-8"); + log.debug("拉卡拉tk数据解密结果:{}", decodedDataStr); + + return decodedDataStr; + } catch (IllegalArgumentException e) { + log.error("Base64解码失败: {}", e.getMessage(), e); + } catch (NoSuchAlgorithmException | NoSuchPaddingException e) { + log.error("RSA算法初始化失败: {}", e.getMessage(), e); + } catch (InvalidKeySpecException | InvalidKeyException e) { + log.error("私钥格式或类型错误: {}", e.getMessage(), e); + } catch (BadPaddingException | IllegalBlockSizeException e) { + log.error("解密数据块大小或填充错误: {}", e.getMessage(), e); + } catch (Exception e) { + log.error("解密过程中出现未知异常: {}", e.getMessage(), e); + } finally { + closeQuietly(out); + } + + return null; + } } diff --git a/mall-shop/src/main/resources/bootstrap-dev.yml b/mall-shop/src/main/resources/bootstrap-dev.yml index cb505b4e..becb451a 100644 --- a/mall-shop/src/main/resources/bootstrap-dev.yml +++ b/mall-shop/src/main/resources/bootstrap-dev.yml @@ -144,7 +144,7 @@ sf-express: #拉卡拉进件配置 lakala: #服务地址 - server_url: https://test.wsmsd.cn/sit + server_url: https://test.wsmsd.cn #应用Id app_id: OP00000003 #商户证书序列号 diff --git a/mall-shop/src/main/resources/bootstrap-local.yml b/mall-shop/src/main/resources/bootstrap-local.yml index 216eeb06..747e6224 100644 --- a/mall-shop/src/main/resources/bootstrap-local.yml +++ b/mall-shop/src/main/resources/bootstrap-local.yml @@ -144,7 +144,7 @@ sf-express: #拉卡拉进件配置 lakala: #服务地址 - server_url: https://test.wsmsd.cn/sit + server_url: https://test.wsmsd.cn #应用Id app_id: OP00000003 #商户证书序列号 @@ -164,7 +164,7 @@ lakala: # 拉卡拉拓客进件配置 tk: #服务地址 - server_url: https://test.wsmsd.cn + server_url: https://test.wsmsd.cn/sit client_id: lsycs client_secret: XPa1HB5d55Ig0qV8 user_no: 29153396 diff --git a/mall-shop/src/main/resources/bootstrap-prod.yml b/mall-shop/src/main/resources/bootstrap-prod.yml index a12f91c2..dec156a2 100644 --- a/mall-shop/src/main/resources/bootstrap-prod.yml +++ b/mall-shop/src/main/resources/bootstrap-prod.yml @@ -171,7 +171,7 @@ lakala: # #终端号码,M0780629(B2B收银台) M0780798(专业化扫码) # term_no: M0780798 #服务地址 - server_url: https://test.wsmsd.cn/sit + server_url: https://test.wsmsd.cn #应用Id app_id: OP00000003 #商户证书序列号 diff --git a/mall-shop/src/main/resources/bootstrap-test.yml b/mall-shop/src/main/resources/bootstrap-test.yml index 55d0859f..2a0b773d 100644 --- a/mall-shop/src/main/resources/bootstrap-test.yml +++ b/mall-shop/src/main/resources/bootstrap-test.yml @@ -148,7 +148,7 @@ sf-express: #拉卡拉进件配置 lakala: #服务地址 - server_url: https://test.wsmsd.cn/sit + server_url: https://test.wsmsd.cn #应用Id app_id: OP00000003 #商户证书序列号 diff --git a/mall-shop/src/main/resources/bootstrap-uat.yml b/mall-shop/src/main/resources/bootstrap-uat.yml index 55d0859f..2a0b773d 100644 --- a/mall-shop/src/main/resources/bootstrap-uat.yml +++ b/mall-shop/src/main/resources/bootstrap-uat.yml @@ -148,7 +148,7 @@ sf-express: #拉卡拉进件配置 lakala: #服务地址 - server_url: https://test.wsmsd.cn/sit + server_url: https://test.wsmsd.cn #应用Id app_id: OP00000003 #商户证书序列号