params) {
+ url = Arrays.stream(params.entrySet().toArray(new Map.Entry[0]))
+ .map(entry -> entry.getKey() + "=" + URLEncoder.encode(entry.getValue().toString(), StandardCharsets.UTF_8))
+ .collect(Collectors.joining("&", url + "?", ""));
+ return req(configDto, url, "GET", "");
+ }
+
+ private static String req(WechatPayConfigDto configDto, String url, String method, String body) {
long timestamp = getTimestamp();
String nonce = getNonceStr();
-
String signature = encryptReqParam(configDto, method, url, body, timestamp, nonce);
-
String authorization = String.format("WECHATPAY2-SHA256-RSA2048 mchid=\"%s\",nonce_str=\"%s\",signature=\"%s\",timestamp=\"%d\",serial_no=\"%s\"",
- configDto.getMerchantId(), nonce, signature, timestamp, "4DE9BAC2EA584C3F274F694C9753CA814C4E9BF4");
+ configDto.getMerchantId(), nonce, signature, timestamp, configDto.getSerialNumber());
- log.info("authorization = {}", authorization);
-
- HttpRequest request = HttpUtil.createPost(configDto.getDomain() + url)
- .header("Authorization", authorization)
- .header("Content-Type", "application/json")
- .header("Wechatpay-Serial", configDto.getPublicKeyId())
-// .header("Wechatpay-Serial", "4DE9BAC2EA584C3F274F694C9753CA814C4E9BF4")
- .body(body);
+ HttpRequest request = switch (method) {
+ case "POST" -> HttpUtil.createPost(configDto.getDomain() + url)
+ .header("Authorization", authorization)
+ .header("Content-Type", "application/json")
+ .header("Wechatpay-Serial", configDto.getPublicKeyId())
+ .body(body);
+ case "GET" -> HttpUtil.createGet(configDto.getDomain() + url)
+ .header("Authorization", authorization)
+ .header("Content-Type", "application/json")
+ .header("Wechatpay-Serial", configDto.getPublicKeyId());
+ default -> throw new CzgException("不支持的请求方法");
+ };
String s = request.execute().body();
- log.info("s = {}", s);
-
- return "";
+ log.info("微信支付请求:url = {}, method: {}, body: {}, resp: {}", url, method, body, s);
+ return s;
}
/**
* 加密请求参数
- * @param configDto 配置
- * @param method 请求方法
- * @param url 请求地址
- * @param body 请求报文主体
- * @return 加密后的报文
*
+ * @param configDto 配置
+ * @param method 请求方法
+ * @param url 请求地址
+ * @param body 请求报文主体
+ * @return 加密后的报文
+ *
* 签名方法
* HTTP请求方法\n
* URL\n
@@ -62,12 +81,12 @@ public class WechatReqUtils {
public static String encryptReqParam(WechatPayConfigDto configDto, String method, String url, String body, long timestamp, String nonce) {
String encryptStr = String.format("%s\n%s\n%d\n%s\n%s\n",
method, url, timestamp, nonce, body);
- System.out.println("encryptStr = \n" + encryptStr);
+ log.info("encryptStr = {}", encryptStr);
Config config = WechatConfig.getRsaConfig(configDto);
Signer signer = config.createSigner();
String signature = signer.sign(encryptStr).getSign();
- System.out.println("signature = " + signature);
+ log.info("签名 signature:{}", signature);
return signature;
}
@@ -82,6 +101,6 @@ public class WechatReqUtils {
* 获取时间戳
*/
private static long getTimestamp() {
- return System.currentTimeMillis()/1000;
+ return System.currentTimeMillis() / 1000;
}
}
From befd2942a2e3d74b7c8c2d1350328121cacd43e4 Mon Sep 17 00:00:00 2001
From: wangw <1594593906@qq.com>
Date: Tue, 30 Dec 2025 11:49:54 +0800
Subject: [PATCH 021/133] =?UTF-8?q?=E6=89=93=E5=8D=B0=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/resources/application-dev.yml | 25 ++++++++++-
.../java/com/czg/order/entity/OrderInfo.java | 44 ++++++++++++++-----
.../order/service/PrintMachineLogService.java | 2 +
.../czg/service/order/print/FeiPrinter.java | 8 ++--
.../service/order/print/PrinterHandler.java | 6 ++-
.../czg/service/order/print/YxyPrinter.java | 8 ++--
.../impl/OrderInfoCustomServiceImpl.java | 3 ++
.../impl/PrintMachineLogServiceImpl.java | 37 +++++++++++++---
8 files changed, 107 insertions(+), 26 deletions(-)
diff --git a/cash-api/order-server/src/main/resources/application-dev.yml b/cash-api/order-server/src/main/resources/application-dev.yml
index a2d9fc027..09d53b35a 100644
--- a/cash-api/order-server/src/main/resources/application-dev.yml
+++ b/cash-api/order-server/src/main/resources/application-dev.yml
@@ -25,7 +25,30 @@ spring:
port: 5672
username: chaozg
password: chaozg123
-
+ # 关键优化:解决MissedHeartbeatException 心跳超时问题
+ connection-timeout: 10000 # 连接超时时间(10秒,避免连接建立过慢)
+ requested-heartbeat: 30 # 心跳间隔调整为30秒(原60秒过长,降低超时概率;过短易误触发)
+ # 高级配置:连接池 & 自动重连(核心优化,避免连接断开后无法恢复)
+ cache:
+ connection:
+ mode: channel # 连接池模式(默认channel,推荐)
+ size: 10 # 最大连接数,根据业务调整
+ channel:
+ size: 50 # 每个连接的最大通道数
+ # 自动重连配置(Spring AMQP 自带,关键兜底)
+ publisher-returns: true
+ template:
+ retry:
+ enabled: true # 开启消息发送重试
+ max-attempts: 3 # 最大重试次数
+ initial-interval: 2000 # 首次重试间隔2秒
+ multiplier: 1.5 # 重试间隔倍增因子
+ listener:
+ simple:
+ retry:
+ enabled: true # 开启消费者重试
+ max-attempts: 3 # 消费者最大重试次数
+ acknowledge-mode: auto # 确认模式(可根据业务改为manual)
dubbo:
application:
name: order-server
diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java b/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
index 9c1dae004..26049bad4 100644
--- a/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
+++ b/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
@@ -2,6 +2,7 @@ package com.czg.order.entity;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
import com.czg.order.dto.LimitRateDTO;
import com.mybatisflex.annotation.Column;
import com.mybatisflex.annotation.Id;
@@ -346,15 +347,38 @@ public class OrderInfo implements Serializable {
// .add(this.getRoundAmount() != null ? this.getRoundAmount() : BigDecimal.ZERO);
}
+ private JSONArray getPrintStatusAsArray() {
+ if (StrUtil.isBlank(printStatus)) {
+ return new JSONArray();
+ }
+ try {
+ return JSONArray.parseArray(printStatus.trim());
+ } catch (Exception e) {
+ return new JSONArray();
+ }
+ }
-// public JSONArray getPrintStatus() {
-// if (StrUtil.isBlank(printStatus)) {
-// return new JSONArray();
-// }
-// try {
-// return JSONArray.parseArray(printStatus.trim());
-// } catch (Exception e) {
-// return new JSONArray();
-// }
-// }
+ public void upPrintStatus(JSONObject printStatus, boolean isPrintSuccess) {
+ String currentDeviceId = printStatus.getString("id");
+ JSONArray oldPrintStatusArray = getPrintStatusAsArray();
+ // 3. 初始化新的打印状态JSON数组(用于存储处理后的结果)
+ JSONArray newPrintStatusArray = new JSONArray();
+ // 场景1:打印成功 - 移除原有数组中与当前设备ID一致的记录,保留其余记录
+ if (oldPrintStatusArray != null && !oldPrintStatusArray.isEmpty()) {
+ for (int i = 0; i < oldPrintStatusArray.size(); i++) {
+ JSONObject deviceObj = oldPrintStatusArray.getJSONObject(i);
+ String deviceId = deviceObj.getString("id");
+ // 仅保留非当前设备ID的记录
+ if (currentDeviceId != null && !currentDeviceId.equals(deviceId)) {
+ newPrintStatusArray.add(deviceObj);
+ }
+ }
+ }
+ if (!isPrintSuccess) {
+ newPrintStatusArray.add(printStatus);
+ }
+ if(newPrintStatusArray.isEmpty()){
+ this.setPrintStatus(newPrintStatusArray.toJSONString());
+ }
+ }
}
diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/service/PrintMachineLogService.java b/cash-common/cash-common-service/src/main/java/com/czg/order/service/PrintMachineLogService.java
index 40c77ab7b..5449bec74 100644
--- a/cash-common/cash-common-service/src/main/java/com/czg/order/service/PrintMachineLogService.java
+++ b/cash-common/cash-common-service/src/main/java/com/czg/order/service/PrintMachineLogService.java
@@ -11,6 +11,8 @@ import com.czg.order.entity.PrintMachineLog;
* @since 2025-03-11
*/
public interface PrintMachineLogService extends IService {
+ void save(Long orderId, PrintMachine config, String bizType, String printContent, String respJson);
+
void save(PrintMachine config, String bizType, String printContent, String respJson);
}
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java
index aa1b6494a..3e79a3efe 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java
@@ -70,7 +70,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
String content = buildDishPrintData(false, getPickupNum(orderInfo), orderInfo.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
orderDetail.getProductName(), orderDetail.getSkuName(), orderDetail.getNum(), remark, orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
String o = sendPrintRequest(machine.getAddress(), content, null, "1");
- printMachineLogService.save(machine, "新订单", content, o);
+ printMachineLogService.save(orderInfo.getId(), machine, "新订单", content, o);
}
@@ -80,7 +80,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
String content = buildDishPrintData(true, getPickupNum(orderInfo), orderInfo.getCreateTime().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")),
orderDetail.getProductName(), orderDetail.getSkuName(), orderDetail.getReturnNum(), remark, orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
String o = sendPrintRequest(machine.getAddress(), content, null, "1");
- printMachineLogService.save(machine, "退款单", content, o);
+ printMachineLogService.save(orderInfo.getId(), machine, "退款单", content, o);
}
@@ -102,7 +102,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
.setDiscountAmount(orderInfo.getOriginAmount().subtract(orderInfo.getPayAmount()).toPlainString());
String string = buildOrderPrintData(printInfoDTO, detailList);
String o = sendPrintRequest(machine.getAddress(), string, null, printerNum);
- printMachineLogService.save(machine, "结算单", string, o);
+ printMachineLogService.save(orderInfo.getId(), machine, "结算单", string, o);
}
@@ -139,7 +139,7 @@ public class FeiPrinter extends PrinterHandler implements PrinterImpl {
String string = buildOrderPrintData(printInfoDTO, detailList);
String resp = sendPrintRequest(machine.getAddress(), string, null, printerNum);
- printMachineLogService.save(machine, "结算单", string, resp);
+ printMachineLogService.save(orderInfo.getId(), machine, "结算单", string, resp);
}
@Override
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterHandler.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterHandler.java
index 6ee130dae..d3598eed9 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterHandler.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/PrinterHandler.java
@@ -342,6 +342,7 @@ public abstract class PrinterHandler {
case PrintTypeEnum.ORDER:
log.info("准备开始打印订单");
if (data instanceof OrderInfo orderInfo) {
+ redisService.set("order:print:" + orderInfo.getId(),"", 180);
List orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
onlyFrontDesk(machine, false, orderInfo, orderDetailList);
} else {
@@ -351,6 +352,7 @@ public abstract class PrinterHandler {
case PrintTypeEnum.PRE_ORDER:
log.info("准备开始打印预结算订单");
if (data instanceof OrderInfo orderInfo) {
+ redisService.set("order:print:" + orderInfo.getId(),"", 180);
List orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
onlyFrontDesk(machine, true, orderInfo, orderDetailList);
} else {
@@ -360,6 +362,7 @@ public abstract class PrinterHandler {
case PrintTypeEnum.ONE:
log.info("准备开始打印菜品单");
if (data instanceof OrderInfo orderInfo) {
+ redisService.set("order:print:" + orderInfo.getId(),"", 180);
List orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
onlyKitchen(machine, orderInfo, orderDetailList);
} else {
@@ -377,6 +380,7 @@ public abstract class PrinterHandler {
case PrintTypeEnum.ONE_AND_ORDER:
log.info("准备开始打印菜品以及结算单");
if (data instanceof OrderInfo orderInfo) {
+ redisService.set("order:print:" + orderInfo.getId(),"", 180);
List orderDetailList = orderDetailService.list(new QueryWrapper().eq(OrderDetail::getOrderId, orderInfo.getId()));
switch (machine.getPrintMethod()) {
case "all":
@@ -462,7 +466,7 @@ public abstract class PrinterHandler {
OrderDetail orderDetail = detailMap.get(item.getId());
redisService.set(RedisCst.getPrintOrderDetailKey(orderInfo.getId(), item.getId()),
JSONObject.toJSONString(new PrintDetailInfo().setPrint(item.getIsPrint() == 1).setDetailId(item.getId())
- .setPrintNum(orderDetail.getNum()).setPrintReturnNum(orderDetail.getReturnNum())), 3600 * 24);
+ .setPrintNum(orderDetail.getNum()).setPrintReturnNum(orderDetail.getReturnNum())), 3600 * 24);
});
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java
index 3f32358a9..238a07d0f 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java
@@ -107,7 +107,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
orderDetail.getNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
String voiceJson = "{\"bizType\":\"2\",\"content\":\"您有一笔新的订单,请及时处理\"}";
String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
- printMachineLogService.save(machine, "新订单", buildDishPrintData, resp);
+ printMachineLogService.save(orderInfo.getId(), machine, "新订单", buildDishPrintData, resp);
}
@@ -117,7 +117,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
orderDetail.getReturnNum(), orderDetail.getRemark(), orderDetail.getProGroupInfo(), orderDetail.getId(), orderDetail.isUrgent());
String voiceJson = "{\"bizType\":\"2\",\"content\":\"\"}";
String resp = sendPrintRequest(machine.getAddress(), buildDishPrintData, voiceJson, "1");
- printMachineLogService.save(machine, "退款单", buildDishPrintData, resp);
+ printMachineLogService.save(orderInfo.getId(), machine, "退款单", buildDishPrintData, resp);
}
@@ -138,7 +138,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
printerNum = machine.getPrintQty().split("\\^")[1];
}
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
- printMachineLogService.save(machine, "退款单", data, resp);
+ printMachineLogService.save(orderInfo.getId(), machine, "退款单", data, resp);
}
@@ -174,7 +174,7 @@ public class YxyPrinter extends PrinterHandler implements PrinterImpl {
printerNum = machine.getPrintQty().split("\\^")[1];
}
String resp = sendPrintRequest(machine.getAddress(), data, voiceJson, printerNum);
- printMachineLogService.save(machine, "结算单", data, resp);
+ printMachineLogService.save(orderInfo.getId(), machine, "结算单", data, resp);
}
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoCustomServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoCustomServiceImpl.java
index 887e8fe76..84572cf5c 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoCustomServiceImpl.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/OrderInfoCustomServiceImpl.java
@@ -1516,6 +1516,9 @@ public class OrderInfoCustomServiceImpl implements OrderInfoCustomService {
@Override
public Boolean printOrder(Long shopId, OrderInfoPrintDTO orderInfoPrintDTO) {
+ if (redisService.hasKey("order:print:" + orderInfoPrintDTO.getId())) {
+ throw new CzgException("网络打印机正在尝试打印中。如需重打,请稍后再试!");
+ }
OrderInfo orderInfo = orderInfoService.getOne(new QueryWrapper().eq(OrderInfo::getShopId, shopId).eq(OrderInfo::getId, orderInfoPrintDTO.getId()));
if (orderInfo == null) {
throw new CzgException("订单信息不存在");
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
index 20bd6f3d0..ff1011632 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
@@ -4,11 +4,14 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.czg.account.entity.PrintMachine;
import com.czg.market.service.OrderInfoService;
+import com.czg.order.entity.OrderInfo;
import com.czg.order.entity.PrintMachineLog;
import com.czg.order.service.PrintMachineLogService;
+import com.czg.service.RedisService;
import com.czg.service.order.mapper.PrintMachineLogMapper;
import com.czg.service.order.print.FeiPrinter;
import com.czg.service.order.print.YxyPrinter;
@@ -20,6 +23,7 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
+import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
@@ -47,6 +51,8 @@ public class PrintMachineLogServiceImpl extends ServiceImpl yxxStatusMap = Map.of(
0, "离线(设备上线后自动补打)",
@@ -55,9 +61,19 @@ public class PrintMachineLogServiceImpl extends ServiceImpl checkPrintStatus(config, entity));
+ ThreadUtil.execAsync(() -> checkPrintStatus(orderId, config, entity));
}
/**
@@ -133,10 +149,11 @@ public class PrintMachineLogServiceImpl extends ServiceImpl future = retryFutureRef.get();
if (future != null && !future.isCancelled()) {
@@ -230,7 +247,15 @@ public class PrintMachineLogServiceImpl extends ServiceImpl
Date: Tue, 30 Dec 2025 13:32:16 +0800
Subject: [PATCH 022/133] =?UTF-8?q?MQ=E9=87=8D=E8=AF=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../order-server/src/main/resources/application-dev.yml | 9 +--------
1 file changed, 1 insertion(+), 8 deletions(-)
diff --git a/cash-api/order-server/src/main/resources/application-dev.yml b/cash-api/order-server/src/main/resources/application-dev.yml
index 09d53b35a..2ac1a07d7 100644
--- a/cash-api/order-server/src/main/resources/application-dev.yml
+++ b/cash-api/order-server/src/main/resources/application-dev.yml
@@ -28,20 +28,13 @@ spring:
# 关键优化:解决MissedHeartbeatException 心跳超时问题
connection-timeout: 10000 # 连接超时时间(10秒,避免连接建立过慢)
requested-heartbeat: 30 # 心跳间隔调整为30秒(原60秒过长,降低超时概率;过短易误触发)
- # 高级配置:连接池 & 自动重连(核心优化,避免连接断开后无法恢复)
- cache:
- connection:
- mode: channel # 连接池模式(默认channel,推荐)
- size: 10 # 最大连接数,根据业务调整
- channel:
- size: 50 # 每个连接的最大通道数
# 自动重连配置(Spring AMQP 自带,关键兜底)
publisher-returns: true
template:
retry:
enabled: true # 开启消息发送重试
max-attempts: 3 # 最大重试次数
- initial-interval: 2000 # 首次重试间隔2秒
+ initial-interval: 3000 # 首次重试间隔2秒
multiplier: 1.5 # 重试间隔倍增因子
listener:
simple:
From a4fc02dcc3cb7703ebd80040d0fb21b9a1bc4938 Mon Sep 17 00:00:00 2001
From: wangw <1594593906@qq.com>
Date: Tue, 30 Dec 2025 13:55:11 +0800
Subject: [PATCH 023/133] =?UTF-8?q?=E6=96=87=E6=A1=A3=E5=9C=B0=E5=9D=80?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/com/czg/service/order/print/FeiPrinter.java | 1 +
.../src/main/java/com/czg/service/order/print/YxyPrinter.java | 4 ++--
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java
index 3e79a3efe..caae46bed 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/FeiPrinter.java
@@ -31,6 +31,7 @@ import java.util.Map;
/**
* @author Administrator
+ * 接口文档
*/
@Component
@Slf4j
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java b/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java
index 238a07d0f..cf1f8a2c5 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/print/YxyPrinter.java
@@ -25,8 +25,8 @@ import java.time.LocalDateTime;
import java.util.*;
/**
- * 云享印打印机
- *
+ * 博实结-云享印打印机
+ * 接口文档
* @author Administrator
*/
@Slf4j
From 0684e0459f55ea52404ae13972d8104f1609687b Mon Sep 17 00:00:00 2001
From: wangw <1594593906@qq.com>
Date: Tue, 30 Dec 2025 14:11:38 +0800
Subject: [PATCH 024/133] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=87=E8=AF=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/com/czg/order/entity/OrderInfo.java | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java b/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
index 26049bad4..1dd24f0af 100644
--- a/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
+++ b/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
@@ -358,8 +358,8 @@ public class OrderInfo implements Serializable {
}
}
- public void upPrintStatus(JSONObject printStatus, boolean isPrintSuccess) {
- String currentDeviceId = printStatus.getString("id");
+ public void upPrintStatus(JSONObject printJson, boolean isPrintSuccess) {
+ String currentDeviceId = printJson.getString("id");
JSONArray oldPrintStatusArray = getPrintStatusAsArray();
// 3. 初始化新的打印状态JSON数组(用于存储处理后的结果)
JSONArray newPrintStatusArray = new JSONArray();
@@ -375,10 +375,10 @@ public class OrderInfo implements Serializable {
}
}
if (!isPrintSuccess) {
- newPrintStatusArray.add(printStatus);
+ newPrintStatusArray.add(printJson);
}
- if(newPrintStatusArray.isEmpty()){
- this.setPrintStatus(newPrintStatusArray.toJSONString());
+ if (newPrintStatusArray.isEmpty()) {
+ printStatus = newPrintStatusArray.toJSONString();
}
}
}
From 93b2309fcdf51545c8d1f48886142454b7983f7b Mon Sep 17 00:00:00 2001
From: wangw <1594593906@qq.com>
Date: Tue, 30 Dec 2025 14:25:37 +0800
Subject: [PATCH 025/133] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=A0=87=E8=AF=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../service/order/service/impl/PrintMachineLogServiceImpl.java | 3 +++
1 file changed, 3 insertions(+)
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
index ff1011632..0f52cc9fb 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
@@ -250,6 +250,9 @@ public class PrintMachineLogServiceImpl extends ServiceImpl
Date: Tue, 30 Dec 2025 15:05:06 +0800
Subject: [PATCH 026/133] =?UTF-8?q?=E8=B5=8B=E5=80=BC=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../java/com/czg/task/DistributionTask.java | 5 -
.../main/java/com/czg/mq/OrderMqListener.java | 6 +-
.../main/java/com/czg/mq/PrintMqListener.java | 6 +-
.../java/com/czg/service/RedisService.java | 111 +++++++++++++++-
.../java/com/czg/order/entity/OrderInfo.java | 2 +-
.../service/impl/CallTableServiceImpl.java | 10 +-
.../service/impl/ShopUserServiceImpl.java | 1 -
.../com/czg/service/account/util/FunUtil.java | 100 --------------
.../impl/PrintMachineLogServiceImpl.java | 94 +++----------
.../com/czg/service/order/utils/FunUtil.java | 125 ------------------
10 files changed, 141 insertions(+), 319 deletions(-)
delete mode 100644 cash-service/account-service/src/main/java/com/czg/service/account/util/FunUtil.java
delete mode 100644 cash-service/order-service/src/main/java/com/czg/service/order/utils/FunUtil.java
diff --git a/cash-api/market-server/src/main/java/com/czg/task/DistributionTask.java b/cash-api/market-server/src/main/java/com/czg/task/DistributionTask.java
index 5e59af7ec..cdc53aad2 100644
--- a/cash-api/market-server/src/main/java/com/czg/task/DistributionTask.java
+++ b/cash-api/market-server/src/main/java/com/czg/task/DistributionTask.java
@@ -1,11 +1,8 @@
package com.czg.task;
import cn.hutool.core.collection.CollUtil;
-import cn.hutool.core.date.DateUtil;
import com.czg.account.entity.ShopInfo;
-import com.czg.account.entity.ShopUser;
import com.czg.account.service.ShopInfoService;
-import com.czg.account.service.ShopUserService;
import com.czg.constant.TableValueConstant;
import com.czg.constants.SystemConstants;
import com.czg.exception.CzgException;
@@ -15,13 +12,11 @@ import com.czg.market.service.MkDistributionUserService;
import com.czg.market.service.OrderInfoService;
import com.czg.order.entity.OrderInfo;
import com.czg.service.market.enums.OrderStatusEnums;
-import com.czg.utils.FunUtils;
import com.mybatisflex.core.query.QueryWrapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.stereotype.Component;
-import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
diff --git a/cash-api/order-server/src/main/java/com/czg/mq/OrderMqListener.java b/cash-api/order-server/src/main/java/com/czg/mq/OrderMqListener.java
index e8054e747..c220d1f3f 100644
--- a/cash-api/order-server/src/main/java/com/czg/mq/OrderMqListener.java
+++ b/cash-api/order-server/src/main/java/com/czg/mq/OrderMqListener.java
@@ -9,7 +9,7 @@ import com.czg.order.entity.MqLog;
import com.czg.order.service.MqLogService;
import com.czg.order.service.OrderInfoCustomService;
import com.czg.order.service.OrderInfoRpcService;
-import com.czg.service.order.utils.FunUtil;
+import com.czg.service.RedisService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
@@ -31,7 +31,7 @@ public class OrderMqListener {
@Resource
private OrderInfoCustomService orderInfoCustomService;
@Resource
- private FunUtil funUtil;
+ private RedisService redisService;
/**
* 订单上菜
@@ -44,7 +44,7 @@ public class OrderMqListener {
info = info.replace("UP_ORDER_DETAIL:", "");
log.info("接收到修改菜品状态mq, info: {}", info);
String finalInfo = info;
- funUtil.debounce("UP_ORDER_DETAIL:" + info, 5, () -> {
+ redisService.debounce("UP_ORDER_DETAIL:" + info, 5, () -> {
orderInfoCustomService.updateOrderDetailStatus(Long.valueOf(finalInfo));
});
diff --git a/cash-api/order-server/src/main/java/com/czg/mq/PrintMqListener.java b/cash-api/order-server/src/main/java/com/czg/mq/PrintMqListener.java
index 33f610667..31781b987 100644
--- a/cash-api/order-server/src/main/java/com/czg/mq/PrintMqListener.java
+++ b/cash-api/order-server/src/main/java/com/czg/mq/PrintMqListener.java
@@ -6,8 +6,8 @@ import com.czg.config.RabbitConstants;
import com.czg.config.RedisCst;
import com.czg.order.entity.MqLog;
import com.czg.order.service.MqLogService;
+import com.czg.service.RedisService;
import com.czg.service.order.print.PrinterHandler;
-import com.czg.service.order.utils.FunUtil;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
@@ -27,7 +27,7 @@ public class PrintMqListener {
@Resource
private MqLogService mqLogService;
@Resource
- private FunUtil funUtil;
+ private RedisService redisService;
@Lazy
@Resource
@@ -59,7 +59,7 @@ public class PrintMqListener {
throw new RuntimeException("订单打印失败,未传递orderId");
}
Boolean printOrder = jsonObject.getBoolean("printOrder");
- funUtil.runFunAndCheckKey(() -> {
+ redisService.runFunAndCheckKey(() -> {
printerHandler.handler(orderId, printOrder != null && !printOrder ? PrinterHandler.PrintTypeEnum.ONE : PrinterHandler.PrintTypeEnum.ONE_AND_ORDER);
return null;
}, RedisCst.getLockKey("orderPrint", orderId));
diff --git a/cash-common/cash-common-redis/src/main/java/com/czg/service/RedisService.java b/cash-common/cash-common-redis/src/main/java/com/czg/service/RedisService.java
index e84608854..c5d078a80 100644
--- a/cash-common/cash-common-redis/src/main/java/com/czg/service/RedisService.java
+++ b/cash-common/cash-common-redis/src/main/java/com/czg/service/RedisService.java
@@ -6,14 +6,15 @@ import jakarta.annotation.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
+import java.util.*;
import java.util.concurrent.TimeUnit;
+import java.util.function.Consumer;
+import java.util.function.Function;
+import java.util.function.Supplier;
/**
* @author GYJoker
@@ -650,4 +651,106 @@ public class RedisService {
}
return JSON.parseArray(jsonStr, type);
}
+
+
+ public static int retryCount = 5;
+
+ /**
+ * 执行任务并保证锁唯一
+ *
+ * @param supplier 业务逻辑
+ * @param lockKey Redis锁的Key
+ * @return 业务逻辑返回值
+ */
+ public T runFunAndCheckKey(Supplier supplier, String lockKey) {
+ String lockValue = String.valueOf(System.nanoTime() + Thread.currentThread().threadId());
+ try {
+ // 尝试获取锁,超时时间 5 秒,防止死锁
+ boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
+ int count = 0;
+ // 初始等待 10ms
+ int retryDelay = 10;
+
+ while (!lock) {
+ // 最多重试 10 次,大约 10 秒
+ if (count++ > 50) {
+ throw new RuntimeException("系统繁忙, 稍后再试");
+ }
+ Thread.sleep(retryDelay);
+ // 指数退避,最大等待 200ms
+ retryDelay = Math.min(retryDelay * 2, 200);
+ lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
+ }
+
+ // 执行任务
+ return supplier.get();
+ } catch (InterruptedException e) {
+ Thread.currentThread().interrupt();
+ throw new RuntimeException("线程被中断", e);
+ } catch (Exception e) {
+ log.error("执行出错:{}", e.getMessage(), e);
+ throw e;
+ } finally {
+ // 释放锁(使用 Lua 脚本确保原子性)
+ unlock(lockKey, lockValue);
+ }
+ }
+
+ /**
+ * 使用 Lua 脚本确保释放锁的原子性
+ *
+ * @param lockKey 锁的 Key
+ * @param lockValue 当前线程的锁值
+ */
+ private void unlock(String lockKey, String lockValue) {
+ String luaScript =
+ "if redis.call('get', KEYS[1]) == ARGV[1] then " +
+ "return redis.call('del', KEYS[1]) " +
+ "else return 0 end";
+ redisTemplate.execute(new DefaultRedisScript<>(luaScript, Long.class),
+ Collections.singletonList(lockKey), lockValue);
+ }
+
+ public static R runFunAndRetry(
+ Supplier function,
+ Function check, Consumer errFun) {
+ R result = function.get();
+ boolean flag = check.apply(result);
+
+ while (flag && retryCount-- > 0) {
+ result = function.get();
+ flag = check.apply(result);
+ }
+
+ if (flag) {
+ errFun.accept(result);
+ }
+ return result;
+ }
+
+
+ /**
+ * 防抖函数:在指定秒数内相同 Key 的任务只会执行一次
+ *
+ * @param key 防抖使用的 Redis Key
+ * @param seconds 防抖时间(秒)
+ * @param task 要执行的业务逻辑
+ * @return true 执行了任务;false 在防抖期内被拦截
+ */
+ public boolean debounce(String key, long seconds, Runnable task) {
+ try {
+ Boolean success = redisTemplate.opsForValue().setIfAbsent(
+ key, "1", seconds, TimeUnit.SECONDS
+ );
+
+ if (Boolean.TRUE.equals(success)) {
+ task.run();
+ return true;
+ }
+ return false;
+ } catch (Exception e) {
+ log.error("防抖函数执行失败 key={} err={}", key, e.getMessage(), e);
+ return false;
+ }
+ }
}
diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java b/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
index 1dd24f0af..40c89fc74 100644
--- a/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
+++ b/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
@@ -377,7 +377,7 @@ public class OrderInfo implements Serializable {
if (!isPrintSuccess) {
newPrintStatusArray.add(printJson);
}
- if (newPrintStatusArray.isEmpty()) {
+ if (!newPrintStatusArray.isEmpty()) {
printStatus = newPrintStatusArray.toJSONString();
}
}
diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/CallTableServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/CallTableServiceImpl.java
index 53d467fe9..0ddc5e49e 100644
--- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/CallTableServiceImpl.java
+++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/CallTableServiceImpl.java
@@ -14,9 +14,9 @@ import com.czg.config.RedisCst;
import com.czg.constants.ParamCodeCst;
import com.czg.exception.CzgException;
import com.czg.resp.CzgResult;
+import com.czg.service.RedisService;
import com.czg.service.account.mapper.CallQueueMapper;
import com.czg.service.account.mapper.CallTableMapper;
-import com.czg.service.account.util.FunUtil;
import com.czg.service.account.util.WechatMiniMsgUtil;
import com.czg.system.dto.SysParamsDTO;
import com.czg.system.service.SysParamsService;
@@ -51,10 +51,10 @@ public class CallTableServiceImpl extends ServiceImpl {
+ return redisService.runFunAndCheckKey(() -> {
String callNumKey = RedisCst.getTableCallNumKey(shopId, callTable.getId());
String value = stringRedisTemplate.opsForValue().get(callNumKey);
AtomicReference newVal = new AtomicReference<>("");
// 初始化
if (StrUtil.isBlank(value)) {
- Boolean setFlag = FunUtil.runFunAndRetry(() -> stringRedisTemplate.opsForValue().setIfAbsent(callNumKey, callTable.getStart().toString()), flag -> !flag,
+ Boolean setFlag = RedisService.runFunAndRetry(() -> stringRedisTemplate.opsForValue().setIfAbsent(callNumKey, callTable.getStart().toString()), flag -> !flag,
_ -> newVal.set(stringRedisTemplate.opsForValue().get(callNumKey)));
if (setFlag) {
diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopUserServiceImpl.java b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopUserServiceImpl.java
index b7dd81f9c..5669504ce 100644
--- a/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopUserServiceImpl.java
+++ b/cash-service/account-service/src/main/java/com/czg/service/account/service/impl/ShopUserServiceImpl.java
@@ -22,7 +22,6 @@ import com.czg.market.vo.InviteUserVO;
import com.czg.market.vo.MemberConfigVO;
import com.czg.order.entity.OrderInfo;
import com.czg.service.account.mapper.ShopUserMapper;
-import com.czg.service.account.util.FunUtil;
import com.czg.utils.FunUtils;
import com.czg.utils.PageUtil;
import com.github.pagehelper.PageHelper;
diff --git a/cash-service/account-service/src/main/java/com/czg/service/account/util/FunUtil.java b/cash-service/account-service/src/main/java/com/czg/service/account/util/FunUtil.java
deleted file mode 100644
index c7d7f2d62..000000000
--- a/cash-service/account-service/src/main/java/com/czg/service/account/util/FunUtil.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package com.czg.service.account.util;
-
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.core.script.DefaultRedisScript;
-import org.springframework.stereotype.Component;
-
-import java.util.Collections;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-/**
- * @author Administrator
- */
-@Slf4j
-@Component
-public class FunUtil {
- @Resource
- private RedisTemplate redisTemplate;
- public static int retryCount = 5;
-
- /**
- * 执行任务并保证锁唯一
- * @param supplier 业务逻辑
- * @param lockKey Redis锁的Key
- * @return 业务逻辑返回值
- */
- public T runFunAndCheckKey(Supplier supplier, String lockKey) {
- String lockValue = String.valueOf(System.nanoTime() + Thread.currentThread().threadId());
- try {
- // 尝试获取锁,超时时间 5 秒,防止死锁
- boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
- int count = 0;
- // 初始等待 10ms
- int retryDelay = 10;
-
- while (!lock) {
- // 最多重试 10 次,大约 10 秒
- if (count++ > 50) {
- throw new RuntimeException("系统繁忙, 稍后再试");
- }
- Thread.sleep(retryDelay);
- // 指数退避,最大等待 200ms
- retryDelay = Math.min(retryDelay * 2, 200);
- lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
- }
-
- // 执行任务
- return supplier.get();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new RuntimeException("线程被中断", e);
- } catch (Exception e) {
- log.error("执行出错:{}", e.getMessage(), e);
- throw e;
- } finally {
- // 释放锁(使用 Lua 脚本确保原子性)
- unlock(lockKey, lockValue);
- }
- }
-
- /**
- * 使用 Lua 脚本确保释放锁的原子性
- * @param lockKey 锁的 Key
- * @param lockValue 当前线程的锁值
- */
- private void unlock(String lockKey, String lockValue) {
- String luaScript =
- "if redis.call('get', KEYS[1]) == ARGV[1] then " +
- "return redis.call('del', KEYS[1]) " +
- "else return 0 end";
- redisTemplate.execute(new DefaultRedisScript<>(luaScript, Long.class),
- Collections.singletonList(lockKey), lockValue);
- }
-
- public static R runFunAndRetry(
- Supplier function,
- Function check, Consumer errFun) {
- log.info("工具类开始执行函数");
- R result = function.get();
- boolean flag = check.apply(result);
-
- log.info("执行结果: {}", result);
-
- while (flag && retryCount-- > 0) {
- log.info("执行函数失败, 剩余尝试次数{}", retryCount);
- result = function.get();
- log.info("执行结果: {}", result);
- flag = check.apply(result);
- }
-
- if (flag) {
- errFun.accept(result);
- }
- return result;
- }
-}
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
index 0f52cc9fb..f8ea58f83 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
@@ -4,9 +4,9 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
-import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.czg.account.entity.PrintMachine;
+import com.czg.config.RedisCst;
import com.czg.market.service.OrderInfoService;
import com.czg.order.entity.OrderInfo;
import com.czg.order.entity.PrintMachineLog;
@@ -247,18 +247,8 @@ public class PrintMachineLogServiceImpl extends ServiceImpl {
+ OrderInfo orderInfo = orderInfoService.getOne(query().select(OrderInfo::getPrintStatus).eq(OrderInfo::getId, orderId));
+ if (orderInfo == null) {
+ orderInfo = new OrderInfo();
+ }
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("id", config.getId());
+ jsonObject.put("name", config.getName());
+ jsonObject.put("time", LocalDateTime.now());
+ orderInfo.upPrintStatus(jsonObject, isPrintSuccess);
+ orderInfoService.update(orderInfo, query().eq(OrderInfo::getId, orderId));
+ return orderInfo;
+ }, RedisCst.getLockKey("UP_ORDER_PRINT", orderId));
+ redisService.del("order:print:" + orderId);
+ }
+
/**
* 统一更新打印日志实体
*
@@ -300,66 +310,6 @@ public class PrintMachineLogServiceImpl extends ServiceImpl 0) {
-// entity.setFailFlag(0);
-// entity.setPrintTime(DateUtil.date().toLocalDateTime());
-// entity.setRespMsg("打印成功");
-// } else {
-// entity.setFailFlag(1);
-// entity.setPrintTime(null);
-// entity.setRespMsg(StrUtil.concat(true, "打印失败,", "_", msg));
-// }
-// }
-// }
-// super.updateById(entity);
-// }
-
// 静态标识,确保关闭钩子仅注册一次
private static volatile boolean shutdownHookRegistered = false;
// 锁对象,保证线程安全
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/utils/FunUtil.java b/cash-service/order-service/src/main/java/com/czg/service/order/utils/FunUtil.java
deleted file mode 100644
index b1dfa4b5d..000000000
--- a/cash-service/order-service/src/main/java/com/czg/service/order/utils/FunUtil.java
+++ /dev/null
@@ -1,125 +0,0 @@
-package com.czg.service.order.utils;
-
-import cn.hutool.core.lang.func.Func0;
-import jakarta.annotation.Resource;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.data.redis.core.RedisTemplate;
-import org.springframework.data.redis.core.script.DefaultRedisScript;
-import org.springframework.stereotype.Component;
-
-import java.util.Collections;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
-import java.util.function.Function;
-import java.util.function.Supplier;
-
-/**
- * @author Administrator
- */
-@Slf4j
-@Component
-public class FunUtil {
- @Resource
- private RedisTemplate redisTemplate;
- public static int retryCount = 5;
-
- /**
- * 执行任务并保证锁唯一
- * @param supplier 业务逻辑
- * @param lockKey Redis锁的Key
- * @return 业务逻辑返回值
- */
- public T runFunAndCheckKey(Supplier supplier, String lockKey) {
- String lockValue = String.valueOf(System.nanoTime() + Thread.currentThread().threadId());
- try {
- // 尝试获取锁,超时时间 5 秒,防止死锁
- boolean lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
- int count = 0;
- // 初始等待 10ms
- int retryDelay = 10;
-
- while (!lock) {
- // 最多重试 10 次,大约 10 秒
- if (count++ > 50) {
- throw new RuntimeException("系统繁忙, 稍后再试");
- }
- Thread.sleep(retryDelay);
- // 指数退避,最大等待 200ms
- retryDelay = Math.min(retryDelay * 2, 200);
- lock = Boolean.TRUE.equals(redisTemplate.opsForValue().setIfAbsent(lockKey, lockValue, 5, TimeUnit.SECONDS));
- }
-
- // 执行任务
- return supplier.get();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new RuntimeException("线程被中断", e);
- } catch (Exception e) {
- log.error("执行出错:{}", e.getMessage(), e);
- throw e;
- } finally {
- // 释放锁(使用 Lua 脚本确保原子性)
- unlock(lockKey, lockValue);
- }
- }
-
- /**
- * 使用 Lua 脚本确保释放锁的原子性
- * @param lockKey 锁的 Key
- * @param lockValue 当前线程的锁值
- */
- private void unlock(String lockKey, String lockValue) {
- String luaScript =
- "if redis.call('get', KEYS[1]) == ARGV[1] then " +
- "return redis.call('del', KEYS[1]) " +
- "else return 0 end";
- redisTemplate.execute(new DefaultRedisScript<>(luaScript, Long.class),
- Collections.singletonList(lockKey), lockValue);
- }
-
- public static R runFunAndRetry(
- Supplier function,
- Function check, Consumer errFun) {
- log.info("工具类开始执行函数");
- R result = function.get();
- boolean flag = check.apply(result);
-
- log.info("执行结果: {}", result);
-
- while (flag && retryCount-- > 0) {
- log.info("执行函数失败, 剩余尝试次数{}", retryCount);
- result = function.get();
- log.info("执行结果: {}", result);
- flag = check.apply(result);
- }
-
- if (flag) {
- errFun.accept(result);
- }
- return result;
- }
-
- /**
- * 防抖函数:在指定秒数内相同 Key 的任务只会执行一次
- * @param key 防抖使用的 Redis Key
- * @param seconds 防抖时间(秒)
- * @param task 要执行的业务逻辑
- * @return true 执行了任务;false 在防抖期内被拦截
- */
- public boolean debounce(String key, long seconds, Runnable task) {
- try {
- Boolean success = redisTemplate.opsForValue().setIfAbsent(
- key, "1", seconds, TimeUnit.SECONDS
- );
-
- if (Boolean.TRUE.equals(success)) {
- task.run();
- return true;
- }
- return false;
- } catch (Exception e) {
- log.error("防抖函数执行失败 key={} err={}", key, e.getMessage(), e);
- return false;
- }
- }
-}
From ee635dcc32e1735edd2f80c4b71ed1a2f8f23b6b Mon Sep 17 00:00:00 2001
From: wangw <1594593906@qq.com>
Date: Tue, 30 Dec 2025 15:17:52 +0800
Subject: [PATCH 027/133] =?UTF-8?q?=E6=97=A5=E6=9C=9F=E6=A0=BC=E5=BC=8F?=
=?UTF-8?q?=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../order/service/impl/PrintMachineLogServiceImpl.java | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
index f8ea58f83..c13a5395c 100644
--- a/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
+++ b/cash-service/order-service/src/main/java/com/czg/service/order/service/impl/PrintMachineLogServiceImpl.java
@@ -2,6 +2,7 @@ package com.czg.service.order.service.impl;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
@@ -280,7 +281,7 @@ public class PrintMachineLogServiceImpl extends ServiceImpl
Date: Tue, 30 Dec 2025 15:21:58 +0800
Subject: [PATCH 028/133] =?UTF-8?q?=E9=87=8D=E6=96=B0=E6=89=93=E5=8D=B0?=
=?UTF-8?q?=E9=97=AE=E9=A2=98=20=E5=A4=B1=E8=B4=A5=E6=A0=87=E8=AF=86?=
=?UTF-8?q?=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/com/czg/order/entity/OrderInfo.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java b/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
index 40c89fc74..f8df987f4 100644
--- a/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
+++ b/cash-common/cash-common-service/src/main/java/com/czg/order/entity/OrderInfo.java
@@ -379,6 +379,8 @@ public class OrderInfo implements Serializable {
}
if (!newPrintStatusArray.isEmpty()) {
printStatus = newPrintStatusArray.toJSONString();
+ } else {
+ printStatus = "";
}
}
}
From acf04b8534f4f7ef551bc6f2cb7cee59ee7f506f Mon Sep 17 00:00:00 2001
From: wangw <1594593906@qq.com>
Date: Wed, 31 Dec 2025 09:24:09 +0800
Subject: [PATCH 029/133] =?UTF-8?q?=E5=BC=80=E5=85=B3=E6=A0=87=E8=AF=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../czg/controller/admin/QuickMenuController.java | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/cash-api/account-server/src/main/java/com/czg/controller/admin/QuickMenuController.java b/cash-api/account-server/src/main/java/com/czg/controller/admin/QuickMenuController.java
index dda983a67..44c786733 100644
--- a/cash-api/account-server/src/main/java/com/czg/controller/admin/QuickMenuController.java
+++ b/cash-api/account-server/src/main/java/com/czg/controller/admin/QuickMenuController.java
@@ -31,16 +31,19 @@ public class QuickMenuController {
@SaAdminCheckPermission(parentName = "悬浮窗", value = "quick:list", name = "悬浮窗-列表")
@GetMapping
- public CzgResult> getQuickList(Integer status) {
+ public CzgResult> getQuickList(@RequestParam(required = false) Integer status,
+ @RequestParam(required = false, defaultValue = "0") Integer isEdit) {
List list = quickMenuService.list(QueryWrapper.create()
.eq(QuickMenu::getShopId, StpKit.USER.getShopId())
.eq(QuickMenu::getStatus, status)
.orderBy(QuickMenu::getSort, true));
- if (CollUtil.isEmpty(list)) {
- list = quickMenuService.list(QueryWrapper.create()
- .eq(QuickMenu::getShopId, 1)
- .eq(QuickMenu::getStatus, status)
- .orderBy(QuickMenu::getSort, true));
+ if (isEdit.equals(0)) {
+ if (CollUtil.isEmpty(list)) {
+ list = quickMenuService.list(QueryWrapper.create()
+ .eq(QuickMenu::getShopId, 1)
+ .eq(QuickMenu::getStatus, status)
+ .orderBy(QuickMenu::getSort, true));
+ }
}
return CzgResult.success(list);
}
From 9a1b5b5cae49baaac28abf36b4f69f92ea29287f Mon Sep 17 00:00:00 2001
From: gong <1157756119@qq.com>
Date: Sun, 4 Jan 2026 10:24:35 +0800
Subject: [PATCH 030/133] =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=AE=9D=E5=85=A5?=
=?UTF-8?q?=E7=BD=91=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/com/czg/alipay/AlipayEntryManager.java | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayEntryManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayEntryManager.java
index d33793279..74fc03406 100644
--- a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayEntryManager.java
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayEntryManager.java
@@ -13,12 +13,13 @@ import com.alipay.v3.util.model.AlipayConfig;
/**
* 支付宝进件管理
*
- * ...
+ * ...
* @author yjjie
* @date 2025/12/29 14:11
*/
public class AlipayEntryManager {
+ // https://opendocs.alipay.com/solution/0dec7x?pathHash=caec4753 直付通
public static void main(String[] args) throws ApiException {
ApiClient defaultClient = Configuration.getDefaultApiClient();
// 初始化alipay参数(全局设置一次)
@@ -35,8 +36,8 @@ public class AlipayEntryManager {
contactInfo.setContactName("张三");
contactInfo.setContactMobile("18866668888");
data.setContactInfo(contactInfo);
- data.setOrderTicket("00ee2d475f374ad097ee0f1ac223fX00");
- data.setAccount("test@alipay.com");
+// data.setOrderTicket("00ee2d475f374ad097ee0f1ac223fX00");
+ data.setAccount("1157756119@qq.com");
try {
AlipayOpenAgentCreateResponseModel response = api.create(data);
System.out.println(response);
From 8d9878a316ed26c23306581ab629bd9f9101fc5a Mon Sep 17 00:00:00 2001
From: gong <1157756119@qq.com>
Date: Sun, 4 Jan 2026 14:20:24 +0800
Subject: [PATCH 031/133] =?UTF-8?q?=E6=94=AF=E4=BB=98=E5=AE=9D=20=E5=9B=BE?=
=?UTF-8?q?=E7=89=87=E4=B8=8A=E4=BC=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/java/com/czg/CommonUtil.java | 41 +++
.../java/com/czg/alipay/AlipayClient.java | 31 +++
.../com/czg/alipay/AlipayEntryManager.java | 47 +++-
.../dto/AlipayCreateContactInfoDto.java | 34 ---
.../com/czg/alipay/dto/AlipayCreateDto.java | 37 ---
.../alipay/dto/config/AlipayConfigDto.java | 34 +++
.../alipay/dto/entry/AlipayAddressReqDto.java | 43 +++
.../dto/entry/AlipayBizCardsReqDto.java | 89 +++++++
.../dto/entry/AlipayContactInfoReqDto.java | 50 ++++
.../alipay/dto/entry/AlipayEntryReqDto.java | 249 ++++++++++++++++++
.../dto/entry/AlipayImageUploadReqDto.java | 31 +++
.../dto/entry/AlipayQualificationsReqDto.java | 30 +++
.../dto/entry/AlipaySettleRuleReqDto.java | 29 ++
.../alipay/dto/entry/AlipaySitesReqDto.java | 148 +++++++++++
.../com/czg/wechat/WechatEntryManager.java | 167 ++++++------
15 files changed, 893 insertions(+), 167 deletions(-)
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/CommonUtil.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayClient.java
delete mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/AlipayCreateContactInfoDto.java
delete mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/AlipayCreateDto.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/config/AlipayConfigDto.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayAddressReqDto.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayBizCardsReqDto.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayContactInfoReqDto.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayEntryReqDto.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayImageUploadReqDto.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayQualificationsReqDto.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipaySettleRuleReqDto.java
create mode 100644 cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipaySitesReqDto.java
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/CommonUtil.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/CommonUtil.java
new file mode 100644
index 000000000..19ab6599b
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/CommonUtil.java
@@ -0,0 +1,41 @@
+package com.czg;
+
+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 2026/1/4 13:58
+ */
+@Slf4j
+public class CommonUtil {
+ /**
+ * 下载图片
+ * @param url 图片地址
+ * @return 图片字节数组
+ */
+ public static byte[] downloadImage(String url) {
+ HttpClient client = HttpClient.newHttpClient();
+ HttpRequest request = HttpRequest.newBuilder()
+ .uri(URI.create(url))
+ .GET()
+ .build();
+
+ try {
+ 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();
+ } catch (Exception e) {
+ log.error("Failed to download image: {}", e.getMessage());
+ return new byte[0];
+ }
+ }
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayClient.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayClient.java
new file mode 100644
index 000000000..44991f37e
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayClient.java
@@ -0,0 +1,31 @@
+package com.czg.alipay;
+
+import com.alipay.v3.ApiClient;
+import com.alipay.v3.Configuration;
+import com.alipay.v3.util.model.AlipayConfig;
+import com.czg.alipay.dto.config.AlipayConfigDto;
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author yjjie
+ * @date 2026/1/4 13:48
+ */
+@Slf4j
+public class AlipayClient {
+
+ public static void setupAlipayConfig(AlipayConfigDto configDto) {
+ try {
+ ApiClient defaultClient = Configuration.getDefaultApiClient();
+ // 初始化alipay参数(全局设置一次)
+ AlipayConfig alipayConfig = new AlipayConfig();
+ alipayConfig.setServerUrl(configDto.getDomain());
+ alipayConfig.setAppId(configDto.getAppId());
+ alipayConfig.setAlipayPublicKey(configDto.getAlipayPublicKey());
+ alipayConfig.setPrivateKey(configDto.getPrivateKey());
+ defaultClient.setAlipayConfig(alipayConfig);
+ } catch (Exception e) {
+ log.error("初始化alipay参数异常", e);
+ }
+
+ }
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayEntryManager.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayEntryManager.java
index 74fc03406..ddce4f17a 100644
--- a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayEntryManager.java
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/AlipayEntryManager.java
@@ -3,24 +3,61 @@ package com.czg.alipay;
import com.alipay.v3.ApiClient;
import com.alipay.v3.ApiException;
import com.alipay.v3.Configuration;
+import com.alipay.v3.api.AlipayMerchantImageApi;
import com.alipay.v3.api.AlipayOpenAgentApi;
-import com.alipay.v3.model.AlipayOpenAgentCreateDefaultResponse;
-import com.alipay.v3.model.AlipayOpenAgentCreateModel;
-import com.alipay.v3.model.AlipayOpenAgentCreateResponseModel;
-import com.alipay.v3.model.ContactModel;
+import com.alipay.v3.model.*;
import com.alipay.v3.util.model.AlipayConfig;
+import com.czg.CommonUtil;
+import com.czg.alipay.dto.config.AlipayConfigDto;
+import com.czg.alipay.dto.entry.AlipayImageUploadReqDto;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.File;
/**
* 支付宝进件管理
*
* ...
+ *
* @author yjjie
* @date 2025/12/29 14:11
*/
+@Slf4j
public class AlipayEntryManager {
+ public static String uploadImage() {
+
+ byte[] bytes = CommonUtil.downloadImage("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png");
+
+ File file = new File("/Users/yjjie/Desktop/111222.jpg");
+
+ AlipayMerchantImageApi api = new AlipayMerchantImageApi();
+
+ AlipayMerchantImageUploadModel model = new AlipayMerchantImageUploadModel();
+ model.setImageType("jpg");
+ try {
+ AlipayMerchantImageUploadResponseModel upload = api.upload(model, file);
+ return upload.getImageId();
+ } catch (ApiException e) {
+ log.error("支付宝上传图片报错,URL:{},错误信息:{}", "url", e.getMessage(), e);
+ return "";
+ }
+ }
+
+ public static void main(String[] args) {
+ AlipayConfigDto configDto = new AlipayConfigDto()
+ .setDomain("https://openapi.alipay.com")
+ .setAppId("2021004174605036")
+ .setPrivateKey("MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQD48HaUoV7OH7os+9L01kHgxzwIhJick4OkFq4aHsntsXEJ J3gedhuEZtV8oHKZ30DPW12IJ4S8NXtpr8OWaqrAPFonf4wVaRY1d0yIAea57kfLEn9oOEEy4FzARgMNDkyxC+/3OUdGbLHpTjfVX3gusXsEhUDy1/WewihAkoNYF37+W3W/uVLzeWoPq0EcUbRv/G/t/p6gL69ltsMAiVFG4Q/Yk24YAN6lYgBPNLXUEwQ1Q+T+1omjfavHgvarKOp33z3JOUH+aGOmDsJ5Y9gyGtJzOCipAd8Zcv+T1ygsEzZYO1/gzcbPnfO1ShqStCHzssuw8FBVx2JdfQKXKMMNAgMBAAECggEAVTrO/pg5Q00titU1Jspsh67u6OOs9H605Ws2dI7yB8VmtAGlaJh7V1t14FN2qSP8poHbhhAxq9aLyGV7C3a9u09udnN+3J28EtYjh7VO732bavWMVXxdJjQWzWWrCb9JlpxFrlkYBA6W4w/6ob0sAqCVQ7jzwbEa0R4cde8ztOa5nysKSfr4YTSs0gqvoiC6fmg8eiRJraEQBoYz9VkKFtOhhh/4w5FhVcYQ2gQvZ3kK3QVuD1eJIQKlCtz8qaox9lXKDiZT4SCmnKshdUL0u5TYIcYeBjZmhJz0Q50KHcpZrCs5y7I0+vRBH3hU+TKSQt7ureymwhbwWMHScLV2gQKBgQD+58SHXhr5M8NGagAmTdsgmCnNv2kOYMd4STyPMY10SVwCv1Bk808ZuP+7e558J1b5/OuDLI5dLq6xrZ/1wLv1G++XqxI00hlFuWS5mUGJVcXotT1mw20rVeUILc7Qe3mLvbMGgfyKf4A7Qa5SSZ4bDeDTJYaFxyiQ281hMzDuPQKBgQD6AiL/Na2/uPH4CG6juwpjYvYVUcjK+7gbRwf3wWsWMpk90Z4ju2iUiP5c1J/oK9P+1T3PIr6M4Xjza8JJj+r9KC/PVB0gBv6vVM96cDpKUEy/UMpcn/T81vqj/Z+WEOODU8Ms6NiTTm+u9ldvpCjbu0u8M+9c0JeIyadJvSTFEQKBgQCsxmFyM3nq8YfpgU2qqNjfBeRH3faSVUy+nj1a/YZYjKS+A/i1BCnYUImeBVNN6chNV342ggvY4xxruDiU9Vcw8wd58O09Oi8BEIFSP6upL6cebUI6Fjo3xlegLJRiwV6INkNTJOYM5hD/mSxUACwXQFfkJipBINXBIgraWD1RLQKBgQCj49axWq0F6+WjZVOyPaD3uh37p9trRUxRhWTxw3fB23WdktaKMgbCqHOmwzP4bRLSEVQtf2dOz1gMqu14b8HqJvgAf/F/11YJ9hz09LEhmjZVjE68HZfqT7uK2W5OX8/lfXmK7TFcj6SjG5YB96lZMhTZ0WnufEd6QkdKDZYXIQKBgQD9GDTcIMbFwbEaKHnfZaTD3f876EGRgsgrCxwdEk7LBCRPwWo7yI929M4psIlpNwNeiyjBkBunWIVkpznp6qPtJqagIPUYesU4f5v6/okq5wcpaNKSkWbIvWVLaLGOiA1aeGJtbpMpyClbSr52puHpRRdvAiIEQ74yYh0JX8q96g==")
+ .setAlipayPublicKey("MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAiQkrz+emAuS1mB3KKDOMmAZRd/BlPbh7fAIHAqAj1+QCZNcV3o2BTLIIqnuKpSlFXDG3uDzp2VsBxcizXuBbFyPGylnD9CgCj5abyh3+FIHPAZ2IM3TtpqImZ0TSPGXrMli4Nir7MvZktgccCqQKCC4o6iaDGz+UwWwJUIPna8fm2tiTZ+KH150CZbKVj4ZGNpBh5XSV/1dRgyQIV9D/EwSbkZ0n6VgKQLJBi0C2UE3QB17aL1Ir6+gDXIDbknN8O7GUD3aMGdThYdSRUb5wp9CZ5qfV7vCS/CgaRo38nhH3NOzkTL+7v0m1ZDHPmqEkn9VzZN6sCQdL7PoAOjHOCwIDAQAB");
+ AlipayClient.setupAlipayConfig(configDto);
+
+ String image = uploadImage();
+ System.out.println("image id = " + image);
+ }
+
// https://opendocs.alipay.com/solution/0dec7x?pathHash=caec4753 直付通
- public static void main(String[] args) throws ApiException {
+ public static void test() throws ApiException {
ApiClient defaultClient = Configuration.getDefaultApiClient();
// 初始化alipay参数(全局设置一次)
AlipayConfig alipayConfig = new AlipayConfig();
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/AlipayCreateContactInfoDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/AlipayCreateContactInfoDto.java
deleted file mode 100644
index 313506dcd..000000000
--- a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/AlipayCreateContactInfoDto.java
+++ /dev/null
@@ -1,34 +0,0 @@
-package com.czg.alipay.dto;
-
-import com.alibaba.fastjson2.annotation.JSONField;
-import lombok.Data;
-
-/**
- * 联系人信息
- * @author yjjie
- * @date 2025/12/29 14:21
- */
-@Data
-public class AlipayCreateContactInfoDto {
-
- /**
- * 【必填】
- * 联系人名称
- */
- @JSONField(name = "contact_name")
- private String contactName;
-
- /**
- * 【必填】
- * 联系人手机号
- */
- @JSONField(name = "contact_mobile")
- private String contactMobile;
-
- /**
- * 【选填】
- * 联系人邮箱
- */
- @JSONField(name = "contact_email")
- private String contactEmail;
-}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/AlipayCreateDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/AlipayCreateDto.java
deleted file mode 100644
index a9f9edd76..000000000
--- a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/AlipayCreateDto.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package com.czg.alipay.dto;
-
-import com.alibaba.fastjson2.annotation.JSONField;
-import lombok.Data;
-
-/**
- * 开启代商户签约、创建应用事务
- * 在 ISV 代商户进行应用创建、产品签约时,用于开启一个操作事务,必须是第一个调用的接口。
- * 场景1:ISV 代商户进行应用创建、产品签约,最后提交事务后需要商户确认才能完成流程;
- * 场景2:服务市场订购及授权,使用订单授权凭证order_ticket开启预授权模式,该模式下提交事务后无需商户确认。
- * @author yjjie
- * @date 2025/12/29 14:19
- */
-@Data
-public class AlipayCreateDto {
-
- /**
- * 【必填】
- * isv代操作的商户账号,可以是支付宝账号,也可以是pid(2088开头)
- */
- @JSONField(name = "account")
- private String account;
-
- /**
- * 【必填】
- * 商户联系人信息,包含联系人名称、手机、邮箱信息。联系人信息将用于接受签约后的重要通知,如确认协议、到期提醒等。
- */
- @JSONField(name = "contact_info")
- private AlipayCreateContactInfoDto contactInfo;
-
- /**
- * 【选填】
- * 订单授权凭证。若传入本参数,则对应事务提交后进入预授权模式。
- */
- @JSONField(name = "order_ticket")
- private String orderTicket;
-}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/config/AlipayConfigDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/config/AlipayConfigDto.java
new file mode 100644
index 000000000..a39bd5478
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/config/AlipayConfigDto.java
@@ -0,0 +1,34 @@
+package com.czg.alipay.dto.config;
+
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * @author yjjie
+ * @date 2026/1/4 13:49
+ */
+@Data
+@Accessors(chain = true)
+public class AlipayConfigDto {
+
+ /**
+ * 支付宝 AppId
+ */
+ private String appId;
+
+ /**
+ * 商户私钥
+ */
+ private String privateKey;
+
+ /**
+ * 支付宝公钥
+ */
+ private String alipayPublicKey;
+
+ /**
+ * 支付宝支付域名
+ *
+ */
+ private String domain;
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayAddressReqDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayAddressReqDto.java
new file mode 100644
index 000000000..349d690eb
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayAddressReqDto.java
@@ -0,0 +1,43 @@
+package com.czg.alipay.dto.entry;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+/**
+ * 经营地址
+ * @author yjjie
+ * @date 2026/1/4 11:20
+ */
+@Data
+public class AlipayAddressReqDto {
+
+ /**
+ * 【必填】
+ * 城市编码
+ * 蚂蚁店铺请按照蚂蚁店铺地区码 表格中填写。
+ * 直付通商户请按照直付通商户地区码 表格中内容填写。
+ */
+ @JSONField(name = "city_code")
+ private String cityCode;
+
+ /**
+ * 【必填】
+ * 区县编码
+ */
+ @JSONField(name = "district_code")
+ private String districtCode;
+
+ /**
+ * 【必填】
+ * 详细地址
+ */
+ @JSONField(name = "address")
+ private String address;
+
+ /**
+ * 【必填】
+ * 省份编码
+ */
+ @JSONField(name = "province_code")
+ private String provinceCode;
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayBizCardsReqDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayBizCardsReqDto.java
new file mode 100644
index 000000000..319fbdb2a
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayBizCardsReqDto.java
@@ -0,0 +1,89 @@
+package com.czg.alipay.dto.entry;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+/**
+ * 结算银行卡信息
+ * @author yjjie
+ * @date 2026/1/4 11:14
+ */
+@Data
+public class AlipayBizCardsReqDto {
+
+ /**
+ * 【必填】
+ * 开户支行名
+ */
+ @JSONField(name = "account_branch_name")
+ private String accountBranchName;
+
+ /**
+ * 【必填】
+ * 卡户名
+ */
+ @JSONField(name = "account_holder_name")
+ private String accountHolderName;
+
+ /**
+ * 【必填】
+ * 开户行所在地-省
+ */
+ @JSONField(name = "account_inst_province")
+ private String accountInstProvince;
+
+ /**
+ * 【必填】
+ * 开户行所在地-市
+ */
+ @JSONField(name = "account_inst_city")
+ private String accountInstCity;
+
+ /**
+ * 【必填】
+ * 开户行简称缩写
+ */
+ @JSONField(name = "account_inst_id")
+ private String accountInstId;
+
+ /**
+ * 【必填】
+ * 银行名称
+ */
+ @JSONField(name = "account_inst_name")
+ private String accountInstName;
+
+ /**
+ * 【必填】
+ * 银行卡号
+ */
+ @JSONField(name = "account_no")
+ private String accountNo;
+
+ /**
+ * 【必填】
+ * 银行卡类型
+ * 【枚举值】
+ * 借记卡: DC
+ * 信用卡: CC
+ */
+ @JSONField(name = "account_type")
+ private String accountType;
+
+ /**
+ * 【必填】
+ * 账号使用类型
+ * 【枚举值】
+ * 对公: 01
+ * 对私: 02
+ */
+ @JSONField(name = "usage_type")
+ private String usageType;
+
+ /**
+ * 【选填】
+ * 联行号
+ */
+ @JSONField(name = "bank_code")
+ private String bankCode;
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayContactInfoReqDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayContactInfoReqDto.java
new file mode 100644
index 000000000..c29dc6ff0
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayContactInfoReqDto.java
@@ -0,0 +1,50 @@
+package com.czg.alipay.dto.entry;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+/**
+ * 商户联系人信息
+ * @author yjjie
+ * @date 2026/1/4 11:02
+ */
+@Data
+public class AlipayContactInfoReqDto {
+ /**
+ * 【必填】
+ * 联系人名字
+ */
+ @JSONField(name = "name")
+ private String name;
+
+ /**
+ * 【必填】
+ * email | mobile | phone 三选一
+ * 电子邮箱
+ */
+ @JSONField(name = "email")
+ private String email;
+
+ /**
+ * 【必填】
+ * email | mobile | phone 三选一
+ * 手机号码
+ */
+ @JSONField(name = "mobile")
+ private String mobile;
+
+ /**
+ * 【必填】
+ * email | mobile | phone 三选一
+ * 电话
+ */
+ @JSONField(name = "phone")
+ private String phone;
+
+ /**
+ * 【必填】
+ * 身份证号
+ */
+ @JSONField(name = "id_card_no")
+ private String idCardNo;
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayEntryReqDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayEntryReqDto.java
new file mode 100644
index 000000000..46fded03d
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayEntryReqDto.java
@@ -0,0 +1,249 @@
+package com.czg.alipay.dto.entry;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 平台商提交二级商户资料进行进件,完成二级商户入驻
+ * ...
+ * @author yjjie
+ * @date 2025/12/29 14:19
+ */
+@Data
+public class AlipayEntryReqDto {
+
+ /**
+ * 【必填】
+ * 商户编号,由一级商户定义,保证在一级商户下唯一即可
+ */
+ @JSONField(name = "external_id")
+ private String externalId;
+
+ /**
+ * 【必填】
+ * 商户别名。支付宝收银台及账单中的商户名称会展示此处设置的别名。如果涉及支付宝APP内的支付,支付结果页也会展示该别名;如果涉及线下当面付场景,请填写线下店铺名称
+ */
+ @JSONField(name = "alias_name")
+ private String aliasName;
+
+ /**
+ * 【必填】
+ * 商户联系人信息。在本业务中,ContactInfo对象中联系人姓名、手机号必填,其他选填
+ */
+ @JSONField(name = "contact_infos")
+ private AlipayContactInfoReqDto contactInfo;
+
+ /**
+ * 【必填】
+ * 默认结算规则。当调用收单接口,settle_info中设置默认结算规则(defaultSettle)时,交易资金将结算至此处设置的默认结算目标账户中。其详细描述及收单接口传参示例参考功能包文档
+ */
+ @JSONField(name = "default_settle_rule")
+ private AlipaySettleRuleReqDto defaultSettleRule;
+
+ /**
+ * 【必填】
+ * 商户使用服务
+ * 可选值有:当面付、jsapi支付、app支付、wap支付、电脑支付、预授权支付、商户代扣、小程序支付、订单码支付。其值会影响其他字段必填性,详见其他字段描述
+ * 当面付: 当面付
+ * jsapi支付: jsapi支付
+ * app支付: app支付
+ * wap支付: wap支付
+ * 电脑支付: 电脑支付
+ * 预授权支付: 预授权支付
+ * 商户代扣: 商户代扣
+ * 小程序支付: 小程序支付
+ * 订单码支付: 订单码支付
+ */
+ @JSONField(name = "service")
+ private List service;
+
+ /**
+ * 【必填】
+ * 商户证件编号
+ * 按商户类型merchant_type的说明提供对应的证件编号
+ */
+ @JSONField(name = "cert_no")
+ private String certNo;
+
+ /**
+ * 【必填】
+ * 商户类别码 mcc
+ * ...
+ * 可查看 进件MCC与资质要求 202212.xlsx,特殊行业要按照MCC说明中的资质一栏上传辅助资质,辅助资质要在 qualifications 中上传,会有人工审核。
+ * 【示例值】B0007
+ */
+ @JSONField(name = "mcc")
+ private String mcc;
+
+ /**
+ * 【选填】
+ * 结算支付宝账号
+ * 结算账号使用支付宝账号时必填,本字段指定交易资金结算的具体支付宝账号,与binding_alipay_logon_id同主体的支付宝账号即可
+ */
+ @JSONField(name = "alipay_logon_id")
+ private String alipayLogonId;
+
+ /**
+ * 【选填】
+ * 法人名称
+ * 非个人商户类型必填
+ */
+ @JSONField(name = "legal_name")
+ private String legalName;
+
+ /**
+ * 【选填】
+ * 法人证件编号
+ * 法人证件编号,非个人商户类型必填
+ */
+ @JSONField(name = "legal_cert_no")
+ private String legalCertNo;
+
+ /**
+ * 【选填】
+ * 商户证件图
+ * 目前只有当商户类型是个人商户且使用当面付服务时才需填写
+ */
+ @JSONField(name = "cert_image_back")
+ private String certImageBack;
+
+ /**
+ * 【选填】
+ * 商户证件图片
+ * 本业务接口中,如果是特殊行业必填;使用当面付服务时,非个人必填,个人结算到卡时必填。其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key。
+ */
+ @JSONField(name = "cert_image")
+ private String certImage;
+
+ /**
+ * 【选填】
+ * 进件的二级商户名称
+ * 一般情况下要与证件的名称相同。个体工商户类型可以放宽到法人名称
+ */
+ @JSONField(name = "name")
+ private String name;
+
+ /**
+ * 【选填】
+ * 法人证件类型
+ * 默认可不填,认为legal_cert_no是大陆身份证。类型包括:100 大陆身份证;105 港澳居民往来内地通行证;106 台湾同胞往来大陆通行证;108 外国人居留证
+ * 【枚举值】
+ * 大陆身份证: 100
+ * 港澳居民往来内地通行证: 105
+ * 台湾同胞往来大陆通行证: 106
+ * 外国人居留证: 108
+ */
+ @JSONField(name = "legal_cert_type")
+ private String legalCertType;
+
+ /**
+ * 【选填】
+ * 商户类型
+ * 01:企业;cert_type填写201(营业执照);cert_no填写营业执照号;
+ * 02:事业单位:cert_type填写218(事业单位法人证书);cert_no填写事业单位法人证书编号;
+ * 03:民办非企业组织:cert_type填写204(民办非企业登记证书);cert_no填写民办非企业登记证书编号;
+ * 04:社会团体:cert_type填写206(社会团体法人登记证书);cert_no填写社会团体法人登记证书编号;
+ * 05:党政及国家机关:cert_type填写219(党政机关批准设立文件/行政执法主体资格证);cert_no填写党政机关批准设立文件/行政执法主体资格证编号;
+ * 06:个人商户:cert_type填写100(个人身份证);cert_no填写个人身份证号码;
+ * 07:个体工商户:cert_type填写201(营业执照);cert_no填写营业执照编号;
+ */
+ @JSONField(name = "merchant_type")
+ private String merchantType;
+
+ /**
+ * 【选填】
+ * 商户证件类型
+ * 按商户类型merchant_type的说明提供对应的证件类型。
+ * 营业执照: 201
+ * 事业单位法人证书: 218
+ * 民办非企业登记证书: 204
+ * 社会团体法人登记证书: 206
+ * 党政机关批准设立文件/行政执法主体资格证: 219
+ * 个人身份证: 100
+ */
+ @JSONField(name = "cert_type")
+ private String certType;
+
+ /**
+ * 【选填】
+ * 证件名称
+ * 目前只有个体工商户商户类型要求填入本字段,填写值为个体工商户营业执照上的名称
+ */
+ @JSONField(name = "cert_name")
+ private String certName;
+
+ /**
+ * 【选填】
+ * 结算银行卡信息
+ * 结算银行卡信息,结算账号使用银行卡时必填。本业务当前只允许传入一张结算卡。个人类型商户不允许结算到银行卡
+ * 【必选条件】结算银行卡信息,结算账号使用银行卡时必填。本业务当前只允许传入一张结算卡。个人类型商户不允许结算到银行卡
+ */
+ @JSONField(name = "biz_cards")
+ private AlipayBizCardsReqDto bizCards;
+
+ /**
+ * 【选填】
+ * 经营地址
+ * 使用当面付服务时必填。地址对象中省、市、区、地址必填,其余选填
+ */
+ @JSONField(name = "business_address")
+ private AlipayAddressReqDto businessAddress;
+
+ /**
+ * 【选填】
+ * 门头照
+ * 使用当面付服务时必填。其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key
+ */
+ @JSONField(name = "out_door_images")
+ private String outDoorImages;
+
+ /**
+ * 【选填】
+ * 内景照
+ * 使用当面付服务时必填。其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key
+ */
+ @JSONField(name = "in_door_images")
+ private String inDoorImages;
+
+ /**
+ * 【选填】
+ * 授权函
+ * 《说明函》模板参考
+ * 当商户名与结算卡户名不一致。《说明函》模板参考。涉及外籍法人(这种情况上传任意能证明身份的图片)时必填,
+ * 其值为使用ant.merchant.expand.indirect.image.upload上传图片得到的一串oss key。(商户类型为个体工商户时,本字段仅需上传营业执照非授权函)
+ */
+ @JSONField(name = "license_auth_letter_image")
+ private String licenseAuthLetterImage;
+
+ /**
+ * 【选填】
+ * 商户站点信息
+ * 包括网站、app、小程序。商户使用服务包含电脑支付、wap支付时,必须填充一个类型为01(网站)的SiteInfo对象,site_type/site_url/site_name必填;
+ * 当包含app支付时,必须至少填充类型为02(APP)或06(支付宝小程序)中一种类型的SiteInfo对象,site_type/site_name必填;当包含jsapi支付时,必须填充一个类型为06(支付宝小程序)的SiteInfo对象;
+ */
+ @JSONField(name = "sites")
+ private AlipaySitesReqDto sites;
+
+ /**
+ * 【选填】
+ * 商户行业资质图片
+ * 当商户的经营类目选择了特殊行业时该字段必填,需要特殊行业资质文件。每项行业资质信息中,industry_qualification_type和industry_qualification_image均必填。
+ */
+ @JSONField(name = "qualifications")
+ private List qualifications;
+
+ /**
+ * 【选填】
+ * 交易场景
+ * 【枚举值】
+ * 小程序支付场景: TINY_APP
+ * H5场景: WAP
+ * 线下当面付场景: OFFLINE
+ * APP支付场景: APP
+ * 网站支付场景: PC
+ */
+ @JSONField(name = "trade_scene")
+ private List tradeScene;
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayImageUploadReqDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayImageUploadReqDto.java
new file mode 100644
index 000000000..a2abcc34e
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayImageUploadReqDto.java
@@ -0,0 +1,31 @@
+package com.czg.alipay.dto.entry;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+import lombok.experimental.Accessors;
+
+/**
+ * 图片上传
+ * @author yjjie
+ * @date 2026/1/4 13:46
+ */
+@Data
+@Accessors(chain = true)
+public class AlipayImageUploadReqDto {
+
+ /**
+ * 【必填】
+ * 图片格式
+ * 支持格式:bmp、jpg、jpeg、png、gif.
+ */
+ @JSONField(name = "image_type")
+ private String imageType;
+
+ /**
+ * 【必填】
+ * 图片二进制字节流
+ * 最大为10M
+ */
+ @JSONField(name = "image_content")
+ private byte[] imageContent;
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayQualificationsReqDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayQualificationsReqDto.java
new file mode 100644
index 000000000..6e4190027
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipayQualificationsReqDto.java
@@ -0,0 +1,30 @@
+package com.czg.alipay.dto.entry;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+/**
+ * 商户行业资质
+ * @author yjjie
+ * @date 2026/1/4 11:40
+ */
+@Data
+public class AlipayQualificationsReqDto {
+
+ /**
+ * 【必填】
+ * 商户行业资质类型 具体选值参见 文档
+ * 【枚举值】
+ * 金融许可证: 323
+ * 【示例值】323
+ */
+ @JSONField(name = "industry_qualification_type")
+ private String industryQualificationType;
+
+ /**
+ * 【必填】
+ * 商户行业资质图片
+ */
+ @JSONField(name = "industry_qualification_image")
+ private String industryQualificationImage;
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipaySettleRuleReqDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipaySettleRuleReqDto.java
new file mode 100644
index 000000000..75881a854
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipaySettleRuleReqDto.java
@@ -0,0 +1,29 @@
+package com.czg.alipay.dto.entry;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+/**
+ * 结算规则
+ * @author yjjie
+ * @date 2026/1/4 11:06
+ */
+@Data
+public class AlipaySettleRuleReqDto {
+
+ /**
+ * 【必填】
+ * 默认结算类型
+ * 可选值有bankCard/alipayAccount。bankCard表示结算到银行卡;alipayAccount表示结算到支付宝账号
+ */
+ @JSONField(name = "default_settle_type")
+ private String defaultSettleType;
+
+ /**
+ * 【必填】
+ * 默认结算目标
+ * 当默认结算类型为bankCard时填写银行卡卡号,其值需在进件填写的结算银行卡范围内;当默认结算类型为alipayAccount时填写支付宝账号登录号,其值需在进件填写的结算支付宝账号范围内。
+ */
+ @JSONField(name = "default_settle_target")
+ private String defaultSettleTarget;
+}
diff --git a/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipaySitesReqDto.java b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipaySitesReqDto.java
new file mode 100644
index 000000000..0e88ad25d
--- /dev/null
+++ b/cash-sdk/aggregation-pay/src/main/java/com/czg/alipay/dto/entry/AlipaySitesReqDto.java
@@ -0,0 +1,148 @@
+package com.czg.alipay.dto.entry;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import lombok.Data;
+
+/**
+ * @author yjjie
+ * @date 2026/1/4 11:31
+ */
+@Data
+public class AlipaySitesReqDto {
+
+ /**
+ * 【必填】
+ * 网站类型
+ * 【枚举值】
+ * 网站: 01
+ * APP: 02
+ * 服务窗: 03
+ * 公众号: 04
+ * 其他: 05
+ * 支付宝小程序: 06
+ * 手机网站/H5: 07
+ */
+ @JSONField(name = "site_type")
+ private String siteType;
+
+ /**
+ * 【选填】
+ * 站点地址
+ * 当传入service,且包含jsapi支付时,sites的site_type=06, site_url必填
+ */
+ @JSONField(name = "site_url")
+ private String siteUrl;
+
+ /**
+ * 【选填】
+ * 站点名称
+ * 当传入service,且包含jsapi支付、小程序支付时,sites的site_type=06, site_name必填
+ */
+ @JSONField(name = "site_name")
+ private String siteName;
+
+ /**
+ * 【选填】
+ * 截图照片
+ * 当传入交易场景trade_scene,且当传入trade_scene=WAP、trade_scene=APP、trade_scene=PC时该参数必传
+ */
+ @JSONField(name = "screenshot_image")
+ private String screenshotImage;
+
+ /**
+ * 【选填】
+ * 小程序appId
+ * 当传入service,且包含jsapi支付时,sites的site_type=06, tiny_app_id必填。
+ */
+ @JSONField(name = "tiny_app_id")
+ private String tinyAppId;
+
+ /**
+ * 【选填】
+ * 测试账号
+ */
+ @JSONField(name = "account")
+ private String account;
+
+ /**
+ * 【选填】
+ * 测试账号密码
+ */
+ @JSONField(name = "password")
+ private String password;
+
+ /**
+ * 【选填】
+ * 上架状态
+ * 【枚举值】
+ * 已上线: ONLINE
+ * 已上线-内部: ONLINE_INNER
+ * 未上线: OFFLINE
+ */
+ @JSONField(name = "status")
+ private String status;
+
+ /**
+ * 【选填】
+ * 授权函照片
+ */
+ @JSONField(name = "auth_letter_image")
+ private String authLetterImage;
+
+ /**
+ * 【选填】
+ * 备注说明
+ */
+ @JSONField(name = "remark")
+ private String remark;
+
+ /**
+ * 【选填】
+ * 备注说明图片
+ */
+ @JSONField(name = "remark_image")
+ private String remarkImage;
+
+ /**
+ * 【选填】
+ * 网站域名
+ */
+ @JSONField(name = "site_domain")
+ private String siteDomain;
+
+ /**
+ * 【选填】
+ * ICP备案主体信息服务名称
+ */
+ @JSONField(name = "icp_service_name")
+ private String icpServiceName;
+
+ /**
+ * 【选填】
+ * ICP备案/许可证号
+ */
+ @JSONField(name = "icp_no")
+ private String icpNo;
+
+ /**
+ * 【选填】
+ * ICP备案主体主办单位名称
+ */
+ @JSONField(name = "icp_org_name")
+ private String icpOrgName;
+
+ /**
+ * 【选填】
+ * 下载地址
+ */
+ @JSONField(name = "download")
+ private String download;
+
+ /**
+ * 【选填】
+ * 应用市场
+ * 【示例值】豌豆荚
+ */
+ @JSONField(name = "market")
+ private String market;
+}
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
index 676da7552..43dc5f8f3 100644
--- 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
@@ -2,6 +2,7 @@ package com.czg.wechat;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONWriter;
+import com.czg.CommonUtil;
import com.czg.wechat.dto.config.WechatPayConfigDto;
import com.czg.wechat.dto.req.entry.*;
import com.czg.wechat.dto.req.entry.business.WechatEntryBusinessReqDto;
@@ -67,7 +68,7 @@ public class WechatEntryManager {
try {
// 获取图片字节数组
- byte[] bytes = downloadImage(url);
+ byte[] bytes = CommonUtil.downloadImage(url);
if (bytes.length == 0) {
log.error("下载的图片内容为空,URL:{}", url);
return "";
@@ -98,22 +99,6 @@ public class WechatEntryManager {
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中提取文件名
*
@@ -187,82 +172,82 @@ public class WechatEntryManager {
.setPublicKeyId("PUB_KEY_ID_0116437794082025111000382377001000")
.setDomain("https://api.mch.weixin.qq.com");
- queryBankList(dto, 0, 10);
+// queryBankList(dto, 0, 10);
-// String string = uploadImage(dto, "https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png");
-// log.info("图片上传成功:{}", string);
+ String string = uploadImage(dto, "https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png");
+ log.info("图片上传成功:{}", string);
- Config config = WechatConfig.getRsaConfig(dto);
- PrivacyEncryptor encryptor = config.createEncryptor();
-
- WechatEntryReqDto reqDto = new WechatEntryReqDto()
- .setBusinessCode("MER_20231025110010000010000000000001");
-
- WechatEntryContactReqDto contactInfo = new WechatEntryContactReqDto()
- .setContactType("LEGAL")
- .setContactName(encryptor.encrypt("张三"))
- .setContactIdType("IDCARD")
- .setContactIdNumber(encryptor.encrypt("110101199001011234"))
- .setContactIdDocCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
- .setContactIdDocCopyBack("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
- .setContactPeriodBegin("2023-10-25")
- .setContactPeriodEnd("2024-10-25")
- .setMobilePhone(encryptor.encrypt("13888888888"))
- .setContactEmail(encryptor.encrypt("123456@qq.com"));
-
- reqDto.setContactInfo(contactInfo);
-
- WechatEntrySubjectReqDto subjectInfo = new WechatEntrySubjectReqDto()
- .setSubjectType("SUBJECT_TYPE_INDIVIDUAL");
-
- WechatEntryLicenseReqDto licenseInfo = new WechatEntryLicenseReqDto()
- .setLicenseCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
- .setLicenseNumber("110101199001011234")
- .setMerchantName("张三商行")
- .setLegalPerson(encryptor.encrypt("张三"))
- .setLicenseAddress("北京")
- .setPeriodBegin("2023-10-25")
- .setPeriodEnd("2024-10-25");
- subjectInfo.setBusinessLicenseInfo(licenseInfo);
-
- WechatEntryIdentityReqDto identityInfo = new WechatEntryIdentityReqDto()
- .setIdHolderType("LEGAL");
- subjectInfo.setIdentityInfo(identityInfo);
-
- reqDto.setSubjectInfo(subjectInfo);
-
- WechatEntryBusinessReqDto businessInfo = new WechatEntryBusinessReqDto()
- .setMerchantShortname("张三商行")
- .setServicePhone("13888888888");
- WechatEntrySalesInfoReqDto salesInfo = new WechatEntrySalesInfoReqDto()
- .setSalesScenesType(List.of("SALES_SCENES_STORE"));
- WechatEntryStoreInfoReqDto storeInfo = new WechatEntryStoreInfoReqDto()
- .setBizStoreName("张三商行")
- .setBizAddressCode("110101")
- .setBizStoreAddress("北京")
- .setStoreEntrancePic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"))
- .setIndoorPic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"));
- salesInfo.setBizStoreInfo(storeInfo);
- businessInfo.setSalesInfo(salesInfo);
-
- reqDto.setBusinessInfo(businessInfo);
-
- WechatEntrySettleReqDto settleInfo = new WechatEntrySettleReqDto()
- .setSettlementId("719")
- .setQualificationType("IDCARD")
- .setQualifications(List.of("110101199001011234"))
- .setActivitiesId("20191030111cff5b5e");
-
- reqDto.setSettlementInfo(settleInfo);
-
- WechatEntryBankAccountReqDto bankAccountInfo = new WechatEntryBankAccountReqDto()
- .setBankAccountType("BANK_ACCOUNT_TYPE_CORPORATE")
- .setAccountBank("ICBC")
- .setBankName("中国工商银行")
- .setAccountName(encryptor.encrypt("张三"))
- .setAccountNumber(encryptor.encrypt("110101199001011234"));
-
- reqDto.setBankAccountInfo(bankAccountInfo);
+// Config config = WechatConfig.getRsaConfig(dto);
+// PrivacyEncryptor encryptor = config.createEncryptor();
+//
+// WechatEntryReqDto reqDto = new WechatEntryReqDto()
+// .setBusinessCode("MER_20231025110010000010000000000001");
+//
+// WechatEntryContactReqDto contactInfo = new WechatEntryContactReqDto()
+// .setContactType("LEGAL")
+// .setContactName(encryptor.encrypt("张三"))
+// .setContactIdType("IDCARD")
+// .setContactIdNumber(encryptor.encrypt("110101199001011234"))
+// .setContactIdDocCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
+// .setContactIdDocCopyBack("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
+// .setContactPeriodBegin("2023-10-25")
+// .setContactPeriodEnd("2024-10-25")
+// .setMobilePhone(encryptor.encrypt("13888888888"))
+// .setContactEmail(encryptor.encrypt("123456@qq.com"));
+//
+// reqDto.setContactInfo(contactInfo);
+//
+// WechatEntrySubjectReqDto subjectInfo = new WechatEntrySubjectReqDto()
+// .setSubjectType("SUBJECT_TYPE_INDIVIDUAL");
+//
+// WechatEntryLicenseReqDto licenseInfo = new WechatEntryLicenseReqDto()
+// .setLicenseCopy("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png")
+// .setLicenseNumber("110101199001011234")
+// .setMerchantName("张三商行")
+// .setLegalPerson(encryptor.encrypt("张三"))
+// .setLicenseAddress("北京")
+// .setPeriodBegin("2023-10-25")
+// .setPeriodEnd("2024-10-25");
+// subjectInfo.setBusinessLicenseInfo(licenseInfo);
+//
+// WechatEntryIdentityReqDto identityInfo = new WechatEntryIdentityReqDto()
+// .setIdHolderType("LEGAL");
+// subjectInfo.setIdentityInfo(identityInfo);
+//
+// reqDto.setSubjectInfo(subjectInfo);
+//
+// WechatEntryBusinessReqDto businessInfo = new WechatEntryBusinessReqDto()
+// .setMerchantShortname("张三商行")
+// .setServicePhone("13888888888");
+// WechatEntrySalesInfoReqDto salesInfo = new WechatEntrySalesInfoReqDto()
+// .setSalesScenesType(List.of("SALES_SCENES_STORE"));
+// WechatEntryStoreInfoReqDto storeInfo = new WechatEntryStoreInfoReqDto()
+// .setBizStoreName("张三商行")
+// .setBizAddressCode("110101")
+// .setBizStoreAddress("北京")
+// .setStoreEntrancePic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"))
+// .setIndoorPic(List.of("https://czg-qr-order.oss-cn-beijing.aliyuncs.com/indexs/shuangbackground.png"));
+// salesInfo.setBizStoreInfo(storeInfo);
+// businessInfo.setSalesInfo(salesInfo);
+//
+// reqDto.setBusinessInfo(businessInfo);
+//
+// WechatEntrySettleReqDto settleInfo = new WechatEntrySettleReqDto()
+// .setSettlementId("719")
+// .setQualificationType("IDCARD")
+// .setQualifications(List.of("110101199001011234"))
+// .setActivitiesId("20191030111cff5b5e");
+//
+// reqDto.setSettlementInfo(settleInfo);
+//
+// WechatEntryBankAccountReqDto bankAccountInfo = new WechatEntryBankAccountReqDto()
+// .setBankAccountType("BANK_ACCOUNT_TYPE_CORPORATE")
+// .setAccountBank("ICBC")
+// .setBankName("中国工商银行")
+// .setAccountName(encryptor.encrypt("张三"))
+// .setAccountNumber(encryptor.encrypt("110101199001011234"));
+//
+// reqDto.setBankAccountInfo(bankAccountInfo);
// entryMerchant(dto, reqDto);
}
From 0b02f66fb58dda335db14ed4a4474402a2951707 Mon Sep 17 00:00:00 2001
From: wangw <1594593906@qq.com>
Date: Mon, 5 Jan 2026 09:37:45 +0800
Subject: [PATCH 032/133] =?UTF-8?q?shop=5Fuser=E6=9F=A5=E8=AF=A2=E5=A4=9A?=
=?UTF-8?q?=E4=B8=AA=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../src/main/resources/mapper/ShopUserMapper.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/cash-service/account-service/src/main/resources/mapper/ShopUserMapper.xml b/cash-service/account-service/src/main/resources/mapper/ShopUserMapper.xml
index e7f917f8e..448d425ae 100644
--- a/cash-service/account-service/src/main/resources/mapper/ShopUserMapper.xml
+++ b/cash-service/account-service/src/main/resources/mapper/ShopUserMapper.xml
@@ -98,7 +98,7 @@
AND a.amount >= #{amount}
-
+ group by a.id
ORDER BY a.create_time DESC