Files
portal-api/app/Http/Services/Telegram.php
T
2026-07-21 08:34:15 +07:00

232 lines
9.0 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
namespace App\Http\Services;
use App\Models\Setting;
use Carbon\Carbon;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Log;
class Telegram
{
protected ?string $token;
protected ?string $group;
public function __construct()
{
$record = Setting::where('key', 'setting')->first();
if ($record) {
$setting = json_decode($record->value);
$this->token = $setting->bot_token ?? null;
$this->group = $setting->bot_id ?? null;
} else {
$this->token = null;
$this->group = null;
}
}
public function SendMessage($message = '')
{
if (!$this->token || !$this->group) {
Log::channel('Custom')->warning('Telegram notification not sent: Missing bot token or group ID');
return null;
}
try {
$url = "https://api.telegram.org/bot$this->token/sendMessage?parse_mode=html&chat_id=$this->group&text=" . urlencode($message);
$response = Http::withoutVerifying()->get($url);
// Log response để debug
Log::channel('Custom')->info('Telegram sendMessage URL: ' . $url);
Log::channel('Custom')->info('Telegram sendMessage response: ' . $response->body());
Log::channel('Custom')->info('Telegram sendMessage status: ' . $response->status());
return $response;
} catch (\Exception $exception) {
Log::channel('Custom')->error('Failed to send Telegram notification: ' . $exception->getMessage());
return null;
}
}
public function SendInformation($product = [], $user = '', $password = '', $port = 22)
{
$msg = "Thông tin truy cập VPS vừa được khởi tạo 🎉 \n";
$msg .= "--------------------------------\n";
$msg .= "| 🌐 IP: " . $product['IpAddress']['ip'] . "\n";
$msg .= "| 📌 User: " . $user . "\n";
$msg .= "| 👉 Port: " . $port . "\n";
$msg .= "| 📺 Password: " . $password . "\n";
$msg .= "| 💾 Hết hạn: " . Carbon::parse($product['next_due_date'])->format('d/m/Y') . "\n";
$msg .= "| 💵 Hệ điều hành: " . $product['Os']['OsGroup']['name'] . $product['Os']['version'] . "\n";
$msg .= "| 📁 Đơn hàng số: #" . $product['order_id'] . "\n";
$msg .= "--------------------------------";
return $this->SendMessage($msg);
}
public function SendErrorMessage($data)
{
$msg = "Admin: Nhận được thông báo lỗi khi khởi tạo dịch vụ \n";
$msg .= "--------------------------------\n";
$msg .= "| " . (is_string($data) ? $data : json_encode($data)) . "\n";
$msg .= "--------------------------------";
return $this->SendMessage($msg);
}
public function SendNewUserRegistration($email, $code, $verificationLink)
{
$msg = "🎉 Thành viên mới vừa đăng ký!\n";
$msg .= "📧 Email: {$email}\n";
$msg .= "🧾 Mã xác thực: {$code}\n";
$msg .= "🔗 Link xác thực: {$verificationLink}";
return $this->SendMessage($msg);
}
public function SendManualDepositPendingApproval($customer, $transaction)
{
$msg = "🔔 Yêu cầu nạp tiền chờ duyệt!\n";
$msg .= "--------------------------------\n";
$msg .= "👤 Khách: {$customer->firstname} {$customer->lastname}\n";
$msg .= "📧 Email: {$customer->email}\n";
$msg .= "💵 Số tiền: " . number_format($transaction->amount, 0, ',', '.') . " VNĐ\n";
$msg .= "🧾 Mã GD: {$transaction->public_code}\n";
$msg .= "🕒 Thời gian: " . Carbon::now()->format('d/m/Y H:i:s') . "\n";
$msg .= "--------------------------------\n";
$msg .= "⚠️ Vui lòng vào admin để xác nhận giao dịch.";
return $this->SendMessage($msg);
}
public function SendCustomerRecharge($customer, $amount)
{
$msg = "💰 Khách hàng vừa nạp tiền vào tài khoản\n";
$msg .= "👤 Tên: {$customer->firstname} {$customer->lastname}\n";
$msg .= "📧 Email: {$customer->email}\n";
$msg .= "💵 Số tiền: " . number_format($amount, 0, ',', '.') . " VNĐ\n";
$msg .= "🕒 Thời gian: " . Carbon::now()->format('d/m/Y H:i:s');
return $this->SendMessage($msg);
}
public function SendJobRunInfo($jobName, $status, $additionalInfo = null)
{
$msg = "⚙️ Thông báo chạy job: {$jobName}\n";
$msg .= "⏱️ Thời gian: " . Carbon::now()->format('d/m/Y H:i:s') . "\n";
$msg .= "📊 Trạng thái: {$status}";
if ($additionalInfo) {
$msg .= "\n📋 Thông tin thêm: " . (is_string($additionalInfo) ? $additionalInfo : json_encode($additionalInfo));
}
return $this->SendMessage($msg);
}
public function SendOrderPaidNotification($invoice)
{
$invoiceItem = $invoice->invoiceItem()->with([
'vps',
'hosting',
'os.osGroup',
'addons.addonItems'
])->first();
if (!$invoiceItem) {
return $this->SendErrorMessage('Không tìm thấy invoice item từ invoice ID: ' . $invoice->id);
}
$product = $invoiceItem->product;
$os = $invoiceItem->os;
$osGroup = $os?->osGroup;
$addons = $invoiceItem->addons;
$msg = "💵 Khách đã thanh toán đơn hàng thành công!\n";
$msg .= "--------------------------------\n";
$msg .= "🧾 Đơn hàng: #{$invoice->order_num}\n";
$msg .= "📦 Sản phẩm: #{$product?->id} - {$product?->name}\n";
$msg .= "🧠 Hệ điều hành: {$osGroup?->name} {$os?->version}\n";
$msg .= "💰 Tổng tiền: " . number_format($invoice->total, 0, ',', '.') . " VNĐ\n";
$msg .= "🧍 Khách: {$invoice->customer?->firstname} {$invoice->customer?->lastname} ({$invoice->customer?->email})\n";
$msg .= "🕒 Ngày thanh toán: " . Carbon::parse($invoice->date_paid)->format('d/m/Y H:i:s') . "\n";
if ($addons && $addons->count()) {
$msg .= "➕ Addons:\n";
foreach ($addons as $addon) {
$msg .= "- {$addon->addonItems->name} (x{$addon->qty}) - " . number_format($addon->price, 0, ',', '.') . " VNĐ\n";
}
}
$msg .= "--------------------------------";
return $this->SendMessage($msg);
}
/**
* Notify one step of the VM rebuild pipeline (success or failure).
*/
public function SendRebuildStepNotification(string $vmName, string $ip, string $step, bool $success, ?string $note = null)
{
$msg = ($success ? '🔄' : '❌') . " Rebuild VPS — {$step}\n";
$msg .= "--------------------------------\n";
$msg .= "🖥️ VM: {$vmName}\n";
$msg .= "🌐 IP: {$ip}\n";
$msg .= "📊 Trạng thái: " . ($success ? 'Hoàn tất ✅' : 'Thất bại ❌') . "\n";
if ($note) {
$msg .= "📝 " . ($success ? 'Ghi chú' : 'Lỗi') . ": {$note}\n";
}
$msg .= "🕒 Thời gian: " . Carbon::now()->format('d/m/Y H:i:s') . "\n";
$msg .= "--------------------------------";
return $this->SendMessage($msg);
}
/**
* Send a photo to Telegram group
* @param string $filePath Local storage path (e.g. Upload/2024/06/01/image.png)
* @param string|null $caption Optional caption for the photo
* @return mixed|null
*/
public function SendPhoto($filePath, $caption = null)
{
if (!$this->token || !$this->group) {
Log::channel('Custom')->warning('Telegram photo not sent: Missing bot token or group ID');
return null;
}
try {
$fullPath = public_path('template/' . $filePath);
if (!file_exists($fullPath)) {
Log::channel('Custom')->error('Telegram photo not sent: File does not exist - ' . $fullPath);
return null;
}
$multipart = [
[
'name' => 'chat_id',
'contents' => $this->group,
],
[
'name' => 'photo',
'contents' => fopen($fullPath, 'r'),
],
];
if ($caption) {
$multipart[] = [
'name' => 'caption',
'contents' => $caption,
];
}
$response = Http::withoutVerifying()
->attach('photo', fopen($fullPath, 'r'), basename($fullPath))
->post("https://api.telegram.org/bot{$this->token}/sendPhoto", [
'chat_id' => $this->group,
'caption' => $caption,
]);
return $response->json();
} catch (\Exception $exception) {
Log::channel('Custom')->error('Failed to send Telegram photo: ' . $exception->getMessage());
return null;
}
}
}