This commit is contained in:
2026-01-08 10:49:30 +08:00
parent 21b9acf3c9
commit e5be277941
39 changed files with 1290 additions and 46 deletions

View File

@@ -0,0 +1,75 @@
package com.czg.controller.admin;
import com.czg.EntryManager;
import com.czg.annotation.Debounce;
import com.czg.dto.req.AggregateMerchantDto;
import com.czg.dto.resp.BankBranchDto;
import com.czg.service.order.dto.AggregateMerchantVO;
import com.czg.service.order.service.ShopDirectMerchantService;
import com.czg.resp.CzgResult;
import com.czg.sa.StpKit;
import com.czg.task.EntryManagerTask;
import jakarta.annotation.Resource;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
* 进件管理
*
* @author ww
*/
@AllArgsConstructor
@RestController
@RequestMapping("/admin/data/entryManager")
public class EntryManagerController {
@Resource
private ShopDirectMerchantService shopDirectMerchantService;
@Resource
private EntryManagerTask entryManagerTask;
/**
* 查询银行支行列表
*
* @param province 省份 陕西省 从 /system/admin/common/region获取
* @param city 城市 西安市 从 /system/admin/common/region获取
* @param instId 顶级机构ID CMB 从 /system/admin/common/bankInfo 获取
*/
@GetMapping("bankBranchList")
public CzgResult<List<BankBranchDto>> queryBankBranchList(String province, String city, String instId) {
return CzgResult.success(EntryManager.queryBankBranchList(province, city, instId));
}
/**
* 获取进件信息
*/
@GetMapping
public CzgResult<AggregateMerchantVO> getEntry(Long shopId) {
return CzgResult.success(shopDirectMerchantService.getEntry(shopId));
}
/**
* 主动查询进件信息状态
* 进件状态是INIT 待处理 AUDIT 审核中 SIGN 待签约
* 3分钟内只能查一次
*/
@GetMapping
@Debounce(value = "#shopId", interval = 1000 * 60 * 3)
public CzgResult<Boolean> queryEntry(Long shopId) {
entryManagerTask.entryManager(shopId);
return CzgResult.success();
}
/**
* 申请进件
*/
@Debounce(value = "#reqDto.shopId")
@PostMapping
public CzgResult<Boolean> entryManager(@RequestBody AggregateMerchantDto reqDto) {
return CzgResult.success(shopDirectMerchantService.entryManager(reqDto));
}
}

View File

@@ -0,0 +1,124 @@
package com.czg.mq;
import cn.hutool.core.util.StrUtil;
import com.czg.EntryManager;
import com.czg.PayCst;
import com.czg.config.RabbitConstants;
import com.czg.config.RedisCst;
import com.czg.dto.resp.EntryRespDto;
import com.czg.order.entity.ShopDirectMerchant;
import com.czg.service.RedisService;
import com.czg.service.order.dto.AggregateMerchantVO;
import com.czg.service.order.service.ShopDirectMerchantService;
import com.rabbitmq.client.Channel;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.ThreadContext;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* 打印mq消息处理器
*
* @author Administrator
*/
@Component
@Slf4j
public class EntryManagerMqListener {
@Resource
private RedisService redisService;
@Resource
private ShopDirectMerchantService shopDirectMerchantService;
String key = RedisCst.SHOP_ENTRY;
@RabbitListener(
bindings = @QueueBinding(
value = @Queue(value = "${spring.profiles.active}-" + RabbitConstants.Queue.SHOP_ENTRY_MANAGER,
durable = "true", exclusive = "false", autoDelete = "false"),
exchange = @Exchange(value = "${spring.profiles.active}-" + RabbitConstants.Exchange.CASH_EXCHANGE),
key = "${spring.profiles.active}-" + RabbitConstants.Queue.SHOP_ENTRY_MANAGER
),
concurrency = "5"
)
@RabbitHandler
public void handle(Message message, Channel channel, String msg) throws IOException {
String messageId = message.getMessageProperties().getMessageId();
if (hasMessageId(messageId)) {
return;
}
try {
Long shopId = Long.valueOf(msg);
// 将唯一标识添加到日志上下文
ThreadContext.put("traceId", messageId);
// 安全转换shopId
if (shopId == null) {
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
return;
}
AggregateMerchantVO entry = shopDirectMerchantService.getEntry(Long.valueOf(msg));
if (entry != null) {
EntryManager.uploadParamImage(entry);
List<String> platform = new ArrayList<>();
if (PayCst.EntryStatus.WAIT.equals(entry.getAlipayStatus())) {
platform.add(PayCst.Platform.ALIPAY);
}
if (PayCst.EntryStatus.WAIT.equals(entry.getWechatStatus())) {
platform.add(PayCst.Platform.WECHAT);
}
EntryRespDto resp = EntryManager.entryMerchant(entry, platform.toArray(new String[0]));
ShopDirectMerchant merchant = new ShopDirectMerchant();
merchant.setShopId(entry.getShopId());
merchant.setWechatStatus(resp.getWechatStatus());
merchant.setWechatErrorMsg(resp.getWechatErrorMsg());
merchant.setAlipayStatus(resp.getAlipayStatus());
merchant.setAlipayErrorMsg(resp.getAlipayErrorMsg());
shopDirectMerchantService.updateById(merchant);
}
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
} catch (Exception e) {
log.error("进件MQ对接业务异常shopId:{}", msg, e);
ShopDirectMerchant merchant = new ShopDirectMerchant();
merchant.setShopId(Long.valueOf(msg));
merchant.setWechatStatus(PayCst.EntryStatus.REJECTED);
merchant.setAlipayStatus(PayCst.EntryStatus.REJECTED);
merchant.setErrorMsg("系统错误,请联系管理员后重试。");
shopDirectMerchantService.updateById(merchant);
channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
} finally {
delMessageId(messageId);
// 清除日志上下文信息
ThreadContext.remove("messageId");
}
}
public boolean hasMessageId(String messageId) {
if (!redisService.hasKey(key)) {
if (StrUtil.isNotBlank(messageId)) {
redisService.leftPush(key, messageId);
return false;
} else {
return true;
}
}
List<Object> list = redisService.lGet(key, 0, -1);
if (!list.contains(messageId)) {
redisService.leftPush(key, messageId);
return false;
}
return true;
}
public void delMessageId(String messageId) {
redisService.lRemove(key, 0, messageId);
}
}

View File

@@ -29,18 +29,14 @@ public class PrintMqListener {
private MqLogService mqLogService;
@Resource
private FunUtil funUtil;
// 注入自定义线程池(建议单独配置,避免使用默认线程池)
@Resource
private ThreadPoolTaskExecutor asyncExecutor;
@Lazy
@Resource
private PrinterHandler printerHandler;
private <T> void invokeFun(String type, String plat, T data, Consumer<T> consumer) {
private <T> void invokeFun(String queue, String type, String plat, T data, Consumer<T> consumer) {
long startTime = DateUtil.date().getTime();
log.info("接收到{}打印消息:{}", type, data);
MqLog mqLog = new MqLog().setQueue(RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE).setMsg(data.toString())
MqLog mqLog = new MqLog().setQueue(queue).setMsg(data.toString())
.setType(type).setPlat(plat).setCreateTime(DateUtil.date().toLocalDateTime());
try {
consumer.accept(data);
@@ -56,7 +52,7 @@ public class PrintMqListener {
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE})
public void orderPrint(String req) {
// 执行核心打印逻辑
invokeFun("orderPrint", "java.order", req, (data) -> {
invokeFun(RabbitConstants.Queue.ORDER_MACHINE_PRINT_QUEUE, "orderPrint", "java.order", req, (data) -> {
JSONObject jsonObject = JSONObject.parseObject(data);
String orderId = jsonObject.getString("orderId");
if (orderId == null) {
@@ -68,33 +64,6 @@ public class PrintMqListener {
return null;
}, RedisCst.getLockKey("orderPrint", orderId));
});
// // 使用异步线程池执行延迟任务,不阻塞当前消费者线程
// CompletableFuture.runAsync(() -> {
// try {
// // 延迟3秒处理
// TimeUnit.SECONDS.sleep(3);
// // 执行核心打印逻辑
// invokeFun("orderPrint", "java.order", req, (data) -> {
// JSONObject jsonObject = JSONObject.parseObject(data);
// String orderId = jsonObject.getString("orderId");
// if (orderId == null) {
// throw new RuntimeException("订单打印失败未传递orderId");
// }
// Boolean printOrder = jsonObject.getBoolean("printOrder");
// funUtil.runFunAndCheckKey(() -> {
// printerHandler.handler(orderId, printOrder != null && !printOrder ? PrinterHandler.PrintTypeEnum.ONE : PrinterHandler.PrintTypeEnum.ONE_AND_ORDER);
// return null;
// }, RedisCst.getLockKey("orderPrint", orderId));
// });
// } catch (InterruptedException e) {
// Thread.currentThread().interrupt();
// // 记录中断日志
// log.warn("打印任务被中断req:{}", req, e);
// } catch (Exception e) {
// // 记录业务异常日志
// log.error("打印任务处理失败req:{}", req, e);
// }
// }, asyncExecutor);
}
/**
@@ -102,14 +71,16 @@ public class PrintMqListener {
*/
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE})
public void handoverPrint(String id) {
invokeFun("handoverPrint", "java.order", id, (data) -> printerHandler.handler(data, PrinterHandler.PrintTypeEnum.HANDOVER));
invokeFun(RabbitConstants.Queue.ORDER_HANDOVER_PRINT_QUEUE, "handoverPrint", "java.order", id, (data) ->
printerHandler.handler(data, PrinterHandler.PrintTypeEnum.HANDOVER));
}
/**
* 交班打印
* 叫号打印
*/
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.CALL_TABLE_PRINT_QUEUE})
@RabbitListener(queues = {"${spring.profiles.active}-" + RabbitConstants.Queue.CALL_TABLE_QUEUE})
public void callTablePrint(String id) {
invokeFun("handoverPrint", "java.order", id, (data) -> printerHandler.handler(data, PrinterHandler.PrintTypeEnum.CALL));
invokeFun(RabbitConstants.Queue.CALL_TABLE_QUEUE, "callTable", "java.order", id, (data) ->
printerHandler.handler(data, PrinterHandler.PrintTypeEnum.CALL));
}
}

View File

@@ -0,0 +1,87 @@
package com.czg.task;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.czg.EntryManager;
import com.czg.PayCst;
import com.czg.account.entity.ShopInfo;
import com.czg.account.service.ShopInfoService;
import com.czg.dto.resp.QueryStatusResp;
import com.czg.order.entity.ShopDirectMerchant;
import com.czg.order.service.ShopOrderStatisticService;
import com.czg.order.service.ShopProdStatisticService;
import com.czg.order.service.ShopTableOrderStatisticService;
import com.czg.service.RedisService;
import com.czg.service.order.service.ShopDirectMerchantService;
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.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;
/**
* 进件查询
*
* @author ww
*/
@Component
@Slf4j
public class EntryManagerTask {
@Resource
private ShopDirectMerchantService shopDirectMerchantService;
@DubboReference
private ShopInfoService shopInfoService;
//每10分钟查一次
@Scheduled(cron = "0 0/10 * * * ? ")
public void run() {
log.info("进件查询,定时任务执行");
long start = System.currentTimeMillis();
entryManager(null);
log.info("进件查询,定时任务执行完毕,耗时:{}ms", start - System.currentTimeMillis());
}
/**
* 查询状态为待处理、待签约、待审核的进件
*/
public void entryManager(Long shopId) {
List<ShopDirectMerchant> list = shopDirectMerchantService.list(QueryWrapper.create()
.eq(ShopDirectMerchant::getShopId, shopId)
.in(ShopDirectMerchant::getWechatStatus, PayCst.EntryStatus.NEED_QUERY_LIST)
.or(ShopDirectMerchant::getAlipayStatus).in(PayCst.EntryStatus.NEED_QUERY_LIST));
if (CollUtil.isEmpty(list)) {
return;
}
for (ShopDirectMerchant shopDirectMerchant : list) {
String wechatMerchantId = "";
String alipayMerchantId = "";
if (PayCst.EntryStatus.NEED_QUERY_LIST.contains(shopDirectMerchant.getWechatStatus())) {
QueryStatusResp wechatStatus = EntryManager.queryWechatEntryStatus(shopDirectMerchant.getMerchantCode());
shopDirectMerchant.setWechatStatus(wechatStatus.getStatus());
shopDirectMerchant.setWechatErrorMsg(wechatStatus.getFailReason());
shopDirectMerchant.setWechatSignUrl(wechatStatus.getSignUrl());
if (PayCst.EntryStatus.FINISH.equals(wechatStatus.getStatus())) {
wechatMerchantId = wechatStatus.getThirdMerchantId();
}
}
if (PayCst.EntryStatus.NEED_QUERY_LIST.contains(shopDirectMerchant.getAlipayStatus())) {
QueryStatusResp alipayStatus = EntryManager.queryAlipayEntryStatus(shopDirectMerchant.getMerchantCode());
shopDirectMerchant.setAlipayStatus(alipayStatus.getStatus());
shopDirectMerchant.setAlipayErrorMsg(alipayStatus.getFailReason());
shopDirectMerchant.setAlipaySignUrl(alipayStatus.getSignUrl());
if (PayCst.EntryStatus.FINISH.equals(alipayStatus.getStatus())) {
alipayMerchantId = alipayStatus.getThirdMerchantId();
}
}
shopDirectMerchantService.updateById(shopDirectMerchant);
if (StrUtil.isNotBlank(wechatMerchantId) || StrUtil.isNotBlank(alipayMerchantId)) {
shopInfoService.editEntry(shopDirectMerchant.getShopId(), wechatMerchantId, alipayMerchantId);
}
}
}
}

View File

@@ -28,6 +28,7 @@ import java.util.List;
/**
* 订单过期处理
* 退款失败 补偿
*
* @author ww
*/