学习目标:
订单支付成功后,我们已经更改了订单支付记录状态,接下来我还有更改订单状态,因为他们是不同的微服务模块,所以我们采用消息队列的方式,保证数据最终一致性;
/**
* 订单支付
*/
public static final String EXCHANGE_DIRECT_PAYMENT_PAY = "exchange.direct.payment.pay";
public static final String ROUTING_PAYMENT_PAY = "payment.pay";
//队列
public static final String QUEUE_PAYMENT_PAY = "queue.payment.pay";
/**
* 减库存
*/
public static final String EXCHANGE_DIRECT_WARE_STOCK = "exchange.direct.ware.stock";
public static final String ROUTING_WARE_STOCK = "ware.stock";
//队列
public static final String QUEUE_WARE_STOCK = "queue.ware.stock";
/**
* 减库存成功,更新订单状态
*/
public static final String EXCHANGE_DIRECT_WARE_ORDER = "exchange.direct.ware.order";
public static final String ROUTING_WARE_ORDER = "ware.order";
//队列
public static final String QUEUE_WARE_ORDER = "queue.ware.order";
<dependency>
<groupId>com.atguigu.gmall</groupId>
<artifactId>rabbit-util</artifactId>
<version>1.0</version>
</dependency>
service-payment
模块com.atguigu.gmall.payment.service.impl.AlipayServiceImpl#paySuccessNotify方法
/**
* 支付宝异步回调:通知商户系统支付结果
*
* @param paramsMap: 支付宝回调提交参数
* @return
*/
@Override
public String paySuccessNotify(Map paramsMap) {
try {
//1. 验签:在支付系统验证提交数据是否为支付宝官方发出,以及在网格传输过程中是否被非法篡改过.避免"虚假"通知.
// TODO 验签成功后,按照支付结果异步通知中的描述,对支付结果中的业务内容进行二次校验,校验成功后在response中返回success并继续商户自身业务处理,校验失败返回failure
//2. 验证订单以及订单金额是否一致(支付宝提交交易金额跟本地交易记录中金额一致)
//2.1 获取提交参数中订单编号 查询本地交易记录
//3. 验证appId是否为商家的
//4. 验证支付宝端交易结果
String tradeStatus = (String) paramsMap.get("trade_status");
if ("TRADE_SUCCESS".equals(tradeStatus)) {
//5. 修改本地交易记录支付状态
//6. 发送消息到MQ通知订单系统修改订单状态
rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_PAY, MqConst.ROUTING_PAYMENT_PAY, paymentInfo.getOrderId());
return "success";
}
}
} catch (Exception e) {
log.error("[支付系统],处理支付回调异常:{}", e);
throw new RuntimeException(e);
}
return "failure";
}
service-order
模块中创建OrderReceiver类添加方法
package com.atguigu.gmall.order.receiver;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.rabbit.config.MqConst;
import com.atguigu.gmall.enums.model.OrderStatus;
import com.atguigu.gmall.enums.model.ProcessStatus;
import com.atguigu.gmall.order.model.OrderInfo;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @author: atguigu
* @create: 2023-06-27 11:56
*/
@Slf4j
@Component
public class OrderReceiver {
@Autowired
private OrderInfoService orderInfoService;
@Autowired
private RedisTemplate redisTemplate;
/**
* 监听支付成功消息,完成订单状态修改
*
* @param orderId 订单ID
* @param message
* @param channel
*/
@SneakyThrows
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_PAY, durable = "true"),
value = @Queue(value = MqConst.QUEUE_PAYMENT_PAY, durable = "true"),
key = MqConst.ROUTING_PAYMENT_PAY
))
public void processPaySucess(Long orderId, Message message, Channel channel) {
if (orderId != null) {
log.info("[订单服务]监听到支付成功消息,订单ID:{}", orderId);
//1.业务处理
String key = "mq:" + orderId + ":md";
Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, orderId, 10, TimeUnit.MINUTES);
if (!flag) {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
return;
}
//1.1 调用业务层完成订单状态修改
orderInfoService.updateOrderStatus(orderId, ProcessStatus.PAID);
//1.2 发送MQ消息通知库存系统进行【拆单】锁定商品库存 -- 分析得知库存系统不允许同一订单多次进行商品锁定,做好幂等性处理
orderInfoService.sendLockStockMsg(orderId);
//2.手动应答消息
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
}
订单模块除了接收到请求改变单据状态,还要发送库存系统
查看看《库存管理系统接口手册》中【减库存的消息队列消费端接口】中的描述,组织相应的消息数据进行传递。
/**
* 发送MQ消息通知库存系统锁定库存
* @param orderId
*/
void sendLockStockMsg(Long orderId);
/**
* 构建第三方库存系统要求参数(包含订单信息,订单明细信息)
*/
Map initWareMap(OrderInfo orderInfo);
/**
* 发送MQ消息通知库存系统锁定库存
* 要求:必须要严格按照库存系统接口要求提交参数
*
* @param orderId
*/
@Override
public void sendLockStockMsg(Long orderId) {
//1.根据订单ID查询订单信息以及明细信息
OrderInfo orderInfo = this.getOrderInfo(orderId);
if (orderInfo != null) {
//2.按照接口要求封装库存系统所需MQ参数
Map<String, Object> mapResult = initWareMap(orderInfo);
rabbitService.sendMsg(MqConst.EXCHANGE_DIRECT_WARE_STOCK, MqConst.ROUTING_WARE_STOCK, JSON.toJSONString(mapResult));
}
}
/**
* 根据订单以及订单明细构建仓库系统所需参数(扣减库存,拆单结果都需要复用该方法)
*
* @param orderInfo
* @return
*/
private Map<String, Object> initWareMap(OrderInfo orderInfo) {
Map<String, Object> mapResult = new HashMap<>();
//1.构建订单相关字段
mapResult.put("orderId", orderInfo.getId());
mapResult.put("consignee", orderInfo.getConsignee());
mapResult.put("consigneeTel", orderInfo.getConsigneeTel());
mapResult.put("orderComment", orderInfo.getOrderComment());
mapResult.put("orderBody", orderInfo.getTradeBody());
mapResult.put("deliveryAddress", orderInfo.getDeliveryAddress());
mapResult.put("paymentWay", PaymentWay.ONLINE.name().equals(orderInfo.getPaymentWay()) ? 1 : 2);
//特别重要:一定要保证拆单响应结果包含该属性
mapResult.put("wareId", orderInfo.getWareId());
//2.循环遍历订单明细构建订单明细对象相关字段
List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
if (!CollectionUtils.isEmpty(orderDetailList)) {
List<Map<Object, Object>> orderDetailMapList = orderDetailList.stream().map(orderDetail -> {
Map<Object, Object> detailMap = new HashMap<>();
detailMap.put("skuId", orderDetail.getSkuId());
detailMap.put("skuName", orderDetail.getSkuName());
detailMap.put("skuNum", orderDetail.getSkuNum());
return detailMap;
}).collect(Collectors.toList());
mapResult.put("details", orderDetailMapList);
}
return mapResult;
}
给仓库系统发送减库存消息后,还要接受减库存成功或者失败的消息。
同样根据《库存管理系统接口手册》中【商品减库结果消息】的说明完成。消费该消息的消息队列监听程序。
接受到消息后主要做的工作就是更新订单状态。
在订单项目中OrderReceiver
/**
* 监听库存系统反馈锁定库存结果
* 根据锁定库存结果更新订单状态
*
* @param stockLockStr
* @param message
* @param channel
*/
@SneakyThrows
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_WARE_ORDER, durable = "true"),
value = @Queue(value = MqConst.QUEUE_WARE_ORDER, durable = "true"),
key = MqConst.ROUTING_WARE_ORDER
))
public void processStockLockResult(String stockLockStr, Message message, Channel channel) {
if (StringUtils.isNotBlank(stockLockStr)) {
log.info("[订单服务]监听库存锁定结果:{}", stockLockStr);
//根据库存提交扣减结果修改订单状态
Map map = JSON.parseObject(stockLockStr, Map.class);
String orderId = (String) map.get("orderId");
String status = (String) map.get("status");
if ("DEDUCTED".equals(status)) {
orderInfoService.updateOrderStatus(Long.valueOf(orderId), ProcessStatus.WAITING_DELEVER);
}
if("OUT_OF_STOCK".equals(status)){
orderInfoService.updateOrderStatus(Long.valueOf(orderId), ProcessStatus.STOCK_EXCEPTION);
}
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
YAPI接口地址:http://192.168.200.128:3000/project/11/interface/api/747
service-order
订单模块OrderApiController
处理拆单请求
/**
* 处理库存系统发送拆单请求
*
* @param orderId
* @param wareSkuMap
* @return
*/
@PostMapping("/orderSplit")
public String orderSplit(@RequestParam("orderId") Long orderId, @RequestParam("wareSkuMap") String wareSkuMap) {
return orderInfoService.orderSplit(orderId, wareSkuMap);
}
OrderInfoService
/**
* 根据库存系统反馈进行拆单
* @param orderId 订单ID
* @param wareSkuMap 仓库跟商品Sku列表映射关系
* @return
*/
String orderSplit(Long orderId, String wareSkuMap);
OrderInfoServiceImpl
/**
* 根据库存系统反馈进行拆单
* 本质:将参数wareSkuMap中集合中元素有几个 新增几个子订单 skuIds中有几件商品就有几个订单明细
*
* @param orderId 订单ID
* @param wareSkuMap 仓库跟商品Sku列表映射关系 [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
* @return
*/
@Override
public String orderSplit(Long orderId, String wareSkuMap) {
log.info("【订单服务】接收库存提交拆单参数:订单id:{},仓库跟sku映射关系:{}", orderId, wareSkuMap);
//1.将接收到参数wareSkuMap转为List集合 泛型:Map
if (StringUtils.isNotBlank(wareSkuMap)) {
List<Map> wareSkuMapList = JSON.parseArray(wareSkuMap, Map.class);
//2.获取原始订单以及订单明细(为后续新增子订单提供基础数据)
OrderInfo originOrderInfo = this.getOrderInfo(orderId);
List<OrderDetail> originOrderOrderDetailList = originOrderInfo.getOrderDetailList();
//3.遍历仓库跟SKU映射Map构建新订单以及订单明细并且将其保存(拆单)--每遍历一次就会产生新子订单
List<OrderInfo> subOrderInfoList = wareSkuMapList.stream().map(wareSkuIdMap -> {
//3.1.获取订单对应出货仓库ID
String wareId = (String) wareSkuIdMap.get("wareId");
//3.2.获取仓库对应商品skuId列表
List<String> skuIds = (List<String>) wareSkuIdMap.get("skuIds");
//3.3. 构建新子订单对象-从原始订单中拷贝给属性赋值
OrderInfo subOrderInfo = new OrderInfo();
BeanUtils.copyProperties(originOrderInfo, subOrderInfo);
//3.3.1 为新子订单属性某些属性进行手动赋值 主键、总金额、父订单ID
subOrderInfo.setId(null); //手动将主键改为空
subOrderInfo.setParentOrderId(originOrderInfo.getId());
//因为相应结果时候必须要指定订单对应出库仓库ID 在这里设置 为新订单关联仓库ID
subOrderInfo.setWareId(wareId);
//3.3.2 找打当前新子订单包含哪些商品 将原始子订单集合进行过滤获取当前新子订单中订单明细商品
List<OrderDetail> subOrderDetailList = originOrderOrderDetailList.stream().filter(originOrderDetail -> {
return skuIds.contains(originOrderDetail.getSkuId().toString());
}).collect(Collectors.toList());
subOrderInfo.setOrderDetailList(subOrderDetailList);
subOrderInfo.sumTotalAmount();
//3.4 将新订单以及订单明细进行保存
//3.4.1 保存订单
this.save(subOrderInfo);
Long subOrderId = subOrderInfo.getId();
//3.4.2 保存订单明细
subOrderDetailList.forEach(orderDetail -> {
orderDetail.setOrderId(subOrderId);
});
orderDetailService.saveBatch(subOrderDetailList);
return subOrderInfo;
}).collect(Collectors.toList());
//4.修改原始订单状态为“SPIT”
this.updateOrderStatus(orderId, ProcessStatus.SPLIT);
//5.按照仓库系统要求进行拆单接口响应(注意:wareId 每个订单对应出货仓库id设置)
List<Map<String, Object>> collect = subOrderInfoList.stream().map(subOrderInfo -> {
Map<String, Object> mapResult = this.initWareMap(subOrderInfo);
return mapResult;
}).collect(Collectors.toList());
return JSON.toJSONString(collect);
}
return null;
}
订单持久层Mapper映射文件中,增加过滤订单条件,将拆分原始订单排除掉 OrderInfoMapper.xml
<!--查询用户订单列表-->
<select id="getOrderList" resultMap="orderInfoMap">
select
oi.id,
oi.consignee,
oi.consignee_tel,
oi.total_amount,
oi.order_status,
oi.user_id,
oi.payment_way,
oi.delivery_address,
oi.order_comment,
oi.out_trade_no,
oi.trade_body,
oi.create_time,
od.id order_deatil_id,
od.sku_id,
od.sku_name,
od.img_url,
od.order_price,
od.sku_num
from order_info oi inner join order_detail od on od.order_id = oi.id
where oi.user_id = #{userId} and oi.order_status != 'SPLIT'
order by oi.create_time
</select>
/**
* 关闭交易
*/
public static final String EXCHANGE_DIRECT_PAYMENT_CLOSE = "exchange.direct.payment.close";
public static final String ROUTING_PAYMENT_CLOSE = "payment.close";
//队列
public static final String QUEUE_PAYMENT_CLOSE = "queue.payment.close";
service-order
中修改com.atguigu.gmall.order.service.impl.OrderInfoServiceImpl#execExpiredOrder方法
/**
* 关闭订单
*
* @param orderId
*/
@Override
public void execExpiredOrder(Long orderId) {
//1.查询订单状态 判断状态 是否为待支付
OrderInfo orderInfo = this.getById(orderId);
if (orderInfo != null && (OrderStatus.UNPAID.name().equals(orderInfo.getOrderStatus()) || OrderStatus.PAID.name().equals(orderInfo.getOrderStatus()))) {
//2.修改为关闭
this.updateOrderStatus(orderId, ProcessStatus.CLOSED);
//3.新增-发送关闭订单消息到MQ通知支付系统关闭交易记录
rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
}
}
package com.atguigu.gmall.payment.receiver;
import com.atguigu.gmall.common.rabbit.config.MqConst;
import com.atguigu.gmall.enums.model.PaymentStatus;
import com.atguigu.gmall.enums.model.PaymentType;
import com.atguigu.gmall.payment.model.PaymentInfo;
import com.atguigu.gmall.payment.service.PaymentInfoService;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import java.util.concurrent.TimeUnit;
/**
* @author: atguigu
* @create: 2023-06-30 09:35
*/
@Slf4j
@Component
public class PaymentReceiver {
@Autowired
private RedisTemplate redisTemplate;
@Autowired
private PaymentInfoService paymentInfoService;
/**
* 监听关闭订单消息,关闭交易记录(本地跟支付宝)
*
* @param orderId
* @param message
* @param channel
*/
@SneakyThrows
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, durable = "true"),
value = @Queue(value = MqConst.QUEUE_PAYMENT_CLOSE, durable = "true"),
key = MqConst.ROUTING_PAYMENT_CLOSE
))
public void processClosePayment(Long orderId, Message message, Channel channel) {
if (orderId != null) {
log.info("[支付服务]监听到关闭交易消息:{}", orderId);
//1.消息幂等性 set nx
String key = "mq:" + orderId + ":close";
Boolean flag = redisTemplate.opsForValue().setIfAbsent(key, orderId, 5, TimeUnit.SECONDS);
if (!flag) {
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
return;
}
//2.关闭交易记录
//2.1 根据订单ID查询本地交易记录
PaymentInfo paymentInfo = paymentInfoService.getPayInfoByOrderIdOrOutTradeNo(orderId.toString(), PaymentType.ALIPAY.name());
if (paymentInfo != null && PaymentStatus.UNPAID.name().equals(paymentInfo.getPaymentStatus())) {
//2.2 修改本地交易记录状态
paymentInfo.setPaymentStatus(PaymentStatus.CLOSED.name());
paymentInfoService.updateById(paymentInfo);
}
}
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
PaymentInfoService
/**
* 根据订单编号/订单ID +支付方式 查询本地交易记录
* @param orderId
* @param paymentType
* @return
*/
PaymentInfo getPayInfoByOrderIdOrOutTradeNo(String orderId, String paymentType);
PaymentInfoServiceImpl
/**
* 根据订单编号/订单ID +支付方式 查询本地交易记录
*
* @param orderId
* @param paymentType
* @return
*/
@Override
public PaymentInfo getPayInfoByOrderIdOrOutTradeNo(String orderId, String paymentType) {
LambdaQueryWrapper<PaymentInfo> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(PaymentInfo::getPaymentType, paymentType);
queryWrapper.and(a -> a.eq(PaymentInfo::getOrderId, orderId).or().eq(PaymentInfo::getOutTradeNo, orderId));
PaymentInfo paymentInfo = this.getOne(queryWrapper);
return paymentInfo;
}
AlipayService接口
/**
* 关闭支付宝交易
* @param paymentInfo
*/
void closeAlipayTrade(PaymentInfo paymentInfo);
AlipayServiceImpl
/**
* 关闭支付宝交易
*
* @param paymentInfo
*/
@Override
public void closeAlipayTrade(PaymentInfo paymentInfo) {
try {
AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
JSONObject bizContent = new JSONObject();
if (StringUtils.isNotBlank(paymentInfo.getOutTradeNo())) {
bizContent.put("out_trade_no", paymentInfo.getOutTradeNo());
}
if (StringUtils.isNotBlank(paymentInfo.getTradeNo())) {
//todo 支付宝交易号,只有付款成功后才有值
bizContent.put("trade_no", paymentInfo.getTradeNo());
}
request.setBizContent(bizContent.toString());
AlipayTradeCloseResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
System.out.println("支付宝交易关闭成功");
} else {
System.out.println("支付宝交易调用失败");
}
} catch (Exception e) {
log.error("[支付宝]关闭交易异常:{}", e);
throw new RuntimeException(e);
}
}
AlipayService
/**
* 获取支付宝交易状态
* @param paymentInfo
* @return
*/
String getAliPayTradeSatus(PaymentInfo paymentInfo);
AlipayServiceImpl
/**
* 查询支付宝交易状态
*
* @param paymentInfo
* @return
*/
@Override
public String getAliPayTradeSatus(PaymentInfo paymentInfo) {
try {
AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
JSONObject jsonObject = new JSONObject();
if (StringUtils.isNotBlank(paymentInfo.getOutTradeNo())) {
jsonObject.put("out_trade_no", paymentInfo.getOutTradeNo());
}
if (StringUtils.isNotBlank(paymentInfo.getTradeNo())) {
//todo 支付宝交易号,只有付款成功后才有值
jsonObject.put("trade_no", paymentInfo.getTradeNo());
}
//jsonObject.put("query_options", Arrays.asList("trade_settle_info"));
request.setBizContent(jsonObject.toJSONString());
AlipayTradeQueryResponse response = alipayClient.execute(request);
if (response.isSuccess()) {
return response.getTradeStatus();
}
} catch (Exception e) {
log.error("[支付宝]获取交易状态异常:{}", e);
throw new RuntimeException(e);
}
return null;
}
service-payment
支付模块监听器中处理
package com.atguigu.gmall.payment;
import com.atguigu.gmall.enums.model.PaymentStatus;
import com.atguigu.gmall.enums.model.PaymentType;
import com.atguigu.gmall.enums.model.PaymentWay;
import com.atguigu.gmall.payment.model.PaymentInfo;
import com.atguigu.gmall.payment.service.AlipayService;
import com.atguigu.gmall.payment.service.PaymentInfoService;
import com.atguigu.gmall.rabbit.config.MqConst;
import com.rabbitmq.client.Channel;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.Exchange;
import org.springframework.amqp.rabbit.annotation.Queue;
import org.springframework.amqp.rabbit.annotation.QueueBinding;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* @author: atguigu
* @create: 2023-08-15 09:26
*/
@Slf4j
@Component
public class PaymentRecevier {
@Autowired
private PaymentInfoService paymentInfoService;
@Autowired
private AlipayService alipayService;
/***
* 监听关闭交易消息(订单超时关闭),将本地交易,支付宝交易同样关闭
* @param outTradeNo 订单编号
* @param channel
* @param message
*/
@SneakyThrows
@RabbitListener(bindings = @QueueBinding(
exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, durable = "true"),
value = @Queue(value = MqConst.QUEUE_PAYMENT_CLOSE, durable = "true"),
key = MqConst.ROUTING_PAYMENT_CLOSE
))
public void processCloseTrade(String outTradeNo, Channel channel, Message message) {
if (StringUtils.isNotBlank(outTradeNo)) {
log.info("[支付服务]监听到关闭交易消息:{}", outTradeNo);
//1.查询本地交易记录是否存在,如果存在修改状态为关闭
PaymentInfo paymentInfo = paymentInfoService.getPaymentInfo(outTradeNo, PaymentType.ALIPAY.name());
if (paymentInfo != null) {
paymentInfo.setPaymentStatus(PaymentStatus.CLOSED.name());
paymentInfoService.updateById(paymentInfo);
//2.查询支付宝交易记录是否存在,如果存在将交易关闭
//2.1 调用支付宝接口查询支付宝交易 如果状态:等待买家付款
String alipayStatus = alipayService.getAliPayTradeSatus(paymentInfo);
//2.2 调用支付宝接口关闭支付宝交易
if("WAIT_BUYER_PAY".equals(alipayStatus)){
alipayService.closeAlipayTrade(paymentInfo);
}
}
channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
}
}
}