From 9f042b9dbd96c7a8aaf94a00aca8dd4aa777cf09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=8B=8F=E7=AB=B9=E7=BA=A2?= Date: Thu, 13 Nov 2025 18:44:19 +0800 Subject: [PATCH] =?UTF-8?q?feat:=E9=92=B1=E5=8C=85=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E5=AF=B9=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- coolstore-partner-common/pom.xml | 4 + .../com/cool/store/utils/KeyFormatUtil.java | 82 +++++ .../cool/store/utils/OpenSignatureUtil.java | 81 ----- .../com/cool/store/utils/RsaSignUtil.java | 309 ++++++++++++++++++ .../store/utils/VerifySignatureUtils.java | 104 ------ .../dto/wallet/AccountAuthenticationDTO.java | 15 + .../cool/store/dto/wallet/AccountInfoDTO.java | 64 ++++ .../cool/store/dto/wallet/AccountNoDTO.java | 15 + .../store/dto/wallet/AccountVerifyDTO.java | 17 + .../com/cool/store/dto/wallet/AddTagDTO.java | 17 + .../com/cool/store/dto/wallet/BankDTO.java | 25 ++ .../cool/store/dto/wallet/BankListDTO.java | 20 ++ .../store/dto/wallet/LargePaymentDTO.java | 53 +++ .../com/cool/store/dto/wallet/PaymentDTO.java | 74 +++++ .../store/dto/wallet/PaymentDetailDTO.java | 32 ++ .../store/dto/wallet/StoreAccountDTO.java | 19 ++ .../request/wallet/AccountAddTagRequest.java | 51 +++ .../request/wallet/AccountVerifyRequest.java | 17 + .../wallet/CreateStoreAndAccountRequest.java | 43 +++ .../request/wallet/CreateStoreRequest.java | 60 ++++ .../store/request/wallet/GetBankRequest.java | 21 ++ .../wallet/LargePaymentDetailRequest.java | 17 + .../request/wallet/LargePaymentRequest.java | 26 ++ .../request/wallet/OutStoreIdRequest.java | 15 + .../request/wallet/PaymentDetailRequest.java | 15 + .../wallet/UpdateStoreAccountRequest.java | 29 ++ .../request/wallet/WalletBasicPageInfo.java | 40 +++ .../cool/store/http/WalletHttpClientRest.java | 231 +++++++++++++ .../service/wallet/WalletApiService.java | 116 +++++++ .../controller/webb/PCTestController.java | 170 +++++++++- .../main/resources/application-ab.properties | 5 + .../resources/application-local.properties | 6 +- .../resources/application-test.properties | 5 + pom.xml | 5 + 34 files changed, 1606 insertions(+), 197 deletions(-) create mode 100644 coolstore-partner-common/src/main/java/com/cool/store/utils/KeyFormatUtil.java create mode 100644 coolstore-partner-common/src/main/java/com/cool/store/utils/RsaSignUtil.java delete mode 100644 coolstore-partner-common/src/main/java/com/cool/store/utils/VerifySignatureUtils.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountAuthenticationDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountInfoDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountNoDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountVerifyDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AddTagDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/BankDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/BankListDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/LargePaymentDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/PaymentDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/PaymentDetailDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/StoreAccountDTO.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/AccountAddTagRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/AccountVerifyRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/CreateStoreAndAccountRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/CreateStoreRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/GetBankRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/LargePaymentDetailRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/LargePaymentRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/OutStoreIdRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/PaymentDetailRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/UpdateStoreAccountRequest.java create mode 100644 coolstore-partner-model/src/main/java/com/cool/store/request/wallet/WalletBasicPageInfo.java create mode 100644 coolstore-partner-service/src/main/java/com/cool/store/http/WalletHttpClientRest.java create mode 100644 coolstore-partner-service/src/main/java/com/cool/store/service/wallet/WalletApiService.java diff --git a/coolstore-partner-common/pom.xml b/coolstore-partner-common/pom.xml index a6081765b..c499b9524 100644 --- a/coolstore-partner-common/pom.xml +++ b/coolstore-partner-common/pom.xml @@ -103,6 +103,10 @@ openpdf 1.3.30 + + org.bouncycastle + bcprov-jdk15on + org.icepdf.os diff --git a/coolstore-partner-common/src/main/java/com/cool/store/utils/KeyFormatUtil.java b/coolstore-partner-common/src/main/java/com/cool/store/utils/KeyFormatUtil.java new file mode 100644 index 000000000..c0a1e190b --- /dev/null +++ b/coolstore-partner-common/src/main/java/com/cool/store/utils/KeyFormatUtil.java @@ -0,0 +1,82 @@ +package com.cool.store.utils; + +/** + * @Author suzhuhong + * @Date 2025/11/13 12:15 + * @Version 1.0 + */ +public class KeyFormatUtil { + + /** + * 将单行密钥转换为标准PEM多行格式 + */ + public static String convertToPEMFormat(String singleLineKey, String keyType) { + if (singleLineKey == null || singleLineKey.trim().isEmpty()) { + throw new IllegalArgumentException("密钥不能为空"); + } + + // 清理密钥,移除可能存在的头尾标记和空白 + String cleanedKey = cleanKey(singleLineKey); + + // 定义头尾标记 + String header = getKeyHeader(keyType); + String footer = getKeyFooter(keyType); + + // 构建多行格式 + StringBuilder pemKey = new StringBuilder(); + pemKey.append(header).append("\n"); + + // 每64个字符换行 + for (int i = 0; i < cleanedKey.length(); i += 64) { + int end = Math.min(i + 64, cleanedKey.length()); + pemKey.append(cleanedKey.substring(i, end)).append("\n"); + } + + pemKey.append(footer); + return pemKey.toString(); + } + + /** + * 清理密钥字符串 + */ + public static String cleanKey(String key) { + return key.replaceAll("-----BEGIN.*-----", "") + .replaceAll("-----END.*-----", "") + .replaceAll("\\s", "") // 移除所有空白字符 + .trim(); + } + + private static String getKeyHeader(String keyType) { + switch (keyType.toUpperCase()) { + case "PRIVATE": + case "PRIVATE_KEY": + return "-----BEGIN PRIVATE KEY-----"; + case "PUBLIC": + case "PUBLIC_KEY": + return "-----BEGIN PUBLIC KEY-----"; + case "RSA_PRIVATE": + return "-----BEGIN RSA PRIVATE KEY-----"; + case "RSA_PUBLIC": + return "-----BEGIN RSA PUBLIC KEY-----"; + default: + throw new IllegalArgumentException("不支持的密钥类型: " + keyType); + } + } + + private static String getKeyFooter(String keyType) { + switch (keyType.toUpperCase()) { + case "PRIVATE": + case "PRIVATE_KEY": + return "-----END PRIVATE KEY-----"; + case "PUBLIC": + case "PUBLIC_KEY": + return "-----END PUBLIC KEY-----"; + case "RSA_PRIVATE": + return "-----END RSA PRIVATE KEY-----"; + case "RSA_PUBLIC": + return "-----END RSA PUBLIC KEY-----"; + default: + throw new IllegalArgumentException("不支持的密钥类型: " + keyType); + } + } +} diff --git a/coolstore-partner-common/src/main/java/com/cool/store/utils/OpenSignatureUtil.java b/coolstore-partner-common/src/main/java/com/cool/store/utils/OpenSignatureUtil.java index a6e6db642..730bebac0 100644 --- a/coolstore-partner-common/src/main/java/com/cool/store/utils/OpenSignatureUtil.java +++ b/coolstore-partner-common/src/main/java/com/cool/store/utils/OpenSignatureUtil.java @@ -112,85 +112,4 @@ public class OpenSignatureUtil { return result.toString(); } - /** - * 构造签名串 - * @param params 参数Map - * @return 构造好的签名串 - */ - public static String buildSignString(Map params) { - return params.entrySet().stream() - // 过滤空值字段 - .filter(entry -> entry.getValue() != null && !entry.getValue().trim().isEmpty()) - // 按参数名 ASCII 码升序排序 - .sorted(Map.Entry.comparingByKey()) - // 格式化为 key=value,值进行URL编码 - .map(entry -> { - try { - String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name()); - return entry.getKey() + "=" + encodedValue; - } catch (Exception e) { - throw new RuntimeException("URL编码失败", e); - } - }) - // 用 & 连接 - .collect(Collectors.joining("&")); - } - - /** - * 使用私钥对签名串进行 RSA-SHA256 签名 - * @param signString 待签名的字符串 - * @param privateKeyStr Base64编码的私钥 - * @return Base64编码的签名 - */ - public static String signWithRsaSha256(String signString, String privateKeyStr) { - try { - // 1. 解码Base64私钥 - byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr); - - // 2. 创建PKCS8编码密钥规范 - PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes); - - // 3. 获取RSA KeyFactory - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - - // 4. 生成私钥对象 - PrivateKey privateKey = keyFactory.generatePrivate(keySpec); - - // 5. 创建Signature实例,使用SHA256withRSA算法 - Signature signature = Signature.getInstance("SHA256withRSA"); - signature.initSign(privateKey); - - // 6. 更新要签名的数据 - signature.update(signString.getBytes(StandardCharsets.UTF_8)); - - // 7. 执行签名 - byte[] digitalSignature = signature.sign(); - - // 8. 对签名结果进行Base64编码 - return Base64.getEncoder().encodeToString(digitalSignature); - - } catch (Exception e) { - throw new RuntimeException("RSA-SHA256签名失败", e); - } - } - - /** - * 完整的签名生成方法 - * @param params 参数Map - * @param privateKeyStr 私钥字符串 - * @return 签名结果 - */ - public static String generateSignature(Map params, String privateKeyStr) { - // 1. 构造签名串 - String signString = buildSignString(params); - log.info("待签名串: {}", signString); - - // 2. 使用私钥进行RSA-SHA256签名 - String signature = signWithRsaSha256(signString, privateKeyStr); - log.info("生成签名: {}", signature); - - return signature; - } - - } \ No newline at end of file diff --git a/coolstore-partner-common/src/main/java/com/cool/store/utils/RsaSignUtil.java b/coolstore-partner-common/src/main/java/com/cool/store/utils/RsaSignUtil.java new file mode 100644 index 000000000..49c44b360 --- /dev/null +++ b/coolstore-partner-common/src/main/java/com/cool/store/utils/RsaSignUtil.java @@ -0,0 +1,309 @@ +package com.cool.store.utils; + +import com.sun.deploy.net.URLEncoder; +import lombok.extern.slf4j.Slf4j; +import org.bouncycastle.asn1.pkcs.RSAPrivateKey; +import sun.security.util.DerInputStream; +import sun.security.util.DerValue; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.security.KeyFactory; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.Signature; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.*; +import java.util.*; +/** + * RSA签名工具类 + * @Author suzhuhong + * @Date 2025/11/12 22:57 + * @Version 1.0 + */ +@Slf4j +public class RsaSignUtil { + + + /** + * 加签方法 + */ + public static String generateSign(Map params, String privateKeyPEM) { + // 移除可能存在的sign字段 + params.remove("sign"); + String afterSort = objectToSortedString(params); + log.info("排序后的参数:{}", afterSort); + String formattedPrivateKey = KeyFormatUtil.convertToPEMFormat(privateKeyPEM, "RSA_PRIVATE"); + return rsaPrivateKeySign(afterSort, privateKeyPEM, "SHA256withRSA"); + } + + /** + * 验签方法 + */ + public static boolean verifySign(Map params, String publicKeyPEM) { + String sign = String.valueOf(params.get("sign")); + params.remove("sign"); + String afterSort = objectToSortedString(params); + return rsaPublicKeyVerify(afterSort, sign, publicKeyPEM, "SHA256withRSA"); + } + + /** + * 查询签名验证 - 主入口方法 + */ + public static boolean querySignCrm(String publicKey, Map params) { + return verifySign(params, publicKey); + } + + /** + * 将对象转换为排序后的字符串 + */ + public static String objectToSortedString(Map obj) { + return convertToSortedString(obj, ""); + } + + /** + * 递归将参数转换为排序字符串 + */ + private static String convertToSortedString(Map params, String prefix) { + // 按键排序 + List keys = new ArrayList<>(params.keySet()); + Collections.sort(keys); + + List parts = new ArrayList<>(); + + for (String key : keys) { + Object value = params.get(key); + if (value == null || "".equals(value) || + (value instanceof Number && ((Number) value).doubleValue() == 0)) { + continue; + } + + String currentKey = key; + if (!prefix.isEmpty()) { + currentKey = prefix + "[" + key + "]"; + } + + if (value instanceof Map) { + @SuppressWarnings("unchecked") + Map nestedMap = (Map) value; + String nestedString = convertToSortedString(nestedMap, currentKey); + if (!nestedString.isEmpty()) { + parts.add(nestedString); + } + } else if (value instanceof List) { + List list = (List) value; + List elemStrs = new ArrayList<>(); + + for (Object element : list) { + String elementStr; + if (element instanceof Map) { + @SuppressWarnings("unchecked") + Map elementMap = (Map) element; + String inner = convertToSortedString(elementMap, ""); + elementStr = "{" + inner + "}"; + } else if (element instanceof Double) { + elementStr = String.format("%.0f", (Double) element); + } else if (element instanceof Float) { + elementStr = String.format("%.0f", (Float) element); + } else { + elementStr = String.valueOf(element); + } + elemStrs.add(elementStr); + } + + // 对元素字符串排序 + Collections.sort(elemStrs); + + // URL编码并添加到parts + for (String es : elemStrs) { + String encodedValue = urlEncode(es); + parts.add(currentKey + "[]=" + encodedValue); + } + } else if (value instanceof Double) { + String strValue = String.format("%.0f", (Double) value); + parts.add(currentKey + "=" + urlEncode(strValue)); + } else if (value instanceof Float) { + String strValue = String.format("%.0f", (Float) value); + parts.add(currentKey + "=" + urlEncode(strValue)); + } else { + String strValue = String.valueOf(value); + parts.add(currentKey + "=" + urlEncode(strValue)); + } + } + + return String.join("&", parts); + } + + /** + * URL编码(替换+为%20) + */ + private static String urlEncode(String value) { + try { + return URLEncoder.encode(value, StandardCharsets.UTF_8.name()) + .replace("+", "%20"); + } catch (Exception e) { + return value; + } + } + + /** + * RSA私钥加签 + */ + public static String rsaPrivateKeySign(String text, String privateKeyPEM, String algorithm) { + try { + // 1. 解析私钥 + log.debug("Received private key PEM: {}", privateKeyPEM); + PrivateKey privateKey = parsePrivateKey(privateKeyPEM); + if (privateKey == null) { + throw new RuntimeException("解析私钥失败"); + } + + // 2. 创建签名实例 + Signature signature = Signature.getInstance(algorithm); + signature.initSign(privateKey); + signature.update(text.getBytes(StandardCharsets.UTF_8)); + + // 3. 生成签名并Base64编码 + byte[] digitalSignature = signature.sign(); + return Base64.getEncoder().encodeToString(digitalSignature); + + } catch (Exception e) { + throw new RuntimeException("加签失败: " + e.getMessage(), e); + } + } + + /** + * RSA公钥验签 + */ + public static boolean rsaPublicKeyVerify(String text, String signBase64, + String publicKeyPEM, String algorithm) { + try { + // 1. 解码Base64签名 + byte[] signature = Base64.getDecoder().decode(signBase64); + + // 2. 解析公钥 + PublicKey publicKey = parsePublicKey(publicKeyPEM); + if (publicKey == null) { + return false; + } + + // 3. 验证签名 + Signature sig = Signature.getInstance(algorithm); + sig.initVerify(publicKey); + sig.update(text.getBytes(StandardCharsets.UTF_8)); + + return sig.verify(signature); + } catch (Exception e) { + return false; + } + } + + /** + * 解析PEM格式私钥(兼容PKCS#1和PKCS#8格式) + */ + private static PrivateKey parsePrivateKey(String privateKeyPEM) { + try { + String pemContent = privateKeyPEM + .replace("-----BEGIN PRIVATE KEY-----", "") + .replace("-----END PRIVATE KEY-----", "") + .replace("-----BEGIN RSA PRIVATE KEY-----", "") + .replace("-----END RSA PRIVATE KEY-----", "") + .replaceAll("\\s", ""); + + byte[] keyBytes = Base64.getDecoder().decode(pemContent); + + // 尝试PKCS#8格式 + try { + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return keyFactory.generatePrivate(keySpec); + } catch (Exception e) { + // 使用Bouncy Castle处理PKCS#1 + RSAPrivateKey rsaPrivKey = RSAPrivateKey.getInstance(keyBytes); + return KeyFactory.getInstance("RSA").generatePrivate( + new RSAPrivateKeySpec(rsaPrivKey.getModulus(), rsaPrivKey.getPrivateExponent())); + } + } catch (Exception e) { + throw new RuntimeException("解析私钥失败: " + e.getMessage(), e); + } + } + + /** + * 解析PKCS#1格式私钥 + */ + private static PrivateKey parsePKCS1PrivateKey(byte[] keyBytes) { + try { + int length = keyBytes.length; + byte[] pkcs8Header = new byte[] { + 0x30, (byte) 0x82, + (byte) ((length + 26) >> 8), (byte) (length + 26), // 总长度 + 0x02, 0x01, 0x00, + 0x30, 0x0D, 0x06, 0x09, 0x2A, (byte) 0x86, 0x48, (byte) 0x86, (byte) 0xF7, 0x0D, 0x01, 0x01, 0x01, 0x05, 0x00, + 0x04, (byte) 0x82, + (byte) (length >> 8), (byte) length // BIT STRING 长度 + }; + + byte[] pkcs8Key = new byte[pkcs8Header.length + keyBytes.length]; + System.arraycopy(pkcs8Header, 0, pkcs8Key, 0, pkcs8Header.length); + System.arraycopy(keyBytes, 0, pkcs8Key, pkcs8Header.length, keyBytes.length); + + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(pkcs8Key); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return keyFactory.generatePrivate(keySpec); + } catch (Exception e) { + throw new RuntimeException("解析PKCS#1私钥失败: " + e.getMessage(), e); + } + } + + /** + * 解析PEM格式公钥(兼容PKCS#1和PKCS#8格式) + */ + private static PublicKey parsePublicKey(String publicKeyPEM) { + try { + // 移除PEM头尾标记和空白字符 + String pemContent = publicKeyPEM + .replace("-----BEGIN PUBLIC KEY-----", "") + .replace("-----END PUBLIC KEY-----", "") + .replace("-----BEGIN RSA PUBLIC KEY-----", "") + .replace("-----END RSA PUBLIC KEY-----", "") + .replaceAll("\\s", ""); + + byte[] keyBytes = Base64.getDecoder().decode(pemContent); + + // 先尝试PKCS#8格式 + try { + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return keyFactory.generatePublic(keySpec); + } catch (Exception e) { + // 如果PKCS#8失败,尝试PKCS#1格式 + return parsePKCS1PublicKey(keyBytes); + } + } catch (Exception e) { + return null; + } + } + + /** + * 解析PKCS#1格式公钥 + */ + private static PublicKey parsePKCS1PublicKey(byte[] keyBytes) { + try { + // PKCS#1 RSA公钥转换为PKCS#8格式 + byte[] pkcs8Prefix = new byte[] { + 0x30, (byte) 0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, (byte) 0x86, + 0x48, (byte) 0x86, (byte) 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, + (byte) 0x82, 0x01, 0x0f, 0x00 + }; + + byte[] pkcs8Key = new byte[pkcs8Prefix.length + keyBytes.length]; + System.arraycopy(pkcs8Prefix, 0, pkcs8Key, 0, pkcs8Prefix.length); + System.arraycopy(keyBytes, 0, pkcs8Key, pkcs8Prefix.length, keyBytes.length); + + X509EncodedKeySpec keySpec = new X509EncodedKeySpec(pkcs8Key); + KeyFactory keyFactory = KeyFactory.getInstance("RSA"); + return keyFactory.generatePublic(keySpec); + } catch (Exception e) { + return null; + } + } +} \ No newline at end of file diff --git a/coolstore-partner-common/src/main/java/com/cool/store/utils/VerifySignatureUtils.java b/coolstore-partner-common/src/main/java/com/cool/store/utils/VerifySignatureUtils.java deleted file mode 100644 index 615968bff..000000000 --- a/coolstore-partner-common/src/main/java/com/cool/store/utils/VerifySignatureUtils.java +++ /dev/null @@ -1,104 +0,0 @@ -package com.cool.store.utils; - -import lombok.extern.slf4j.Slf4j; -import java.nio.charset.StandardCharsets; -import java.security.*; -import java.security.spec.X509EncodedKeySpec; -import java.util.*; -import java.util.stream.Collectors; -import java.net.URLEncoder; -import java.util.Base64; - -/** - *RSA-SHA256 验签工具类 - * @Author suzhuhong - * @Date 2025/11/12 15:15 - * @Version 1.0 - */ -@Slf4j -public class VerifySignatureUtils { - - /** - * 验证签名 - * @param params 参数Map(包含sign字段) - * @param publicKeyStr Base64编码的公钥 - * @return 验签结果 - */ - public static boolean verifySignature(Map params, String publicKeyStr) { - try { - // 1. 从参数中提取签名(并移除,不参与签名串构造) - String receivedSignature = params.get("sign"); - if (receivedSignature == null || receivedSignature.trim().isEmpty()) { - throw new IllegalArgumentException("签名参数sign不能为空"); - } - - // 2. 创建参数的副本,移除sign字段 - Map paramsForSign = new HashMap<>(params); - paramsForSign.remove("sign"); - - // 3. 构造签名串(与签名方相同的规则) - String signString = buildSignString(paramsForSign); - log.info("验签待签名串: {}", signString); - - // 4. 验证签名 - return verifyRsaSha256(signString, receivedSignature, publicKeyStr); - - } catch (Exception e) { - log.error("验签过程异常: ", e.getMessage()); - return false; - } - } - - /** - * 构造签名串(与签名方相同的逻辑) - */ - private static String buildSignString(Map params) { - return params.entrySet().stream() - .filter(entry -> entry.getValue() != null && !entry.getValue().trim().isEmpty()) - .sorted(Map.Entry.comparingByKey()) - .map(entry -> { - try { - String encodedValue = URLEncoder.encode(entry.getValue(), StandardCharsets.UTF_8.name()); - return entry.getKey() + "=" + encodedValue; - } catch (Exception e) { - throw new RuntimeException("URL编码失败", e); - } - }) - .collect(Collectors.joining("&")); - } - - /** - * RSA-SHA256 验签 - */ - private static boolean verifyRsaSha256(String data, String signature, String publicKeyStr) { - try { - // 1. 解码Base64公钥 - byte[] publicKeyBytes = Base64.getDecoder().decode(publicKeyStr); - - // 2. 创建X509编码密钥规范 - X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyBytes); - - // 3. 获取RSA KeyFactory - KeyFactory keyFactory = KeyFactory.getInstance("RSA"); - - // 4. 生成公钥对象 - PublicKey publicKey = keyFactory.generatePublic(keySpec); - - // 5. 创建Signature实例 - Signature sig = Signature.getInstance("SHA256withRSA"); - sig.initVerify(publicKey); - - // 6. 更新要验证的数据 - sig.update(data.getBytes(StandardCharsets.UTF_8)); - - // 7. 解码收到的签名 - byte[] signatureBytes = Base64.getDecoder().decode(signature); - - // 8. 执行验证 - return sig.verify(signatureBytes); - - } catch (Exception e) { - throw new RuntimeException("RSA-SHA256验签失败", e); - } - } -} \ No newline at end of file diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountAuthenticationDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountAuthenticationDTO.java new file mode 100644 index 000000000..e5de9cf48 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountAuthenticationDTO.java @@ -0,0 +1,15 @@ +package com.cool.store.dto.wallet; + +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 16:06 + * @Version 1.0 + */ +@Data +public class AccountAuthenticationDTO { + + private Integer accountStatus; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountInfoDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountInfoDTO.java new file mode 100644 index 000000000..323cd9ae9 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountInfoDTO.java @@ -0,0 +1,64 @@ +package com.cool.store.dto.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + + +/** + * 门店签约人账户 + * @Author suzhuhong + * @Date 2025/11/13 16:54 + * @Version 1.0 + */ +@Data +public class AccountInfoDTO { + + @ApiModelProperty(value = "结算卡业务类型 枚举值:1:对公 2:对私", required = true) + private String accountType; + + @ApiModelProperty(value = "营业执照号码") + private String licenseNo; + + @ApiModelProperty(value = "工商注册名称") + private String licenseName; + + @ApiModelProperty(value = "法人姓名") + private String legalName; + + @ApiModelProperty(value = "法人证件号码") + private String legalNo; + + @ApiModelProperty(value = "法人联系电话") + private String legalPhone; + + @ApiModelProperty(value = "门店编号", required = true) + private String storeSn; + + @ApiModelProperty(value = "账户编号", required = true) + private String accountNo; + + @ApiModelProperty(value = "账户名称", required = true) + private String accountName; + + @ApiModelProperty(value = "账户别名", required = true) + private String accountAliasName; + + @ApiModelProperty(value = "结算银行卡号", required = true) + private String accountCardNo; + + @ApiModelProperty(value = "结算卡银行预留手机号", required = true) + private String accountPhone; + + @ApiModelProperty(value = "开户支行名称", required = true) + private String bankName; + + @ApiModelProperty(value = "支行编号", required = true) + private String bankNo; + + @ApiModelProperty(value = "账户状态 1:待提交 2:待鉴权 3:鉴权中 4:开通", required = true) + private Integer accountStatus; + + @ApiModelProperty(value = "账户余额", required = true) + private String totalAmount; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountNoDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountNoDTO.java new file mode 100644 index 000000000..c78f890d7 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountNoDTO.java @@ -0,0 +1,15 @@ +package com.cool.store.dto.wallet; + +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 14:58 + * @Version 1.0 + */ +@Data +public class AccountNoDTO { + + private String accountNo; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountVerifyDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountVerifyDTO.java new file mode 100644 index 000000000..d8a8c78aa --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AccountVerifyDTO.java @@ -0,0 +1,17 @@ +package com.cool.store.dto.wallet; + +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 16:09 + * @Version 1.0 + */ +@Data +public class AccountVerifyDTO { + + private String outStoreId; + + private Integer accountStatus; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AddTagDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AddTagDTO.java new file mode 100644 index 000000000..0408d50d8 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/AddTagDTO.java @@ -0,0 +1,17 @@ +package com.cool.store.dto.wallet; + +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 14:59 + * @Version 1.0 + */ +@Data +public class AddTagDTO { + + private Integer status; + + private Integer addTagType; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/BankDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/BankDTO.java new file mode 100644 index 000000000..9375c398f --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/BankDTO.java @@ -0,0 +1,25 @@ +package com.cool.store.dto.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 10:54 + * @Version 1.0 + */ +@Data +public class BankDTO { + + @ApiModelProperty("银行编号") + private String headCode; + @ApiModelProperty("银行名称") + private String headName; + @ApiModelProperty("支行号") + private String branchCode; + @ApiModelProperty("支行名称") + private String branchName; + @ApiModelProperty("支行地址") + private String branchAddress; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/BankListDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/BankListDTO.java new file mode 100644 index 000000000..a7441adf3 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/BankListDTO.java @@ -0,0 +1,20 @@ +package com.cool.store.dto.wallet; + +import com.cool.store.request.wallet.WalletBasicPageInfo; +import lombok.Data; + +import java.util.List; + +/** + * @Author suzhuhong + * @Date 2025/11/13 14:36 + * @Version 1.0 + */ +@Data +public class BankListDTO { + + WalletBasicPageInfo page; + + List pageData; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/LargePaymentDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/LargePaymentDTO.java new file mode 100644 index 000000000..f95e440cf --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/LargePaymentDTO.java @@ -0,0 +1,53 @@ +package com.cool.store.dto.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 17:15 + * @Version 1.0 + */ +@Data +public class LargePaymentDTO { + + @ApiModelProperty(value = "外部门店唯一标识", required = true) + private String outStoreId; + + @ApiModelProperty(value = "请求预支付Id", required = true) + private String paymentId; + + @ApiModelProperty(value = "收款码唯一流水号", required = true) + private String transOrderTrace; + + @ApiModelProperty(value = "付款人账户编号", required = true) + private String payerAcctNo; + + @ApiModelProperty(value = "付款人户名", required = true) + private String payerAcctName; + + @ApiModelProperty(value = "付款银行名称") + private String payerBankName; + + @ApiModelProperty(value = "付款银行行号") + private String payerBankNo; + + @ApiModelProperty(value = "充值金额", required = true) + private String amt; + + @ApiModelProperty(value = "收款账号", required = true) + private String payeeAccNo; + + @ApiModelProperty(value = "收款账户名称", required = true) + private String payeeAccName; + + @ApiModelProperty(value = "收款银行名称", required = true) + private String payeeBankName; + + @ApiModelProperty(value = "收款银行行号", required = true) + private String payeeBankNo; + + @ApiModelProperty(value = "账号过期时间") + private String expireTime; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/PaymentDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/PaymentDTO.java new file mode 100644 index 000000000..aac3aa8bd --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/PaymentDTO.java @@ -0,0 +1,74 @@ +package com.cool.store.dto.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.Pattern; +import java.util.List; + +/** + * @Author suzhuhong + * @Date 2025/11/13 18:23 + * @Version 1.0 + */ +@Data +public class PaymentDTO { + + @ApiModelProperty(name = "外部门店唯一标识", required = true) + private String outStoreId; + + @ApiModelProperty(name = "请求预支付Id", required = true) + private String paymentId; + + @ApiModelProperty(name = "收款码唯一流水号", required = true) + private String transOrderTrace; + + @ApiModelProperty(name = "金额", required = true) + private String totalFee; + + @ApiModelProperty(name = "状态:1-成功 2-失败 3-支付中 4-撤销", required = true) + private Integer orderStatus; + + @ApiModelProperty(name = "利楚订单号(商户订单号)") + private String outTradeNo; + + @ApiModelProperty(name = "通道订单号(银行订单号)") + private String channelOrderNo; + + @ApiModelProperty(name = "付款人账号") + private String payerAccNo; + + @ApiModelProperty(name = "付款人户名") + private String payerAccName; + + @ApiModelProperty(name = "付款人银行名称") + private String payerBankName; + + @ApiModelProperty(name = "付款银行行号") + private String payerBankNo; + + @ApiModelProperty(name = "收款账号", required = true) + private String payeeAccNo; + + @ApiModelProperty(name = "收款账户名称", required = true) + private String payeeAccName; + + @ApiModelProperty(name = "收款银行名称", required = true) + private String payeeBankName; + + @ApiModelProperty(name = "收款银行行号", required = true) + private String payeeBankNo; + + @ApiModelProperty(name = "账号过期时间") + private String expireTime; + + @ApiModelProperty(name = "创建时间") + private String createTime; + + @ApiModelProperty(name = "付款明细") + private List payList; + + + + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/PaymentDetailDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/PaymentDetailDTO.java new file mode 100644 index 000000000..c20e7492a --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/PaymentDetailDTO.java @@ -0,0 +1,32 @@ +package com.cool.store.dto.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 17:38 + * @Version 1.0 + */ +@Data +public class PaymentDetailDTO { + + @ApiModelProperty(value = "打款金额", required = true) + private String tranAmt; + + @ApiModelProperty(value = "付款人账号", required = true) + private String payerAccountName; + + @ApiModelProperty(value = "付款时间", required = true) + private String paySuccessTime; + + @ApiModelProperty(value = "付款银行账号", required = true) + private String payerAccountBankNo; + + @ApiModelProperty(value = "银行受理时间", required = true) + private String tranSeqNo; + + @ApiModelProperty(value = "付款账号", required = true) + private String payerAccountNo; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/StoreAccountDTO.java b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/StoreAccountDTO.java new file mode 100644 index 000000000..d3f88e374 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/dto/wallet/StoreAccountDTO.java @@ -0,0 +1,19 @@ +package com.cool.store.dto.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 14:54 + * @Version 1.0 + */ +@Data +public class StoreAccountDTO { + + /** + * 营帐通的账户ID + */ + private String accountId; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/AccountAddTagRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/AccountAddTagRequest.java new file mode 100644 index 000000000..0e5db1110 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/AccountAddTagRequest.java @@ -0,0 +1,51 @@ +package com.cool.store.request.wallet; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.Pattern; + + +/** + * @Author suzhuhong + * @Date 2025/11/13 14:09 + * @Version 1.0 + */ +@Data +@ApiModel(description = "营业执照信息请求参数") +public class AccountAddTagRequest { + + @ApiModelProperty(value = "外部门店唯一标识", required = true) + @NotBlank(message = "外部门店唯一标识不能为空") + private String outStoreId; + + @ApiModelProperty(value = "营业执照号码", required = true) + @NotBlank(message = "营业执照号码不能为空") + private String licenseNo; + + @ApiModelProperty(value = "工商注册名称", required = true) + @NotBlank(message = "工商注册名称不能为空") + private String licenseName; + + @ApiModelProperty(value = "营业执照到期日(格式YYYY-MM-DD),如果证件到期日期为“长期”,则传:“2999-12-31”)") + private String licenseExpire; + + @ApiModelProperty(value = "法人姓名", required = true) + @NotBlank(message = "法人姓名不能为空") + private String legalName; + + @ApiModelProperty(value = "法人证件号码", required = true) + @NotBlank(message = "法人证件号码不能为空") + private String legalNo; + + @ApiModelProperty(value = "证件发证日期 yyyy-MM-dd") + private String idCardStartDate; + + @ApiModelProperty(value = "证件到期日期 yyyy-MM-dd,如果证件到期日期为“长期”,则传:“2999-12-31”") + private String idCardEndDate; + + @ApiModelProperty(value = "法人联系电话", required = true) + @NotBlank(message = "法人联系电话不能为空") + private String legalPhone; +} \ No newline at end of file diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/AccountVerifyRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/AccountVerifyRequest.java new file mode 100644 index 000000000..bc0f40c47 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/AccountVerifyRequest.java @@ -0,0 +1,17 @@ +package com.cool.store.request.wallet; + +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 16:08 + * @Version 1.0 + */ +@Data +public class AccountVerifyRequest { + + private String outStoreId; + + private String verifyNo; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/CreateStoreAndAccountRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/CreateStoreAndAccountRequest.java new file mode 100644 index 000000000..21148fae1 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/CreateStoreAndAccountRequest.java @@ -0,0 +1,43 @@ +package com.cool.store.request.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 13:49 + * @Version 1.0 + */ +@Data +public class CreateStoreAndAccountRequest { + + @ApiModelProperty(name = "CRM门店编号", required = true) + private String outStoreId; + @ApiModelProperty(name = "组织编号", required = true) + private String orgCode; + @ApiModelProperty(name = "组织名称", required = true) + private String orgName; + @ApiModelProperty(name = "联系电话", required = true) + private String phoneNumber; + @ApiModelProperty(name = "结算卡业务类型 枚举值:1:对公 2:对私", required = true) + private Integer accountType; + @ApiModelProperty(name = "开户类型:1企业 2个体工商户,3个人(小微商户) ", required = true) + private Integer businessType; + @ApiModelProperty(name = "法人姓名", required = true) + private String legalName; + @ApiModelProperty(name = "法人证件号码", required = true) + private String legalNo; + @ApiModelProperty(name = "账户简称", required = true) + private String accountAliasName; + @ApiModelProperty(name = "结算银行卡号", required = true) + private String accountCardno; + @ApiModelProperty(name = "结算卡银行预留手机号", required = true) + private String accountPhone; + @ApiModelProperty(name = "支行编号", required = true) + private String bankNo; + @ApiModelProperty(name = "开户支行名称", required = true) + private String bankName; + + + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/CreateStoreRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/CreateStoreRequest.java new file mode 100644 index 000000000..295493fe8 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/CreateStoreRequest.java @@ -0,0 +1,60 @@ +package com.cool.store.request.wallet; + +import com.sun.istack.NotNull; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotBlank; + +/** + * @Author suzhuhong + * @Date 2025/11/13 14:07 + * @Version 1.0 + */ +@Data +public class CreateStoreRequest { + + @ApiModelProperty(value = "CRM门店编号", required = true) + @NotBlank(message = "CRM门店编号不能为空") + private String outStoreId; + + @ApiModelProperty(value = "门店编号", required = true) + @NotBlank(message = "门店编号不能为空") + private String storeSn; + + @ApiModelProperty(value = "门店名称", required = true) + @NotBlank(message = "门店名称不能为空") + private String storeName; + + @ApiModelProperty(value = "门店内部名称") + private String inStoreName; + + @ApiModelProperty(value = "组织编号", required = true) + @NotBlank(message = "组织编号不能为空") + private String orgCode; + + @ApiModelProperty(value = "组织名称", required = true) + @NotBlank(message = "组织名称不能为空") + private String orgName; + + @ApiModelProperty(value = "联系电话", required = true) + @NotBlank(message = "联系电话不能为空") + private String phoneNumber; + + @ApiModelProperty(value = "门店模式: 1.社会加盟 2.强管 3.强加盟", required = true) + private Integer storeMode; + + @ApiModelProperty(value = "省-标准行政区域编码", required = true) + private Integer province; + + @ApiModelProperty(value = "市-标准行政区域编码", required = true) + private Integer city; + + @ApiModelProperty(value = "区县-标准行政区域编码", required = true) + private Integer district; + + @ApiModelProperty(value = "门店地址", required = true) + @NotBlank(message = "门店地址不能为空") + private String address; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/GetBankRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/GetBankRequest.java new file mode 100644 index 000000000..6d8f8f0fc --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/GetBankRequest.java @@ -0,0 +1,21 @@ +package com.cool.store.request.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 10:55 + * @Version 1.0 + */ +@Data +public class GetBankRequest { + + @ApiModelProperty("银行名称") + private String headName; + @ApiModelProperty("关键字查询") + private String keyword; + @ApiModelProperty("分页查询参数") + private WalletBasicPageInfo page; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/LargePaymentDetailRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/LargePaymentDetailRequest.java new file mode 100644 index 000000000..b24aadec2 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/LargePaymentDetailRequest.java @@ -0,0 +1,17 @@ +package com.cool.store.request.wallet; + +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 18:28 + * @Version 1.0 + */ +@Data +public class LargePaymentDetailRequest { + + private String transOrderTrace; + + private String paymentId; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/LargePaymentRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/LargePaymentRequest.java new file mode 100644 index 000000000..a7e1b9521 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/LargePaymentRequest.java @@ -0,0 +1,26 @@ +package com.cool.store.request.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 17:00 + * @Version 1.0 + */ +@Data +public class LargePaymentRequest { + + @ApiModelProperty(name = "商户门店编号",required = true) + private String outStoreId; + + @ApiModelProperty(name = "请求预支付Id",required = true) + private String paymentId; + + @ApiModelProperty(name = "签约人名称",required = true) + private String payerAccName; + + @ApiModelProperty(name = "支付金额",required = true) + private String amt; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/OutStoreIdRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/OutStoreIdRequest.java new file mode 100644 index 000000000..67126ef08 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/OutStoreIdRequest.java @@ -0,0 +1,15 @@ +package com.cool.store.request.wallet; + +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 16:05 + * @Version 1.0 + */ +@Data +public class OutStoreIdRequest { + + private String outStoreId; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/PaymentDetailRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/PaymentDetailRequest.java new file mode 100644 index 000000000..8cfded563 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/PaymentDetailRequest.java @@ -0,0 +1,15 @@ +package com.cool.store.request.wallet; + +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 17:37 + * @Version 1.0 + */ +@Data +public class PaymentDetailRequest { + + private String paymentId; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/UpdateStoreAccountRequest.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/UpdateStoreAccountRequest.java new file mode 100644 index 000000000..ed37eef29 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/UpdateStoreAccountRequest.java @@ -0,0 +1,29 @@ +package com.cool.store.request.wallet; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + * @Author suzhuhong + * @Date 2025/11/13 16:46 + * @Version 1.0 + */ +@Data +public class UpdateStoreAccountRequest { + + @ApiModelProperty(name = "商户门店编号",required = true) + private String outStoreId; + @ApiModelProperty(name = "法人/自然人证件号码",required = true) + private String idnum; + @ApiModelProperty(name = "签约人姓名(对私结算卡必传)以上二选一",required = true) + private String accountName; + @ApiModelProperty(name = "结算银行卡号",required = true) + private String accountCardno; + @ApiModelProperty(name = "结算卡银行预留手机号。",required = true) + private String accountPhone; + @ApiModelProperty(name = "支行编号",required = true) + private String bankNo; + @ApiModelProperty(name = "开户支行名称",required = true) + private String bankName; + +} diff --git a/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/WalletBasicPageInfo.java b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/WalletBasicPageInfo.java new file mode 100644 index 000000000..4a1cde0a2 --- /dev/null +++ b/coolstore-partner-model/src/main/java/com/cool/store/request/wallet/WalletBasicPageInfo.java @@ -0,0 +1,40 @@ +package com.cool.store.request.wallet; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiModelProperty; +import io.swagger.models.auth.In; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * @Author suzhuhong + * @Date 2025/11/13 10:56 + * @Version 1.0 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class WalletBasicPageInfo { + + @ApiModelProperty(name = "当前页码",required = true) + private Integer currentPage; + + @ApiModelProperty(name = "每页数量",required = true) + private Integer pageSize; + + private Integer total; + + private Integer count; + + private Boolean first; + + private Boolean last; + + public WalletBasicPageInfo(Integer currentPage, Integer pageSize){ + this.currentPage = currentPage; + this.pageSize = pageSize; + } + + +} diff --git a/coolstore-partner-service/src/main/java/com/cool/store/http/WalletHttpClientRest.java b/coolstore-partner-service/src/main/java/com/cool/store/http/WalletHttpClientRest.java new file mode 100644 index 000000000..aeb5cf88f --- /dev/null +++ b/coolstore-partner-service/src/main/java/com/cool/store/http/WalletHttpClientRest.java @@ -0,0 +1,231 @@ +package com.cool.store.http; + +import com.cool.store.enums.ErrorCodeEnum; +import com.cool.store.exception.ServiceException; +import com.cool.store.utils.RsaSignUtil; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.ObjectMapper; +import lombok.extern.slf4j.Slf4j; +import okhttp3.*; +import org.apache.poi.ss.formula.functions.T; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +/** + * @Author suzhuhong + * @Date 2025/11/13 10:00 + * @Version 1.0 + */ +@Service +@Slf4j +public class WalletHttpClientRest { + + @Autowired + private OkHttpClient okHttpClient; + + @Autowired + private ObjectMapper objectMapper; + + @Value("${cool.api.rsa.private.key}") + private String coolPrivateKey; + @Value("${wallet.api.rsa.public.key}") + private String walletPublicKey; + + + /** + * 发送带签名的POST请求 + */ + public T postWithSign(String url, Object request, Class responseType) { + try { + // 1. 准备请求参数 + Map requestParams = convertToMap(request); + requestParams.put("timestamp", System.currentTimeMillis()); + requestParams.put("key", "360155690205317"); + // 2. 生成签名 + String signature = RsaSignUtil.generateSign(requestParams,coolPrivateKey); + requestParams.put("sign", signature); + + // 3. 发送请求 + String responseJson = executePost(url, requestParams); + + // 4. 解析响应 + return parseResponse(responseJson, responseType); + + } catch (ServiceException e) { + throw e; + } catch (Exception e) { + // 其他异常统一包装为RuntimeException + log.error("发送带签名POST请求失败: {}", url, e); + throw new RuntimeException("接口调用异常: " + e.getMessage(), e); + } + } + + /** + * 发送带签名和验签的POST请求 + */ + public T postWithSignAndVerify(String url, Object request, Class responseType) { + try { + // 1. 准备请求参数 + Map requestParams = convertToMap(request); + requestParams.put("timestamp", System.currentTimeMillis()); + + // 2. 生成签名 + String signature = RsaSignUtil.generateSign(requestParams,coolPrivateKey); + requestParams.put("sign", signature); + + // 3. 发送请求 + String responseJson = executePost(url, requestParams); + + // 4. 解析响应并验证签名 + return parseAndVerifyResponse(responseJson, responseType); + + } catch (Exception e) { + log.error("发送带签名和验签POST请求失败: {}", url, e); + throw new RuntimeException(e.getMessage()); + } + } + + /** + * 发送普通POST请求(无签名) + */ + public T post(String url, Object request, Class responseType) { + try { + String responseJson = executePost(url, request); + return parseResponse(responseJson, responseType); + } catch (Exception e) { + log.error("发送POST请求失败: {}", url, e); + throw new RuntimeException("调用外部接口失败: " + e.getMessage()); + } + } + + /** + * 执行POST请求 + */ + private String executePost(String url, Object body) throws IOException { + String jsonBody = objectMapper.writeValueAsString(body); + RequestBody requestBody = RequestBody.create( MediaType.parse("application/json; charset=utf-8"),jsonBody); + + Request request = new Request.Builder() + .url(url) + .post(requestBody) + .addHeader("Content-Type", "application/json") + .build(); + + log.info("发送POST请求: {}, 数据: {}", url, jsonBody); + + try (Response response = okHttpClient.newCall(request).execute()) { + if (!response.isSuccessful()) { + throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR,response.code() + " " + response.message()); + } + + + String responseBody = response.body().string(); + log.info("收到响应: {}", responseBody); + + checkBusinessResponseCode(responseBody); + + return responseBody; + } + } + + private void checkBusinessResponseCode(String responseJson) throws IOException { + try { + Map responseMap = objectMapper.readValue(responseJson, + new TypeReference>() { + }); + + Object codeObj = responseMap.get("code"); + if (codeObj != null) { + int code = 0; + if (codeObj instanceof Number) { + code = ((Number) codeObj).intValue(); + } else { + code = Integer.parseInt(codeObj.toString()); + } + + if (code != 200) { + String msg = (String) responseMap.get("msg"); + throw new ServiceException(ErrorCodeEnum.THIRD_API_ERROR, + "code: " + code + ", msg: " + msg); + } + } + } catch (ServiceException e) { + throw e; + } catch (Exception e) { + // 如果解析失败,说明可能不是标准格式,继续处理 + log.debug("无法解析响应码格式: {}", e.getMessage()); + } + } + + /** + * 解析响应 + */ + @SuppressWarnings("unchecked") + private T parseResponse(String responseJson, Class responseType) throws Exception { + if (responseType == String.class) { + return (T) responseJson; + } + + // 解析为通用响应格式 + Map responseMap = objectMapper.readValue(responseJson, + new TypeReference>() {}); + + + + // 如果返回类型是Map,直接返回 + if (responseType == Map.class) { + return (T) responseMap; + } + + // 提取data字段 + Object data = responseMap.get("data"); + if (data != null && responseType != Object.class) { + return objectMapper.convertValue(data, responseType); + } + + return objectMapper.convertValue(responseMap, responseType); + } + + /** + * 解析响应并验证签名 + */ + @SuppressWarnings("unchecked") + private T parseAndVerifyResponse(String responseJson, Class responseType) throws Exception { + // 解析为Map来验证签名 + Map responseMap = objectMapper.readValue(responseJson, + new TypeReference>() {}); + + // 验证响应签名 + String responseSign = (String) responseMap.get("sign"); + if (responseSign != null) { + // 移除sign字段后进行验签 + Map verifyParams = new HashMap<>(responseMap); + + boolean isValid = RsaSignUtil.verifySign(verifyParams, walletPublicKey); + if (!isValid) { + throw new SecurityException("响应签名验证失败"); + } + log.debug("响应签名验证成功"); + } + + // 返回指定类型的数据 + return parseResponse(responseJson, responseType); + } + + /** + * 转换为Map + */ + @SuppressWarnings("unchecked") + private Map convertToMap(Object obj) { + if (obj instanceof Map) { + return (Map) obj; + } + return objectMapper.convertValue(obj, new TypeReference>() {}); + } + +} diff --git a/coolstore-partner-service/src/main/java/com/cool/store/service/wallet/WalletApiService.java b/coolstore-partner-service/src/main/java/com/cool/store/service/wallet/WalletApiService.java new file mode 100644 index 000000000..45990e0bd --- /dev/null +++ b/coolstore-partner-service/src/main/java/com/cool/store/service/wallet/WalletApiService.java @@ -0,0 +1,116 @@ +package com.cool.store.service.wallet; + +import com.cool.store.dto.wallet.*; +import com.cool.store.http.WalletHttpClientRest; +import com.cool.store.request.wallet.*; +import org.springframework.stereotype.Service; + +import javax.annotation.Resource; + +/** + * @Author suzhuhong + * @Date 2025/11/13 10:51 + * @Version 1.0 + */ +@Service +public class WalletApiService { + + @Resource + WalletHttpClientRest walletHttpClientRest; + + /** + * 在平安扫呗系统中,创建签约人账户 + * @param request + * @return + */ + public StoreAccountDTO createStoreAndAccount(CreateStoreAndAccountRequest request){ + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/account/v1/createStoreAndAccount", request, StoreAccountDTO.class); + } + + /** + * 开通失败 开通 + * @param request + * @return + */ + public StoreAccountDTO updateStoreAccount(UpdateStoreAccountRequest request){ + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/account/v1/updateStoreAccount", request, StoreAccountDTO.class); + } + + /** + * 创建门店接口 + * @param request + * @return + */ + public AccountNoDTO createStore(CreateStoreRequest request){ + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/v1/createStoreAndAccount", request, AccountNoDTO.class); + } + + /** + * 银行发送短信接口 + * @param request + * @return + */ + public AccountAuthenticationDTO authentication(OutStoreIdRequest request){ + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/account/v1/authentication", request, AccountAuthenticationDTO.class); + } + + /** + * 门店开通平安银行接口 + * @param request + * @return + */ + public AccountVerifyDTO openAccount(AccountVerifyRequest request){ + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/account/v1/openAccount", request, AccountVerifyDTO.class); + } + + /** + * 签约人账户打标升级 + * @param request + * @return + */ + public AddTagDTO addTag(AccountAddTagRequest request){ + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/account/v1/addTag", request, AddTagDTO.class); + } + + /** + * 获取账户信息 + * @param request + * @return + */ + public AccountInfoDTO getAccountInfo(OutStoreIdRequest request){ + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/account/v1/getAccountInfo", request, AccountInfoDTO.class); + } + + /** + * 大额预支付接口 + * @param request + * @return + */ + public LargePaymentDTO largePayment(LargePaymentRequest request){ + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/payment/v1/largePayment", request, LargePaymentDTO.class); + } + + /** + * 大额预支付查询接口 + * @param request + * @return + */ + public PaymentDTO largePaymentQuery(PaymentDetailRequest request){ + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/trans/v1/largePaymentQuery", request, PaymentDTO.class); + } + + /** + * 获取支行信息 + * @param request + * @return + */ + public BankListDTO getBankList(GetBankRequest request) { + return walletHttpClientRest.postWithSign("https://api.dev.wenmatech.com:443/open/crm/base/v1/findPageBank", request, BankListDTO.class); + } + + + + + + +} diff --git a/coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java b/coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java index ce2e5c02e..0818faab5 100644 --- a/coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java +++ b/coolstore-partner-web/src/main/java/com/cool/store/controller/webb/PCTestController.java @@ -2,15 +2,13 @@ package com.cool.store.controller.webb; import com.alibaba.fastjson.JSONObject; import com.cool.store.constants.CommonConstants; -import com.cool.store.constants.RedisConstant; import com.cool.store.dao.*; import com.cool.store.dto.FoodTokenDTO; import com.cool.store.dto.GetAccessTokenDTO; import com.cool.store.dto.HqtTokenDTO; import com.cool.store.dto.ModifyPasswordDTO; import com.cool.store.dto.huoma.*; -import com.cool.store.dto.wechat.CallbackMessageDTO; -import com.cool.store.dto.wechat.WechatTemplateMessageDTO; +import com.cool.store.dto.wallet.*; import com.cool.store.entity.*; import com.cool.store.enums.DownSystemTypeEnum; import com.cool.store.enums.MessageEnum; @@ -20,13 +18,13 @@ import com.cool.store.enums.wechat.WechatTemplateEnum; import com.cool.store.handler.WeChatHandler; import com.cool.store.job.XxlJobHandler; import com.cool.store.mapper.FranchiseFeeMapper; -import com.cool.store.mapper.LineInfoMapper; import com.cool.store.mapper.ShopInfoMapper; import com.cool.store.mq.util.HttpRestTemplateService; import com.cool.store.request.*; import com.cool.store.request.bigdata.ProfitDataRequest; import com.cool.store.request.huoma.ShopBasicInfoRequest; import com.cool.store.request.oppty.*; +import com.cool.store.request.wallet.*; import com.cool.store.request.xgj.PushFranchiseFeeRequest; import com.cool.store.response.ResponseResult; import com.cool.store.response.bigdata.ActDataResponse; @@ -39,16 +37,12 @@ import com.cool.store.response.oppty.OpportunityDetailResponse; import com.cool.store.response.oppty.OpportunityInfoPageResponse; import com.cool.store.service.*; import com.cool.store.service.impl.CommonService; -import com.cool.store.service.impl.OrderSysInfoServiceImpl; import com.cool.store.service.impl.UserAuthMappingServiceImpl; +import com.cool.store.service.wallet.WalletApiService; import com.cool.store.service.wechat.WechatTemplateService; import com.cool.store.service.xinfa.XinFaBusinessService; -import com.cool.store.service.xinfa.XinFaDeviceService; -import com.cool.store.utils.CoolDateUtils; -import com.cool.store.utils.RedisConstantUtil; -import com.cool.store.utils.RedisUtilPool; +import com.cool.store.utils.RsaSignUtil; import com.cool.store.utils.poi.StringUtils; -import com.fasterxml.jackson.core.JsonProcessingException; import io.swagger.annotations.ApiOperation; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; @@ -58,7 +52,6 @@ import org.springframework.web.bind.annotation.*; import javax.annotation.Resource; import javax.validation.Valid; import java.util.*; -import java.util.stream.Collectors; @Slf4j @RestController @@ -638,4 +631,159 @@ public class PCTestController { return ResponseResult.success(publishStatus); } + + public static void main(String[] args) { + // 测试数据 + Map params = new HashMap<>(); + params.put("name", "张三"); + params.put("age", 25); + params.put("amount", 100.50); + params.put("timestamp", System.currentTimeMillis()); + + List> items = new ArrayList<>(); + Map item1 = new HashMap<>(); + item1.put("id", 1); + item1.put("name", "商品A"); + item1.put("price", 29.99); + items.add(item1); + + Map item2 = new HashMap<>(); + item2.put("id", 2); + item2.put("name", "商品B"); + item2.put("price", 39.99); + items.add(item2); + + params.put("items", items); + + String privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEpQIBAAKCAQEA0erPAWesjkp9J4htmfCyqKS9npmT9dW3KqWTfb4c7x/QBUtK\n" + + "uokWOO0XikHd4bGUa9kl+twSv/5A3kYz1B9eg6wRuDJoads+G5U7rVQjzdoUtLaf\n" + + "3lNXkuSehl4uHUPQfNa6vcmvzraXPxJjEpYzj9WZh7uJqq2oSgw42H1qdbFCXSaE\n" + + "5BwsOb+2vZXjzh4RO10Sy3Qb1UqGsoZoxVzrtDeEctCjrecFyQr96L2UtYa4NTxS\n" + + "Tfu4rgObrwIOMvqqnLsXEzK/rd6kIHYjkZYQCOa48AedWp2YKQ7Ldclj+VMLnXvl\n" + + "42J9exVkbs++8k3P5sI9fdZX4Ey2RBjnSoAo/QIDAQABAoIBACbBGi8I+CE77M+1\n" + + "3wAu4RkD8xL7CQc3ic2ojGqIRPi7r5CuphD6mpzvXqtyfhd7DKr9h8bAxwBlnQ28\n" + + "ObjVgsI96/aM7dxvMs/uVPpqwIJyWuTDG5A05EPVC9REQnC6Mp09mnPL7rZz3Mfy\n" + + "6dIGY2YQWfwmWiPl1B45k+wZ+WPZPI0JVnvRzM881kf4aAhEAt08i9VoihylwVAj\n" + + "WIPmLuhf6ZcqI5q8iUsjfO22wZJsudVTCA/dsJdNxv+1RDKeYnSLJL79cZQcodqE\n" + + "hFqTy6vnn2dMsaHH7dpphU27barxUjeL482SR7kFfMqEXn5sltRn/3ep+3sf4Ph2\n" + + "vMtoZeECgYEA6gXzEtT9ZOeAMp4BRGmfNZ0TQLprPPVSwudz/uUBE4j/vyhfXkh9\n" + + "p7hqwyoxN+Z8b65yINvx8yP6hge6ek/MyAwBCZyfIRxZAPZu1eEGoYKl391ubFt2\n" + + "EIVqrN2DtAvzHMr5B/E2VHBq6AJm/rERFX5oKsg6zHS9tPLhgGnWVd0CgYEA5aFW\n" + + "OrtiqZJlp1MHQ4OeWBJatBSynkORdxCW7ic0CKbkYus0NSz1SsvskpbnfEXNB53x\n" + + "98qJxRhSopg/DC4m7XqxjSf9lY3HH4Y/9907olj33yGAnLWC88GivVndt577u/Xh\n" + + "YRCk33vOQ3GoibEdjnpMOkWmOfwYG/FsRWWQvaECgYEA1N2siEisZIgel+wZAv2A\n" + + "D+hchtgKi1wqd5bIb+Yl4HsRBfPXK4+MnG6mzfcm5c4FCiEHNtRZc+waCKgm+vJz\n" + + "NtOUbgXEyP1cCAAgOPOCcI7CCqsDshRPhB+XNL4Y+kCUVnBZrNu/q3bGB1uIC8tL\n" + + "2t0sKx4OPcNCe8EhVQjwKRECgYEA4uothdhKRPtwDIsVsHfN74Yjr7SMVay7gIca\n" + + "PrjqyGnzYnS+oJWOx50AaFNK6Rko5JAF3jF9NxE0B4yfMPAic6Y88hpEkpcJ4HMP\n" + + "n2Y1WdbFCu/WYgVUJICCys6VNLCcXj85umtyIY38Y9VbEMW/SV49GZBeFQqy4FoP\n" + + "/fvBrkECgYEAnfjTDYwgdmJdsUqyNzAocwcJXG2rVtYc7Txrl0TltcwuJmgoSywd\n" + + "zyOP2R9+NZsfoxWDzG0/yr15ApMvUcnnTwHN/8bGQ9SLatFLKqS4EtdwDKKS1JvN\n" + + "bs7V1myQGpt7jbShZOI0e6Fs4xP8ujxsLeGgiq9mZrS9UdRj5XKDoVM=\n" + + "-----END RSA PRIVATE KEY-----"; + + String publicKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0erPAWesjkp9J4htmfCy\n" + + "qKS9npmT9dW3KqWTfb4c7x/QBUtKuokWOO0XikHd4bGUa9kl+twSv/5A3kYz1B9e\n" + + "g6wRuDJoads+G5U7rVQjzdoUtLaf3lNXkuSehl4uHUPQfNa6vcmvzraXPxJjEpYz\n" + + "j9WZh7uJqq2oSgw42H1qdbFCXSaE5BwsOb+2vZXjzh4RO10Sy3Qb1UqGsoZoxVzr\n" + + "tDeEctCjrecFyQr96L2UtYa4NTxSTfu4rgObrwIOMvqqnLsXEzK/rd6kIHYjkZYQ\n" + + "COa48AedWp2YKQ7Ldclj+VMLnXvl42J9exVkbs++8k3P5sI9fdZX4Ey2RBjnSoAo\n" + + "/QIDAQAB"; + + try { + // 1. 加签 + String sign = RsaSignUtil.generateSign(new HashMap<>(params), privateKey); + System.out.println("生成的签名: " + sign); + + // 2. 将签名放入参数中 + params.put("sign", sign); + + // 3. 验签 + boolean isValid = RsaSignUtil.verifySign(new HashMap<>(params), publicKey); + System.out.println("验签结果: " + isValid); + + // 4. 测试排序字符串生成 + String sortedString = RsaSignUtil.objectToSortedString(params); + System.out.println("排序后的字符串: " + sortedString); + + } catch (Exception e) { + e.printStackTrace(); + } + } + + + @Resource + WalletApiService walletApiService; + + @ApiOperation("获取银行信息") + @PostMapping("/getBankList") + public ResponseResult getBankList(@RequestBody GetBankRequest request) { + BankListDTO bankList = walletApiService.getBankList(request); + return ResponseResult.success(bankList); + } + + @ApiOperation("签约人开通信息") + @PostMapping("/createStoreAndAccount") + public ResponseResult createStoreAndAccount(@RequestBody CreateStoreAndAccountRequest request) { + StoreAccountDTO dto = walletApiService.createStoreAndAccount(request); + return ResponseResult.success(dto); + } + + @ApiOperation("创建门店接口") + @PostMapping("/createStore") + public ResponseResult createStore(@RequestBody CreateStoreRequest request) { + AccountNoDTO accountNoDTO = walletApiService.createStore(request); + return ResponseResult.success(accountNoDTO); + } + + + @ApiOperation("打标接口") + @PostMapping("/addTag") + public ResponseResult addTag(@RequestBody AccountAddTagRequest request) { + AddTagDTO addTag = walletApiService.addTag(request); + return ResponseResult.success(addTag); + } + + @ApiOperation("门店签约人账户鉴权申请接口") + @PostMapping("/authentication") + public ResponseResult authentication(@RequestBody OutStoreIdRequest request) { + AccountAuthenticationDTO accountAuthenticationDTO = walletApiService.authentication(request); + return ResponseResult.success(accountAuthenticationDTO); + } + + + @ApiOperation("门店签约人账户开通接口") + @PostMapping("/openAccount") + public ResponseResult openAccount(@RequestBody AccountVerifyRequest request) { + AccountVerifyDTO accountVerifyDTO = walletApiService.openAccount(request); + return ResponseResult.success(accountVerifyDTO); + } + + @ApiOperation("获取账户信息") + @PostMapping("/getAccountInfo") + public ResponseResult getAccountInfo(@RequestBody OutStoreIdRequest request) { + AccountInfoDTO accountInfo = walletApiService.getAccountInfo(request); + return ResponseResult.success(accountInfo); + } + + + @ApiOperation("大额预支付接口") + @PostMapping("/largePayment") + public ResponseResult largePayment(@RequestBody LargePaymentRequest request) { + LargePaymentDTO largePayment = walletApiService.largePayment(request); + return ResponseResult.success(largePayment); + } + + @ApiOperation("大额预支付查询接口") + @PostMapping("/largePaymentQuery") + public ResponseResult largePaymentQuery(@RequestBody PaymentDetailRequest request) { + PaymentDTO PaymentDTO = walletApiService.largePaymentQuery(request); + return ResponseResult.success(PaymentDTO); + } + + + + + } diff --git a/coolstore-partner-web/src/main/resources/application-ab.properties b/coolstore-partner-web/src/main/resources/application-ab.properties index 02d7bbe98..e14312016 100644 --- a/coolstore-partner-web/src/main/resources/application-ab.properties +++ b/coolstore-partner-web/src/main/resources/application-ab.properties @@ -156,3 +156,8 @@ huoMa.franchise.stores.account = 13563273279 huoMa.franchise.stores.password = Zx@123456. huoMa.restaurant.stores.account = 18656552865 huoMa.restaurant.stores.password = ZX123456 + +cool.api.rsa.private.key=MIIEpQIBAAKCAQEA0erPAWesjkp9J4htmfCyqKS9npmT9dW3KqWTfb4c7x/QBUtKuokWOO0XikHd4bGUa9kl+twSv/5A3kYz1B9eg6wRuDJoads+G5U7rVQjzdoUtLaf3lNXkuSehl4uHUPQfNa6vcmvzraXPxJjEpYzj9WZh7uJqq2oSgw42H1qdbFCXSaE5BwsOb+2vZXjzh4RO10Sy3Qb1UqGsoZoxVzrtDeEctCjrecFyQr96L2UtYa4NTxSTfu4rgObrwIOMvqqnLsXEzK/rd6kIHYjkZYQCOa48AedWp2YKQ7Ldclj+VMLnXvl42J9exVkbs++8k3P5sI9fdZX4Ey2RBjnSoAo/QIDAQABAoIBACbBGi8I+CE77M+13wAu4RkD8xL7CQc3ic2ojGqIRPi7r5CuphD6mpzvXqtyfhd7DKr9h8bAxwBlnQ28ObjVgsI96/aM7dxvMs/uVPpqwIJyWuTDG5A05EPVC9REQnC6Mp09mnPL7rZz3Mfy6dIGY2YQWfwmWiPl1B45k+wZ+WPZPI0JVnvRzM881kf4aAhEAt08i9VoihylwVAjWIPmLuhf6ZcqI5q8iUsjfO22wZJsudVTCA/dsJdNxv+1RDKeYnSLJL79cZQcodqEhFqTy6vnn2dMsaHH7dpphU27barxUjeL482SR7kFfMqEXn5sltRn/3ep+3sf4Ph2vMtoZeECgYEA6gXzEtT9ZOeAMp4BRGmfNZ0TQLprPPVSwudz/uUBE4j/vyhfXkh9p7hqwyoxN+Z8b65yINvx8yP6hge6ek/MyAwBCZyfIRxZAPZu1eEGoYKl391ubFt2EIVqrN2DtAvzHMr5B/E2VHBq6AJm/rERFX5oKsg6zHS9tPLhgGnWVd0CgYEA5aFWOrtiqZJlp1MHQ4OeWBJatBSynkORdxCW7ic0CKbkYus0NSz1SsvskpbnfEXNB53x98qJxRhSopg/DC4m7XqxjSf9lY3HH4Y/9907olj33yGAnLWC88GivVndt577u/XhYRCk33vOQ3GoibEdjnpMOkWmOfwYG/FsRWWQvaECgYEA1N2siEisZIgel+wZAv2AD+hchtgKi1wqd5bIb+Yl4HsRBfPXK4+MnG6mzfcm5c4FCiEHNtRZc+waCKgm+vJzNtOUbgXEyP1cCAAgOPOCcI7CCqsDshRPhB+XNL4Y+kCUVnBZrNu/q3bGB1uIC8tL2t0sKx4OPcNCe8EhVQjwKRECgYEA4uothdhKRPtwDIsVsHfN74Yjr7SMVay7gIcaPrjqyGnzYnS+oJWOx50AaFNK6Rko5JAF3jF9NxE0B4yfMPAic6Y88hpEkpcJ4HMPn2Y1WdbFCu/WYgVUJICCys6VNLCcXj85umtyIY38Y9VbEMW/SV49GZBeFQqy4FoP/fvBrkECgYEAnfjTDYwgdmJdsUqyNzAocwcJXG2rVtYc7Txrl0TltcwuJmgoSywdzyOP2R9+NZsfoxWDzG0/yr15ApMvUcnnTwHN/8bGQ9SLatFLKqS4EtdwDKKS1JvNbs7V1myQGpt7jbShZOI0e6Fs4xP8ujxsLeGgiq9mZrS9UdRj5XKDoVM= +cool.api.rsa.public.key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0erPAWesjkp9J4htmfCyqKS9npmT9dW3KqWTfb4c7x/QBUtKuokWOO0XikHd4bGUa9kl+twSv/5A3kYz1B9eg6wRuDJoads+G5U7rVQjzdoUtLaf3lNXkuSehl4uHUPQfNa6vcmvzraXPxJjEpYzj9WZh7uJqq2oSgw42H1qdbFCXSaE5BwsOb+2vZXjzh4RO10Sy3Qb1UqGsoZoxVzrtDeEctCjrecFyQr96L2UtYa4NTxSTfu4rgObrwIOMvqqnLsXEzK/rd6kIHYjkZYQCOa48AedWp2YKQ7Ldclj+VMLnXvl42J9exVkbs++8k3P5sI9fdZX4Ey2RBjnSoAo/QIDAQAB +wallet.api.rsa.public.key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOmsrFtFPTnEzfpJ/hDl5RODBxw4i9Ex3NmmG/N7A1+by032zZZgLLpdNh8y5otjFY07Nyr4FGKFRSSuDiTk8vfx3pv6ImS1Rxjjg4qdVHIfqhCeB0Z2ZPuBD3Gbj8hHFEtXZq8+msAFu/5ZQjiVhgs5WWBjh54LYWSum+d9+wIDAQAB + diff --git a/coolstore-partner-web/src/main/resources/application-local.properties b/coolstore-partner-web/src/main/resources/application-local.properties index 087420e81..61008e74f 100644 --- a/coolstore-partner-web/src/main/resources/application-local.properties +++ b/coolstore-partner-web/src/main/resources/application-local.properties @@ -141,4 +141,8 @@ hqt.token.url=https://tc.cloud.hecom.cn hqt.token.username=18161486722 hqt.token.grant_type=client_credentials hqt.token.client.id=WrPffdGpcWkcPsbN -hqt.token.client.secret=rYe9Cwug5LwQNIBJAiW0a7weF9CAhYCD \ No newline at end of file +hqt.token.client.secret=rYe9Cwug5LwQNIBJAiW0a7weF9CAhYCD + +cool.api.rsa.private.key=MIIEpQIBAAKCAQEA0erPAWesjkp9J4htmfCyqKS9npmT9dW3KqWTfb4c7x/QBUtKuokWOO0XikHd4bGUa9kl+twSv/5A3kYz1B9eg6wRuDJoads+G5U7rVQjzdoUtLaf3lNXkuSehl4uHUPQfNa6vcmvzraXPxJjEpYzj9WZh7uJqq2oSgw42H1qdbFCXSaE5BwsOb+2vZXjzh4RO10Sy3Qb1UqGsoZoxVzrtDeEctCjrecFyQr96L2UtYa4NTxSTfu4rgObrwIOMvqqnLsXEzK/rd6kIHYjkZYQCOa48AedWp2YKQ7Ldclj+VMLnXvl42J9exVkbs++8k3P5sI9fdZX4Ey2RBjnSoAo/QIDAQABAoIBACbBGi8I+CE77M+13wAu4RkD8xL7CQc3ic2ojGqIRPi7r5CuphD6mpzvXqtyfhd7DKr9h8bAxwBlnQ28ObjVgsI96/aM7dxvMs/uVPpqwIJyWuTDG5A05EPVC9REQnC6Mp09mnPL7rZz3Mfy6dIGY2YQWfwmWiPl1B45k+wZ+WPZPI0JVnvRzM881kf4aAhEAt08i9VoihylwVAjWIPmLuhf6ZcqI5q8iUsjfO22wZJsudVTCA/dsJdNxv+1RDKeYnSLJL79cZQcodqEhFqTy6vnn2dMsaHH7dpphU27barxUjeL482SR7kFfMqEXn5sltRn/3ep+3sf4Ph2vMtoZeECgYEA6gXzEtT9ZOeAMp4BRGmfNZ0TQLprPPVSwudz/uUBE4j/vyhfXkh9p7hqwyoxN+Z8b65yINvx8yP6hge6ek/MyAwBCZyfIRxZAPZu1eEGoYKl391ubFt2EIVqrN2DtAvzHMr5B/E2VHBq6AJm/rERFX5oKsg6zHS9tPLhgGnWVd0CgYEA5aFWOrtiqZJlp1MHQ4OeWBJatBSynkORdxCW7ic0CKbkYus0NSz1SsvskpbnfEXNB53x98qJxRhSopg/DC4m7XqxjSf9lY3HH4Y/9907olj33yGAnLWC88GivVndt577u/XhYRCk33vOQ3GoibEdjnpMOkWmOfwYG/FsRWWQvaECgYEA1N2siEisZIgel+wZAv2AD+hchtgKi1wqd5bIb+Yl4HsRBfPXK4+MnG6mzfcm5c4FCiEHNtRZc+waCKgm+vJzNtOUbgXEyP1cCAAgOPOCcI7CCqsDshRPhB+XNL4Y+kCUVnBZrNu/q3bGB1uIC8tL2t0sKx4OPcNCe8EhVQjwKRECgYEA4uothdhKRPtwDIsVsHfN74Yjr7SMVay7gIcaPrjqyGnzYnS+oJWOx50AaFNK6Rko5JAF3jF9NxE0B4yfMPAic6Y88hpEkpcJ4HMPn2Y1WdbFCu/WYgVUJICCys6VNLCcXj85umtyIY38Y9VbEMW/SV49GZBeFQqy4FoP/fvBrkECgYEAnfjTDYwgdmJdsUqyNzAocwcJXG2rVtYc7Txrl0TltcwuJmgoSywdzyOP2R9+NZsfoxWDzG0/yr15ApMvUcnnTwHN/8bGQ9SLatFLKqS4EtdwDKKS1JvNbs7V1myQGpt7jbShZOI0e6Fs4xP8ujxsLeGgiq9mZrS9UdRj5XKDoVM= +cool.api.rsa.public.key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0erPAWesjkp9J4htmfCyqKS9npmT9dW3KqWTfb4c7x/QBUtKuokWOO0XikHd4bGUa9kl+twSv/5A3kYz1B9eg6wRuDJoads+G5U7rVQjzdoUtLaf3lNXkuSehl4uHUPQfNa6vcmvzraXPxJjEpYzj9WZh7uJqq2oSgw42H1qdbFCXSaE5BwsOb+2vZXjzh4RO10Sy3Qb1UqGsoZoxVzrtDeEctCjrecFyQr96L2UtYa4NTxSTfu4rgObrwIOMvqqnLsXEzK/rd6kIHYjkZYQCOa48AedWp2YKQ7Ldclj+VMLnXvl42J9exVkbs++8k3P5sI9fdZX4Ey2RBjnSoAo/QIDAQAB +wallet.api.rsa.public.key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOmsrFtFPTnEzfpJ/hDl5RODBxw4i9Ex3NmmG/N7A1+by032zZZgLLpdNh8y5otjFY07Nyr4FGKFRSSuDiTk8vfx3pv6ImS1Rxjjg4qdVHIfqhCeB0Z2ZPuBD3Gbj8hHFEtXZq8+msAFu/5ZQjiVhgs5WWBjh54LYWSum+d9+wIDAQAB diff --git a/coolstore-partner-web/src/main/resources/application-test.properties b/coolstore-partner-web/src/main/resources/application-test.properties index b9182bd10..3792da08d 100644 --- a/coolstore-partner-web/src/main/resources/application-test.properties +++ b/coolstore-partner-web/src/main/resources/application-test.properties @@ -169,3 +169,8 @@ huoMa.franchise.stores.account = 13563273279 huoMa.franchise.stores.password = Zx@123456. huoMa.restaurant.stores.account = 18656552865 huoMa.restaurant.stores.password = ZX123456 + + +cool.api.rsa.private.key=MIIEpQIBAAKCAQEA0erPAWesjkp9J4htmfCyqKS9npmT9dW3KqWTfb4c7x/QBUtKuokWOO0XikHd4bGUa9kl+twSv/5A3kYz1B9eg6wRuDJoads+G5U7rVQjzdoUtLaf3lNXkuSehl4uHUPQfNa6vcmvzraXPxJjEpYzj9WZh7uJqq2oSgw42H1qdbFCXSaE5BwsOb+2vZXjzh4RO10Sy3Qb1UqGsoZoxVzrtDeEctCjrecFyQr96L2UtYa4NTxSTfu4rgObrwIOMvqqnLsXEzK/rd6kIHYjkZYQCOa48AedWp2YKQ7Ldclj+VMLnXvl42J9exVkbs++8k3P5sI9fdZX4Ey2RBjnSoAo/QIDAQABAoIBACbBGi8I+CE77M+13wAu4RkD8xL7CQc3ic2ojGqIRPi7r5CuphD6mpzvXqtyfhd7DKr9h8bAxwBlnQ28ObjVgsI96/aM7dxvMs/uVPpqwIJyWuTDG5A05EPVC9REQnC6Mp09mnPL7rZz3Mfy6dIGY2YQWfwmWiPl1B45k+wZ+WPZPI0JVnvRzM881kf4aAhEAt08i9VoihylwVAjWIPmLuhf6ZcqI5q8iUsjfO22wZJsudVTCA/dsJdNxv+1RDKeYnSLJL79cZQcodqEhFqTy6vnn2dMsaHH7dpphU27barxUjeL482SR7kFfMqEXn5sltRn/3ep+3sf4Ph2vMtoZeECgYEA6gXzEtT9ZOeAMp4BRGmfNZ0TQLprPPVSwudz/uUBE4j/vyhfXkh9p7hqwyoxN+Z8b65yINvx8yP6hge6ek/MyAwBCZyfIRxZAPZu1eEGoYKl391ubFt2EIVqrN2DtAvzHMr5B/E2VHBq6AJm/rERFX5oKsg6zHS9tPLhgGnWVd0CgYEA5aFWOrtiqZJlp1MHQ4OeWBJatBSynkORdxCW7ic0CKbkYus0NSz1SsvskpbnfEXNB53x98qJxRhSopg/DC4m7XqxjSf9lY3HH4Y/9907olj33yGAnLWC88GivVndt577u/XhYRCk33vOQ3GoibEdjnpMOkWmOfwYG/FsRWWQvaECgYEA1N2siEisZIgel+wZAv2AD+hchtgKi1wqd5bIb+Yl4HsRBfPXK4+MnG6mzfcm5c4FCiEHNtRZc+waCKgm+vJzNtOUbgXEyP1cCAAgOPOCcI7CCqsDshRPhB+XNL4Y+kCUVnBZrNu/q3bGB1uIC8tL2t0sKx4OPcNCe8EhVQjwKRECgYEA4uothdhKRPtwDIsVsHfN74Yjr7SMVay7gIcaPrjqyGnzYnS+oJWOx50AaFNK6Rko5JAF3jF9NxE0B4yfMPAic6Y88hpEkpcJ4HMPn2Y1WdbFCu/WYgVUJICCys6VNLCcXj85umtyIY38Y9VbEMW/SV49GZBeFQqy4FoP/fvBrkECgYEAnfjTDYwgdmJdsUqyNzAocwcJXG2rVtYc7Txrl0TltcwuJmgoSywdzyOP2R9+NZsfoxWDzG0/yr15ApMvUcnnTwHN/8bGQ9SLatFLKqS4EtdwDKKS1JvNbs7V1myQGpt7jbShZOI0e6Fs4xP8ujxsLeGgiq9mZrS9UdRj5XKDoVM= +cool.api.rsa.public.key=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0erPAWesjkp9J4htmfCyqKS9npmT9dW3KqWTfb4c7x/QBUtKuokWOO0XikHd4bGUa9kl+twSv/5A3kYz1B9eg6wRuDJoads+G5U7rVQjzdoUtLaf3lNXkuSehl4uHUPQfNa6vcmvzraXPxJjEpYzj9WZh7uJqq2oSgw42H1qdbFCXSaE5BwsOb+2vZXjzh4RO10Sy3Qb1UqGsoZoxVzrtDeEctCjrecFyQr96L2UtYa4NTxSTfu4rgObrwIOMvqqnLsXEzK/rd6kIHYjkZYQCOa48AedWp2YKQ7Ldclj+VMLnXvl42J9exVkbs++8k3P5sI9fdZX4Ey2RBjnSoAo/QIDAQAB +wallet.api.rsa.public.key=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCOmsrFtFPTnEzfpJ/hDl5RODBxw4i9Ex3NmmG/N7A1+by032zZZgLLpdNh8y5otjFY07Nyr4FGKFRSSuDiTk8vfx3pv6ImS1Rxjjg4qdVHIfqhCeB0Z2ZPuBD3Gbj8hHFEtXZq8+msAFu/5ZQjiVhgs5WWBjh54LYWSum+d9+wIDAQAB diff --git a/pom.xml b/pom.xml index f3901d5b8..7ee22a7a9 100644 --- a/pom.xml +++ b/pom.xml @@ -232,6 +232,11 @@ alibabacloud-dysmsapi20170525 2.0.24 + + org.bouncycastle + bcprov-jdk15on + 1.70 +