| 
					
					
					
				 | 
				@ -0,0 +1,79 @@ | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				<?php | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				namespace App\Console\Commands; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				use App\Common\OrderStatus; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				use App\Models\Order; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				use App\Models\Product; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				use Illuminate\Console\Command; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				use Illuminate\Support\Facades\DB; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				class OrderTimeout extends Command | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				{ | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    /** | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     * The name and signature of the console command. | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     * | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     * @var string | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     */ | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    protected $signature = 'order:timeout'; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    /** | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     * The console command description. | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     * | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     * @var string | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     */ | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    protected $description = '订单超时未支付,取消订单并返回库存'; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    /** | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     * Create a new command instance. | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     * | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     * @return void | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				     */ | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    public function __construct() | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				        parent::__construct(); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
					/** | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
					 * Execute the console command. | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
					 * | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
					 * @return int | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
					 */ | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    public function handle() | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
					{ | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
						//记录最小ID,下次查询时按ID正序查询,只处理大于该ID的订单,避免重复扫描数据库
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
						$min_id = Order::query()->where('status', OrderStatus::UNPAID)->min('id'); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    	while (true) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
							Order::query() | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
								->where([ | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
									['status', '=', OrderStatus::UNPAID], | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
									['id', '>=', $min_id], | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
								]) | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
								->whereNotNull('timeout') | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
								->orderBy('id') | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
								->chunk(100, function ($order) use (&$min_id) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
									foreach ($order as $v) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
										if (!is_null($v->timeout) && strtotime($v->timeout) < time()) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
											DB::beginTransaction(); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
											try { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
												//取消订单
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
												$v->status = OrderStatus::CANCEL; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
												$v->save(); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
												//加回库存
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
												Product::whereIn('id', explode(',', $v->product_ids))->increment('stock', $v->num); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				
 | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
												DB::commit(); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
											} catch (\Exception $exception) { | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
												DB::rollBack(); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
											} | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
										} | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
										$min_id = $v->id; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
									} | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
								}); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
							$this->line('[' . date('Y-m-d H:i:s') . "] ID游标:$min_id ,等待下一个任务"); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
							sleep(3); | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
						} | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
						return 0; | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				    } | 
			
		
		
	
		
			
				 | 
				 | 
				 | 
				 | 
				 | 
				} |