update bug

This commit is contained in:
Pham Bao
2025-07-29 22:49:14 +07:00
parent b048edee11
commit 21a2dfe855
15 changed files with 540 additions and 158 deletions
@@ -0,0 +1,245 @@
<?php
namespace App\Jobs\VirtualMachine\Create;
use App\Http\Services\Telegram;
use App\Http\Services\vCenter;
use App\Models\ModuleVmware;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;
class AssignIPJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public string $vmId;
public int $moduleVmwareId;
public string $availableIP;
/**
* Create a new job instance.
*/
public function __construct(string $vmId, int $moduleVmwareId, string $availableIP)
{
$this->vmId = $vmId;
$this->moduleVmwareId = $moduleVmwareId;
$this->availableIP = $availableIP;
}
/**
* Execute the job.
*/
public function handle(vCenter $vCenter, Telegram $telegram)
{
try {
Log::info('🔧 Bắt đầu AssignIPJob', [
'vm_id' => $this->vmId,
'module_vmware_id' => $this->moduleVmwareId,
'assigned_ip' => $this->availableIP
]);
// Lấy thông tin ModuleVmware
$moduleVmware = ModuleVmware::with(['ipAddress.host.datacenter.vCenter'])->find($this->moduleVmwareId);
if (!$moduleVmware || !$moduleVmware->ipAddress) {
Log::error('❌ Không tìm thấy ModuleVmware hoặc IP address', [
'vm_id' => $this->vmId,
'module_vmware_id' => $this->moduleVmwareId
]);
$telegram->SendErrorMessage([
'error' => 'ModuleVmware or IP address not found',
'vm_id' => $this->vmId,
'module_vmware_id' => $this->moduleVmwareId
], 'AssignIPJob - Data Not Found');
return;
}
// Login vào vCenter
$vcenter = $moduleVmware->ipAddress->host->datacenter->vCenter;
if (!$vCenter->loginServer($vcenter)) {
Log::error('❌ Không thể login vào vCenter cho AssignIP', [
'vm_id' => $this->vmId,
'vcenter_host' => $vcenter->host
]);
$telegram->SendErrorMessage([
'error' => 'Cannot login to vCenter',
'vm_id' => $this->vmId,
'vcenter_host' => $vcenter->host
], 'AssignIPJob - vCenter Login Failed');
return;
}
// Kiểm tra OS family và assign IP
$this->handleIPAssignment($vCenter, $this->vmId, $moduleVmware, $this->availableIP, $telegram);
} catch (\Throwable $e) {
Log::error('❌ Lỗi trong AssignIPJob: ' . $e->getMessage(), [
'vm_id' => $this->vmId,
'module_vmware_id' => $this->moduleVmwareId,
'error' => $e->getMessage(),
'trace' => $e->getTraceAsString()
]);
$telegram->SendErrorMessage([
'error' => $e->getMessage(),
'vm_id' => $this->vmId,
'module_vmware_id' => $this->moduleVmwareId,
'file' => $e->getFile(),
'line' => $e->getLine()
], 'AssignIPJob - Exception');
}
}
/**
* Handle IP assignment based on OS family
*/
private function handleIPAssignment(vCenter $vCenter, string $vmId, ModuleVmware $moduleVmware, string $availableIP, Telegram $telegram): void
{
try {
// Kiểm tra OS family trước khi assign IP
$osFamily = $this->checkVMOSFamily($vCenter, $vmId);
if ($osFamily === 'WINDOWS') {
Log::info('✅ Phát hiện Windows VM, bắt đầu assign IP', [
'vm_id' => $vmId,
'os_family' => $osFamily,
'assigned_ip' => $availableIP
]);
// Assign IP cho Windows VM
$assignIPResult = $vCenter->assignIPWindows($moduleVmware, $vmId);
if (is_array($assignIPResult) && !$assignIPResult['error']) {
Log::info('✅ Assign IP Windows thành công', [
'vm_id' => $vmId,
'result' => $assignIPResult['data']
]);
$telegram->SendJobRunInfo(
'AssignIPWindows',
'success',
[
'vm_id' => $vmId,
'assigned_ip' => $availableIP,
'result' => $assignIPResult['data']
]
);
} else {
Log::warning('⚠️ Assign IP Windows thất bại', [
'vm_id' => $vmId,
'error' => $assignIPResult['data'] ?? 'Unknown error'
]);
$telegram->SendErrorMessage([
'error' => 'Assign IP Windows failed',
'vm_id' => $vmId,
'details' => $assignIPResult['data'] ?? 'Unknown error'
], 'AssignIPWindows - Failed');
}
} elseif ($osFamily === 'LINUX' || $osFamily === 'OTHER') {
Log::info('ℹ️ Phát hiện non-Windows VM, hệ thống đang nâng cấp', [
'vm_id' => $vmId,
'os_family' => $osFamily
]);
$telegram->SendJobRunInfo(
'AssignIP',
'upgrade',
[
'vm_id' => $vmId,
'os_family' => $osFamily,
'message' => 'Hệ thống đang nâng cấp để hỗ trợ IP assignment cho ' . $osFamily
]
);
} else {
Log::warning('⚠️ Không thể xác định OS family', [
'vm_id' => $vmId,
'os_family' => $osFamily
]);
$telegram->SendErrorMessage([
'error' => 'Cannot determine OS family',
'vm_id' => $vmId,
'os_family' => $osFamily
], 'AssignIP - Unknown OS');
}
} catch (\Exception $e) {
Log::error('❌ Lỗi khi handle IP assignment: ' . $e->getMessage(), [
'vm_id' => $vmId,
'error' => $e->getMessage()
]);
$telegram->SendErrorMessage([
'error' => 'IP Assignment handling failed',
'vm_id' => $vmId,
'details' => $e->getMessage()
], 'HandleIPAssignment - Exception');
}
}
/**
* Check VM OS family using vCenter API
*/
private function checkVMOSFamily(vCenter $vCenter, string $vmId): string
{
try {
// Kiểm tra session còn valid không
$check = $vCenter->checkApiExits();
if (!$check) {
Log::warning('vCenter session expired, cannot check OS family');
return 'UNKNOWN';
}
// Gọi API để lấy guest identity
$response = Http::withoutVerifying()
->withHeaders([
'vmware-api-session-id' => $vCenter->token
])
->get("https://{$vCenter->apiUri}/rest/vcenter/vm/{$vmId}/guest/identity");
if ($response->successful()) {
$data = $response->json();
if (isset($data['value']['family'])) {
$family = strtoupper($data['value']['family']);
Log::info('✅ Phát hiện OS family', [
'vm_id' => $vmId,
'family' => $family,
'full_name' => $data['value']['full_name'] ?? 'Unknown'
]);
return $family;
} else {
Log::warning('⚠️ Không tìm thấy family trong response', [
'vm_id' => $vmId,
'response' => $data
]);
return 'UNKNOWN';
}
} else {
Log::warning('⚠️ API call thất bại khi check OS family', [
'vm_id' => $vmId,
'status' => $response->status(),
'response' => $response->body()
]);
return 'UNKNOWN';
}
} catch (\Exception $e) {
Log::error('❌ Exception khi check OS family: ' . $e->getMessage(), [
'vm_id' => $vmId,
'error' => $e->getMessage()
]);
return 'UNKNOWN';
}
}
}
@@ -3,18 +3,23 @@
namespace App\Jobs\VirtualMachine\Create;
use App\Http\Facade\SignRSA;
use App\Http\Services\Discord;
use App\Http\Services\Telegram;
use App\Http\Services\vCenter;
use App\Jobs\Mail\Customer\VMCreationFailedJob;
use App\Jobs\VirtualMachine\Create\AssignIPJob;
use App\Jobs\VirtualMachine\Create\ConfigCLICommand;
use App\Models\OrderItem;
use App\Models\Os;
use App\Services\VMDataService;
use App\Models\ModuleVmware;
use App\Models\ModuleIpAddress;
use App\Models\IpPool;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Http;
class CreateVirtualMachineJob implements ShouldQueue
{
@@ -35,7 +40,7 @@ class CreateVirtualMachineJob implements ShouldQueue
/**
* Execute the job.
*/
public function handle(vCenter $vCenter, Discord $discord, VMDataService $vmDataService)
public function handle(vCenter $vCenter, Telegram $telegram)
{
try {
$product = $this->item->getProductAttribute(); // dùng helper trong OrderItem
@@ -43,7 +48,7 @@ class CreateVirtualMachineJob implements ShouldQueue
if (!$product) {
$errorMessage = "Không tìm thấy sản phẩm từ OrderItem #{$this->item->id}";
Log::warning($errorMessage);
$discord->SendErrorMessage($errorMessage, 'CreateVirtualMachineJob - Missing Product');
$telegram->SendErrorMessage($errorMessage, 'CreateVirtualMachineJob - Missing Product');
if (!$this->isRetry) {
$this->sendFailureNotification($errorMessage);
@@ -60,7 +65,7 @@ class CreateVirtualMachineJob implements ShouldQueue
if (!$vcenter || !$host || !$datacenter) {
$errorMessage = "Thiếu thông tin host/datacenter/vcenter từ sản phẩm ID #{$product->id}";
Log::error($errorMessage);
$discord->SendErrorMessage([
$telegram->SendErrorMessage([
'error' => $errorMessage,
'product_id' => $product->id,
'order_item_id' => $this->item->id,
@@ -79,7 +84,7 @@ class CreateVirtualMachineJob implements ShouldQueue
if (!$vCenter->loginServer($vcenter)) {
$errorMessage = "Login vào vCenter thất bại với host: {$vcenter->host}";
Log::error($errorMessage);
$discord->SendErrorMessage([
$telegram->SendErrorMessage([
'error' => $errorMessage,
'vcenter_host' => $vcenter->host,
'vcenter_user' => $vcenter->user,
@@ -102,70 +107,28 @@ class CreateVirtualMachineJob implements ShouldQueue
// Lấy addon từ order item
if ($this->item->addons) {
Log::info("🔍 Tìm thấy addons cho order item", [
'order_item_id' => $this->item->id,
'addons_count' => $this->item->addons->count(),
'addons' => $this->item->addons->map(function($addon) {
return [
'id' => $addon->id,
'addon_id' => $addon->addon_id,
'qty' => $addon->qty,
'price' => $addon->price,
'addon_name' => $addon->addonItems?->name ?? 'Unknown'
];
})
]);
foreach ($this->item->addons as $orderAddon) {
$addon = $orderAddon->addonItems;
if (!$addon) {
Log::warning("⚠️ Addon không tìm thấy addonItems", [
'order_addon_id' => $orderAddon->id,
'addon_id' => $orderAddon->addon_id
]);
continue;
}
if (!$addon) continue;
$addonName = strtolower(trim($addon->name));
$quantity = (int) $orderAddon->qty;
Log::info("🔍 Xử lý addon", [
'addon_name' => $addon->name,
'addon_name_lower' => $addonName,
'quantity' => $quantity,
'addon_id' => $addon->id
]);
switch ($addonName) {
case 'cpu':
$addonData['cpu'] += $quantity;
Log::info("✅ Thêm CPU addon: +{$quantity}");
break;
case 'ram':
$addonData['ram'] += $quantity;
Log::info("✅ Thêm RAM addon: +{$quantity}GB");
break;
case 'disk':
case 'ssd':
$addonData['disk'] += $quantity;
Log::info("✅ Thêm Disk addon: +{$quantity}GB");
break;
default:
Log::warning("⚠️ Addon không được nhận diện: {$addonName}");
break;
}
}
} else {
Log::info("ℹ️ Không có addons cho order item {$this->item->id}");
}
Log::info('📊 Thông tin addon được xử lý', [
'order_item_id' => $this->item->id,
'addon_data' => $addonData,
'addons_count' => $this->item->addons?->count() ?? 0,
'has_addons' => !empty($addonData) && array_sum($addonData) > 0
]);
$result = $vCenter->CreateVirtualMachine([
'item' => $this->item,
'host' => $host,
@@ -194,7 +157,7 @@ class CreateVirtualMachineJob implements ShouldQueue
if (is_array($result) && ($result['error'] ?? false)) {
$errorMessage = 'Tạo máy ảo thất bại: ' . json_encode($result);
Log::warning($errorMessage);
$discord->SendErrorMessage([
$telegram->SendErrorMessage([
'error' => $result['error'] ?? 'Unknown error',
'result' => $result,
'product_id' => $product->id,
@@ -211,7 +174,7 @@ class CreateVirtualMachineJob implements ShouldQueue
} elseif ($result === 'Login_Again') {
$errorMessage = 'Tạo máy ảo thất bại: cần đăng nhập lại.';
Log::error($errorMessage);
$discord->SendErrorMessage([
$telegram->SendErrorMessage([
'error' => $errorMessage,
'product_id' => $product->id,
'order_item_id' => $this->item->id,
@@ -234,91 +197,86 @@ class CreateVirtualMachineJob implements ShouldQueue
$invoice = \App\Models\Invoice::where('order_id', $this->item->order->id)->first();
if ($invoice) {
$invoice->update(['vm_id' => $vmId]);
Log::info('✅ Đã lưu vm_id vào bảng invoice', [
'vm_id' => $vmId,
'invoice_id' => $invoice->id,
'order_id' => $this->item->order->id
]);
} else {
Log::warning('⚠️ Không tìm thấy invoice cho order', [
'order_id' => $this->item->order->id,
'vm_id' => $vmId
]);
}
// Start VM ngay sau khi tạo thành công
Log::info('🚀 Bắt đầu khởi động VM sau khi tạo thành công', [
'vm_id' => $vmId,
'order_item_id' => $this->item->id
]);
$startResult = $vCenter->StartVirtualMachine($vmId);
if ($startResult === 'Login_Again') {
// Thử đăng nhập lại và start VM
Log::info('🔄 Thử đăng nhập lại vCenter để start VM', [
'vm_id' => $vmId,
'vcenter_host' => $vcenter->host
]);
if ($vCenter->loginServer($vcenter)) {
$startResult = $vCenter->StartVirtualMachine($vmId);
Log::info('✅ Đăng nhập lại thành công, thử start VM lần nữa', [
'vm_id' => $vmId,
'start_result' => $startResult
]);
} else {
Log::error('❌ Không thể đăng nhập lại vCenter để start VM', [
'vm_id' => $vmId,
'vcenter_host' => $vcenter->host
]);
}
}
// Start VM ngay sau khi tạo thành công (sử dụng API trực tiếp)
$startResult = $this->startVirtualMachineDirectly($vCenter, $vmId);
if (is_array($startResult) && $startResult['error'] === false) {
Log::info('✅ Khởi động VM thành công', [
'vm_id' => $vmId,
'order_item_id' => $this->item->id,
'result' => $startResult['data']
]);
// Dispatch ConfigCLICommand để cấu hình VM và lấy password
$configJob = new ConfigCLICommand($vmId, $this->item, $vCenter);
dispatch($configJob)->delay(now()->addMinutes(2)); // Chờ 2 phút để VM boot hoàn toàn
}
// Lưu dữ liệu VM vào database
try {
$customer = $this->item->order->customer;
$serverName = $this->item->server_name ?? 'VM-' . $vmId;
Log::info('✅ Đã dispatch ConfigCLICommand job', [
'vm_id' => $vmId,
'order_item_id' => $this->item->id
// 1. Lấy IP available từ IPPool
$networkId = $product->ipAddress?->module_network_id ?? 1;
$availableIP = $this->getAvailableIPFromPool($networkId);
// 2. Tạo ModuleIpAddress với IP từ pool
$moduleIpAddress = ModuleIpAddress::create([
'vm_name' => $serverName,
'module_host_id' => $host->id,
'module_network_id' => $networkId,
'ip' => $availableIP,
'gateway' => $product->ipAddress?->gateway ?? '0.0.0.0',
'netmask' => $product->ipAddress?->netmask ?? '255.255.255.0',
'dns' => $product->ipAddress?->dns ?? '8.8.8.8',
'status' => 1 // 1 = Assigned
]);
} else {
Log::warning('⚠️ Khởi động VM thất bại', [
'vm_id' => $vmId,
'order_item_id' => $this->item->id,
'error' => $startResult['data']
// 3. Tạo ModuleVmware với IP address vừa tạo
$moduleVmware = ModuleVmware::create([
'name' => $serverName,
'module_ip_address_id' => $moduleIpAddress->id,
'port' => 22,
'order_id' => $this->item->order->id,
'first_payment' => $this->item->order->first_payment ?? 0,
'next_payment' => $this->item->order->next_payment ?? 0,
'next_due_date' => $this->item->order->next_due_date ?? null,
'next_invoice' => $this->item->order->next_invoice ?? 0,
'user' => 'root',
'password' => '',
'hostname' => $serverName,
'vmware_id' => $vmId,
'os_id' => $this->item->os_id ?? 1,
'customer_id' => $customer->id,
'status' => 1
]);
}
// Lưu dữ liệu VM và IP address vào database
$ipAddresses = [];
if (is_array($result)) {
$ipAddresses = $result['ip_addresses'] ?? [];
}
$saveResult = $vmDataService->saveVMData($this->item, $vmId, $ipAddresses);
if ($saveResult['success']) {
// 4. Cập nhật product với module_vmware_id
$product->module_vmware_id = $moduleVmware->id;
$product->save();
Log::info('✅ Lưu dữ liệu VM và IP address thành công', [
'vm_id' => $saveResult['vm']->id,
'vmware_id' => $vmId,
'ip_address_id' => $saveResult['ip_address']->id,
'module_vmware_id' => $moduleVmware->id,
'module_ip_address_id' => $moduleIpAddress->id,
'assigned_ip' => $availableIP,
'name' => $serverName,
'order_item_id' => $this->item->id
]);
} else {
Log::error('❌ Lỗi khi lưu dữ liệu VM và IP address', [
// Dispatch AssignIPJob để chạy sau 5 phút
AssignIPJob::dispatch($vmId, $moduleVmware->id, $availableIP)
->delay(now()->addMinutes(5));
Log::info('✅ Đã dispatch AssignIPJob để chạy sau 5 phút', [
'vm_id' => $vmId,
'module_vmware_id' => $moduleVmware->id,
'assigned_ip' => $availableIP,
'delay_minutes' => 5
]);
} catch (\Exception $e) {
Log::error('❌ Lỗi khi lưu dữ liệu VM và IP address: ' . $e->getMessage(), [
'vmware_id' => $vmId,
'error' => $saveResult['message'],
'order_item_id' => $this->item->id
'order_item_id' => $this->item->id,
'error' => $e->getMessage()
]);
}
@@ -331,17 +289,8 @@ class CreateVirtualMachineJob implements ShouldQueue
}
}
// Log thông tin addon đã được áp dụng
if (!empty($addonData) && array_sum($addonData) > 0) {
Log::info('Addon đã được áp dụng thành công', [
'vm_id' => $vmId,
'addon_data' => $addonData,
'order_item_id' => $this->item->id
]);
}
// Gửi thông báo thành công
$discord->SendJobRunInfo(
$telegram->SendJobRunInfo(
'CreateVirtualMachineJob',
'success',
[
@@ -364,7 +313,7 @@ class CreateVirtualMachineJob implements ShouldQueue
'trace' => $e->getTraceAsString()
]);
$discord->SendErrorMessage([
$telegram->SendErrorMessage([
'error' => $e->getMessage(),
'file' => $e->getFile(),
'line' => $e->getLine(),
@@ -379,6 +328,88 @@ class CreateVirtualMachineJob implements ShouldQueue
}
}
/**
* Get available IP from IPPool that doesn't exist in ModuleIpAddress
*/
private function getAvailableIPFromPool(int $networkId): string
{
// Lấy tất cả IP từ IPPool theo network_id, order by ip_address
$ipPoolList = IpPool::where('module_network_id', $networkId)
->orderBy('ip_address')
->get();
if ($ipPoolList->isEmpty()) {
// Nếu không có IP trong pool, trả về IP default
return '0.0.0.0';
}
// Lấy tất cả IP đã được assign trong ModuleIpAddress
$assignedIPs = ModuleIpAddress::where('module_network_id', $networkId)
->pluck('ip')
->toArray();
// Tìm IP đầu tiên chưa được assign
foreach ($ipPoolList as $ipPool) {
if (!in_array($ipPool->ip_address, $assignedIPs)) {
Log::info('✅ Lấy IP available từ pool', [
'ip' => $ipPool->ip_address,
'network_id' => $networkId
]);
return $ipPool->ip_address;
}
}
// Nếu tất cả IP đã được assign, log warning và trả về IP default
Log::warning('⚠️ Không có IP available trong pool', [
'network_id' => $networkId,
'total_ips_in_pool' => $ipPoolList->count(),
'assigned_ips' => count($assignedIPs)
]);
return '0.0.0.0';
}
/**
* Start VM directly using vCenter API
*/
private function startVirtualMachineDirectly(vCenter $vCenter, string $vmId): array|string
{
try {
// Kiểm tra xem đã có session chưa
$check = $vCenter->checkApiExits();
if (!$check) {
return 'Login_Again';
}
// Gọi API start VM trực tiếp
$response = Http::withoutVerifying()
->withHeaders([
'vmware-api-session-id' => $vCenter->token
])
->post("https://{$vCenter->apiUri}/rest/vcenter/vm/{$vmId}/power/start");
if ($response->status() === 200) {
return [
'error' => false,
'data' => 'success'
];
}
return [
'error' => true,
'data' => $response->body()
];
} catch (\Exception $e) {
Log::error('Lỗi khi start VM: ' . $e->getMessage());
return [
'error' => true,
'data' => $e->getMessage()
];
}
}
/**
* Send failure notification to customer
*/
@@ -4,13 +4,13 @@ namespace App\Jobs\VirtualMachine;
use App\Enums\Invoice\InvoiceStatus;
use App\Enums\Order\OrderStatus;
use App\Http\Services\Discord;
use App\Http\Services\Telegram;
use App\Http\Services\Invoice\InvoiceService;
use App\Jobs\VirtualMachine\Create\CreateVirtualMachineJob;
use App\Models\Invoice;
use App\Models\Order;
use App\Models\OrderItem;
use App\Services\VMDataService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
@@ -39,7 +39,7 @@ class ProcessOrderPaymentJob implements ShouldQueue
/**
* Execute the job.
*/
public function handle(InvoiceService $invoiceService, Discord $discord): void
public function handle(InvoiceService $invoiceService, Telegram $telegram): void
{
try {
$user = $this->order->customer;
@@ -57,7 +57,7 @@ class ProcessOrderPaymentJob implements ShouldQueue
'user_credit' => $user->credit,
'order_amount' => $this->order->amount
]);
$discord->SendErrorMessage($errorMessage, 'ProcessOrderPaymentJob - Insufficient Credit');
$telegram->SendErrorMessage($errorMessage, 'ProcessOrderPaymentJob - Insufficient Credit');
return;
}
@@ -101,7 +101,7 @@ class ProcessOrderPaymentJob implements ShouldQueue
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');
$telegram->SendErrorMessage($errorMessage, 'ProcessOrderPaymentJob - No VM Creation Attempt');
return;
}
@@ -109,7 +109,7 @@ class ProcessOrderPaymentJob implements ShouldQueue
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');
$telegram->SendErrorMessage($errorMessage, 'ProcessOrderPaymentJob - Empty VM Results');
return;
}
@@ -129,8 +129,8 @@ class ProcessOrderPaymentJob implements ShouldQueue
$invoiceService->markAsPaid($invoice);
$this->order->update(['status' => OrderStatus::ACTIVE->value]);
// Gửi thông báo Discord
$discord->SendOrderPaidNotification($invoice);
// Gửi thông báo Telegram
$telegram->SendOrderPaidNotification($invoice);
DB::commit();
@@ -156,7 +156,7 @@ class ProcessOrderPaymentJob implements ShouldQueue
// 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, [
$telegram->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');
}
@@ -172,7 +172,7 @@ class ProcessOrderPaymentJob implements ShouldQueue
// Đã 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, [
$telegram->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');
@@ -189,7 +189,7 @@ class ProcessOrderPaymentJob implements ShouldQueue
'trace' => $e->getTraceAsString()
]);
$discord->SendErrorMessage([
$telegram->SendErrorMessage([
'error' => $e->getMessage(),
'order_id' => $this->order->id,
'order_num' => $this->order->order_num,
@@ -206,11 +206,10 @@ class ProcessOrderPaymentJob implements ShouldQueue
{
try {
$vCenter = app(\App\Http\Services\vCenter::class);
$discord = app(Discord::class);
$vmDataService = app(VMDataService::class);
$telegram = app(\App\Http\Services\Telegram::class);
$vmJob = new CreateVirtualMachineJob($item, $this->retryCount > 0);
return $vmJob->handle($vCenter, $discord, $vmDataService);
return $vmJob->handle($vCenter, $telegram);
} catch (\Throwable $e) {
Log::error("Lỗi khi tạo VM cho order item #{$item->id}: " . $e->getMessage(), [