TP5.1 实现超时未支付订单自动关闭
对于这个需求,我以前写过Laravel
版本的。今天想在TP5.1
中实现这个功能,但是网上基本没什么教程可供参考,所以写篇文章仅供大家学习。
一、前台
1、先来加载订单确认页面
当下单成功后,通过 js
跳转到订单确认页,在 checkout.html
中:
{block name="js"}
<script>$(function () {//去付款,就是下单,跳到订单确认页$("#pay").click(function () {var address_id = $(".address").data('id');if (address_id == '') {alert('请先填写一个送货地址~');return false;}$.ajax({type: 'POST',url: '/index/Order/store',success: function (data) {if (data.status == 0) {alert(data.info);location.href = '/index/Cart/index';return false;}//微信支付location.href = '/index/Order/pay/id/' + data.order_id;}})});});
</script>
{/block}
2、在 Order.php
中增加对应方法,代码如下:
/**** 订单确认页* @param $id*/
public function pay($id)
{$order = \app\common\model\Order::with('address')->find($id);return view('order/show_pay', compact('order'));
}
3、修改 show_pay.html
页面代码:
{extend name="layout/app" /}{block name="content"}
<div id="wrapper"><div class="page-order-pay" data-log="在线支付"><div class="box box1"><div class="p1"><span class="icon-checked"></span><span>订单提交成功</span></div><div class="p2"><span style="color: #FF5722">请在30分钟内完成支付,超时订单将自动关闭。</span></div><div class="p2"><p class="count" style="color: #D92E2E"></p></div></div><div class="box box2"><div class="p">订单金额:{$order->total_price}元 订单编号:{$order->out_trade_no}</div><div class="p h_box"><div>收货信息:</div><div class="flex_1">{$order->address->name} {$order->address->tel}<br>{$order->address->province} {$order->address->city} {$order->address->area} {$order->address->detail}</div></div><div class="p">发票类型:个人电子发票 <p>发票抬头:个人</p></div></div><div class="box box3"><div class="head"><span>请选择支付方式</span></div><div class="list"><div class="item active"><div data-log="A0-支付宝" class="inner"><div class="p">微信</div><div class="p right">大额支付推荐使用微信快捷支付</div></div></div></div></div><div class="box box4"><div class="p p1"><p>本次需支付:<span class="hot">{$order->total_price}元</span></p></div></div><div class="box box5"><a href="javascript:;" data-log="bottom-bankgo" class="ui-button"><span>立即支付</span></a></div></div>
</div>
{/block}{block name="js"}
<script>$(function () {window.onload = function () {countDown();function addZero(i) {return i < 10 ? "0" + i : i + "";}function countDown() {var nowtime = new Date();var endtime = new Date({:json_encode($order->create_time)})endtime.setSeconds(endtime.getSeconds() + 30); // 设置30秒// endtime.setMinutes(endtime.getMinutes() + 30); // 设置30分钟var lefttime = parseInt(endtime.getTime() - nowtime.getTime()) / 1000;var m = parseInt(lefttime / 60 % 60);var s = parseInt(lefttime % 60);m = addZero(m);s = addZero(s);document.querySelector(".count").innerHTML = `剩余支付时间:${m} 分 ${s} 秒`;if (lefttime <= 0) {document.querySelector(".count").innerHTML = "订单已失效";return;}setTimeout(countDown, 1000);}}})
</script>
{/block}
上面的这段 js
参考文章 https://blog.csdn.net/LightLinV/article/details/88602302
这里js里面使用 {:json_encode($order->create_time)} 来解析读取订单创建的时间,其实就是把控制器传过来的 $order->create_time 变量变成一个 JSON 字符串,赋值给 JS 的 endtime 变量。
此时,正常步骤下单,出现的页面样式如下:
现在我们看到的时间其实是一个假的时间显示,并不能实现真正的功能。接下来,我们来实现超时未支付关闭订单的功能。
首先我们在 orders
表中增加一个字段 closed
,TINYINT
类型,长度 1
,默认值 1
。其中 1
代表正常订单,0
代表失效订单。
然后执行下面的命令安装消息队列,参考文档:https://github.com/top-think/think-queue
composer require topthink/think-queue 2.0.4
注意:如果是TP6版本请去掉后面的版本号,TP5.1只能安装上面的包。
此举会在项目的config
文件夹里创建queue.php
文件,修改该文件配置如下:
return ['REDIS_CLIENT' => 'predis','REDIS_HOST' => '127.0.0.1','connector' => 'redis' // 这里默认是sync,是一个同步操作,我需要任务延迟执行,所以配置的redis,当然也可用database
];
二、后台
1、我们手动来创建一个任务,在application/job/CloseOrder.php
创建任务文件,在 CloseOrder.php
中添加代码:
<?phpnamespace app\job;use think\queue\Job;
use app\common\model\Order;class CloseOrder
{public function fire(Job $job, $data){$order = Order::where('out_trade_no', $data['out_trade_no'])->find();// 如果已经支付则不需要关闭订单,直接退出if ($order->pay_time) {return;}Order::where('id', $order->id)->update(['closed' => false]);// 循环遍历订单中的商品,将订单中的数量加回到商品的库存中去foreach ($order->orderProducts as $item) {$item->product->addStock($item->num);}if ($job->attempts() > 3) {//通过这个方法可以检查这个任务已经重试了几次了return;}//如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法$job->delete();// 也可以重新发布这个任务$job->release(env('order_ttl')); //$delay为延迟时间}public function failed($data){// ...任务达到最大重试次数后,失败了}
}
然后在 app\common\model\Product
商品模型里面新增方法:
/**** 增加库存* @param $num* @return int*/
public function addStock($num)
{return $this->setInc('stock', $num);
}
这个方法是用于延迟队列任务执行成功后,退回对应库存的
在 app\common\model\OrderProduct.php
中添加代码如下:
public function product()
{return $this->belongsTo('Product', 'product_id');
}
2、触发任务
当事务提交成功后,执行任务处理器。在 app/index/controller/Order.php
控制器的 store
方法中,添加如下代码:
use think\Queue;
use app\job\CloseOrder;
.
.
.
// 提交事务
Db::commit();
Queue::later(env('order_ttl'), CloseOrder::class, $data = $order, $queue = null);
上面的order_ttl是延迟时间,我们在.env文件中,配置时间为30,代表30秒。其他参数解释,请参考上面消息队列的文档,已经解释的很清楚了。
.env
配置如下:
order_ttl=30
接下来安装redis
!!!这里说明一下,根据自己电脑环境的
PHP版本来做对应安装,若之前已安装过下面的3、4步,请忽略!!!
3、安装 Redis
服务
brew install redis #Mac电脑直接全局安装
启动服务
redis-server
成功后,你会看到如下图所示:
我的电脑目前安装的PHP
版本是7.4.5
php -v #查看版本 PHP 7.4.5 (cli)which php #查看PHP本地路径 /usr/local/bin/php
4、安装php-redis
扩展,参考地址:https://pecl.php.net/package/redis/。
这里我下载的是redis-5.0.2
, 点击右边的版本号即可下载,下载后在文件目录依次执行下面的命令解压编译:
tar xzf redis-5.0.2.tgz #解压
cd redis-5.0.2phpize ./configure --with-php-config=/usr/local/bin/php-config # 这里的路径请换成自己的make install #编译安装
接下来在已启用的php
配置文件php.ini
启用redis
,路径视安装路径为准,我的路径为:/usr/local/etc/php/php.ini
.在配置文件中添加:
extension=redis.so;
检查redis
扩展是否成功安装,有redis
字样输出即是成功安装
php -m | grep redis
5、由于在config/queue.php
文件中配置了predis
,所以执行最后一步安装:
composer require predis/predis
6、监听任务并执行
php think queue:listenphp think queue:work
7、测试
进入商品表,任意选择一个商品并将其加入购物车,记住库存数量,提交订单。
经测试,发现下单后,对应商品的库存减少了,30
秒后,当任务执行成功,发现订单表的 closed
字段有原来的 1
修改成了 0
,并且库存还原。
TP5.1 实现超时未支付订单自动关闭相关推荐
- 1.超时未支付订单处理
1.超时未支付订单处理 1.1 需求分析 超过限定时间并未支付的订单,我们需要进行超时订单的处理:先调用微信支付api,查询该订单的支付状态.如果未支付调用关闭订单的api,并修改订单状态为已关闭,并 ...
- B2C电商项目(第十三天、超时未支付订单处理、订单批量发货、确认收货与自动收货)
订单处理 课程内容: 通过 rabbitmq的延迟消息完成超时订单处理 完成批量发货功能,了解第三方物流系统 完成自动收货功能 一.超时未支付订单处理 1.1 需求分析 超过限定时间并未支付的订单,我 ...
- 从零开发短视频电商 30分钟未支付订单自动关闭、七天自动确认收货等延迟任务问题
文章目录 常见延迟任务 常见解决方案 主动形式 被动形式 基于Redis实现ZSet的方式.键空间通知的方式 ZSet的方式 键空间通知的方式 RocketMQ延迟消息 延迟消息级别配置 客户端发送延 ...
- 定时任务 - 定时关闭超期未支付订单
/*** 关闭超时未支付订单*/ public void closeOrder(); @Transactional(propagation = Propagation.REQUIRED) @Overr ...
- 订单超时未支付自动关闭的几种实现方案
做电商,就会遇到订单超时问题,而且还经常被拿来面试提问! 今天,周末放假,抽时间给大家总结了几种订单超时未支付自动关闭的实现方案.同时,我手机还有几套电商类从零架构到实现的视频教程,如有需要,可以加我 ...
- Java秒杀系统实战系列~RabbitMQ死信队列处理超时未支付的订单(转)
转自: https://juejin.cn/post/6844903903130042376 文末有源代码,非常棒 摘要: 本篇博文是"Java秒杀系统实战系列文章"的第十篇,本篇 ...
- 订单超时未支付的解决方案
订单超时未支付的解决方案 定时任务实现 被动取消 JDK的延迟队列 代码演示 时间轮算法 代码演示 Redis zset 实现延迟任务 代码演示 MQ 延时消息 代码演示 写在最后 在前面的文章 第三 ...
- Java秒杀系统实战系列~定时任务补充处理超时未支付的订单
摘要: 本篇博文是"Java秒杀系统实战系列文章"的第十一篇,本篇博文我们将借助定时任务调度组件来辅助"失效超时未支付的订单记录"的处理,用以解决上篇博文中采用 ...
- rabbitMQ实现订单超时未支付自动取消订单
前期准备 下面展示一些 内联代码片. 1.配置文件,导入jar包 server:port: 8983 spring:application:name: API-RABBITMQdatasource:t ...
最新文章
- arXiv | 图表示方法驱动大分子计算研究
- Thymeleaf在循环时设置递增序号
- 分享一些书籍,方方面面,很多值得一读
- C# Windows Phone 8 WP8 开发,取得手机萤幕大小两种方法。
- cpu真实占用率检測工具
- bigquery_到Google bigquery的sql查询模板,它将您的报告提升到另一个层次
- 关于用户自定义控件与引用该控件的页面之间的javascript脚本冲突
- Linux命令学习手册-gpg命令
- 外星人进化_外星人真的比人类强大吗?科学家给出几种猜想,你认同吗?
- 存用部首查字典如何查_SCI文献阅读技巧:3位博士总结如何看文献,干货满满!...
- android在线音乐播放器教程,简单实现Android本地音乐播放器
- 操作日志 | 上证50是续命仙丹还是饮鸩毒药?
- 蓝牙设备删除失败_十代混动雅阁车载蓝牙连接不上怎么办?
- 刘禹锡最经典诗文10首,每一首都是千古名作,读懂受益一生
- 行车记录仪摄像头4线
- 机械结构day_13
- windows 自带计算器介绍
- 怎么使用GK888CN打印机批量打印条码
- 基于MATLAB的BPSK和QPSK调制的性能比较
- 基于imx6ull打造流媒体视频监控:ffmpeg + nginx + rtmp