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

目录:

(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.rhkb.cn/news/424507.html

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

相关文章

探索Python轻量级数据库:TinyDB的奇妙之旅

文章目录 探索Python轻量级数据库&#xff1a;TinyDB的奇妙之旅背景&#xff1a;为何选择TinyDB&#xff1f;什么是TinyDB&#xff1f;如何安装TinyDB&#xff1f;简单库函数使用方法场景应用常见Bug及解决方案总结 探索Python轻量级数据库&#xff1a;TinyDB的奇妙之旅 背景&…

Redis入门2

在java中操作Redis Redis的Java客户端 Redis 的 Java 客户端很多&#xff0c;常用的几种: Jedis Lettuce Spring Data Redis Spring Data Redis 是 Spring 的一部分&#xff0c;对 Redis 底层开发包进行了高度封装。 在 Spring 项目中&#xff0c;可以使用Spring Data R…

Vue介绍、窗体内操作、窗体间操作学习

系列文章目录 第一章 基础知识、数据类型学习 第二章 万年历项目 第三章 代码逻辑训练习题 第四章 方法、数组学习 第五章 图书管理系统项目 第六章 面向对象编程&#xff1a;封装、继承、多态学习 第七章 封装继承多态习题 第八章 常用类、包装类、异常处理机制学习 第九章 集…

【Linux】Ubuntu 22.04 shell实现MySQL5.7 tar 一键安装

参考 https://blog.csdn.net/qq_35995514/article/details/134350572?spm1001.2014.3001.5501 源文章是centos 的 教程&#xff0c;这里为了大家的方便&#xff0c;再原作者基础上做了修改&#xff0c;记录了ubuntu的22.04的我的配置&#xff0c;加了一个删除原有mysql 的脚本…

【诉讼流程-健身房-违约认定-私教课-诉讼书前提材料整理-民事诉讼-自我学习-铺平通往法律的阶梯-讲解(2)】

【诉讼流程-健身房-违约-私教课-前期法律流程-民事诉讼-自我学习-铺平通往法律的阶梯-讲解&#xff08;2&#xff09;】 &#xff08;1&#xff09;前言说明1、目的2、一个小测试1、更换原教练2、频繁更换教练3、上课估计拖课&#xff0c;占用上课时间&#xff0c;抽烟等。4、以…

Python计算机视觉 第10章-OpenCV

Python计算机视觉 第10章-OpenCV OpenCV 是一个C 库&#xff0c;用于&#xff08;实时&#xff09;处理计算视觉问题。实时处理计算机视觉的 C 库&#xff0c;最初由英特尔公司开发&#xff0c;现由 Willow Garage 维护。OpenCV 是在 BSD 许可下发布的开源库&#xff0c;这意味…

2024/9/11学校教的响应式前端能学到什么?

9.11 1&#xff09;砌砖 确定整体框架&#xff0c;而不是想到一点写一点&#xff0c;类似盖大楼&#xff0c;不是想到哪盖到哪&#xff0c;先砌砖&#xff0c;再装修 砌砖前先划分好砌砖范围(初始化样式) 清除body自带的内外边距 * { margin: 0; padding: 0; }去掉li的小圆点…

【新片场-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…

微信小程序开发第三课

1 wxml语法 1.1 模版语法 # 1 在页面 xx.js 的 Page() 方法的 data 对象中进行声明定义 # 2 在xx.wxml 中使用 {{}} 包裹&#xff0c;显示数据 # 3 可以显示如下&#xff0c;不能编写js语句或js方法-变量-算数运算-三元运算-逻辑判断# 4 只是单纯通过赋值&#xff0c;js中…

快速生成服务器响应json-server的安装和使用

json-server介绍地址:https://www.geeksforgeeks.org/json-server-setup-and-introduction/ 1.json-server是什么? 基于自定义的json文件,快速生成服务端响应,可用于前端调试接口 2.安装和卸载json-server 2.1 安装: 使用npm命令: npm install -g json-server 2.2 卸载 npm …

工厂方法模式和抽象工厂模式

工厂方法模式 一个工厂只能创建一种产品 工厂方法模式的结构 工厂方法模式包含以下4个角色 Product&#xff08;抽象产品&#xff09; ConcreteProduct&#xff08;具体产品&#xff09; Factory&#xff08;抽象工厂&#xff09; ConcreteFactory&#xff08;具体工厂…

(论文解读)Visual-Language Prompt Tuning with Knowledge-guided Context Optimization

Comment: accepted by CVPR2023 基于知识引导上下文优化的视觉语言提示学习 摘要 提示调优是利用任务相关的可学习标记将预训练的视觉语言模型&#xff08;VLM&#xff09;适应下游任务的有效方法。基于CoOp的代表性的工作将可学习的文本token与类别token相结合&#xff0c;…

项目需求 | MySQL增量备份与恢复的完整操作指南

目录 一、MySql数据库增量备份的工作原理 1、全量备份与增量备份 2、增量备份原理 二、进行增量备份 步骤1&#xff1a;启用二进制日志 使用 SHOW VARIABLES 命令查看二进制日志状态 步骤2&#xff1a;执行增量备份脚本 三、使用增量备份恢复损坏的数据库 步骤1&#…

WSL安装Redis

前言 本来一直是在虚拟机的Ubuntu开发 但是 搞着搞着内存不足 导致我某些数据损坏了 然后目前迁移到Wsl开发 运行WSL的相较于虚拟机你不需要很多的性能开销&#xff01; 我只是代码开发和git交互&#xff0c;如果是搞逆向还是虚拟机。 记录一下redis 安装卸载 免得以后又忘了…

java基于PDF底层内容流的解析对文本内容进行编辑

本文实现了基于坐标位置对PDF内容的底层修改而非覆盖&#xff0c;因此不会出现在某些高级PDF编辑器中可以移除插入内容或者文件随着编辑次数增多而大幅增大&#xff08;原因是原内容还在文件中&#xff09;的问题&#xff0c;而且使用的pdfbox是一个开源的、免费的PDF处理库&am…

SSHamble:一款针对SSH技术安全的研究与分析工具

关于SSHamble SSHamble是一款功能强大的SSH技术安全分析与研究工具&#xff0c;该工具基于Go语言开发&#xff0c;可以帮助广大研究人员更好地分析SSH相关的安全技术与缺陷问题。 功能介绍 SSHamble 是用于 SSH 实现的研究工具&#xff0c;其中包含下列功能&#xff1a; 1、针…

ESP01的AT指令连接到阿里云平台

物联网平台提供安全可靠的设备连接通信能力&#xff0c;支持设备数据采集上云&#xff0c;规则引擎流转数据和云端数据下发设备端。此外&#xff0c;也提供方便快捷的设备管理能力&#xff0c;支持物模型定义&#xff0c;数据结构化存储&#xff0c;和远程调试、监控、运维。总…

移动UI案例:工具类app整套案例

工具类App是指提供各种实用工具和功能的手机应用程序。这些工具可以包括但不限于日历、闹钟、备忘录、翻译、计算器、单位转换、天气预报、地图导航、音乐播放器、相机、视频编辑等。这些工具类App能够帮助用户解决日常生活和工作中的各种问题&#xff0c;提高效率和便利性。 …

Java数据结构(十)——冒泡排序、快速排序

文章目录 冒泡排序算法介绍代码实现优化策略复杂度和稳定性 快速排序算法介绍优化策略非递归实现代码演示复杂度和稳定性 冒泡排序 算法介绍 冒泡排序是一种简单的排序算法。它重复地遍历要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就交换。遍历…

多线程篇(其它容器- CopyOnWriteArrayList)(持续更新迭代)

一、CopyOnWriteArrayList&#xff08;一&#xff09; 1. 简介 并发包中的并发List只有CopyOnWriteArrayList。 CopyOnWriteArrayList是一个线程安全的ArrayList&#xff0c;对其进行的修改操作都是在底层的一个复制的数 组&#xff08;快照&#xff09;上进行的&#xff0…