order = $order; $this->retryCount = $retryCount; } /** * Execute the job. */ public function handle(InvoiceService $invoiceService, Discord $discord): void { try { $user = $this->order->customer; $invoice = $this->order->invoice; if (!$user || !$invoice) { Log::error("Không tìm thấy thông tin user hoặc invoice cho order #{$this->order->order_num}"); return; } // Kiểm tra credit if ($user->credit < $this->order->amount) { $errorMessage = "Không đủ credit để thanh toán đơn hàng #{$this->order->order_num}"; Log::error($errorMessage, [ 'user_credit' => $user->credit, 'order_amount' => $this->order->amount ]); $discord->SendErrorMessage($errorMessage, 'ProcessOrderPaymentJob - Insufficient Credit'); return; } // Tạo VM cho các sản phẩm VPS $vmCreationResults = []; $allVMsCreated = true; $hasVMCreationAttempt = false; foreach ($this->order->orderItems as $item) { try { // Chỉ tạo VM cho sản phẩm VPS (product_type = 4) if ($item->product_type == 4) { $hasVMCreationAttempt = true; // Tạo VM và lấy kết quả $vmCreationResult = $this->createVirtualMachine($item); $vmCreationResults[] = [ 'order_item_id' => $item->id, 'product_name' => $item->getProductAttribute()?->name ?? 'Unknown', 'success' => $vmCreationResult ]; if (!$vmCreationResult) { $allVMsCreated = false; } } } catch (\Throwable $e) { Log::error("Lỗi khi tạo VM cho order item #{$item->id}: " . $e->getMessage()); $vmCreationResults[] = [ 'order_item_id' => $item->id, 'product_name' => $item->getProductAttribute()?->name ?? 'Unknown', 'success' => false, 'error' => $e->getMessage() ]; $allVMsCreated = false; } } // Kiểm tra xem có thực sự có VM nào được tạo không if (!$hasVMCreationAttempt) { $errorMessage = "Không có sản phẩm VPS nào được xử lý trong đơn hàng #{$this->order->order_num}"; Log::error($errorMessage); $discord->SendErrorMessage($errorMessage, 'ProcessOrderPaymentJob - No VM Creation Attempt'); return; } // Kiểm tra kết quả tạo VM if (empty($vmCreationResults)) { $errorMessage = "Không có kết quả tạo VM nào được trả về cho đơn hàng #{$this->order->order_num}"; Log::error($errorMessage); $discord->SendErrorMessage($errorMessage, 'ProcessOrderPaymentJob - Empty VM Results'); return; } // Kiểm tra xem có ít nhất một VM thành công không $successfulVMs = array_filter($vmCreationResults, fn($vm) => $vm['success']); $failedVMs = array_filter($vmCreationResults, fn($vm) => !$vm['success']); // Nếu tất cả VM được tạo thành công, tiến hành thanh toán if ($allVMsCreated && count($successfulVMs) > 0) { DB::beginTransaction(); try { // Trừ tiền người dùng $user->decrement('credit', (int) $this->order->amount); // Cập nhật trạng thái hóa đơn và đơn hàng $invoiceService->markAsPaid($invoice); $this->order->update(['status' => OrderStatus::ACTIVE->value]); // Gửi thông báo Discord $discord->SendOrderPaidNotification($invoice); DB::commit(); // Gửi thông báo thành công cho khách hàng $this->sendSuccessNotification($vmCreationResults); } catch (\Throwable $e) { DB::rollBack(); throw $e; } } else { // Có lỗi khi tạo VM hoặc không có VM nào thành công $errorDetails = [ 'order_id' => $this->order->id, 'order_num' => $this->order->order_num, 'vm_results' => $vmCreationResults, 'total_vms' => count($vmCreationResults), 'successful_vms' => count($successfulVMs), 'failed_vms' => count($failedVMs), 'all_vms_created' => $allVMsCreated ]; // Kiểm tra trường hợp đặc biệt: có VPS nhưng không có VM nào thành công if (count($vmCreationResults) > 0 && count($successfulVMs) === 0) { Log::error("Có sản phẩm VPS nhưng không có VM nào được tạo thành công", $errorDetails); $discord->SendErrorMessage(array_merge($errorDetails, [ 'error' => 'Tất cả VM đều thất bại - không có VM nào thành công' ]), 'ProcessOrderPaymentJob - All VMs Failed'); } // Thử lại nếu chưa vượt quá số lần thử if ($this->retryCount < self::MAX_RETRIES) { Log::warning("Có lỗi khi tạo VM, thử lại lần " . ($this->retryCount + 1), $errorDetails); // Thử lại sau 5 phút self::dispatch($this->order, $this->retryCount + 1) ->delay(now()->addMinutes(5)); } else { // Đã thử hết số lần, gửi thông báo lỗi Log::error("Đã thử tạo VM {$this->retryCount} lần nhưng vẫn thất bại", $errorDetails); $discord->SendErrorMessage(array_merge($errorDetails, [ 'error' => 'Không thể tạo VM sau nhiều lần thử', 'retry_count' => $this->retryCount ]), 'ProcessOrderPaymentJob - VM Creation Failed After Retries'); // Gửi thông báo lỗi cho khách hàng $this->sendFailureNotification($vmCreationResults); } } } catch (\Throwable $e) { Log::error("Lỗi trong ProcessOrderPaymentJob: " . $e->getMessage(), [ 'order_id' => $this->order->id, 'order_num' => $this->order->order_num, 'trace' => $e->getTraceAsString() ]); $discord->SendErrorMessage([ 'error' => $e->getMessage(), 'order_id' => $this->order->id, 'order_num' => $this->order->order_num, 'file' => $e->getFile(), 'line' => $e->getLine() ], 'ProcessOrderPaymentJob - Exception'); } } /** * Tạo VM cho một order item */ private function createVirtualMachine(OrderItem $item): bool { try { $vCenter = app(\App\Http\Services\vCenter::class); $discord = app(Discord::class); $vmDataService = app(VMDataService::class); $vmJob = new CreateVirtualMachineJob($item, $this->retryCount > 0); return $vmJob->handle($vCenter, $discord, $vmDataService); } catch (\Throwable $e) { Log::error("Lỗi khi tạo VM cho order item #{$item->id}: " . $e->getMessage(), [ 'order_item_id' => $item->id, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return false; } } /** * Send success notification to customer */ private function sendSuccessNotification(array $vmResults): void { try { $customer = $this->order->customer; // Gửi email thông báo thành công \App\Jobs\Mail\Customer\OrderPaymentSuccessJob::dispatch([ 'customer_email' => $customer->email, 'customer_name' => trim($customer->firstname . ' ' . $customer->lastname), 'order_id' => $this->order->id, 'order_num' => $this->order->order_num, 'amount' => $this->order->amount, 'vm_results' => $vmResults ]); } catch (\Throwable $e) { Log::error('Không thể gửi email thông báo thành công: ' . $e->getMessage()); } } /** * Send failure notification to customer */ private function sendFailureNotification(array $vmResults): void { try { $customer = $this->order->customer; // Gửi email thông báo lỗi \App\Jobs\Mail\Customer\VMCreationFailedJob::dispatch([ 'customer_email' => $customer->email, 'customer_name' => trim($customer->firstname . ' ' . $customer->lastname), 'product_name' => 'Multiple Products', 'order_id' => $this->order->id, 'order_num' => $this->order->order_num, 'error_message' => 'Không thể khởi tạo máy chủ ảo sau nhiều lần thử. Vui lòng liên hệ admin để được hỗ trợ.', 'vm_results' => $vmResults ]); } catch (\Throwable $e) { Log::error('Không thể gửi email thông báo lỗi: ' . $e->getMessage()); } } }