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

目录:

(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,一经查实,立即删除!

相关文章

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为打印全部❄️❄️获得指定元素的分数❄️❄️返回集合内的成员个数❄️❄…

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;不同的信息架构框架各有其独…

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;也可…

MongoDB日志级别

日志 查看当前的日志级别 根据你提供的 MongoDB 命令结果&#xff0c;命令 db.adminCommand({ getParameter: "logComponentVerbosity" }) 返回了 "ok" : 0&#xff0c;这意味着命令执行失败&#xff0c;没有成功获取到日志级别的配置信息。错误信息 &quo…

【JAVA入门】Day45 - 压缩流 / 解压缩流

【JAVA入门】Day45 - 压缩流 / 解压缩流 文章目录 【JAVA入门】Day45 - 压缩流 / 解压缩流一、解压缩流二、压缩流 在文件传输过程中&#xff0c;文件体积比较大&#xff0c;传输较慢&#xff0c;因此我们发明了一种方法&#xff0c;把文件里的数据压缩到一种压缩文件中&#x…

[苍穹外卖]-10WebSocket入门与实战

WebSocket WebSocket是基于TCP的一种新的网络协议, 实现了浏览器与服务器的全双工通信, 即一次握手,建立持久连接,双向数据传输 区别 HTTP是短连接, WebSocket是长连接HTTP单向通信, 基于请求响应模型WebSocket支持双向通信 相同 HTTP和WebSocket底层都是TCP连接 应用场景…

JVM 调优篇7 调优案例1-堆空间的优化解决

一 jvm优化 1.1 优化实施步骤 1)减少使用全局变量和大对象&#xff1b; 2)调整新生代的大小到最合适&#xff1b; 3)设置老年代的大小为最合适&#xff1b; 4)选择合适的GC收集器&#xff1b; 1.2 关于GC优化原则 多数的Java应用不需要在服务器上进行GC优化&#xff1b…

【ArcGISProSDK】初识

ArcGIS Pro SDK 提供四种主要的可扩展性模式&#xff1a;加载项、托管配置、插件数据源和 CoreHost 应用程序。 各模块文件对比 API 核心 核心程序集位于 {ArcGIS Pro 安装文件夹}\bin 中。 程序集描述ArcGIS.Core.dll 提供 CIM、地理数据库、几何图形和公共设施网络 API。 …

Notepad++插件:TextFX 去除重复行

目录 一、下载插件 TextFX Characters 二、去重实操 2.1 选中需要去重的文本 2.2 操作插件 2.3 结果展示 2.3.1 点击 Sort lines case sensitive (at column) 2.3.2 点击 Sort lines case insensitive (at column) 一、下载插件 TextFX Characters 点【插件】-【插件管理…

从头开始学MyBatis—02基于xml和注解分别实现的增删改查

首先介绍此次使用的数据库结构&#xff0c;然后引出注意事项。 通过基于xml和基于注解的方式分别实现了增删改查&#xff0c;还有获取参数值、返回值的不同类型对比&#xff0c;帮助大家一次性掌握两种代码编写能力。 目录 数据库 数据库表 实体类 对应的实体类如下&#x…

KTM580030bit 绝对角度细分器支持最多 4096 对极与一键非线性自校准集成双 16bit 2M SAR ADC

KTM5800 是一款 30bit 绝对角度细分 4096 对极编码细分器&#xff0c;可以与磁电阻传感器&#xff08; AM R/TMR &#xff09;搭配&#xff0c;构成一个高速高精度的非接触磁性编码器模块。它具有以非常高的采样速率 读取传感器上的差分模拟正弦和余弦信号的能力&#xf…