尚品汇-订单拆单、支付宝关闭交易、关闭过期订单整合(五十)

目录:

(1)拆单接口

(2)取消订单业务补充关闭支付记录

(3)支付宝关闭交易

(4)查询支付交易记录

(5)PaymentFeignClient 远程接口

(6)整合关闭过期订单

(1)拆单接口

仓库表:不是同一个仓库

在service_order模块

订单实现拆单接口OrderService

List<OrderInfo> orderSplit(Long orderId, String wareSkuMap);

拆单接口实现类OrderServiceImpl

@Override
@Transactional
public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {
    ArrayList<OrderInfo> orderInfoArrayList = new ArrayList<>();
    /*
    1.  先获取到原始订单 107
    2.  将wareSkuMap 转换为我们能操作的对象 [{"wareId":"1","skuIds":["2","10"]},{"wareId":"2","skuIds":["3"]}]
        方案一:class Param{
                    private String wareId;
                    private List<String> skuIds;
                }
        方案二:看做一个Map mpa.put("wareId",value); map.put("skuIds",value)

    3.  创建一个新的子订单 108 109 。。。
    4.  给子订单赋值
    5.  保存子订单到数据库
    6.  修改原始订单的状态
    7.  测试
     */


   //获取父订单
    OrderInfo orderInfoOrigin = getOrderInfoById(orderId);
    List<Map> maps = JSON.parseArray(wareSkuMap, Map.class);
    if (maps != null) {
        for (Map map : maps) {
            String wareId = (String) map.get("wareId");

            List<String> skuIds = (List<String>) map.get("skuIds");

            OrderInfo subOrderInfo = new OrderInfo();
            // 属性拷贝
            BeanUtils.copyProperties(orderInfoOrigin, subOrderInfo);
            // 防止主键冲突
            subOrderInfo.setId(null);
            //设置付订单id
            subOrderInfo.setParentOrderId(orderId);
            // 赋值仓库Id
            subOrderInfo.setWareId(wareId);

            // 计算子订单的金额: 必须有订单明细
            // 获取到子订单明细
            // 声明一个集合来存储子订单明细
            ArrayList<OrderDetail> orderDetails = new ArrayList<>();

            //获取父订单商品总明细
            List<OrderDetail> orderDetailList = orderInfoOrigin.getOrderDetailList();
            // 表示主主订单明细中获取到子订单的明细
            if (orderDetailList != null && orderDetailList.size() > 0) {
                for (OrderDetail orderDetail : orderDetailList) {
                    // 获取子订单明细的商品Id
                    for (String skuId : skuIds) {

                        //对比是否是当前仓库的商品,就收集
                        if (Long.parseLong(skuId) == orderDetail.getSkuId().longValue()) {
                            // 将订单明细添加到集合
                            orderDetails.add(orderDetail);
                        }
                    }
                }
            }
            subOrderInfo.setOrderDetailList(orderDetails);
            // 计算总金额
            subOrderInfo.sumTotalAmount();
            // 保存子订单 submitOrdser(subOrderInfo)
                saveOrderInfo(subOrderInfo);
            // 将子订单添加到集合中!
            orderInfoArrayList.add(subOrderInfo);
        }
    }
    // 修改原始订单的状态
    updateOrderStatus(orderId, ProcessStatus.SPLIT);
    return orderInfoArrayList;
}

拆单接口控制器:OrderApiController:

/**
 * 拆单业务
 * @param request
 * @return
 */
@RequestMapping("orderSplit")
public String orderSplit(HttpServletRequest request){
    String orderId = request.getParameter("orderId");
    String wareSkuMap = request.getParameter("wareSkuMap");

    // 拆单:获取到的子订单集合
    List<OrderInfo> subOrderInfoList = orderService.orderSplit(Long.parseLong(orderId),wareSkuMap);
    // 声明一个存储map的集合
    ArrayList<Map> mapArrayList = new ArrayList<>();
    // 生成子订单集合
    for (OrderInfo orderInfo : subOrderInfoList) {
        Map map = orderService.initWareOrder(orderInfo);
        // 添加到集合中!
        mapArrayList.add(map);
    }
    return JSON.toJSONString(mapArrayList);
}

前面已经写了:

实现类

多了两条子订单

库存系统表:

订单任务

订单任务详情

(2)取消订单业务补充关闭支付记录

用户没有点击扫码支付,不会调用支付宝的接口,这个时候订单超时后直接关闭订单就行了,当点击扫码支付后,会调用支付宝接口这个时候就会生成PaymentInfo对象,这个时候超时了,还需要关闭支付记录

此时如果用户扫码了,但是没有支付,订单超时了,这个时候还需要关闭支付宝交易记录

关闭订单流程图:

在处理超时订单里:添加代码

在MqConst中添加常量

/**
 * 关闭交易
 */
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";

根据业务进行发送1或2,2是有支付记录

在取消订单实现类中发送消息关闭交易

更改接口

2是有支付记录,才发送消息

@Override
public void execExpiredOrder(Long orderId) {
    // orderInfo
    updateOrderStatus(orderId, ProcessStatus.CLOSED);

      rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE, MqConst.ROUTING_PAYMENT_CLOSE, orderId);
}

service-payment模块接收消息

编写消费者

package com.atguigu.gmall.payment.receiver;

@Component
public class PaymentReceiver {

    @Autowired
    private PaymentService paymentService;

    @SneakyThrows
    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = MqConst.QUEUE_PAYMENT_CLOSE,durable = "true"),
            exchange = @Exchange(value = MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE),
            key = {MqConst.ROUTING_PAYMENT_CLOSE}
    ))
    public void closePayment(Long orderId , Message message, Channel channel){
        if (null != orderId){
            // 关闭交易
            paymentService.closePayment(orderId);
        }
        // 手动ack
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
    }
}

编写关闭交易记录接口与实现类

复制代码
PaymentService
/**
 * 关闭过期交易记录
 * @param orderId
 */
void closePayment(Long orderId);

@Override
public void closePayment(Long orderId) {
    // 设置关闭交易记录的条件  118
    QueryWrapper<PaymentInfo> paymentInfoQueryWrapper = new QueryWrapper<>();
    paymentInfoQueryWrapper.eq("order_id",orderId);
    // 如果当前的交易记录不存在,则不更新交易记录
    Integer count = paymentInfoMapper.selectCount(paymentInfoQueryWrapper);
    if (null == count || count.intValue()==0) return;
    // 在关闭支付宝交易之前。还需要关闭paymentInfo
    PaymentInfo paymentInfo = new PaymentInfo();
    paymentInfo.setPaymentStatus(PaymentStatus.ClOSED.name());
    paymentInfoMapper.update(paymentInfo,paymentInfoQueryWrapper);

}

提交订单超时后会关闭订单

(3)支付宝关闭交易

复制代码
AlipayService接口
/***
 * 关闭交易
 * @param orderId
 * @return
 */
Boolean closePay(Long orderId);

编写实现类

@SneakyThrows
@Override
public Boolean closePay(Long orderId) {
    OrderInfo orderInfo = orderFeignClient.getOrderInfo(orderId);
    AlipayTradeCloseRequest request = new AlipayTradeCloseRequest();
    HashMap<String, Object> map = new HashMap<>();
    // map.put("trade_no",paymentInfo.getTradeNo()); // 从paymentInfo 中获取!
        map.put("out_trade_no",orderInfo.getOutTradeNo());
    map.put("operator_id","YX01");
    request.setBizContent(JSON.toJSONString(map));

    AlipayTradeCloseResponse response = alipayClient.execute(request);
    if(response.isSuccess()){
        System.out.println("调用成功");
        return true;
    } else {
        System.out.println("调用失败");
        return false;
    }
}

编写控制器AlipayController :

http://localhost:8205/api/payment/alipay/closePay/25
// 根据订单Id关闭订单
@GetMapping("closePay/{orderId}")
@ResponseBody
public Boolean closePay(@PathVariable Long orderId){
    Boolean aBoolean = alipayService.closePay(orderId);
    return aBoolean;
}

(4)查询支付交易记录

编写接口:AlipayService

/**
 * 根据订单查询是否支付成功!
  * @param orderId
 * @return
 */
Boolean checkPayment(Long orderId);

编写实现类

@SneakyThrows
@Override
public Boolean checkPayment(Long orderId) {
    // 根据订单Id 查询订单信息
    OrderInfo orderInfo = orderFeignClient.getOrderInfo(orderId);
    AlipayTradeQueryRequest request = new AlipayTradeQueryRequest();
    HashMap<String, Object> map = new HashMap<>();
    map.put("out_trade_no",orderInfo.getOutTradeNo());
    // 根据out_trade_no 查询交易记录
    request.setBizContent(JSON.toJSONString(map));
    AlipayTradeQueryResponse response = alipayClient.execute(request);
    if(response.isSuccess()){
        System.out.println("调用成功");
        return true;
    } else {
        System.out.println("调用失败")
        return false;
    }
}

编写控制器

// 查看是否有交易记录
@RequestMapping("checkPayment/{orderId}")
@ResponseBody
public Boolean checkPayment(@PathVariable Long orderId){
    // 调用退款接口
    boolean flag = alipayService.checkPayment(orderId);
    return flag;
}

没有支付返回false

支付后返回true

在AlipayController 添加查询PaymentInfo 数据接口

查询支付记录

@GetMapping("getPaymentInfo/{outTradeNo}")
@ResponseBody
public PaymentInfo getPaymentInfo(@PathVariable String outTradeNo){
    PaymentInfo paymentInfo = paymentService.getPaymentInfo(outTradeNo, PaymentType.ALIPAY.name());
    if (null!=paymentInfo){
        return paymentInfo;
    }
    return null;
}

(5)PaymentFeignClient 远程接口

创建service-payment-client

package com.atguigu.gmall.payment.client;
@FeignClient(value = "service-payment",fallback = PaymentDegradeFeignClient.class)
public interface PaymentFeignClient {

    @GetMapping("api/payment/alipay/closePay/{orderId}")
    Boolean closePay(@PathVariable Long orderId);

    @GetMapping("api/payment/alipay/checkPayment/{orderId}")
    Boolean checkPayment(@PathVariable Long orderId);

    @GetMapping("api/payment/alipay/getPaymentInfo/{outTradeNo}")
    PaymentInfo getPaymentInfo(@PathVariable String outTradeNo);

}

PaymentDegradeFeignClient实现类

@Component
public class PaymentDegradeFeignClient implements PaymentFeignClient {
    @Override<dependency>
    <groupId>com.atguigu.gmall</groupId>
    <artifactId>service-payment-client</artifactId>
    <version>1.0</version>
</dependency>

    public Boolean closePay(Long orderId) {
        return null;
    }

    @Override
    public Boolean checkPayment(Long orderId) {
        return null;
    }

    @Override
    public PaymentInfo getPaymentInfo(String outTradeNo) {
        return null;
    }
    
}

(6)整合关闭过期订单

在订单service-order项目中添加依赖

<dependency>
    <groupId>com.atguigu.gmall</groupId>
    <artifactId>service-payment-client</artifactId>
    <version>1.0</version>
</dependency>

OrderReceiver 整合代码

复制代码
接口:OrderService
/**
 * 更新过期订单
 * @param orderId
 * @param flag
 */
void execExpiredOrder(Long orderId,String flag);

@Override
public void execExpiredOrder(Long orderId,String flag) {
    // 调用方法 状态
    updateOrderStatus(orderId,ProcessStatus.CLOSED);

    //2代表支付宝有交易记录就是扫码了没有支付
    if ("2".equals(flag)){
        // 发送消息队列,关闭支付宝的交易记录。
        rabbitService.sendMessage(MqConst.EXCHANGE_DIRECT_PAYMENT_CLOSE,MqConst.ROUTING_PAYMENT_CLOSE,orderId);
    }
}
@Autowired
private RabbitService rabbitService;

@Autowired
private PaymentFeignClient paymentFeignClient;
//  监听消息
@SneakyThrows
@RabbitListener(queues = MqConst.QUEUE_ORDER_CANCEL)
public void orderCancel(Long orderId, Message message, Channel channel){
    try {
        //  判断订单id 是否存在!
        if (orderId!=null){
            //  根据订单Id 查询订单对象
            OrderInfo orderInfo = orderService.getById(orderId);
            //  判断
            if(orderInfo!=null && "UNPAID".equals(orderInfo.getOrderStatus()) && "UNPAID".equals(orderInfo.getProcessStatus())){
                //  关闭过期订单! 还需要关闭对应的 paymentInfo ,还有alipay.
                //  orderService.execExpiredOrder(orderId);
                //  查询支付记录信息paymentInfo -远程调用是否存在!
                PaymentInfo paymentInfo = paymentFeignClient.getPaymentInfo(orderInfo.getOutTradeNo());
                //  判断 用户点击了扫码支付
                if(paymentInfo!=null && "UNPAID".equals(paymentInfo.getPaymentStatus())){

                    //  查看是否有支付宝交易记录!
                    Boolean flag = paymentFeignClient.checkPayment(orderId);
                    //  判断
                    if (flag){
                        //  flag = true , 有支付宝记录
                        //  调用关闭接口! 扫码未支付这样才能关闭成功!
                        Boolean result = paymentFeignClient.closePay(orderId);
                        //  判断
                        if (result){
                            //  result = true; 关闭成功!未付款!需要关闭orderInfo, paymentInfo,Alipay
                            orderService.execExpiredOrder(orderId,"2");
                        }else {
                            //  result = false; 表示付款!
                            //  说明已经付款了! 正常付款成功都会走异步通知!
                        }
                    }else {
                        //  没有交易记录,不需要关闭支付!  需要关闭orderInfo, paymentInfo
                          //关闭订单,关闭支付记录
                        orderService.execExpiredOrder(orderId,"2");
                    }

                }else {
                    //  只关闭订单orderInfo!
                    orderService.execExpiredOrder(orderId,"1");
                }
            }
        }
        
    } catch (Exception e) {
        //  写入日志...
        e.printStackTrace();
    }
    //  手动确认
    channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
}

不进行支付

相关推荐
chnyi6_ya几秒前
深度学习的笔记
服务器·人工智能·pytorch
让学习成为一种生活方式5 分钟前
解析药用植物重楼甾体皂苷生物合成中的连续糖基化及其抗真菌作用-文献精读49
linux·数据库·算法·天然产物化学
凯哥是个大帅比42 分钟前
ubuntu20.04 GLIBC从2.35降级到2.31
linux
iHero1 小时前
【Ubuntu】在 Ubuntu 22.04.3 LTS 安装 davfs2 通过 Nextcloud WebDAV 挂载到 Ubuntu 的目录上
linux·ubuntu·nextcloud
心勤则明1 小时前
Netty配置SSL证书加密
服务器·https·ssl
清园暖歌1 小时前
Ubuntu 不重装系统增加交换空间大小
linux·运维·ubuntu·交换空间
黎相思1 小时前
操作系统迁移(CentOs -> Ubuntu)
linux·ubuntu·gitee·centos
写bug如流水1 小时前
在Ubuntu 20.04上安装pgAdmin 4
linux·运维·ubuntu
冰红茶兑滴水1 小时前
Linux 线程控制
linux·c++·算法
IT良1 小时前
while循环及简单案例
linux·服务器