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

目录:

(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.  先获取到原始订单 1072.  将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);//设置付订单idsubOrderInfo.setParentOrderId(orderId);// 赋值仓库IdsubOrderInfo.setWareId(wareId);// 计算子订单的金额: 必须有订单明细// 获取到子订单明细// 声明一个集合来存储子订单明细ArrayList<OrderDetail> orderDetails = new ArrayList<>();//获取父订单商品总明细List<OrderDetail> orderDetailList = orderInfoOrigin.getOrderDetailList();// 表示主主订单明细中获取到子订单的明细if (orderDetailList != null && orderDetailList.size() > 0) {for (OrderDetail orderDetail : orderDetailList) {// 获取子订单明细的商品Idfor (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) {// orderInfoupdateOrderStatus(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 {@Autowiredprivate 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);}// 手动ackchannel.basicAck(message.getMessageProperties().getDeliveryTag(),false);}
}

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

PaymentService
/*** 关闭过期交易记录* @param orderId*/
void closePayment(Long orderId);
@Override
public void closePayment(Long orderId) {// 设置关闭交易记录的条件  118QueryWrapper<PaymentInfo> paymentInfoQueryWrapper = new QueryWrapper<>();paymentInfoQueryWrapper.eq("order_id",orderId);// 如果当前的交易记录不存在,则不更新交易记录Integer count = paymentInfoMapper.selectCount(paymentInfoQueryWrapper);if (null == count || count.intValue()==0) return;// 在关闭支付宝交易之前。还需要关闭paymentInfoPaymentInfo 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;}@Overridepublic Boolean checkPayment(Long orderId) {return null;}@Overridepublic 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,AlipayorderService.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);
}

不进行支付 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/53981.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

指针与函数传递

title: 指针与函数传递 date: 2024-09-14 21:33:51 description: 函数传递多个元素 tags: c language skaiuijing 理解指针 很多人经常使用指针&#xff0c;看到这个标题可能不屑一顾。但笔者想说&#xff0c;把指针当作理所当然而不去探索它的本质&#xff0c;这是不对的。…

Go语言错误处理详解

Go语言以其简洁、高效和并发能力著称。在实际开发中&#xff0c;错误处理是一个不可避免且至关重要的部分。本文将深入探讨Go语言中的错误处理机制&#xff0c;涵盖其原理、使用方法、最佳实践&#xff0c;并提供丰富的代码示例和中文注释。 一、错误处理的基本概念 在Go语言…

7. 探究模型参数与显存的关系以及不同精度造成的影响

这篇文章将探讨两个重点&#xff1a; 模型参数与显存&#xff08;GPU 内存&#xff09;之间的关系不同精度的导入方式&#xff0c;以及它们对显存和性能的影响 理解这些概念会让你在模型的选择上更加游刃有余。 文章目录 模型参数与显存的关系模型参数量与内存占用GPU 显存需求…

JMeter脚本开发

环境部署 Ubuntu系统 切换到root用户 sudo su 安装上传下载的命令 apt install lrzsz 切换文件目录 cd / 创建文件目录 mkdir java 切换到Java文件夹下 cd java 输入rz回车 选择jdk Linux文件上传 解压安装包 tar -zxvf jdktab键 新建数据库 运行sql文件 选择sql文件即…

基于51单片机的电饭锅控制系统proteus仿真

地址&#xff1a; https://pan.baidu.com/s/1CGyg6uPhFI0MeaBWwe_HAg 提取码&#xff1a;1234 仿真图&#xff1a; 芯片/模块的特点&#xff1a; AT89C52/AT89C51简介&#xff1a; AT89C52/AT89C51是一款经典的8位单片机&#xff0c;是意法半导体&#xff08;STMicroelectro…

RedisTemplate操作ZSet的API

文章目录 ⛄概述⛄常见命令有⛄RedisTemplate API❄️❄️ 向集合中插入元素&#xff0c;并设置分数❄️❄️向集合中插入多个元素,并设置分数❄️❄️按照排名先后(从小到大)打印指定区间内的元素, -1为打印全部❄️❄️获得指定元素的分数❄️❄️返回集合内的成员个数❄️❄…

前端网络层性能优化

前言 在数字时代&#xff0c;速度已成为互联网体验的关键。用户对网页加载时间的容忍度越来越低&#xff0c;每一毫秒的延迟都可能导致用户的流失。根据谷歌的研究&#xff0c;页面加载时间超过3秒的网站&#xff0c;其跳出率会增加120%。在这个以用户为中心的网络世界里&…

Git换行符自动转换参数core.autocrlf的用法

core.autocrlf 是 Git 中用于控制换行符自动转换的配置选项。它有以下几个可能的值&#xff1a; 1. true 作用&#xff1a;在 checkin 时将 CRLF 转换为 LF&#xff0c;在 checkout 时将 LF 转换为 CRLF。适用场景&#xff1a;适用于 Windows 用户&#xff0c;希望在本地文件…

LineageOS刷机教程

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ LineageOS 是一个基于 Android 开源项目&#xff08;AOSP&#xff09;的开源操作系统&#xff0c;主要由社区开发者维护。它起源于 CyanogenMod 项目&#xff…

10年Python程序员教你多平台采集10万+电商数据【附实例】

10万级电商数据采集需要注意什么&#xff1f; 在进行10万级电商数据采集时&#xff0c;有许多关键因素需要注意&#xff1a; 1. 采集平台覆盖&#xff1a;确保可以覆盖主流的电商平台&#xff0c;如淘宝、天猫、京东、拼多多等。 2. 数据字段覆盖&#xff1a;检查是否可以对平…

go 笔记

数据结构与 方法&#xff08;增删改查&#xff09; 安装goland,注意版本是2024.1.1&#xff0c;不是2024.2.1&#xff0c;软件下载地址也在链接中提供了 ‘go’ 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 在 Windows 搜索栏中输入“环境变量”&#…

架构理论碰撞:对比TOGAF、Zachman、DODAF和FEAF等主流架构框架

信息架构框架对比分析&#xff1a;选择适合企业的最佳方案 在企业数字化转型过程中&#xff0c;信息架构的设计与实施至关重要。成功的信息架构能够有效地支持业务流程优化&#xff0c;提升数据管理效率&#xff0c;推动技术创新。然而&#xff0c;不同的信息架构框架各有其独…

linux gcc 静态库的简单介绍

在 Linux 上&#xff0c;使用 GCC 编译器来创建和调用静态库时&#xff0c;涉及的实现原理和调用机制可以分为以下几个步骤&#xff1a; 1. 静态库的创建 静态库&#xff08;通常以 .a 结尾&#xff09;是由多个目标文件&#xff08;.o 文件&#xff09;打包在一起的归档文件…

判断线是否相交、判断点是否在线上、求线相交交点

先定义个点、线结构 typedef struct tagStruVertex {double x;double y;double distanceTo(const tagStruVertex& point) const{return sqrt((x - point.x) * (x - point.x) (y - point.y) * (y - point.y));}bool equal(const tagStruVertex& point) const{if (poin…

COMTRADE binary数据文件解析

一、COMTRADE 二进制文件的解析需要用到cfg文件中的配置信息&#xff0c;以及dat文件中的数据。 二、cfg文件 1、cfg文件整体配置 2、cfg文件实例 厂站名&#xff0c;记录装置&#xff0c;COMTRADE标准版本年号 SMARTSTATION,IED123,2013 总通道数&#xff0c;模拟通道编号&…

记录word转xml文件踩坑

word文件另存为xml文件后&#xff0c;xml文件乱码 解决方法&#xff1a; 1.用word打开.docx文件 2.另存为xml文件 3.点击工具 -> Web选项 -> 编码&#xff0c;选择UTF-8 4.点击确定 5.使用notpad打开xml文件 6.使用xml tool进行xml格式化即可。

uniapp小程序,使用腾讯地图获取定位

本篇文章分享一下在实际开发小程序时遇到的需要获取用户当前位置的问题&#xff0c;在小程序开发过程中经常使用到获取定位功能。uniapp官方也提供了相应的API供我们使用。 官网地址&#xff1a;uni.getLocation(OBJECT)) 官网获取位置的详细介绍这里就不再讲述了&#xff0c;大…

安宝特方案 | 医疗AR眼镜,重新定义远程会诊体验

【AR眼镜&#xff1a;重新定义远程会诊体验】 在快速发展的医疗领域&#xff0c;安宝特医疗AR眼镜以其尖端技术和创新功能&#xff0c;引领远程会诊的未来&#xff0c;致力于为为医生和患者带来更高效、精准和无缝的医疗体验。 探索安宝特医疗AR眼镜如何在医疗行业中引领新风潮…

视频推拉流/直播点播EasyDSS平台安装失败并报错“install mediaserver error”是什么原因?

TSINGSEE青犀视频推拉流/直播点播EasyDSS平台支持音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务&#xff0c;在应用场景中可实现视频直播、点播、转码、管理、录像、检索、时移回看等。此外&#xff0c;平台还支持用户自行上传视频文件&#xff0c;也可…

Gitbook 本地安装教程

Gitbook 本地安装教程 安装 node [nodejs的v10.21.0版本&#xff0c;下载地址&#xff1a;https://nodejs.org/dist/v10.21.0/node-v10.21.0-x64.msi] 其他版本有问题 npmnpm install -g gitbook-cligitbook init [初始化目录结构]gitbook build [编译]gitbook serve [运行] …