700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > TP5.1 实现超时未支付订单自动关闭

TP5.1 实现超时未支付订单自动关闭

时间:2022-02-23 07:58:08

相关推荐

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}元 &nbsp;&nbsp; 订单编号:{$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参考文章 /LightLinV/article/details/88602302

这里js里面使用 {:json_encode($order->create_time)} 来解析读取订单创建的时间,其实就是把控制器传过来的 $order->create_time 变量变成一个 JSON 字符串,赋值给 JS 的 endtime 变量。

此时,正常步骤下单,出现的页面样式如下:

现在我们看到的时间其实是一个假的时间显示,并不能实现真正的功能。接下来,我们来实现超时未支付关闭订单的功能。

首先我们在orders表中增加一个字段closedTINYINT类型,长度1,默认值1。其中1代表正常订单,0代表失效订单。

然后执行下面的命令安装消息队列,参考文档:/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扩展,参考地址:/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,并且库存还原。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。