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();
+ }
}