关于Laravel取消超时未支付订单的菜鸡解决方案(定时任务)

由 Jefsky 发布于 2024-03-04

需求是这样的:

很多时候用户下单之后不会立刻结账付款,把订单一直挂着,甚至有些用户久而久之把订单忘记了。这样会导致库存一直被占用,经营无法正常进行了。所以,建议给用户订单一个超时时间,够钟就系统自动取消订单。

大概思想

用的是Laravel里的任务调度,每分钟调度一次,执行查询所有没确定的订单,然后统一取消。弊端就是时效性有点欠缺吧,固定时间执行,会出现订单时间到了,但是还没到任务调度时间。还有个问题就是,固定每分钟执行,就算明知道没有新订单了,还是会去调度,如果数据量大,问题就很大了。

操作

创建一个命令文件

php artisan make:command CancelOrdersByUnpaid

编辑 app/Console/Commands/CancelOrdersByUnpaid.php 文件:

namespace App\Console\Commands;

use App\Helpers\ResponseEnum;
use App\Models\ShopOrder;
use App\Service\Api\ShopOrderGoodsService;
use App\Service\Api\UserCouponService;
use Illuminate\Console\Command;
use Carbon\Carbon;
use Illuminate\Support\Facades\Log;

class CancelUnpaidOrders extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'orders:cancel';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Command description';

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $unpaidOrders = ShopOrder::where('status', '0')->where('add_time', 'subHours(24)))->get();
        if(!empty($unpaidOrders)){
            foreach ($unpaidOrders as $order) {
                $order->status = '-1';
                $order->save();
                ShopOrderGoodsService::cancelDataByOrderId($order->id);
                if ($order->user_coupon_id) {
                    $update_data['id'] = $order->user_coupon_id;
                    $update_data['user_id'] = $order->user_id;
                    $update_data['is_use'] = '0';
                    UserCouponService::updateInfoByOrder($update_data);
                }
            }
        }
        Log::info('取消订单定时任务执行'.time());
        return Command::SUCCESS;
    }
}

修改 app/Console/Kernel.php 文件,注册定时任务:

protected function schedule(Schedule $schedule)
    {
        // $schedule->command('inspire')->hourly();
        $schedule->command('orders:cancel')->everyMinute()->onSuccess(function () {
            Log::info('schedule任务执行成功'.time());
        })
        ->onFailure(function () {
            Log::info('schedule任务执行失败'.time());
        });

        Log::info('schedule任务'.time());
    }

配置服务器Cron

crontab -e 打开cron配置

添加 * * * * * cd /www/wwwroot/project && php artisan schedule:run >> /dev/null 2>&1

执行 php artisan schedule:run

至此 Laravel取消超时未支付订单的菜鸡解决方案 基本完成