diff --git a/cash-dependencies/pom.xml b/cash-dependencies/pom.xml
index b5163a004..cbbd275f7 100644
--- a/cash-dependencies/pom.xml
+++ b/cash-dependencies/pom.xml
@@ -42,6 +42,7 @@
2.5.1
2.9.10
4.1.128.Final
+ 0.2.17
@@ -268,6 +269,12 @@
netty-codec-mqtt
${netty.version}
+
+
+ com.github.wechatpay-apiv3
+ wechatpay-java
+ ${wechatpay.version}
+
diff --git a/cash-sdk/aggregation-pay/pom.xml b/cash-sdk/aggregation-pay/pom.xml
new file mode 100644
index 000000000..3df1fb396
--- /dev/null
+++ b/cash-sdk/aggregation-pay/pom.xml
@@ -0,0 +1,30 @@
+
+
+ 4.0.0
+
+ com.czg
+ cash-sdk
+ 1.0.0
+
+
+ aggregation-pay
+ jar
+ 聚合支付
+
+
+
+ 21
+ 21
+ UTF-8
+
+
+
+
+ com.github.wechatpay-apiv3
+ wechatpay-java
+
+
+
+
\ No newline at end of file
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatConfig.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatConfig.java
new file mode 100644
index 000000000..ace7aaab8
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatConfig.java
@@ -0,0 +1,47 @@
+package com.czg.wechat;
+
+import com.czg.wechat.dto.config.WechatPayConfigDto;
+import com.wechat.pay.java.core.Config;
+import com.wechat.pay.java.core.RSAPublicKeyConfig;
+import com.wechat.pay.java.service.file.FileUploadService;
+
+/**
+ * 微信支付 配置
+ *
+ * @author yjjie
+ * @date 2025/12/26 09:33
+ */
+public class WechatConfig {
+
+ /**
+ * 获取微信支付配置
+ * @param dto 微信支付配置
+ * @return 微信支付配置
+ */
+ public static Config getConfig(WechatPayConfigDto dto) {
+ return new RSAPublicKeyConfig.Builder()
+ .merchantId(dto.getMerchantId())
+ .privateKey(dto.getPrivateKey())
+ .publicKey(dto.getPublicKey())
+ .publicKeyId(dto.getPublicKeyId())
+ .merchantSerialNumber(dto.getSerialNumber())
+ .apiV3Key(dto.getApiV3Key())
+ .build();
+ }
+
+ public static FileUploadService getFileUploadService(Config config) {
+ return new FileUploadService.Builder()
+ .config(config)
+ .build();
+ }
+
+ /**
+ * 获取文件上传服务
+ * @param dto 微信支付配置
+ * @return 文件上传服务
+ */
+ public static FileUploadService getFileUploadService(WechatPayConfigDto dto) {
+ return getFileUploadService(getConfig(dto));
+ }
+
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatEncrypt.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatEncrypt.java
new file mode 100644
index 000000000..82c2cd179
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatEncrypt.java
@@ -0,0 +1,47 @@
+package com.czg.wechat;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+/**
+ * 微信支付加解密
+ * @author yjjie
+ * @date 2025/12/26 10:58
+ */
+public class WechatEncrypt {
+
+ public static String getFileBytesSha256(byte[] input) throws NoSuchAlgorithmException {
+ return bytesToHex(calculateSha256(input));
+ }
+
+ /**
+ * 核心方法:计算字节数组的 SHA-256 哈希值
+ * @param input 待计算的字节数组
+ * @return SHA-256 哈希值(32 字节的字节数组)
+ */
+ private static byte[] calculateSha256(byte[] input) throws NoSuchAlgorithmException {
+ // 获取 SHA-256 消息摘要实例(Java 21 完全兼容)
+ MessageDigest digest = MessageDigest.getInstance("SHA-256");
+ // 计算哈希值
+ return digest.digest(input);
+ }
+
+ /**
+ * 辅助方法:将字节数组转换为十六进制字符串(SHA-256 结果常用格式)
+ * @param bytes 待转换的字节数组
+ * @return 十六进制字符串(SHA-256 对应 64 位字符串)
+ */
+ private static String bytesToHex(byte[] bytes) {
+ StringBuilder hexString = new StringBuilder();
+ // Java 21 可使用 var 简化声明
+ for (var b : bytes) {
+ // 将字节转换为两位十六进制数,不足补 0
+ String hex = Integer.toHexString(0xff & b);
+ if (hex.length() == 1) {
+ hexString.append('0');
+ }
+ hexString.append(hex);
+ }
+ return hexString.toString();
+ }
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatEntryManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatEntryManager.java
new file mode 100644
index 000000000..162a2ba72
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatEntryManager.java
@@ -0,0 +1,157 @@
+package com.czg.wechat;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.czg.wechat.dto.config.WechatPayConfigDto;
+import com.wechat.pay.java.service.file.FileUploadService;
+import com.wechat.pay.java.service.file.model.FileUploadResponse;
+import lombok.extern.slf4j.Slf4j;
+
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+
+/**
+ * 微信支付进件 管理
+ *
+ * @author yjjie
+ * @date 2025/12/26 10:57
+ */
+@Slf4j
+public class WechatEntryManager {
+
+ public static String uploadImage(WechatPayConfigDto configDto, String url) {
+ // 校验入参
+ if (configDto == null || url == null || url.trim().isEmpty()) {
+ log.error("上传图片失败:配置或URL参数为空");
+ return "";
+ }
+
+ FileUploadService service = WechatConfig.getFileUploadService(configDto);
+
+ try {
+ // 获取图片字节数组
+ byte[] bytes = downloadImage(url);
+ if (bytes.length == 0) {
+ log.error("下载的图片内容为空,URL:{}", url);
+ return "";
+ }
+
+ // 2. 计算SHA256
+ String sha256Hex = WechatEncrypt.getFileBytesSha256(bytes);
+
+ // 3. 构造元数据(从URL提取文件名,或自定义)
+ JSONObject meta = new JSONObject();
+ meta.put("sha256", sha256Hex);
+ // 从URL提取文件名,若提取失败则使用默认名
+ String fileName = extractFileNameFromUrl(url);
+ meta.put("filename", fileName);
+
+ // 4. 上传图片到微信接口
+ FileUploadResponse uploadResponse = service.uploadImage(
+ configDto.getDomain() + "/v3/merchant/media/upload",
+ meta.toJSONString(),
+ fileName,
+ bytes
+ );
+
+ return uploadResponse.getMediaId();
+ } catch (Exception e) {
+ log.error("微信上传图片报错,URL:{},错误信息:{}", url, e.getMessage(), e);
+ }
+ return "";
+ }
+
+ public static byte[] downloadImage(String url) throws Exception {
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .GET()
+ .build();
+
+ HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
+
+ if (response.statusCode() != 200) {
+ throw new RuntimeException("Failed to download image, status code: " + response.statusCode());
+ }
+
+ return response.body();
+ }
+
+ /**
+ * 从URL中提取文件名
+ *
+ * @param url 图片URL
+ * @return 提取的文件名,失败则返回默认名
+ */
+ private static String extractFileNameFromUrl(String url) {
+ try {
+ if (url.contains("/")) {
+ String fileName = url.substring(url.lastIndexOf("/") + 1);
+ // 如果文件名包含参数,截取?之前的部分
+ if (fileName.contains("?")) {
+ fileName = fileName.substring(0, fileName.indexOf("?"));
+ }
+ // 如果提取的文件名有效,直接返回
+ if (fileName.contains(".")) {
+ return fileName;
+ }
+ }
+ } catch (Exception e) {
+ log.warn("提取文件名失败,使用默认文件名", e);
+ }
+ // 默认文件名
+ return "upload_" + System.currentTimeMillis() + ".png";
+ }
+
+ public static void main(String[] args) {
+ WechatPayConfigDto dto = new WechatPayConfigDto()
+ .setMerchantId("1643779408")
+ .setApiV3Key("a92baac5eb7a36ed8ec198113e769a03")
+ .setSerialNumber("4DE9BAC2EA584C3F274F694C9753CA814C4E9BF4")
+ .setPublicKey("""
+ -----BEGIN PUBLIC KEY-----
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtbeWXEEjBaYtw2OyM+SC
+ aCEMbryRXi4duKxx3vYG4rUVix+d5/Jz7Khev4Upml9zC+Xxvv/G9bHWAUyolzqD
+ wefahGurIxr43r4GJVnQ4i5G6BbBVw5d4Vuz0y/9Zd14zmc/EmBpT0Ml26H7tOZl
+ n1LSbQ4xNFkrRKrNEcExBLxkCd+K5K2TREZznywIi0izbHImvuzM8IneuR51FiqK
+ pdFnAjTwb126EIj6ECkL6KLCl8RWqpfiX8SFiolSQLs1/w79O0sIUk96X2zWpnoW
+ rTDFatPif/VEKl3y2dTlxxDxoZtVi48yTDW00OMzVl5D67oX3FVK0KsjHJSCfGlZ
+ 6wIDAQAB
+ -----END PUBLIC KEY-----""")
+ .setPrivateKey("""
+ -----BEGIN PRIVATE KEY-----
+ MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDqnAZhTxT572fo
+ 6wvSr8Rt0vRXg+EFKC6UvUiNE24oocQU5fjedX9KL/+fmoqay/xqIxvxvCNFTs4J
+ zlMqavSl6bMWCpjvf/Ry82JmN1v2kJEO4lgP8BsEiqlUpObCH8BMAVUOn1j+9q4Q
+ uZJJcbtRvec2fNweDM8EJp4B7RlUdDbHm86lfcDVp8iini7VjDp6D7aHT+C8A8OT
+ ugxQIquDec778wVd9r2Sv3+t6rAzFs+n+Zu++2xtFEPhO5N0wjrLHaukl+9crU+1
+ lktjDzcPd07SwGZ+A+3BTmW3UCramI3506e/3MWBECB7ge+gM4URAV0nJJCLH/Im
+ WgEvPMr5AgMBAAECggEBAKv+wraoMWqiVv1tA/froAgbtcJLDranJK8qrXuvmPz0
+ yzm+91qvrSgIVFEADUk67swo/R2Vng37nhWWS2Y3jy/rSr2H+2Lp3Z5ATA0/3I3A
+ onfU/FaC4mvL9CP32KzMdj/CYkccDzSsSCQ+x75MQNXGcTGDDCSDo2kZnpEu73j3
+ aqvO1jbqTGWigRfjOIaIhStjQIT8nEm/3mJ4f5dM9M6FMz33mhax8EahSgvdahYB
+ t45iaGOWw81OJhmry47EvpwjXBl7jtO2HX3LiLbq5Ebcwu1zqDz5NM7ttnnGAqWC
+ 6y7JN5Vt4wPYrCydiUDe7dj0looffr2yw6MkNfYjLGECgYEA+FAvbEInQEi9YguS
+ CQtLHngqvYeai66tvyykog9o38KHnPGx2Myf+rn/Hcp7KNRfjd5G34CCNg7KLnrx
+ YIYh6+2bY3jirzdYUxuNKGbvM4gky/6M/P9zHF/uALKOE02yArdqemf4UxUvrYCc
+ JdXsAMqvbpdvW1aGgNRB32YCkG0CgYEA8d89vawsCjNCEUh0VWTMoBLFoex3qBMZ
+ rfzYQeBo6bDCRlAlUVzl+ouBUxSYxP/U8rzeNaRzGUwRLmlGMjyIr58FBlHsg2cR
+ DlsX3HVCUjpS6sgPXOqakdiLfhMcHZAspislSyVfeS3TbUWiA45+5PuNUq+EZYwl
+ ESsB1+yfRT0CgYEA0Ct49ksnWM8iZbXJgeeD3FFlk2rBd2TDqEem5W4Bv8T3p+0/
+ 6b7yR2HyrGj5gys3yFmWFP1JLESN3xWWkhMhEQcrg+LuN3Iwi8vHNR3GXu892f7W
+ 96q4OAt8Hf2S+j/igkB99YyANDbIt63gOh/zMF67X/14j5wkOpC3gK+maqkCgYEA
+ s7nIrPoUt3ejLiiCmTmPe5q3VDzcJP4cZNau8zSHgK6hjZHcSPsYwPWMoWl6o1fe
+ qoiBLacHB9MoKS58xLOKdcVZ/Ho/ntylJd+2eVCAeY1xM5h5IfgJ5znbXVFh4O3S
+ 357L1Wzt5qOQqW/GlZH65LevKbPWU4axvHISqpnfN5kCgYEAqiqLuAPu84VSsqsE
+ GFh25t+1f0JY1sNfilE3/t9AdQeeCFv/5z9KB1kMt3a5ZFeVonsFIvCyaOJjhSkj
+ 4HCB94vWS7NuN5G9r874lMaPbZYQGwrcVaf265tN7cYYr3gUx1qB6+u+fh/kcft1
+ BBmTzhb0zp5k8ngwAkA1g/LK204=
+ -----END PRIVATE KEY-----""")
+ .setPublicKeyId("PUB_KEY_ID_0116437794082025111000382377001000")
+ .setDomain("https://api.mch.weixin.qq.com");
+
+ String string = uploadImage(dto, "https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png");
+ log.info("图片上传成功:{}", string);
+ }
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatPayManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatPayManager.java
new file mode 100644
index 000000000..897ad8fc3
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/WechatPayManager.java
@@ -0,0 +1,11 @@
+package com.czg.wechat;
+
+/**
+ * @author yjjie
+ * @date 2025/12/26 09:15
+ */
+public class WechatPayManager {
+
+ public static void main(String[] args) {
+ }
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/dto/config/WechatPayConfigDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/dto/config/WechatPayConfigDto.java
new file mode 100644
index 000000000..a0cb78bc4
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/wechat/dto/config/WechatPayConfigDto.java
@@ -0,0 +1,49 @@
+package com.czg.wechat.dto.config;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @author yjjie
+ * @date 2025/12/26 09:21
+ */
+@Data
+@Accessors(chain = true)
+public class WechatPayConfigDto {
+
+ /**
+ * 商户号
+ */
+ private String merchantId;
+
+ /**
+ * Api V3密钥
+ */
+ private String apiV3Key;
+
+ /**
+ * 商户证书序列号
+ */
+ private String serialNumber;
+
+ /**
+ * 商户私钥
+ */
+ private String privateKey;
+
+ /**
+ * 商户公钥
+ */
+ private String publicKey;
+
+ /**
+ * 商户公钥 ID
+ */
+ private String publicKeyId;
+
+ /**
+ * 微信支付域名
+ *
+ */
+ private String domain;
+}
diff --git a/cash-sdk/pom.xml b/cash-sdk/pom.xml
index 55ee0e62b..b92f22d79 100644
--- a/cash-sdk/pom.xml
+++ b/cash-sdk/pom.xml
@@ -13,6 +13,7 @@
第三方内容
czg-pay
+ aggregation-pay
cash-sdk