From b4d10a7306825c0180d1e9d3f3dc524f7db096d0 Mon Sep 17 00:00:00 2001 From: JIAN Date: Thu, 19 Sep 2024 19:46:10 +0800 Subject: [PATCH] =?UTF-8?q?feat(health):=E6=96=B0=E5=A2=9E=E5=BB=B6?= =?UTF-8?q?=E6=97=B6=E9=98=9F=E5=88=97=E5=A4=84=E7=90=86=E8=B6=85=E6=97=B6?= =?UTF-8?q?=E8=AE=A2=E5=8D=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jzo2o-health/pom.xml | 6 +- .../config/DelayQueueConfiguration.java | 61 ++++++++++++++++++ .../health/constant/HealthMqConstants.java | 23 +++++++ .../health/listener/OrderStatusListener.java | 62 +++++++++++++++++-- .../service/impl/OrderCreateServiceImpl.java | 6 ++ .../impl/ReservationSettingServiceImpl.java | 2 +- 6 files changed, 152 insertions(+), 8 deletions(-) create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/config/DelayQueueConfiguration.java create mode 100644 jzo2o-health/src/main/java/com/jzo2o/health/constant/HealthMqConstants.java diff --git a/jzo2o-health/pom.xml b/jzo2o-health/pom.xml index a941d30..b2cff47 100644 --- a/jzo2o-health/pom.xml +++ b/jzo2o-health/pom.xml @@ -6,8 +6,8 @@ com.jzo2o jzo2o-health 1.0-SNAPSHOT - health - health + jzo2o-health + jzo2o-health jzo2o-parent @@ -100,4 +100,4 @@ - + \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/config/DelayQueueConfiguration.java b/jzo2o-health/src/main/java/com/jzo2o/health/config/DelayQueueConfiguration.java new file mode 100644 index 0000000..ff0bcdf --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/config/DelayQueueConfiguration.java @@ -0,0 +1,61 @@ +package com.jzo2o.health.config; + +import com.jzo2o.health.constant.HealthMqConstants; +import com.jzo2o.rabbitmq.config.RabbitMqConfiguration; +import org.springframework.amqp.core.*; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +import java.util.concurrent.TimeUnit; + +/** + * RabbitMQ延时队列 + * @author JIAN + */ +@Configuration +@Import(RabbitMqConfiguration.class) +public class DelayQueueConfiguration { + @Bean + public Exchange delayExchange() { + return ExchangeBuilder + .topicExchange(HealthMqConstants.Exchanges.HEALTH_ORDER) + .durable(true) + .build(); + } + + @Bean + public Queue delayQueueIn() { + return QueueBuilder + .durable(HealthMqConstants.Queues.DELAY_IN) + // 订单默认15分钟超时 + .ttl((int) TimeUnit.MINUTES.toMillis(15)) + .deadLetterExchange(HealthMqConstants.Exchanges.HEALTH_ORDER) + .deadLetterRoutingKey(HealthMqConstants.RoutingKeys.ORDER_OVERTIME_OUT) + .build(); + } + + @Bean + public Queue delayQueueOut() { + return QueueBuilder.durable(HealthMqConstants.Queues.DELAY_OUT) + .build(); + } + + @Bean + public Binding bindDelayQueueIn() { + return BindingBuilder + .bind(delayQueueIn()) + .to(delayExchange()) + .with(HealthMqConstants.RoutingKeys.ORDER_OVERTIME_IN) + .noargs(); + } + + @Bean + public Binding bindDelayQueueOut() { + return BindingBuilder + .bind(delayQueueOut()) + .to(delayExchange()) + .with(HealthMqConstants.RoutingKeys.ORDER_OVERTIME_OUT) + .noargs(); + } +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/constant/HealthMqConstants.java b/jzo2o-health/src/main/java/com/jzo2o/health/constant/HealthMqConstants.java new file mode 100644 index 0000000..dde8a0b --- /dev/null +++ b/jzo2o-health/src/main/java/com/jzo2o/health/constant/HealthMqConstants.java @@ -0,0 +1,23 @@ +package com.jzo2o.health.constant; + +import com.jzo2o.common.constants.MqConstants; + +/** + * 即刻体检MQ常量 + * @author JIAN + */ +public interface HealthMqConstants extends MqConstants { + interface Exchanges extends MqConstants.Exchanges { + String HEALTH_ORDER = "health.exchange.topic.order"; + } + + interface Queues extends MqConstants.Queues { + String DELAY_IN = "health.queue.orders.delay.in"; + String DELAY_OUT = "health.queue.orders.delay.out"; + } + + interface RoutingKeys extends MqConstants.RoutingKeys { + String ORDER_OVERTIME_IN = "order.overtime.in"; + String ORDER_OVERTIME_OUT = "order.overtime.out"; + } +} \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java b/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java index 4a847d3..42e3d13 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/listener/OrderStatusListener.java @@ -1,17 +1,25 @@ package com.jzo2o.health.listener; +import com.jzo2o.api.trade.TradingApi; +import com.jzo2o.api.trade.dto.response.TradingResDTO; import com.jzo2o.api.trade.enums.TradingStateEnum; -import com.jzo2o.common.constants.MqConstants; +import com.jzo2o.common.constants.UserType; import com.jzo2o.common.expcetions.DBException; import com.jzo2o.common.model.msg.TradeStatusMsg; import com.jzo2o.common.utils.CollUtils; import com.jzo2o.common.utils.JsonUtils; +import com.jzo2o.common.utils.ObjectUtils; +import com.jzo2o.health.constant.HealthMqConstants; import com.jzo2o.health.constant.TradeConstants; import com.jzo2o.health.enums.OrderPayStatusEnum; import com.jzo2o.health.enums.OrderStatusEnum; import com.jzo2o.health.model.OrderUpdateStatusDTO; +import com.jzo2o.health.model.domain.Orders; +import com.jzo2o.health.model.domain.OrdersCancelled; +import com.jzo2o.health.service.IOrderCancelService; import com.jzo2o.health.service.IOrderCommonService; import com.jzo2o.health.service.IOrderCreateService; +import com.jzo2o.health.service.IReservationSettingService; import lombok.extern.slf4j.Slf4j; import org.springframework.amqp.core.ExchangeTypes; import org.springframework.amqp.rabbit.annotation.Exchange; @@ -37,6 +45,12 @@ public class OrderStatusListener { private IOrderCommonService orderCommonService; @Resource private TransactionTemplate transactionTemplate; + @Resource + private IOrderCancelService orderCancelService; + @Resource + private IReservationSettingService reservationSettingService; + @Resource + private TradingApi tradingApi; /** * 接收支付成功信息 @@ -44,10 +58,10 @@ public class OrderStatusListener { */ @RabbitListener(bindings = @QueueBinding( value = @Queue(name = TradeConstants.MQ_TRADE_QUEUE), - exchange = @Exchange(name = MqConstants.Exchanges.TRADE, type = ExchangeTypes.TOPIC), - key = MqConstants.RoutingKeys.TRADE_UPDATE_STATUS)) + exchange = @Exchange(name = HealthMqConstants.Exchanges.TRADE, type = ExchangeTypes.TOPIC), + key = HealthMqConstants.RoutingKeys.TRADE_UPDATE_STATUS)) public void listenTradeUpdatePayStatusMsg(String msg) { - log.info("接收到支付结果状态的消息 ({})-> {}", MqConstants.Queues.ORDERS_TRADE_UPDATE_STATUS, msg); + log.info("接收到支付结果状态的消息 ({})-> {}", HealthMqConstants.Queues.ORDERS_TRADE_UPDATE_STATUS, msg); List msgList = JsonUtils.parseArray(msg).toList(TradeStatusMsg.class); if (CollUtils.isEmpty(msgList)) { @@ -76,4 +90,44 @@ public class OrderStatusListener { } }); } + + @RabbitListener(bindings = @QueueBinding( + value = @Queue(name = HealthMqConstants.Queues.DELAY_OUT), + exchange = @Exchange(name = HealthMqConstants.Exchanges.HEALTH_ORDER, type = ExchangeTypes.TOPIC), + key = HealthMqConstants.RoutingKeys.ORDER_OVERTIME_OUT)) + public void handleOverTimeOrder(String msg) { + Long orderId = Long.parseLong(msg); + if (ObjectUtils.isEmpty(orderId)) { + return; + } + + Orders order = orderCommonService.getById(orderId); + if (ObjectUtils.isEmpty(order)) { + return; + } + + if (order.getOrderStatus() == OrderStatusEnum.NO_PAY && order.getPayStatus() == OrderPayStatusEnum.NO_PAY) { + Long tradingOrderNo = order.getTradingOrderNo(); + if (ObjectUtils.isNotEmpty(tradingOrderNo)) { + // 再次请求防止已支付 + TradingResDTO tradingResDTO = tradingApi.findTradResultByTradingOrderNo(tradingOrderNo); + if (ObjectUtils.isNotEmpty(tradingResDTO) && tradingResDTO.getTradingState() == TradingStateEnum.YJS) { + return; + } + } + + // 事务更新数据表(取消订单) + transactionTemplate.executeWithoutResult(status -> { + orderCancelService.cancelOrder(OrdersCancelled.builder() + .id(orderId) + .cancelTime(LocalDateTime.now()) + .cancelReason("订单超时自动取消") + .cancellerType(UserType.SYSTEM) + .build()); + + // 已预约人数 - 1 + reservationSettingService.plusReservationCount(order.getReservationDate(), -1); + }); + } + } } \ No newline at end of file diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java index 2cc73fa..54f3a64 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/OrderCreateServiceImpl.java @@ -30,6 +30,7 @@ import com.jzo2o.health.model.dto.response.OrdersPayResDTO; import com.jzo2o.health.model.dto.response.PlaceOrderResDTO; import com.jzo2o.health.properties.TradeProperties; import com.jzo2o.health.service.*; +import com.jzo2o.rabbitmq.client.RabbitClient; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; @@ -64,6 +65,8 @@ public class OrderCreateServiceImpl extends ServiceImpl im private RedisTemplate redisTemplate; @Resource private TransactionTemplate transactionTemplate; + @Resource + private RabbitClient rabbitClient; /** * 生成订单号(2位年+2位月+2位日+13位序号) @@ -125,6 +128,9 @@ public class OrderCreateServiceImpl extends ServiceImpl im reservationSettingService.plusReservationCount(placeOrderReqDTO.getReservationDate(), 1); }); + // 发送消息到延时队列处理超时订单(发送检测的订单id) + rabbitClient.sendMsg("health.exchange.topic.order", "order.overtime.in", orderId.toString()); + return new PlaceOrderResDTO(orderId); } diff --git a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java index c308aca..cae96d6 100644 --- a/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java +++ b/jzo2o-health/src/main/java/com/jzo2o/health/service/impl/ReservationSettingServiceImpl.java @@ -100,7 +100,7 @@ public class ReservationSettingServiceImpl extends ServiceImpl