This commit is contained in:
baodev0
2026-08-19 11:03:43 +07:00
parent 2deb4ad74e
commit 8d0a5322ea
6 changed files with 209 additions and 1 deletions
@@ -190,7 +190,14 @@ class ClientController extends Controller
*/
public function register(ClientRegisterRequest $request)
{
$result = $this->authService->registerClient($request->validated());
$data = $request->validated();
if (!empty($data['trial_config'])) {
$decoded = json_decode((string) $data['trial_config'], true);
$data['trial_config'] = is_array($decoded) ? $decoded : null;
}
$result = $this->authService->registerClient($data);
$client = $result['client'];
$this->activityLogger->logAuth('register', 'customer', $client->id, $client->email);
@@ -44,6 +44,11 @@ class ClientRegisterRequest extends FormRequest
'min:6',
'confirmed'
],
'trial_config' => [
'nullable',
'string',
],
];
}
+20
View File
@@ -84,6 +84,26 @@ class Telegram
return $this->SendMessage($msg);
}
public function SendTrialRegistration($client, array $trialConfig = [])
{
$msg = "🧪 Khách hàng vừa đăng ký dùng thử Cloud VPS!\n";
$msg .= "--------------------------------\n";
$msg .= "👤 Tên: {$client->fullname}\n";
$msg .= "📧 Email: {$client->email}\n";
$msg .= "📱 SĐT: {$client->phone}\n";
$msg .= "--------------------------------\n";
$msg .= "🖥️ CPU: " . ($trialConfig['cpu'] ?? '-') . "\n";
$msg .= "💾 RAM: " . ($trialConfig['ram'] ?? '-') . "\n";
$msg .= "💽 SSD: " . ($trialConfig['ssd'] ?? '-') . "\n";
$msg .= "🧠 Hệ điều hành: " . ($trialConfig['os'] ?? '-') . "\n";
if (!empty($trialConfig['other'])) {
$msg .= "📝 Yêu cầu khác: {$trialConfig['other']}\n";
}
$msg .= "🕒 Thời gian: " . Carbon::now()->format('d/m/Y H:i:s');
return $this->SendMessage($msg);
}
public function SendManualDepositPendingApproval($customer, $transaction)
{
$msg = "🔔 Yêu cầu nạp tiền chờ duyệt!\n";
@@ -0,0 +1,36 @@
<?php
namespace App\Mail\Admin;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class TrialRegistrationRequest extends Mailable
{
use Queueable, SerializesModels;
public function __construct(public array $data) {}
public function envelope(): Envelope
{
return new Envelope(
subject: '[ADMIN] Yêu cầu dùng thử Cloud VPS - ' . ($this->data['customer_name'] ?? 'N/A'),
);
}
public function content(): Content
{
return new Content(
view: 'emails.admin.trial-registration-request',
with: $this->data,
);
}
public function attachments(): array
{
return [];
}
}
@@ -2,9 +2,12 @@
namespace App\Services\Api\Client;
use App\Http\Services\Telegram;
use App\Mail\Admin\TrialRegistrationRequest as TrialRegistrationRequestMail;
use App\Mail\Customer\VerifyAccount as VerifyAccountMail;
use App\Mail\Customer\Welcome as WelcomeMail;
use App\Models\RefreshToken;
use App\Models\Setting;
use App\Repositories\Api\Client\ClientRepositoryInterface;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
@@ -85,9 +88,50 @@ class ClientAuthService
$this->sendVerifyEmail($client, $code);
if (!empty($data['trial_config'])) {
$this->notifyAdminTrialRegistration($client, $data['trial_config']);
}
return ['client' => $client];
}
/**
* Báo admin (email + Telegram) khi khách hàng đăng ký dùng thử Cloud VPS.
*/
protected function notifyAdminTrialRegistration($client, array $trialConfig): void
{
try {
$setting = Setting::where('key', 'setting')->first();
$settingValue = $setting ? json_decode((string) $setting->value, true) : [];
$adminEmail = $settingValue['admin_email'] ?? null;
if ($adminEmail) {
Mail::to($adminEmail)->send(new TrialRegistrationRequestMail([
'company_name' => $settingValue['company'] ?? config('app.name', 'Portal Admin'),
'customer_name' => $client->fullname,
'customer_email' => $client->email,
'customer_phone' => $client->phone,
'cpu' => $trialConfig['cpu'] ?? null,
'ram' => $trialConfig['ram'] ?? null,
'ssd' => $trialConfig['ssd'] ?? null,
'os' => $trialConfig['os'] ?? null,
'other' => $trialConfig['other'] ?? null,
'created_at' => now()->format('d/m/Y H:i:s'),
]));
} else {
Log::warning('Trial registration admin email not sent: admin_email not configured.', [
'customer_id' => $client->id,
]);
}
} catch (\Throwable $e) {
Log::warning('Send trial registration admin email failed: ' . $e->getMessage(), [
'customer_id' => $client->id,
]);
}
(new Telegram())->SendTrialRegistration($client, $trialConfig);
}
/**
* Xác thực OTP — kích hoạt tài khoản, trả về token.
*/
@@ -0,0 +1,96 @@
<!DOCTYPE html>
<html lang="vi">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Yêu cầu dùng thử Cloud VPS</title>
<style>
* { box-sizing: border-box; }
body { font-family: 'Segoe UI', Arial, sans-serif; background: #f0f4f8; margin: 0; padding: 0; }
.wrapper { max-width: 620px; margin: 30px auto; }
.card { background: #fff; border-radius: 12px; overflow: hidden; box-shadow: 0 4px 20px rgba(0,0,0,0.08); }
.header { background: linear-gradient(135deg, #ea580c 0%, #f97316 100%); padding: 34px 40px; text-align: center; }
.header .icon { font-size: 44px; margin-bottom: 10px; }
.header h1 { color: #fff; margin: 0 0 6px; font-size: 22px; font-weight: 700; }
.header p { color: #ffedd5; margin: 0; font-size: 14px; }
.body { padding: 34px 40px; }
.section-label { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; color: #9ca3af; margin: 24px 0 10px; }
.section-label:first-child { margin-top: 0; }
.info-table { width: 100%; border-collapse: collapse; background: #f9fafb; border: 1px solid #e5e7eb; border-radius: 8px; overflow: hidden; }
.info-table td { padding: 11px 16px; font-size: 14px; border-bottom: 1px solid #f3f4f6; }
.info-table tr:last-child td { border-bottom: none; }
.info-table td:first-child { color: #6b7280; width: 42%; }
.info-table td:last-child { font-weight: 600; color: #111827; word-break: break-word; }
.badge { display: inline-block; padding: 3px 10px; border-radius: 999px; font-size: 12px; font-weight: 700; background: #fff7ed; color: #c2410c; }
.notice { background: #fffbeb; border-left: 3px solid #f59e0b; padding: 12px 16px; border-radius: 0 6px 6px 0; font-size: 13px; color: #92400e; margin-top: 24px; line-height: 1.6; }
.footer { text-align: center; padding: 20px 40px; border-top: 1px solid #f3f4f6; font-size: 12px; color: #9ca3af; }
</style>
</head>
<body>
<div class="wrapper">
<div class="card">
<div class="header">
<div class="icon">🧪</div>
<h1>Yêu cầu dùng thử Cloud VPS</h1>
<p>{{ $created_at ?? now()->format('d/m/Y H:i:s') }}</p>
</div>
<div class="body">
<div class="section-label">Thông tin khách hàng</div>
<table class="info-table">
<tr>
<td>Họ tên</td>
<td>{{ $customer_name ?? 'N/A' }}</td>
</tr>
<tr>
<td>Email</td>
<td>{{ $customer_email ?? 'N/A' }}</td>
</tr>
<tr>
<td>Số điện thoại</td>
<td>{{ $customer_phone ?? 'N/A' }}</td>
</tr>
</table>
<div class="section-label">Cấu hình yêu cầu</div>
<table class="info-table">
<tr>
<td>CPU</td>
<td>{{ $cpu ?: '-' }}</td>
</tr>
<tr>
<td>RAM</td>
<td>{{ $ram ?: '-' }}</td>
</tr>
<tr>
<td>SSD</td>
<td>{{ $ssd ?: '-' }}</td>
</tr>
<tr>
<td>Hệ điều hành</td>
<td>{{ $os ?: '-' }}</td>
</tr>
@if(!empty($other))
<tr>
<td>Yêu cầu khác</td>
<td>{{ $other }}</td>
</tr>
@endif
<tr>
<td>Trạng thái</td>
<td><span class="badge">Chờ khởi tạo</span></td>
</tr>
</table>
<div class="notice">
Vui lòng vào trang quản trị để khởi tạo VPS dùng thử theo cấu hình khách hàng yêu cầu.
</div>
</div>
<div class="footer">
© {{ date('Y') }} {{ $company_name ?? 'Portal Admin' }} — Email này được gửi tự động.
</div>
</div>
</div>
</body>
</html>