diff --git a/xdclass-common/src/main/java/net/jieyuu/model/OrderMessage.java b/xdclass-common/src/main/java/net/jieyuu/model/OrderMessage.java new file mode 100644 index 0000000..827974c --- /dev/null +++ b/xdclass-common/src/main/java/net/jieyuu/model/OrderMessage.java @@ -0,0 +1,18 @@ +package net.jieyuu.model; + + +import lombok.Data; + +@Data +public class OrderMessage { + /** + * 消息id + */ + private Long messageId; + + /** + * 订单号 + */ + private String outTradeNo; + +} diff --git a/xdclass-order-service/src/main/java/net/jieyuu/mapper/ProductOrderMapper.java b/xdclass-order-service/src/main/java/net/jieyuu/mapper/ProductOrderMapper.java index 3874ff0..384d740 100644 --- a/xdclass-order-service/src/main/java/net/jieyuu/mapper/ProductOrderMapper.java +++ b/xdclass-order-service/src/main/java/net/jieyuu/mapper/ProductOrderMapper.java @@ -2,10 +2,11 @@ package net.jieyuu.mapper; import net.jieyuu.model.ProductOrderDO; import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import org.apache.ibatis.annotations.Param; /** *

- * Mapper 接口 + * Mapper 接口 *

* * @author jieyuu @@ -13,4 +14,5 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; */ public interface ProductOrderMapper extends BaseMapper { + void updateOrderPayState(@Param("outTradeNo") String outTradeNo, @Param("newState") String newState, @Param("oldState") String oldState); } diff --git a/xdclass-order-service/src/main/java/net/jieyuu/mq/ProductOrderMQListener.java b/xdclass-order-service/src/main/java/net/jieyuu/mq/ProductOrderMQListener.java new file mode 100644 index 0000000..31dd6ba --- /dev/null +++ b/xdclass-order-service/src/main/java/net/jieyuu/mq/ProductOrderMQListener.java @@ -0,0 +1,50 @@ +package net.jieyuu.mq; + +import com.rabbitmq.client.Channel; +import lombok.extern.slf4j.Slf4j; +import net.jieyuu.model.OrderMessage; +import net.jieyuu.service.ProductOrderService; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitHandler; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.IOException; + + +@Slf4j +@Component +@RabbitListener(queues = "${mqconfig.order_close_queue}") +public class ProductOrderMQListener { + + + @Autowired + private ProductOrderService productOrderService; + + /** + * 消息重复消费,幂等性保障 + * + * @param orderMessage + * @param message + * @param channel + * @throws IOException + */ + @RabbitHandler + public void closeProductOrder(OrderMessage orderMessage, Message message, Channel channel) throws IOException { + log.info("监听到消息:closeProductOrder:{} ", orderMessage); + long msgTag = message.getMessageProperties().getDeliveryTag(); + + try { + boolean flag = productOrderService.closeProductOrder(orderMessage); + if (flag) {// 关单成功 + channel.basicAck(msgTag, false); + } else {// 失败 + channel.basicAck(msgTag, true);// 重新入队 + } + } catch (IOException e) { + log.error("定时关单失败:{}", orderMessage); + channel.basicReject(msgTag, true); + } + } +} diff --git a/xdclass-order-service/src/main/java/net/jieyuu/service/ProductOrderService.java b/xdclass-order-service/src/main/java/net/jieyuu/service/ProductOrderService.java index 1f8e492..a5032e7 100644 --- a/xdclass-order-service/src/main/java/net/jieyuu/service/ProductOrderService.java +++ b/xdclass-order-service/src/main/java/net/jieyuu/service/ProductOrderService.java @@ -1,5 +1,6 @@ package net.jieyuu.service; +import net.jieyuu.model.OrderMessage; import net.jieyuu.model.ProductOrderDO; import com.baomidou.mybatisplus.extension.service.IService; import net.jieyuu.request.ConfirmOrderRequest; @@ -31,4 +32,11 @@ public interface ProductOrderService extends IService { * @return */ String queryProductOrderState(String outTradeNo); + + /** + * 队列监听定时关单接口 + * + * @param orderMessage + */ + boolean closeProductOrder(OrderMessage orderMessage); } diff --git a/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java b/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java index 61191ed..8bcc926 100644 --- a/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java +++ b/xdclass-order-service/src/main/java/net/jieyuu/service/impl/ProductOrderServiceImpl.java @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import lombok.extern.slf4j.Slf4j; +import net.jieyuu.config.RabbitMQConfig; import net.jieyuu.enums.*; import net.jieyuu.exception.BizException; import net.jieyuu.feign.CouponFeignService; @@ -11,11 +12,8 @@ import net.jieyuu.feign.ProductFeignService; import net.jieyuu.feign.UserFeignService; import net.jieyuu.interceptor.LoginInterceptor; import net.jieyuu.mapper.ProductOrderItemMapper; -import net.jieyuu.model.LoginUser; -import net.jieyuu.model.OrderItemVO; -import net.jieyuu.model.ProductOrderDO; +import net.jieyuu.model.*; import net.jieyuu.mapper.ProductOrderMapper; -import net.jieyuu.model.ProductOrderItemDO; import net.jieyuu.request.ConfirmOrderRequest; import net.jieyuu.request.LockCouponRecordRequest; import net.jieyuu.request.LockProductRequest; @@ -26,6 +24,8 @@ import net.jieyuu.utils.CommonUtil; import net.jieyuu.utils.JsonData; import net.jieyuu.vo.CouponRecordVO; import net.jieyuu.vo.ProductOrderAddressVO; +import org.apache.commons.lang3.StringUtils; +import org.springframework.amqp.rabbit.core.RabbitTemplate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -62,6 +62,12 @@ public class ProductOrderServiceImpl extends ServiceImpl orderItemList) { + private void saveProductOrderItems(String orderOutTradeNo, Long orderId, List orderItemList) { List orderItemDOList = orderItemList.stream().map(obj -> { ProductOrderItemDO itemDO = new ProductOrderItemDO(); @@ -361,4 +372,35 @@ public class ProductOrderServiceImpl extends ServiceImpl().eq("out_trade_no", orderMessage.getOutTradeNo())); + + if (productOrderDO == null) { + log.warn("直接确认消息,订单不存在:{}", orderMessage); + return true; + } + + if (productOrderDO.getState().equalsIgnoreCase(ProductOrderStateEnum.PAY.name())) {// 成功消费 + log.info("直接确认消息,订单支付成功:{}", orderMessage); + return true; + } + // 向第三方支付查询支付情况 todo + + + + String payResult = ""; + // 订单结果为空,支付不成功,取消订单 + if (StringUtils.isBlank(payResult)) { + productOrderMapper.updateOrderPayState(orderMessage.getOutTradeNo(), ProductOrderStateEnum.CANCEL.name(), ProductOrderStateEnum.NEW.name()); + log.info("结果为空,则未支付成功,本地取消订单:{}", orderMessage); + return true; + } else { + // 将订单状态改为已经支付 + log.warn("支付成功,主动修改订单状态为已支付,造成该元婴的情况可能是支付通道回调有问题:{}", orderMessage); + productOrderMapper.updateOrderPayState(orderMessage.getOutTradeNo(), ProductOrderStateEnum.PAY.name(), ProductOrderStateEnum.NEW.name()); + return true; + } + } } diff --git a/xdclass-order-service/src/main/resources/mapper/ProductOrderMapper.xml b/xdclass-order-service/src/main/resources/mapper/ProductOrderMapper.xml index 09180ff..f97f11a 100644 --- a/xdclass-order-service/src/main/resources/mapper/ProductOrderMapper.xml +++ b/xdclass-order-service/src/main/resources/mapper/ProductOrderMapper.xml @@ -4,25 +4,35 @@ - - - - - - - - - - - - - - + + + + + + + + + + + + + + - id, out_trade_no, state, create_time, total_amount, pay_amount, pay_type, nickname, head_img, user_id, del, update_time, order_type, receiver_address + id + , out_trade_no, state, create_time, total_amount, pay_amount, pay_type, nickname, head_img, user_id, del, update_time, order_type, receiver_address + + + + update product_order + set `state` = #{newState} + where out_trade_no = #{outTradeNo} + and `state` = #{oldState} + + diff --git a/xdclass-order-service/src/test/java/biz/DemoApplicationTests.java b/xdclass-order-service/src/test/java/biz/DemoApplicationTests.java index d513fa9..c892610 100644 --- a/xdclass-order-service/src/test/java/biz/DemoApplicationTests.java +++ b/xdclass-order-service/src/test/java/biz/DemoApplicationTests.java @@ -3,6 +3,7 @@ package biz; import lombok.extern.slf4j.Slf4j; import net.jieyuu.OrderApplication; import net.jieyuu.model.CouponRecordMessage; +import net.jieyuu.model.OrderMessage; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.amqp.rabbit.core.RabbitTemplate; @@ -21,14 +22,13 @@ public class DemoApplicationTests { @Test public void send() { rabbitTemplate.convertAndSend("order.event.exchange", "order.close.delay.routing.key", "this is a new order"); - } @Test public void testCouponRecordRelease() { - CouponRecordMessage message = new CouponRecordMessage(); + OrderMessage message = new OrderMessage(); message.setOutTradeNo("123456abc"); - message.setTaskId(1l); + message.setMessageId(1l); rabbitTemplate.convertAndSend("order.event.exchange", "order.close.delay.routing.key", message); }