response()->json(['api' => 'ok'])); Route::prefix('v1') /* Api for Admin */ ->group(function () { Route::prefix('system')->middleware(['auth:sanctum'])->group(function () { Route::controller(ModuleController::class)->group(function () { Route::get('get-list-vcenter', 'getVCenter')->name('api.getVCenter'); Route::get('get-list-datacenter', 'getDatacenter')->name('api.getDatacenter'); Route::get('get-list-host', 'getHost')->name('api.getHost'); Route::get('get-list-datastore', 'getDatastore')->name('api.getDatastore'); Route::get('get-list-network', 'getNetwork')->name('api.getNetwork'); Route::get('get-list-ipaddress', 'getIpAddress')->name('api.getIPAddress'); Route::get('get-list-version-os', 'getOsServerVersion')->name('api.getVersion'); Route::get('get-list-os-group', 'getOsGroup')->name('api.getOsGroup'); }); Route::get('test-ssh-connection', function (ServiceVCenter $serviceVCenter) { Log::info('🧪 API Test SSH Connection - Starting test via route'); return response()->json($serviceVCenter->testSSHConnection()); })->name('api.testSSHConnection'); Route::post('rebuild-vps', [\App\Http\Controllers\Api\VpsActionController::class, 'rebuildVps']) ->name('api.system.rebuildVps'); Route::get('get-list-product', function () { $type_id = \request()->get('type'); if (!$type_id) { return response()->json(['error' => true, 'message' => 'Please choose Type']); } if ($type_id === 1 || $type_id === 2) { return response()->json(['error' => true, 'message' => 'Not Found']); } $model = null; switch ($type_id) { case 3: $model = Hosting::select('id', 'name', 'price', 'price_sale')->get(); break; case 4: $model = VPS::select('id', 'name', 'price', 'price_sale', 'module_host_id')->get(); break; default: break; } if (!$model) { return response()->json(['error' => true, 'message' => 'Not Found']); } return response()->json(['error' => false, 'data' => $model->all()]); })->name('api.getProduct'); Route::get('get-list-product-type', function () { $type = Type::select('id', 'name')->get(); return response()->json(['error' => false, 'data' => $type->all()]); })->name('api.getProductType'); Route::get('get-ticket-console', function (Request $request, ServiceVCenter $serviceVCenter) { $product_id = $request->get('product'); if (!$product_id) { return response()->json(['error' => true, 'message' => "Please choose product"]); } $product = ModuleVmware::with('ipAddress.host.datacenter.vCenter')->find($product_id); if (!$product) { return response()->json(['error' => true, 'message' => "Can't find product"]); } $vcenter = null; if ($product->ipAddress && $product->ipAddress->host && $product->ipAddress->host->datacenter && $product->ipAddress->host->datacenter->vCenter) { $vcenter = $product->ipAddress->host->datacenter->vCenter; } if (!$vcenter) { return response()->json(['error' => true, 'message' => "Can't find vCenter information"]); } // Đăng nhập vCenter trước khi lấy ticket if (!$serviceVCenter->loginServer($vcenter)) { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập vào vCenter' ]); } $ConsoleTicket = $serviceVCenter->GetConsoleTickets($product->vmware_id); // Nếu login hết hạn, thử login lại 1 lần nữa if ($ConsoleTicket === 'Login_Again') { if ($serviceVCenter->loginServer($vcenter)) { $ConsoleTicket = $serviceVCenter->GetConsoleTickets($product->vmware_id); } else { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập lại vào vCenter' ]); } } // Nếu vẫn lỗi, trả về lỗi rõ ràng if (is_string($ConsoleTicket)) { return response()->json([ 'error' => true, 'message' => "Failed to get console ticket: $ConsoleTicket" ]); } if ($ConsoleTicket['error']) { return response()->json([ 'error' => true, 'message' => $ConsoleTicket['data'] ]); } return response()->json([ 'error' => false, 'data' => $ConsoleTicket['data'], 'host' => $vcenter->host, 'vmware-api-session-id' => $serviceVCenter->token ])->cookie('vmware-api-session-id', $serviceVCenter->token, 60, '/', null, false, false); })->name('api.GetConsoleTicket'); Route::get('get-version-os', function () { $group_id = \request()->get('group'); if (!$group_id) { return response()->json(['error' => true, 'message' => 'Please choose Host']); } $group_os = OsGroup::find($group_id); if (!$group_os) { return response()->json(['error' => true, 'message' => 'Can\'t find Group Os']); } $os = Os::where('os_group_id', $group_id)->select('id', 'version')->get(); if ($os->count()) { $os = array_map(function ($array) { $array['name'] = $array['version']; unset($array['version']); return $array; }, $os->all()); return response()->json(['error' => false, 'data' => $os]); } return response()->json(['error' => true, 'message' => 'Can\'t find Os by Os Group ID #' . $group_id]); })->name('api.GetVersionOs'); Route::post('get-all-image', function (Media $media) { $files = $media->getAllMedia(); $data = view('administrator.pages.component.media')->with('media', $files)->render(); return response()->json(['data' => $data]); })->name('api.GetAllImage'); Route::get('get-list-addon', function () { $product = request()->input('product'); if (!$product) { return response()->json(['error' => true, 'data' => 'Yêu cầu không hợp lệ']); } $allAddon = Addon::get(); $formAddon = view('administrator.pages.component.addon')->with([ 'addon' => $allAddon ])->render(); return response()->json(['error' => false, 'data' => $formAddon]); })->name('api.GetAddonProduct'); Route::post('add-addon-to-product', function (Request $request) { $order = $request->order; $product = $request->product; $cpu = $request->cpu; $ram = $request->ram; $ssd = $request->ssd; if (!$cpu && !$ram && !$ssd) { return response()->json(['error' => true, 'message' => 'Invalid Request']); } if (!$product) { return response()->json(['error' => true, 'message' => 'Invalid Request']); } $product = ModuleVmware::find($request->product); if (!$product) { return response()->json(['error' => true, 'message' => 'Invalid Request']); } if ($order && $order != $product->order_id) { return response()->json(['error' => true, 'message' => 'Invalid Request']); } $invoice_id = 0; $billing_sw = 0; $order = \App\Models\Order::with('OrderItem')->find($product->order_id); if ($order && $order->OrderItem) { $order_item = $order->OrderItem->first(); $invoice_id = $order_item->invoice_id; $billing_sw = $order_item->billing; } $invoice = Invoice::find($invoice_id); if (!$invoice) { return response()->json(['error' => true, 'message' => 'Invalid Request']); } $addon = []; $item = []; $total = 0; if ($cpu) { $item['cpu'] = $cpu; } if ($ram) { $item['ram'] = $ram; } if ($ssd) { $item['ssd'] = $ssd; } foreach ($item as $key => $value) { $addonItem = Addon::where('name', 'like', "%$key%")->first(); $message = "Addon " . strtoupper($key); switch ($billing_sw) { case 2: $billing = 1; $message .= " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::now()->addMonths(1)->format('d/m/Y') . " )"; break; case 3: $billing = 3; $message .= " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::now()->addMonths(3)->format('d/m/Y') . " )"; break; case 4: $billing = 6; $message .= " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::now()->addMonths(6)->format('d/m/Y') . " )"; break; case 5: $billing = 12; $message .= " ( " . Carbon::today()->format('d/m/Y') . " - " . Carbon::now()->addMonths(12)->format('d/m/Y') . " )"; break; } $addon[] = [ 'customer_id' => $product->customer_id, 'type_id' => 1, 'due_date' => Carbon::now()->hour(23)->minute(59)->second(59)->timestamp, 'product_id' => $addonItem->id, 'parent_id' => $product->id, 'relid' => 0, 'description' => $message, 'invoice_type' => "1", 'billing' => $billing_sw, 'amount' => $addonItem->price * $value * $billing, 'tax' => 1, ]; $total += $addonItem->price * $value * $billing; } try { DB::beginTransaction(); if ($order !== 0) { $order->increment('amount', ($total + (0.1 * $total))); $invoice->increment('total', ($total + (0.1 * $total))); $invoice->increment('tax', 0.1 * $total); $invoice->increment('sub_total', $total); $product->increment('first_payment', $total); $product->increment('next_payment', $total); $allAddon = array_map(function ($item) use ($invoice) { $item['invoice_id'] = $invoice->id; return $item; }, $addon); InvoiceItem::insert($allAddon); $addonInsert = InvoiceItem::select('id')->latest('id')->take(count($allAddon))->get(); foreach ($addonInsert as $item) { DB::table('order__order_item')->insert([ 'order_id' => $order->id, 'InvoiceItem_id' => $item->id ]); } } else { $invoice_added = Invoice::insertGetId([ 'date' => Carbon::now()->timestamp, 'due_date' => $product->next_due_date, 'sub_total' => $total, 'tax' => $total * 0.1, 'total' => $total + ($total * 0.1), 'payment_id' => 1, 'customer_id' => $product->customer_id, 'invoice_type' => 1, 'status' => 0 ]); $order_id = \App\Models\Order::insertGetId([ 'order_num' => App\Http\Helpers\Helper::generateUniqueCode(), 'customer_id' => $product->customer_id, 'user_id' => $request->user()->id, 'date' => Carbon::now()->timestamp, 'payment_id' => 1, 'invoice_id' => $invoice_added, 'amount' => $total + ($total * 0.1), 'client_ip' => $request->getClientIp(), 'status' => 0 ]); $allAddon = array_map(function ($item) use ($invoice_added) { $item['invoice_id'] = $invoice_added; return $item; }, $addon); InvoiceItem::insert($allAddon); $addonInsert = InvoiceItem::select('id')->latest('id')->take(count($allAddon))->get(); foreach ($addonInsert as $item) { DB::table('order__order_item')->insert([ 'order_id' => $order_id, 'InvoiceItem_id' => $item->id ]); } } DB::commit(); } catch (Exception $exception) { DB::rollBack(); return response()->json(['error' => true, 'message' => $exception->getMessage()]); } return response()->json(['error' => false, 'message' => 'Added Addon to Product Successfully']); })->name('api.AcceptAddon'); Route::post('create-slug', function (Request $request) { return Str::slug($request->get('name')); })->name('api.CreateSlug'); Route::post('get-service-product', function (Request $request) { $validate = Validator::make( $request->all(), [ 'host' => 'required|numeric' ] ); if ($validate->failed()) { return response()->json(['error' => true, 'message' => 'Invalid request']); } $host = ModuleHost::with('Datacenter.vCenter')->find($request->host); if (!$host) { return response()->json(['error' => true, 'message' => 'Invalid request']); } $datacenter = ModuleDatacenter::where('vcenter_id', $host->Datacenter->vcenter_id)->select( 'id', 'name' )->get(); $allHost = ModuleHost::where('module_datacenter_id', $host->module_datacenter_id)->select( 'id', 'name' )->get(); $vcenter = vCenter::select('id', 'host')->get(); return response()->json([ 'error' => false, 'data' => [ 'host' => $allHost, 'datacenter' => $datacenter, 'vcenter' => $vcenter, 'choose' => [ 'datacenter' => $host->module_datacenter_id, 'vcenter' => $host->Datacenter->vcenter_id, 'host' => $request->host ] ] ]); })->name('api.GetServiceProduct'); Route::post('update-file-customer', function (Request $request) { $validate = Validator::make( $request->all(), [ 'user_id' => 'required|numeric', 'file' => 'required|string' ] ); if ($validate->failed()) { return response()->json(['error' => true, 'message' => 'Invalid request']); } $user = Customer::find($request->user_id); if (!$user) { return response()->json(['error' => true, 'message' => 'Invalid request']); } $fileName = str_replace(env('APP_URL') . '/uploads/files/', '', $request->file); $file = File::insertGetId([ 'filename' => $fileName, 'file_url' => $request->file, 'customer_id' => $request->user_id ]); if ($file) { return response()->json(['error' => false, 'message' => 'New file updated successfully']); } return response()->json(['error' => true, 'message' => 'Invalid request']); })->name('api.CustomerUpdateFile'); Route::post('remove-file-customer', function (Request $request) { $validate = Validator::make( $request->all(), [ 'file' => 'required|numeric' ] ); if ($validate->failed()) { return response()->json(['error' => true, 'message' => 'Invalid request']); } $file = File::find($request->file); if (!$file) { return response()->json(['error' => true, 'message' => 'Invalid request']); } $file->delete(); return response()->json(['error' => false, 'message' => 'The request was processed successfully']); })->name('api.CustomerRemoveFile'); }); }) /* Api for customer */ ->group(function () { Route::middleware(['auth:sanctum']) ->group(function () { Route::post('get-status-virtual-machine', function (Request $request, ServiceVCenter $serviceVCenter) { $vmware_id = $request->vmware_id; $product_id = $request->product_id; if (!$vmware_id || !$product_id) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } $product = ModuleVmware::with('ipAddress.host.datacenter.vCenter')->find($product_id); if (!$product) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } if ($vmware_id != $product->vmware_id) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } if ($product->status == 4) { return response()->json(['error' => false, 'message' => 'Dịch vụ hết hạn', 'expiry' => true]); } if ($product->status == 3) { return response()->json([ 'error' => false, 'message' => 'Đang khởi tạo', 'expiry' => false, 'pending' => true ]); } $serviceVCenter->token = $product->ipAddress->host->datacenter->vCenter->token; $serviceVCenter->apiUri = $product->ipAddress->host->datacenter->vCenter->host; $VirtualMachine = $serviceVCenter->CheckVirtualMachine($vmware_id); if ($VirtualMachine === 'Login_Again') { $token = $serviceVCenter->loginServer($product->ipAddress->host->datacenter->vCenter); if ($token) { vCenter::where( 'id', $product->ipAddress->host->datacenter->vCenter->id )->update(['token' => $token]); $serviceVCenter->token = $token; } $VirtualMachine = $serviceVCenter->CheckVirtualMachine($vmware_id); } // Check if VirtualMachine is still a string (Login_Again or other error) if (is_string($VirtualMachine)) { return response()->json(['error' => true, 'message' => "Failed to check virtual machine: $VirtualMachine"]); } if ($VirtualMachine['error']) { return response()->json(['error' => true, 'message' => $VirtualMachine['message']]); } $status = 3; if ($VirtualMachine['data']['state'] === 'RUNNING') { $product->update([ 'status' => 1 ]); } if ($VirtualMachine['data']['state'] === 'NOT_RUNNING') { $product->update([ 'status' => 0 ]); } $product = ModuleVmware::find($product_id); $data = view('form.action')->with([ 'user' => $request->user('')->id, 'item' => $product ])->render(); return response()->json([ 'error' => false, 'message' => $VirtualMachine['data'], 'expiry' => false, 'data' => $data ]); })->name('api.GetVirtualMachineStatus'); Route::get('get-list-group-os', function () { $host_id = \request()->get('host'); if (!$host_id) { return response()->json(['error' => true, 'message' => 'Please choose Host']); } $host = ModuleHost::find($host_id); if (!$host) { return response()->json(['error' => true, 'message' => 'Can\'t find Host']); } $osGroup = OsGroup::where('ModuleHost_id', $host_id)->select('id', 'name')->get(); if ($osGroup->count()) { return response()->json(['error' => false, 'data' => $osGroup->all()]); } return response()->json([ 'error' => true, 'message' => 'Can\'t find OsGroup by Host ID #' . $host_id ]); })->name('api.user.getOsGroup'); Route::get('get-list-version-os', function () { $group_id = \request()->get('group'); if (!$group_id) { return response()->json(['error' => true, 'message' => 'Please choose Host']); } $group_os = OsGroup::find($group_id); if (!$group_os) { return response()->json(['error' => true, 'message' => 'Can\'t find Group Os']); } $os = Os::where('os_group_id', $group_id)->select('id', 'version')->get(); if ($os->count()) { $os = array_map(function ($array) { $array['name'] = $array['version']; unset($array['version']); return $array; }, $os->all()); return response()->json(['error' => false, 'data' => $os]); } return response()->json([ 'error' => true, 'message' => 'Can\'t find Os by Os Group ID #' . $group_id ]); })->name('api.user.GetVersionOs'); Route::get('list-snapshot', function () { $product_id = request()->input('product'); $user_id = request()->input('user'); if (!$product_id || !$user_id) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } $snapshot = ModuleSnapshot::where(function ($query) use ($product_id, $user_id) { $query->where('customer_id', $user_id); $query->where('ModuleVmware_id', $product_id); })->get(); $data = view('form.snapshot')->with([ 'snapshot' => $snapshot, 'user' => $user_id, 'product' => $product_id ])->render(); return response()->json(['error' => false, 'data' => $data]); })->name('api.user.GetSnapshot'); Route::get('get-list-addon', function () { $product = request()->input('product'); if (!$product) { return response()->json(['error' => true, 'data' => 'Yêu cầu không hợp lệ']); } $billing = InvoiceItem::select('billing') ->where('type_id', 4) ->where('relid', $product)->first(); if (!$billing) { return response()->json(['error' => true, 'data' => 'Yêu cầu không hợp lệ']); } $allAddon = Addon::get(); $formAddon = view('form.upgrade')->with([ 'addon' => $allAddon, 'billing' => $billing->billing, 'product' => $product ])->render(); return response()->json(['error' => false, 'data' => $formAddon]); })->name('api.user.GetAddonProduct'); Route::post('payment-invoice', function () { $invoice_id = \request()->input('invoice'); if (!$invoice_id) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } $invoice = Invoice::with('Order', 'InvoiceItem')->find($invoice_id); if (!$invoice) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } if ($invoice->status == 1) { return response()->json(['error' => true, 'message' => 'Hoá đơn đã được thanh toán!']); } $customer = Customer::find(auth()->id()); if (!$customer) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } if ($customer->credit < $invoice->total) { return response()->json([ 'error' => true, 'message' => 'Tài khoản của quý khách không đủ để thực hiện thanh toán' ]); } $products = []; $next_due_date = 0; $next_invoice = 0; if ($invoice->InvoiceItem->count()) { foreach ($invoice->InvoiceItem->where('relid', '<>', 0) as $item) { $product = $item->GetRelidProduct(); $products[] = $product; $time = $product->next_due_date; switch ($item->billing) { case 2: $next_due_date = Carbon::parse($time)->addMonths(1)->timestamp; $next_invoice = Carbon::parse($time)->addMonths(1)->timestamp; break; case 3: $next_due_date = Carbon::parse($time)->addMonths(3)->timestamp; $next_invoice = Carbon::parse($time)->addMonths(3)->timestamp; break; case 4: $next_due_date = Carbon::parse($time)->addMonths(6)->timestamp; $next_invoice = Carbon::parse($time)->addMonths(6)->timestamp; break; case 5: $next_due_date = Carbon::parse($time)->addMonths(12)->timestamp; $next_invoice = Carbon::parse($time)->addMonths(12)->timestamp; break; } } } try { DB::beginTransaction(); $customer->update([ 'credit' => ($customer->credit - $invoice->total) ]); $invoice->update([ 'status' => 1, 'date_paid' => time() ]); $order = $invoice->Order; $jobs = []; if ($order && $order->status !== 1 && $invoice->invoice_type == 1) { $order->update([ 'status' => 1 ]); $addon = []; $product = 0; foreach ( $order->OrderItem->where('parent_id', 0)->whereIn( 'type_id', [3, 4] ) as $key => $item ) { if ($item->type_id == 3) { $Server = ModuleHostingServer::where('status', 1)->first(); ModuleHosting::find($item->relid)->update(['module_server_id' => $Server->id]); $jobs[] = new CreateHostingJobs($item->relid); } else { $product = $item->GetRelidProduct(); $os = Os::with('OsGroup')->find($product->os_id); if ($os && $os->OsGroup) { $ipaddress = ModuleIpAddress::where( 'ModuleHost_id', $os->OsGroup->ModuleHost_id )->where('status', 0)->first(); if ($ipaddress) { $product->update([ 'ModuleIpAddress_id' => $ipaddress->id ]); $ipaddress->update([ 'status' => 1 ]); $jobs[] = new CreateVMJobs($product->id); } } } } foreach ($order->OrderItem as $item) { if ($item->type_id == 1) { $itemData = $item->GetItemProduct(); $price = 0; switch ($item->billing) { case 2: $price = $item->amount / 1; break; case 3: $price = $item->amount / 3; break; case 4: $price = $item->amount / 6; break; case 5: $price = $item->amount / 12; break; } $addon[strtolower($itemData->name)] = (int) $price / $itemData->price; $product = $item->parent_id; } } if ($order->OrderItem->count() === count($addon)) { dispatch(new UpgradeVirtualMachine( $product, $addon, $order->id ))->delay(now()->addSeconds(10)); } } else { foreach ($products as $item) { if (isset($item->vmware_id)) { $jobs[] = new \App\Jobs\VirtualMachine\Action\VMJobs($item->id, 'Start', true); } if (isset($item->server_domain_id)) { $jobs[] = new \App\Jobs\Hosting\HostingJobs($item->id, 'Activate'); } $item->update([ 'next_due_date' => $next_due_date, 'next_invoice' => $next_invoice ]); } } if (count($jobs)) { foreach ($jobs as $item) { dispatch($item)->delay(now()->addSeconds(10)); } } DB::commit(); } catch (Exception $exception) { DB::rollBack(); return response()->json(['error' => true, 'message' => $exception->getMessage()]); } return response()->json(['error' => false, 'message' => "Thanh toán hoá đơn thành công"]); })->name('api.user.PaymentInvoice'); Route::post('renew-services', function () { $product_id = \request()->input('product'); $type_id = \request()->input('type'); $billing = \request()->input('billing'); if (!$product_id || !$type_id || !$billing) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } $product = null; switch ($type_id) { case 3: $product = ModuleHosting::find($product_id); break; case 4: $product = ModuleVmware::find($product_id); break; } if (!$product) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } $customer = Customer::find(auth()->id()); if (!$customer) { return response()->json(['error' => true, 'message' => 'Yêu cầu không hợp lệ']); } $item = InvoiceItem::where(function ($query) use ($product_id, $type_id) { $query->where('invoice_type', 1); $query->where(function ($_query) use ($product_id) { $_query->where('relid', $product_id); $_query->Orwhere('parent_id', $product_id); }); if ($type_id == 4) { $query->whereIn('type_id', [1, 4]); } else { $query->where('type_id', $type_id); } })->get(); $nextPay = (int) $product->next_payment; $renew_item = []; if ($item->count()) { foreach ($item as $key => $_item) { $renew_item[$key] = $_item->replicate(); $subMessage = ''; switch ((int) $billing) { case 2: $subMessage = " ( " . Carbon::parse($product->next_due_date)->format('d/m/Y') . " - " . Carbon::parse($product->next_due_date)->addMonths(1)->format('d/m/Y') . " )"; break; case 3: $subMessage = " ( " . Carbon::parse($product->next_due_date)->format('d/m/Y') . " - " . Carbon::parse($product->next_due_date)->addMonths(3)->format('d/m/Y') . " )"; break; case 4: $subMessage = " ( " . Carbon::parse($product->next_due_date)->format('d/m/Y') . " - " . Carbon::parse($product->next_due_date)->addMonths(6)->format('d/m/Y') . " )"; break; case 5: $subMessage = " ( " . Carbon::parse($product->next_due_date)->format('d/m/Y') . " - " . Carbon::parse($product->next_due_date)->addMonths(12)->format('d/m/Y') . " )"; break; } $renew_item[$key]->invoice_type = 0; $renew_item[$key]->description = $_item->GetItemProduct()->name . $subMessage; $renew_item[$key]->billing = $billing; } } switch ((int) $billing) { case 2: $nextPay *= 1; break; case 3: $nextPay *= 3; break; case 4: $nextPay *= 6; break; case 5: $nextPay *= 12; break; } $date_exp = Carbon::now()->diffInDays(Carbon::parse($product->next_due_date), false); $invoice_data = [ 'date' => Carbon::now()->timestamp, 'due_date' => $date_exp > 0 ? $product->next_due_date : Carbon::now()->timestamp, 'payment_id' => 1, 'sub_total' => $nextPay, 'tax' => $nextPay * (10 / 100), 'total' => $nextPay + ($nextPay * (10 / 100)), 'invoice_type' => 0, 'customer_id' => $product->customer_id, 'status' => 0 ]; try { DB::beginTransaction(); $invoice_id = Invoice::insertGetId($invoice_data); foreach ($renew_item as $item) { $item->invoice_id = $invoice_id; $item->save(); } DB::commit(); } catch (Exception $exception) { DB::rollBack(); return response()->json(['error' => true, 'message' => $exception->getMessage()]); } return response()->json([ 'error' => false, 'message' => "Yêu cầu gia hạn được xử lý thành công. Vui lòng thanh toán hoá đơn để hoàn tất!" ]); })->name('api.user.RenewService'); Route::get('get-ticket-console', function (Request $request, ServiceVCenter $serviceVCenter) { $product_id = $request->get('product'); if (!$product_id) { return response()->json(['error' => true, 'message' => "Please choose product"]); } $product = ModuleVmware::with('ipAddress.host.datacenter.vCenter')->find($product_id); if (!$product) { return response()->json(['error' => true, 'message' => "Can't find product"]); } // Validate that the product belongs to the authenticated user if ($product->customer_id != user()->id) { return response()->json([ 'error' => true, 'message' => 'Không có quyền truy cập máy ảo này' ]); } // Check if service is expired if ($product->status == 4) { return response()->json(['error' => true, 'message' => 'Dịch vụ đã hết hạn']); } // Check if VM is still initializing if ($product->status == 3) { return response()->json(['error' => true, 'message' => 'Máy ảo đang khởi tạo']); } $vcenter = null; if ($product->ipAddress && $product->ipAddress->host && $product->ipAddress->host->datacenter && $product->ipAddress->host->datacenter->vCenter) { $vcenter = $product->ipAddress->host->datacenter->vCenter; } if (!$vcenter) { return response()->json(['error' => true, 'message' => "Can't find vCenter information"]); } // Đăng nhập vCenter trước khi lấy ticket if (!$serviceVCenter->loginServer($vcenter)) { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập vào vCenter' ]); } $ConsoleTicket = $serviceVCenter->GetConsoleTickets($product->vmware_id); // Nếu login hết hạn, thử login lại 1 lần nữa if ($ConsoleTicket === 'Login_Again') { if ($serviceVCenter->loginServer($vcenter)) { $ConsoleTicket = $serviceVCenter->GetConsoleTickets($product->vmware_id); } else { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập lại vào vCenter' ]); } } // Nếu vẫn lỗi, trả về lỗi rõ ràng if (is_string($ConsoleTicket)) { return response()->json([ 'error' => true, 'message' => "Failed to get console ticket: $ConsoleTicket" ]); } if ($ConsoleTicket['error']) { return response()->json([ 'error' => true, 'message' => $ConsoleTicket['data'] ]); } return response()->json([ 'error' => false, 'data' => $ConsoleTicket['data'], 'host' => $vcenter->host, 'vmware-api-session-id' => $serviceVCenter->token ])->cookie('vmware-api-session-id', $serviceVCenter->token, 60, '/', null, false, false); })->name('api.user.GetConsoleTicket'); Route::post('start-virtual-machine', function (Request $request, ServiceVCenter $serviceVCenter) { $vm_id = $request->input('vm_id') ?: $request->json('vm_id'); if (!$vm_id) { $jsonData = json_decode($request->getContent(), true); $vm_id = $jsonData['vm_id'] ?? null; } if (!$vm_id) { return response()->json([ 'error' => true, 'message' => 'Yêu cầu không hợp lệ - vm_id không được tìm thấy', ]); } $vm = ModuleVmware::where('vmware_id', $vm_id)->first(); if (!$vm) { $vm = ModuleVmware::where('id', $vm_id)->first(); } if (!$vm) { $allVMs = ModuleVmware::where('vmware_id', 'like', '%' . $vm_id . '%') ->orWhere('id', 'like', '%' . $vm_id . '%') ->get(); return response()->json([ 'error' => true, 'message' => 'Không tìm thấy thông tin máy ảo', 'debug' => [ 'vm_id_received' => $vm_id, 'similar_vms_count' => $allVMs->count(), 'similar_vms' => $allVMs->toArray() ] ]); } if ($vm->customer_id != user()->id) { return response()->json([ 'error' => true, 'message' => 'Không có quyền truy cập máy ảo này' ]); } if ($vm->status == 4) { return response()->json(['error' => true, 'message' => 'Dịch vụ đã hết hạn']); } if ($vm->status == 3) { return response()->json(['error' => true, 'message' => 'Máy ảo đang khởi tạo']); } $vcenter = null; if ($vm->ipAddress && $vm->ipAddress->host && $vm->ipAddress->host->datacenter && $vm->ipAddress->host->datacenter->vCenter) { $vcenter = $vm->ipAddress->host->datacenter->vCenter; } if (!$vcenter) { return response()->json([ 'error' => true, 'message' => 'Không tìm thấy thông tin vCenter' ]); } if (!$serviceVCenter->loginServer($vcenter)) { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập vào vCenter' ]); } $result = $serviceVCenter->StartVirtualMachine($vm_id); if ($result === "Login_Again") { if ($serviceVCenter->loginServer($vcenter)) { $result = $serviceVCenter->StartVirtualMachine($vm_id); } else { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập lại vào vCenter' ]); } } // Check if result is still a string (Login_Again or other error) if (is_string($result)) { return response()->json(['error' => true, 'message' => "Failed to start virtual machine: $result"]); } if ($result['error']) { return response()->json(['error' => true, 'message' => $result['data']]); } $vm->update(['status' => 1]); return response()->json([ 'error' => false, 'message' => 'Khởi động máy ảo thành công' ]); })->name('api.user.StartVirtualMachine'); Route::post('stop-virtual-machine', function (Request $request, ServiceVCenter $serviceVCenter) { $vm_id = $request->input('vm_id') ?: $request->json('vm_id'); if (!$vm_id) { $jsonData = json_decode($request->getContent(), true); $vm_id = $jsonData['vm_id'] ?? null; } if (!$vm_id) { return response()->json([ 'error' => true, 'message' => 'Yêu cầu không hợp lệ - vm_id không được tìm thấy' ]); } $vm = ModuleVmware::where('vmware_id', $vm_id)->first(); if (!$vm) { $vm = ModuleVmware::where('id', $vm_id)->first(); } if (!$vm) { return response()->json([ 'error' => true, 'message' => 'Không tìm thấy thông tin máy ảo' ]); } if ($vm->customer_id != user()->id) { return response()->json([ 'error' => true, 'message' => 'Không có quyền truy cập máy ảo này' ]); } if ($vm->status == 4) { return response()->json(['error' => true, 'message' => 'Dịch vụ đã hết hạn']); } if ($vm->status == 3) { return response()->json(['error' => true, 'message' => 'Máy ảo đang khởi tạo']); } $vcenter = null; if ($vm->ipAddress && $vm->ipAddress->host && $vm->ipAddress->host->datacenter && $vm->ipAddress->host->datacenter->vCenter) { $vcenter = $vm->ipAddress->host->datacenter->vCenter; } if (!$vcenter) { return response()->json([ 'error' => true, 'message' => 'Không tìm thấy thông tin vCenter' ]); } if (!$serviceVCenter->loginServer($vcenter)) { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập vào vCenter' ]); } $result = $serviceVCenter->ShutdownGuestVirtualMachine($vm_id); if ($result === "Login_Again") { if ($serviceVCenter->loginServer($vcenter)) { $result = $serviceVCenter->ShutdownGuestVirtualMachine($vm_id); } else { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập lại vào vCenter' ]); } } // Check if result is still a string (Login_Again or other error) if (is_string($result)) { return response()->json(['error' => true, 'message' => "Failed to stop virtual machine: $result"]); } if ($result['error']) { return response()->json(['error' => true, 'message' => $result['data']]); } $vm->update(['status' => 0]); return response()->json([ 'error' => false, 'message' => 'Tắt máy ảo thành công' ]); })->name('api.user.StopVirtualMachine'); Route::get('get-ip-address', function (Request $request, ServiceVCenter $serviceVCenter) { try { $validator = Validator::make($request->all(), [ 'vm_id' => 'required|string|max:255', ]); if ($validator->fails()) { return response()->json([ 'error' => true, 'message' => 'Dữ liệu không hợp lệ', 'errors' => $validator->errors() ], 422); } $vmId = $request->input('vm_id'); $vm = ModuleVmware::where('vmware_id', $vmId) ->orWhere('id', $vmId) ->first(); if (!$vm) { return response()->json([ 'error' => true, 'message' => 'Không tìm thấy thông tin máy ảo' ], 404); } if ($vm->status == 4) { return response()->json([ 'error' => true, 'message' => 'Dịch vụ đã hết hạn' ], 400); } if ($vm->status == 3) { return response()->json([ 'error' => true, 'message' => 'Máy ảo đang khởi tạo' ], 400); } $vcenter = $vm->ipAddress->host->datacenter->vCenter ?? null; if (!$vcenter) { return response()->json([ 'error' => true, 'message' => 'Không tìm thấy thông tin vCenter' ], 500); } if (!$serviceVCenter->loginServer($vcenter)) { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập vào vCenter' ], 500); } // Gọi 2 endpoint $identity = Http::withoutVerifying() ->withHeaders(['vmware-api-session-id' => $serviceVCenter->token]) ->get("https://{$serviceVCenter->apiUri}/rest/vcenter/vm/{$vm->vmware_id}/guest/identity") ->json(); $networking = Http::withoutVerifying() ->withHeaders(['vmware-api-session-id' => $serviceVCenter->token]) ->get("https://{$serviceVCenter->apiUri}/rest/vcenter/vm/{$vm->vmware_id}/guest/networking") ->json(); // Parse IP $ipAddresses = []; // (1) Từ networking if (isset($networking['value']['interfaces'])) { foreach ($networking['value']['interfaces'] as $interface) { foreach ($interface['ip_addresses'] ?? [] as $ip) { if (isset($ip['ip_address']) && filter_var($ip['ip_address'], FILTER_VALIDATE_IP)) { $ipAddresses[] = [ 'ip' => $ip['ip_address'], 'type' => $ip['type'] ?? 'unknown', 'state' => $ip['state'] ?? 'unknown', ]; } } } } // (2) Nếu networking rỗng, fallback từ identity if (empty($ipAddresses) && isset($identity['value']['ip_address'])) { $ip = $identity['value']['ip_address']; if (filter_var($ip, FILTER_VALIDATE_IP)) { $ipAddresses[] = [ 'ip' => $ip, 'type' => strpos($ip, ':') !== false ? 'IPV6' : 'IPV4', 'state' => 'unknown', ]; } } // Update trạng thái if (!empty($ipAddresses)) { $vm->update(['status' => 1]); } return response()->json([ 'error' => false, 'message' => 'Lấy IP address thành công', 'data' => [ 'vm_id' => $vm->vmware_id, 'hostname' => $vm->hostname, 'status' => $vm->status, 'ip_addresses' => $ipAddresses, 'guest_info' => [ 'family' => $identity['value']['family'] ?? null, 'full_name' => $identity['value']['full_name']['default_message'] ?? null, 'host_name' => $identity['value']['host_name'] ?? null, ] ] ]); } catch (\Exception $e) { Log::error('❌ Lỗi khi lấy IP address của VM', [ 'vm_id' => $request->input('vm_id'), 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return response()->json([ 'error' => true, 'message' => 'Lỗi hệ thống: ' . $e->getMessage() ], 500); } })->name('api.user.GetIPAddress'); Route::get('get-vm-info', function (Request $request, ServiceVCenter $serviceVCenter) { try { $validator = Validator::make($request->all(), [ 'vm_id' => 'required|string|max:255', ]); if ($validator->fails()) { return response()->json([ 'error' => true, 'message' => 'Dữ liệu không hợp lệ', 'errors' => $validator->errors() ], 422); } $vmId = $request->input('vm_id'); $vcenter = vCenter::first(); if (!$vcenter) { return response()->json([ 'error' => true, 'message' => 'Không tìm thấy thông tin vCenter' ], 500); } // Sử dụng token có sẵn nếu có $serviceVCenter->apiUri = $vcenter->host; $serviceVCenter->token = $vcenter->token; // Gọi API với timeout 5s $vmInfo = Http::withoutVerifying() ->timeout(5) ->withHeaders(['vmware-api-session-id' => $serviceVCenter->token]) ->get("https://{$serviceVCenter->apiUri}/rest/vcenter/vm/{$vmId}") ->json(); // Nếu token hết hạn, login lại 1 lần duy nhất if (isset($vmInfo['type']) && str_contains($vmInfo['value']['messages'][0]['default_message'] ?? '', 'session')) { if (!$serviceVCenter->loginServer($vcenter)) { return response()->json([ 'error' => true, 'message' => 'Không thể đăng nhập vào vCenter' ], 500); } // Thử lại với token mới $vmInfo = Http::withoutVerifying() ->timeout(5) ->withHeaders(['vmware-api-session-id' => $serviceVCenter->token]) ->get("https://{$serviceVCenter->apiUri}/rest/vcenter/vm/{$vmId}") ->json(); } if (isset($vmInfo['type'])) { return response()->json([ 'error' => true, 'message' => 'Không thể lấy thông tin VM từ vCenter' ], 500); } return response()->json([ 'error' => false, 'message' => 'Lấy thông tin VM thành công', 'data' => [ 'vm_id' => $vmId, 'name' => $vmInfo['value']['name'] ?? 'Unknown', 'guest_os' => $vmInfo['value']['guest_OS'] ?? 'UNKNOWN', 'power_state' => $vmInfo['value']['power_state'] ?? 'UNKNOWN', 'cpu' => [ 'count' => $vmInfo['value']['cpu']['count'] ?? 0, 'cores_per_socket' => $vmInfo['value']['cpu']['cores_per_socket'] ?? 0, 'hot_add_enabled' => $vmInfo['value']['cpu']['hot_add_enabled'] ?? false, ], 'memory' => [ 'size_MiB' => $vmInfo['value']['memory']['size_MiB'] ?? 0, 'hot_add_enabled' => $vmInfo['value']['memory']['hot_add_enabled'] ?? false, ], 'disks' => array_map(function ($disk) { return [ 'key' => $disk['key'] ?? '', 'label' => $disk['value']['label'] ?? '', 'capacity' => $disk['value']['capacity'] ?? 0, 'type' => $disk['value']['type'] ?? '', ]; }, $vmInfo['value']['disks'] ?? []), 'nics' => array_map(function ($nic) { return [ 'key' => $nic['key'] ?? '', 'label' => $nic['value']['label'] ?? '', 'mac_address' => $nic['value']['mac_address'] ?? '', 'network_name' => $nic['value']['backing']['network_name'] ?? '', 'state' => $nic['value']['state'] ?? '', ]; }, $vmInfo['value']['nics'] ?? []), 'identity' => [ 'instance_uuid' => $vmInfo['value']['identity']['instance_uuid'] ?? '', 'bios_uuid' => $vmInfo['value']['identity']['bios_uuid'] ?? '', ], 'hardware' => [ 'version' => $vmInfo['value']['hardware']['version'] ?? '', 'upgrade_policy' => $vmInfo['value']['hardware']['upgrade_policy'] ?? '', ], 'boot' => [ 'type' => $vmInfo['value']['boot']['type'] ?? '', 'efi_legacy_boot' => $vmInfo['value']['boot']['efi_legacy_boot'] ?? false, ] ], 'raw_data' => $vmInfo['value'] ?? null ]); } catch (\Exception $e) { Log::error('❌ Lỗi khi lấy thông tin VM', [ 'vm_id' => $request->input('vm_id'), 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return response()->json([ 'error' => true, 'message' => 'Lỗi hệ thống: ' . $e->getMessage() ], 500); } })->name('api.user.GetVMInfo'); Route::get('get-vm-info/{vm_id}/{params?}', function (Request $request, ServiceVCenter $serviceVCenter, $vm_id, $params = null) { try { $vcenter = vCenter::first(); if (!$vcenter) { return response()->json([ 'error' => true, 'message' => __('vCenter configuration not found') ], 500); } // Login to vCenter first if (!$serviceVCenter->loginServer($vcenter)) { return response()->json([ 'error' => true, 'message' => __('Cannot login to vCenter') ], 500); } $vmInfo = $serviceVCenter->GetDetailVirtualMachine($vm_id); if ($vmInfo['error']) { return response()->json([ 'error' => true, 'message' => __('Cannot get VM information from vCenter') ], 500); } $vmData = $vmInfo['data']; // Parse các tham số được yêu cầu $requestedParams = []; if ($params) { // Tách các param bằng dấu phẩy hoặc dấu + $requestedParams = preg_split('/[,+]/', $params); } // Mapping dữ liệu đầy đủ $allData = [ 'vm_id' => $vm_id, 'name' => $vmData['name'] ?? 'Unknown', 'guest_os' => $vmData['guest_OS'] ?? 'UNKNOWN', 'power_state' => $vmData['power_state'] ?? 'UNKNOWN', 'cpu_count' => $vmData['cpu']['count'] ?? 0, 'cpu_cores_per_socket' => $vmData['cpu']['cores_per_socket'] ?? 0, 'cpu_hot_add' => $vmData['cpu']['hot_add_enabled'] ?? false, 'memory_size' => $vmData['memory']['size_MiB'] ?? 0, 'memory_hot_add' => $vmData['memory']['hot_add_enabled'] ?? false, 'instance_uuid' => $vmData['identity']['instance_uuid'] ?? '', 'bios_uuid' => $vmData['identity']['bios_uuid'] ?? '', 'hardware_version' => $vmData['hardware']['version'] ?? '', 'boot_type' => $vmData['boot']['type'] ?? '', 'efi_legacy_boot' => $vmData['boot']['efi_legacy_boot'] ?? false, ]; // Thêm thông tin disk if (isset($vmData['disks']) && !empty($vmData['disks'])) { $firstDisk = $vmData['disks'][0] ?? null; if ($firstDisk) { $allData['disk_capacity'] = $firstDisk['value']['capacity'] ?? 0; $allData['disk_label'] = $firstDisk['value']['label'] ?? ''; $allData['disk_type'] = $firstDisk['value']['type'] ?? ''; } } // Thêm thông tin network if (isset($vmData['nics']) && !empty($vmData['nics'])) { $firstNic = $vmData['nics'][0] ?? null; if ($firstNic) { $allData['mac_address'] = $firstNic['value']['mac_address'] ?? ''; $allData['network_name'] = $firstNic['value']['backing']['network_name'] ?? ''; $allData['network_state'] = $firstNic['value']['state'] ?? ''; } } // Nếu không có params cụ thể, trả về tất cả if (empty($requestedParams)) { return response()->json([ 'error' => false, 'message' => __('Successfully retrieved all VM information'), 'data' => $allData ]); } // Lọc chỉ những thông tin được yêu cầu $filteredData = []; foreach ($requestedParams as $param) { $param = trim($param); if (array_key_exists($param, $allData)) { $filteredData[$param] = $allData[$param]; } else { $filteredData[$param] = null; // Hoặc có thể bỏ qua } } return response()->json([ 'error' => false, 'message' => __('Successfully retrieved VM information'), 'data' => $filteredData ]); } catch (\Exception $e) { Log::error('❌ Lỗi khi lấy thông tin VM với params', [ 'vm_id' => $vm_id, 'params' => $params, 'error' => $e->getMessage(), 'trace' => $e->getTraceAsString() ]); return response()->json([ 'error' => true, 'message' => __('System error: :error', ['error' => $e->getMessage()]) ], 500); } })->name('api.user.GetVMInfoWithParams'); }); }); Route::any('{any}', function () { return response()->json([ 'error' => true, 'message' => 'API Route not found' ], 404); })->where('any', '.*');