From f6f36fddd8eaa8eea3cf24d800705040e900a459 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=8B?= <2536636506@qq.com> Date: Tue, 7 May 2024 19:00:03 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E4=BB=98=E9=80=80=E6=AC=BE+=E5=BC=82?= =?UTF-8?q?=E6=AD=A5=E4=B8=BB=E5=8A=A8=E6=9F=A5=E8=AF=A2=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E6=83=85=E5=86=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- group-module/group_order/pom.xml | 5 + .../com/group/order/config/AliPayUtil.java | 76 +++++++++++++++ .../group/order/config/RabbitAdminConfig.java | 49 ++++++++++ .../group/order/config/RabbitMQConfig.java | 92 +++++++++++++++++++ .../order/controller/KillOrderController.java | 25 ++++- .../com/group/order/mq/OrderConsumer.java | 83 +++++++++++++++++ .../java/com/group/order/mq/OrderProduct.java | 30 ++++++ .../group/order/service/KillOrderService.java | 4 + .../service/impl/KillOrderServiceImpl.java | 36 ++++++++ 9 files changed, 396 insertions(+), 4 deletions(-) create mode 100644 group-module/group_order/src/main/java/com/group/order/config/AliPayUtil.java create mode 100644 group-module/group_order/src/main/java/com/group/order/config/RabbitAdminConfig.java create mode 100644 group-module/group_order/src/main/java/com/group/order/config/RabbitMQConfig.java create mode 100644 group-module/group_order/src/main/java/com/group/order/mq/OrderConsumer.java create mode 100644 group-module/group_order/src/main/java/com/group/order/mq/OrderProduct.java diff --git a/group-module/group_order/pom.xml b/group-module/group_order/pom.xml index 72920b4..52ec4bd 100644 --- a/group-module/group_order/pom.xml +++ b/group-module/group_order/pom.xml @@ -36,5 +36,10 @@ alipay-easysdk 2.2.0 + + + org.springframework.boot + spring-boot-starter-amqp + \ No newline at end of file diff --git a/group-module/group_order/src/main/java/com/group/order/config/AliPayUtil.java b/group-module/group_order/src/main/java/com/group/order/config/AliPayUtil.java new file mode 100644 index 0000000..76f1069 --- /dev/null +++ b/group-module/group_order/src/main/java/com/group/order/config/AliPayUtil.java @@ -0,0 +1,76 @@ +package com.group.order.config; + +import cn.hutool.json.JSONObject; +import com.alipay.api.AlipayApiException; +import com.alipay.api.AlipayClient; +import com.alipay.api.domain.AlipayTradeQueryModel; +import com.alipay.api.request.AlipayTradeQueryRequest; +import com.alipay.api.request.AlipayTradeRefundRequest; +import com.alipay.api.response.AlipayTradeQueryResponse; +import com.alipay.api.response.AlipayTradeRefundResponse; +import com.group.common.domin.pojo.PayDetail; +import com.group.common.result.R; +import com.group.order.service.PayDetailService; +import lombok.extern.log4j.Log4j2; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; + +/** + * 支付宝接口的调用配置 + */ +@Component +@Log4j2 +public class AliPayUtil { + + @Autowired + private AlipayClient alipayClient; + + public R refund(PayDetail payDetail) { + AlipayTradeRefundRequest request = new AlipayTradeRefundRequest(); + JSONObject bizContent = new JSONObject(); + bizContent.put("out_trade_no", payDetail.getPayDetail()); + bizContent.put("refund_amount", payDetail.getPayPrice()); + bizContent.put("out_request_no", "HZ01RF002"); + request.setBizContent(bizContent.toString()); + try { + AlipayTradeRefundResponse response = alipayClient.execute(request); + log.info("调用接口回复: " + response); + if (response.isSuccess()) { + log.info("退款成功"); + return R.ok().put("data",response.getBody()); + } else { + log.info("退款失败"); + return R.error(); + } + } catch (AlipayApiException e) { + throw new RuntimeException(e); + } + } + + public R selectOrder(PayDetail payDetail) { + AlipayTradeQueryRequest request = new AlipayTradeQueryRequest(); + AlipayTradeQueryModel model = new AlipayTradeQueryModel(); + model.setOutTradeNo(payDetail.getPayDetail()); + ArrayList list = new ArrayList<>(); + list.add("trade_settle_info"); + list.add("fund_bill_list"); + model.setQueryOptions(list); + //设置支付宝交易号 + model.setTradeNo(payDetail.getPayPay()); + request.setBizModel(model); + try { + AlipayTradeQueryResponse response = alipayClient.execute(request); + if (response.isSuccess()) { + return R.ok(); + } else { + return R.error(); + } + } catch (AlipayApiException e) { + throw new RuntimeException(e); + } + + } + +} diff --git a/group-module/group_order/src/main/java/com/group/order/config/RabbitAdminConfig.java b/group-module/group_order/src/main/java/com/group/order/config/RabbitAdminConfig.java new file mode 100644 index 0000000..946ba4e --- /dev/null +++ b/group-module/group_order/src/main/java/com/group/order/config/RabbitAdminConfig.java @@ -0,0 +1,49 @@ +package com.group.order.config; + +import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitAdmin; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class RabbitAdminConfig { + + @Value("${spring.rabbitmq.host}") + private String host; + @Value("${spring.rabbitmq.username}") + private String username; + @Value("${spring.rabbitmq.password}") + private String password; + @Value("${spring.rabbitmq.virtualhost}") + private String virtualhost; + + /** + * 构建RabbitMQ的连接工厂 + * @return + */ + @Bean + public ConnectionFactory connectionFactory() { + CachingConnectionFactory connectionFactory = new CachingConnectionFactory(); + connectionFactory.setAddresses(host); + connectionFactory.setUsername(username); + connectionFactory.setPassword(password); + connectionFactory.setVirtualHost(virtualhost); + return connectionFactory; + } + + + /** + * 初始化RabbitAdmin + * @param connectionFactory + * @return + */ + @Bean + public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) { + RabbitAdmin rabbitAdmin = new RabbitAdmin(connectionFactory); + rabbitAdmin.setAutoStartup(true); + return rabbitAdmin; + } + +} diff --git a/group-module/group_order/src/main/java/com/group/order/config/RabbitMQConfig.java b/group-module/group_order/src/main/java/com/group/order/config/RabbitMQConfig.java new file mode 100644 index 0000000..c596fc9 --- /dev/null +++ b/group-module/group_order/src/main/java/com/group/order/config/RabbitMQConfig.java @@ -0,0 +1,92 @@ +package com.group.order.config; + + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.connection.CorrelationData; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.MessageConverter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import javax.annotation.PostConstruct; + +@Configuration +public class RabbitMQConfig { + public static final String DELAY_QUEUE_NAME="delay_queue"; + public static final String DELAY_EXCHANGE_NAME="delay_exchange"; + public static final String DEAD_QUEUE_NAME="dead_queue"; + public static final String DEAD_EXCHANGE_NAME ="dead_exchange"; + public static final String DEAD_ROUTING_KEY="dead_routing_key"; + public static final String DELAY_ROUTING_KEY="delay_routing_key"; + + //创建消息转换器 + @Bean + public MessageConverter messageConverter(){ + return new Jackson2JsonMessageConverter(); + } + + @Bean + public Queue delayQueue(){ + return QueueBuilder + .durable(DELAY_QUEUE_NAME) + .deadLetterExchange(DEAD_EXCHANGE_NAME) + .deadLetterRoutingKey(DEAD_ROUTING_KEY) + .ttl(30*60*1000) + .build(); + } + + @Bean + public Queue deadLetterQueue(){ + return QueueBuilder + .durable(DEAD_QUEUE_NAME) + .build(); + } + + @Bean + public Exchange delayExchange(){ + return new DirectExchange(DELAY_EXCHANGE_NAME); + } + + @Bean + public Exchange deadLetterExchange(){ + return new DirectExchange(DEAD_EXCHANGE_NAME); + } + + @Bean + public Binding delayBinding(){ + return BindingBuilder + .bind(delayQueue()) + .to((DirectExchange)delayExchange()) + .with(DELAY_ROUTING_KEY); + } + + @Bean + public Binding deadLetterBinding(){ + return BindingBuilder + .bind(deadLetterQueue()) + .to((DirectExchange)deadLetterExchange()) + .with(DEAD_ROUTING_KEY); + } + //完成rabbitTemplate模版配置 + @Bean + public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){ + RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory); + rabbitTemplate.setMessageConverter(messageConverter()); + return rabbitTemplate; + } + //配置监听器容器 + @Bean + public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(ConnectionFactory connectionFactory){ + SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); + factory.setConnectionFactory(connectionFactory); + factory.setMessageConverter(messageConverter()); + return factory; + } +} diff --git a/group-module/group_order/src/main/java/com/group/order/controller/KillOrderController.java b/group-module/group_order/src/main/java/com/group/order/controller/KillOrderController.java index 0e9caff..d76000d 100644 --- a/group-module/group_order/src/main/java/com/group/order/controller/KillOrderController.java +++ b/group-module/group_order/src/main/java/com/group/order/controller/KillOrderController.java @@ -6,6 +6,7 @@ import com.group.common.domin.pojo.KillOrderEntity; import com.group.common.domin.pojo.PayDetail; import com.group.common.result.R; import com.group.order.config.AliPayConfig; +import com.group.order.mq.OrderProduct; import com.group.order.pojo.ReqPay; import com.group.order.service.KillOrderService; import com.group.order.service.PayDetailService; @@ -45,10 +46,8 @@ public class KillOrderController { */ @PostMapping("/addOrder") public R addOrder(@RequestBody KillOrderEntity killOrderEntity) { - if (killOrderService.save(killOrderEntity)) { - return R.error(); - } - return R.ok(); + + return killOrderService.addOrder(killOrderEntity); } /** @@ -115,6 +114,24 @@ public class KillOrderController { } } + @Autowired + private OrderProduct orderProduct; + + /** + * 测试延迟队列的使用 + */ + @GetMapping("/test") + public void test(@RequestParam String message){ + orderProduct.sendMessage(message); + } + + /** + * 订单申请退款 + */ + @GetMapping("/refund/{id}") + public R refund(@PathVariable("id")Integer id){ + return killOrderService.refund(id); + } diff --git a/group-module/group_order/src/main/java/com/group/order/mq/OrderConsumer.java b/group-module/group_order/src/main/java/com/group/order/mq/OrderConsumer.java new file mode 100644 index 0000000..76693e5 --- /dev/null +++ b/group-module/group_order/src/main/java/com/group/order/mq/OrderConsumer.java @@ -0,0 +1,83 @@ +package com.group.order.mq; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.group.common.domin.pojo.KillOrderEntity; +import com.group.common.domin.pojo.PayDetail; +import com.group.common.result.R; +import com.group.order.config.AliPayUtil; +import com.group.order.config.RabbitMQConfig; +import com.group.order.service.KillOrderService; +import com.group.order.service.PayDetailService; +import com.rabbitmq.client.Channel; +import lombok.extern.log4j.Log4j2; +import org.springframework.amqp.core.Message; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Date; +import java.util.List; + +/** + * 接受订单id判断和处理 + */ +@Component +@Log4j2 +public class OrderConsumer { + + @Autowired + private KillOrderService killOrderService; + + @Autowired + private PayDetailService payDetailService; + + @Autowired + private AliPayUtil aliPayUtil; + + @RabbitListener(queues = RabbitMQConfig.DEAD_QUEUE_NAME) + public void orderConsumer(Message message, Channel channel) { + Integer orderId = Integer.valueOf(new String(message.getBody())); + //延迟队列是为了保证订单在一段时间的有效性 + //通过订单id获取订单 + KillOrderEntity entity = killOrderService.getById(orderId); + //通过订单的状态判断是否已经成功支付 + //如果已经成功支付 + if (entity.getKillState().equals(2)){ + return; + } + //获取支付明细判断是否正在支付中 + List list = payDetailService + .list( + new LambdaQueryWrapper() + .eq(PayDetail::getPayOrder, orderId) + ); + //如果没有支付明细 + if (list.isEmpty()){ + //修改订单支付状态为失败 + entity.setKillState(3); + killOrderService.updateById(entity); + } + //最新的支付流水 + PayDetail payDetail = list.get(list.size() - 1); + //如果支付明细支付成功,但是订单状态未修改 + if (payDetail.getPayState().equals(2)){ + entity.setKillState(2); + killOrderService.updateById(entity); + } + //如果支付状态为正在支付 + if (payDetail.getPayState().equals(1)){ + //向支付宝主动发起请求查询订单状态 + R r = aliPayUtil.selectOrder(payDetail); + if (r.get("code").equals(0)){ + log.info(r.get("data")); + payDetail.setPayState(2); + payDetailService.updateById(payDetail); + entity.setKillState(2); + killOrderService.updateById(entity); + } + + } + + } + +} diff --git a/group-module/group_order/src/main/java/com/group/order/mq/OrderProduct.java b/group-module/group_order/src/main/java/com/group/order/mq/OrderProduct.java new file mode 100644 index 0000000..2b62f6e --- /dev/null +++ b/group-module/group_order/src/main/java/com/group/order/mq/OrderProduct.java @@ -0,0 +1,30 @@ +package com.group.order.mq; + +import com.group.order.config.RabbitAdminConfig; +import com.group.order.config.RabbitMQConfig; +import lombok.extern.log4j.Log4j2; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.Date; + +/** + * 发送订单id到延迟队列中 + */ +@Component +@Log4j2 +public class OrderProduct { + + @Autowired + private RabbitTemplate rabbitTemplate; + + public void sendMessage(String message){ + log.info("当前时间:{} 发送一条信息给两个TTL队列{}",new Date().toString(),message); + rabbitTemplate.convertAndSend( + RabbitMQConfig.DELAY_EXCHANGE_NAME, + RabbitMQConfig.DELAY_ROUTING_KEY + ,message + ); + } +} diff --git a/group-module/group_order/src/main/java/com/group/order/service/KillOrderService.java b/group-module/group_order/src/main/java/com/group/order/service/KillOrderService.java index 3952b5a..c0961ea 100644 --- a/group-module/group_order/src/main/java/com/group/order/service/KillOrderService.java +++ b/group-module/group_order/src/main/java/com/group/order/service/KillOrderService.java @@ -12,4 +12,8 @@ import javax.servlet.http.HttpServletResponse; */ public interface KillOrderService extends IService { R payKill(ReqPay pay, HttpServletResponse response); + + R addOrder(KillOrderEntity killOrderEntity); + + R refund(Integer id); } diff --git a/group-module/group_order/src/main/java/com/group/order/service/impl/KillOrderServiceImpl.java b/group-module/group_order/src/main/java/com/group/order/service/impl/KillOrderServiceImpl.java index 6e6f896..5bfe1c2 100644 --- a/group-module/group_order/src/main/java/com/group/order/service/impl/KillOrderServiceImpl.java +++ b/group-module/group_order/src/main/java/com/group/order/service/impl/KillOrderServiceImpl.java @@ -1,13 +1,16 @@ package com.group.order.service.impl; import cn.hutool.core.util.IdUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.group.common.domin.pojo.KillOrderEntity; import com.group.common.domin.pojo.PayDetail; import com.group.common.result.R; +import com.group.order.config.AliPayUtil; import com.group.order.mapper.KillOrderMapper; import com.group.order.mapper.PayDetailMapper; +import com.group.order.mq.OrderProduct; import com.group.order.payMethod.PayContext; import com.group.order.payMethod.PayType; import com.group.order.pojo.ReqPay; @@ -73,4 +76,37 @@ public class KillOrderServiceImpl extends ServiceImpl list = payDetailService.list(new LambdaQueryWrapper().eq(PayDetail::getPayOrder, id)); + PayDetail payDetail = list.get(list.size() - 1); + R refund = aliPayUtil.refund(payDetail); + if (refund.get("code").equals(0)){ + //修改订单状态 + entity.setKillState(4); + updateById(entity); + //修改支付流水详情的状态 + payDetail.setPayState(4); + payDetailService.updateById(payDetail); + } + return R.error(); + } }