diff --git a/TELEGRAM_BOT_WEBHOOK.md b/TELEGRAM_BOT_WEBHOOK.md new file mode 100644 index 0000000..13ce98f --- /dev/null +++ b/TELEGRAM_BOT_WEBHOOK.md @@ -0,0 +1,266 @@ +# ๐Ÿค– Telegram Bot Webhook Integration + +Dokumentasi untuk integrasi Telegram Bot webhook dengan API. + +## ๐Ÿ“‹ Overview + +Webhook Telegram Bot terintegrasi dengan Fast API untuk mengecek tagihan PDAM melalui bot Telegram. + +## ๐Ÿš€ Setup + +### 1. Konfigurasi Environment + +Pastikan konfigurasi di `.env` sudah benar: + +```env +# Telegram API Configuration +TELEGRAM_BOT_TOKEN=8325211525:AAGPN-Ko2UZr-OIshu54jvi_7wzaMClR8SA + +# Fast API Configuration (for Telegram Bot) +FAST_API_CLIENT_ID=FAS_1753810437_4ff75b +FAST_API_CLIENT_SECRET=d286ae4f60902d63b72854a38cdaeb9436c6e011f99ad4cf57e512fd6573f711 + +# Base URL (untuk memanggil Fast API) +BASE_URL=https://api.wipay.id +``` + +### 2. Set Webhook di Telegram + +Set webhook URL ke endpoint API: + +**Windows (CMD/PowerShell):** +```cmd +curl -X POST "https://api.telegram.org/bot8325211525:AAGPN-Ko2UZr-OIshu54jvi_7wzaMClR8SA/setWebhook" -d "url=https://api.wipay.id/telegram/webhook" +``` + +**Linux/Mac:** +```bash +curl -X POST "https://api.telegram.org/bot/setWebhook" \ + -d "url=https://api.wipay.id/telegram/webhook" +``` + +**Atau gunakan browser (Paling Mudah):** +``` +https://api.telegram.org/bot8325211525:AAGPN-Ko2UZr-OIshu54jvi_7wzaMClR8SA/setWebhook?url=https://api.wipay.id/telegram/webhook +``` + +**PowerShell (Alternatif):** +```powershell +Invoke-WebRequest -Uri "https://api.telegram.org/bot8325211525:AAGPN-Ko2UZr-OIshu54jvi_7wzaMClR8SA/setWebhook?url=https://api.wipay.id/telegram/webhook" -Method POST +``` + +### 3. Verifikasi Webhook + +Cek status webhook: +```bash +curl "https://api.telegram.org/bot/getWebhookInfo" +``` + +## ๐Ÿ“ Endpoint + +### POST /telegram/webhook + +Endpoint untuk menerima update dari Telegram. + +**Request:** +- Method: `POST` +- Content-Type: `application/json` +- Body: Telegram Update JSON (dikirim otomatis oleh Telegram) + +**Response:** +```json +{ + "status": "ok" +} +``` + +## ๐ŸŽฏ Fitur Bot + +### Commands + +1. **/start** - Memulai bot dan menampilkan menu utama +2. **/cekid** - Menampilkan ID Telegram user +3. **/tagihan** - Memulai proses cek tagihan + +### Menu Inline + +1. **Cek Tagihan** - Memulai proses cek tagihan +2. **Cek ID Telegram** - Menampilkan ID Telegram user +3. **Bantuan** - Menampilkan daftar perintah + +### Flow Cek Tagihan + +1. User klik "Cek Tagihan" atau ketik `/tagihan` +2. Bot meminta nomor pelanggan +3. User memasukkan nomor pelanggan (contoh: `059912`) +4. Bot memanggil Fast API `/fast/check_bill` +5. Bot menampilkan hasil tagihan + +## ๐Ÿ“ File Structure + +``` +tim-backend/timo.wipay.id_api/ +โ”œโ”€โ”€ src/ +โ”‚ โ”œโ”€โ”€ Controllers/ +โ”‚ โ”‚ โ””โ”€โ”€ TelegramBotController.php # Controller untuk webhook +โ”‚ โ””โ”€โ”€ Helpers/ +โ”‚ โ”œโ”€โ”€ TelegramHelper.php # Helper untuk Telegram API +โ”‚ โ””โ”€โ”€ SessionHelper.php # Helper untuk session management +โ”œโ”€โ”€ storage/ +โ”‚ โ””โ”€โ”€ telegram_sessions.json # File session (auto-generated) +โ””โ”€โ”€ logs/ + โ””โ”€โ”€ telegram_bot.log # Log bot (auto-generated) +``` + +## ๐Ÿ”ง Komponen + +### TelegramBotController + +Controller utama yang menangani webhook: +- `webhook()` - Entry point untuk webhook +- `handleCallbackQuery()` - Handle inline button clicks +- `handleMessage()` - Handle text messages +- `handlePelangganInput()` - Handle nomor pelanggan input + +### TelegramHelper + +Helper untuk interaksi dengan Telegram API: +- `sendText()` - Kirim pesan teks +- `sendMenu()` - Kirim pesan dengan inline keyboard +- `answerCallback()` - Jawab callback query +- `cleanUtf8()` - Clean UTF-8 text +- `safe()` - Escape HTML +- `log()` - Logging + +### SessionHelper + +Helper untuk session management (file-based): +- `getSession()` - Ambil session +- `setSession()` - Set session +- `clearSession()` - Hapus session +- `loadSessions()` - Load semua sessions +- `saveSessions()` - Save semua sessions + +## ๐Ÿ“Š Response Format + +### Fast API Response + +Bot memanggil `/fast/check_bill` dan memproses response: + +```json +{ + "status": "success", + "data": { + "errno": 0, + "error": "", + "recordsTotal": 1, + "data": [ + { + "pel_nama": "EKSAN HADI", + "pel_alamat": "PERUM AGNIA D1 NO.17", + "rek_bln": 12, + "rek_thn": 2025, + "pemakaian": 11, + "rek_total": 82740, + "rek_ket": "Tagihan Air" + } + ] + } +} +``` + +### Error Cases + +1. **errno = 5**: Wajib bayar di loket +2. **recordsTotal = 0**: Tidak ada tagihan +3. **recordsTotal = 1**: Satu tagihan (tampilkan detail) +4. **recordsTotal > 1**: Multiple tagihan (tampilkan list) + +## ๐Ÿ” Logging + +Semua aktivitas bot di-log ke file: +- `logs/telegram_bot.log` + +Format log: +``` +[2026-01-26 10:30:45] RAW UPDATE: {...} +[2026-01-26 10:30:45] SEND TEXT - Chat ID: 123456, HTTP: 200, Response: {...} +``` + +## ๐Ÿ›ก๏ธ Security + +1. **No Authentication Required**: Webhook endpoint tidak memerlukan autentikasi (Telegram akan mengirim request langsung) +2. **Fast API Authentication**: Bot menggunakan API Key untuk memanggil Fast API +3. **Session Management**: Session disimpan di file system (bisa diubah ke database jika diperlukan) + +## ๐Ÿงช Testing + +### Test Webhook Lokal + +1. Install ngrok: +```bash +ngrok http 8000 +``` + +2. Set webhook ke ngrok URL: +```bash +curl -X POST "https://api.telegram.org/bot/setWebhook" \ + -d "url=https://your-ngrok-url.ngrok.io/telegram/webhook" +``` + +3. Test dengan mengirim pesan ke bot + +### Test dengan cURL + +```bash +curl -X POST "http://localhost:8000/telegram/webhook" \ + -H "Content-Type: application/json" \ + -d '{ + "update_id": 123456789, + "message": { + "message_id": 1, + "from": { + "id": 123456789, + "first_name": "Test", + "username": "testuser" + }, + "chat": { + "id": 123456789, + "type": "private" + }, + "date": 1234567890, + "text": "/start" + } + }' +``` + +## ๐Ÿ“ Notes + +1. **Session Storage**: Saat ini menggunakan file-based storage. Untuk production, pertimbangkan menggunakan database atau Redis. + +2. **Error Handling**: Bot akan menampilkan pesan error yang user-friendly jika terjadi masalah. + +3. **Rate Limiting**: Telegram memiliki rate limiting sendiri. Tidak perlu implement rate limiting tambahan. + +4. **Webhook Security**: Untuk production, pertimbangkan untuk memverifikasi signature dari Telegram (belum diimplementasikan). + +## ๐Ÿ”„ Migration dari Script PHP Lama + +Script PHP lama sudah di-migrate ke struktur Slim Framework: +- โœ… Semua fungsi sudah di-convert ke class methods +- โœ… Session management menggunakan helper class +- โœ… Telegram API calls menggunakan helper class +- โœ… Logging terintegrasi dengan sistem logging +- โœ… Error handling lebih robust + +## ๐ŸŽฏ Next Steps + +1. **Database Session**: Migrate session dari file ke database +2. **Webhook Verification**: Implement signature verification +3. **More Commands**: Tambahkan command lain sesuai kebutuhan +4. **Payment Integration**: Integrate dengan payment flow jika diperlukan + +--- + +**Last Updated**: 2026-01-26 +**Status**: โœ… Ready for Production diff --git a/public/index.php b/public/index.php index d1c9d65..052a2ff 100644 --- a/public/index.php +++ b/public/index.php @@ -215,5 +215,9 @@ $app->get('/fast/mandiri/{tanggal}', [$fastController, 'mandiri']); $app->post('/site/verify_bri', [$siteController, 'verifyBri']); $app->post('/site/approve/{id_trx}', [$siteController, 'approve']); +// Telegram Bot Routes +$telegramBotController = new \App\Controllers\TelegramBotController(); +$app->post('/telegram/webhook', [$telegramBotController, 'webhook']); + // Run app $app->run(); diff --git a/src/Controllers/TelegramBotController.php b/src/Controllers/TelegramBotController.php new file mode 100644 index 0000000..2f96b87 --- /dev/null +++ b/src/Controllers/TelegramBotController.php @@ -0,0 +1,266 @@ +fastApiId = $_ENV['FAST_API_CLIENT_ID'] ?? 'FAS_1753810437_4ff75b'; + $this->fastApiSecret = $_ENV['FAST_API_CLIENT_SECRET'] ?? 'd286ae4f60902d63b72854a38cdaeb9436c6e011f99ad4cf57e512fd6573f711'; + $this->fastApiUrl = $_ENV['BASE_URL'] ?? 'https://api.wipay.id'; + } + + /** + * POST /telegram/webhook + * Webhook endpoint untuk menerima update dari Telegram + */ + public function webhook(Request $request, Response $response): Response + { + try { + // Get raw input + $raw = $request->getBody()->getContents(); + TelegramHelper::log("RAW UPDATE: $raw"); + + $update = json_decode($raw, true); + + if (!$update) { + return ResponseHelper::json($response, [ + 'status' => 'error', + 'message' => 'Invalid JSON' + ], 400); + } + + // Handle callback query (button clicks) + if (isset($update["callback_query"])) { + $this->handleCallbackQuery($update["callback_query"]); + return ResponseHelper::json($response, ['status' => 'ok'], 200); + } + + // Handle regular message + if (isset($update["message"])) { + $this->handleMessage($update["message"]); + return ResponseHelper::json($response, ['status' => 'ok'], 200); + } + + // Unknown update type + return ResponseHelper::json($response, ['status' => 'ok'], 200); + + } catch (\Exception $e) { + error_log("Telegram Webhook Error: " . $e->getMessage()); + return ResponseHelper::json($response, [ + 'status' => 'error', + 'message' => $e->getMessage() + ], 500); + } + } + + /** + * Handle callback query (inline button clicks) + */ + private function handleCallbackQuery($callbackQuery) + { + $chatId = $callbackQuery["message"]["chat"]["id"]; + $data = $callbackQuery["data"]; + $callbackQueryId = $callbackQuery["id"]; + + // Answer callback to remove loading state + TelegramHelper::answerCallback($callbackQueryId); + + if ($data == "menu_tagihan") { + SessionHelper::clearSession($chatId); + SessionHelper::setSession($chatId, "WAIT_PEL"); + + TelegramHelper::sendText($chatId, + "Masukkan Nomor Pelanggan PDAM.\nContoh: 059912" + ); + return; + } + + if ($data == "menu_cekid") { + TelegramHelper::sendMenu($chatId, "ID Telegram Anda: $chatId"); + return; + } + + if ($data == "menu_bantuan") { + TelegramHelper::sendMenu($chatId, + "Perintah Bot:\n" . + "- /cekid\n" . + "- /tagihan\n" + ); + return; + } + } + + /** + * Handle regular message + */ + private function handleMessage($message) + { + $chatId = $message["chat"]["id"]; + $text = $message["text"] ?? ""; + $firstName = TelegramHelper::safe($message["from"]["first_name"] ?? "Pelanggan"); + $username = TelegramHelper::safe($message["from"]["username"] ?? ""); + $displayName = $username ? "@$username" : $firstName; + + // Handle commands + if ($text == "/start") { + SessionHelper::clearSession($chatId); + + $msg = "Halo $displayName\n" . + "Selamat datang di Tirta Intan Mobile Bot.\n\n" . + "Gunakan menu di bawah untuk memulai."; + + TelegramHelper::sendMenu($chatId, $msg); + return; + } + + if ($text == "/cekid") { + TelegramHelper::sendMenu($chatId, "ID Telegram Anda: $chatId"); + return; + } + + if ($text == "/tagihan") { + SessionHelper::clearSession($chatId); + SessionHelper::setSession($chatId, "WAIT_PEL"); + + TelegramHelper::sendText($chatId, + "Masukkan Nomor Pelanggan PDAM.\nContoh: 059912" + ); + return; + } + + // Handle user input based on session + $session = SessionHelper::getSession($chatId); + + if ($session == "WAIT_PEL") { + $this->handlePelangganInput($chatId, $text); + return; + } + + // Unknown command + TelegramHelper::sendMenu($chatId, + "Perintah tidak dikenali.\nGunakan menu di bawah atau ketik /bantuan." + ); + } + + /** + * Handle pelanggan number input + */ + private function handlePelangganInput($chatId, $text) + { + $pelNo = preg_replace('/\D/', '', $text); + SessionHelper::clearSession($chatId); + + TelegramHelper::log("User input pel_no: $pelNo"); + + // Call Fast API check_bill + $url = $this->fastApiUrl . "/fast/check_bill"; + $payload = json_encode(["no_sl" => $pelNo]); + + TelegramHelper::log("CALL FAST API: $url payload=$payload"); + + $ch = curl_init($url); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, [ + "Content-Type: application/json", + "X-Client-ID: " . $this->fastApiId, + "X-Client-Secret: " . $this->fastApiSecret + ]); + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + $apiResponse = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + TelegramHelper::log("FAST API RESPONSE (HTTP $httpCode): $apiResponse"); + + $res = json_decode($apiResponse, true); + + // Safety check if response failed + if (!$res || !isset($res["data"])) { + TelegramHelper::sendMenu($chatId, + "Terjadi kesalahan saat menghubungi server.\nSilakan coba lagi nanti." + ); + return; + } + + $data = $res["data"]; + $errno = $data["errno"] ?? -1; + $error = TelegramHelper::safe($data["error"] ?? ""); + $rows = $data["data"] ?? []; + $count = $data["recordsTotal"] ?? 0; + + // CASE: WAJIB DI LOKET (errno 5) + if ($errno == 5) { + $msg = "Nomor pelanggan " . TelegramHelper::safe($pelNo) . " $error.\n\n" . + "Silakan bayar di loket PDAM atau hubungi:\n+62 823-8891-0073 (Rais Haerullah)."; + + TelegramHelper::sendMenu($chatId, $msg); + return; + } + + // CASE: TIDAK ADA TAGIHAN + if ($count == 0) { + $msg = "Tidak ada tagihan untuk nomor pelanggan " . TelegramHelper::safe($pelNo) . ".\n" . + "Status: $error"; + + TelegramHelper::sendMenu($chatId, $msg); + return; + } + + // CASE: SATU TAGIHAN + if ($count == 1) { + $r = $rows[0]; + + $msg = "Tagihan PDAM Tirta Intan\n\n" . + "Nama: " . TelegramHelper::safe($r["pel_nama"]) . "\n" . + "Alamat: " . TelegramHelper::safe($r["pel_alamat"]) . "\n" . + "Bulan: " . $r["rek_bln"] . " / " . $r["rek_thn"] . "\n" . + "Pemakaian: " . $r["pemakaian"] . " m3\n\n" . + "Total Tagihan: Rp " . number_format($r["rek_total"], 0, ',', '.') . "\n\n"; + + TelegramHelper::sendMenu($chatId, $msg); + return; + } + + // CASE: MULTI TAGIHAN + $nama = TelegramHelper::safe($rows[0]["pel_nama"] ?? ""); + $alamat = TelegramHelper::safe($rows[0]["pel_alamat"] ?? ""); + + $list = ""; + $sum = 0; + + foreach ($rows as $row) { + $bln = $row["rek_bln"]; + $thn = $row["rek_thn"]; + $ket = TelegramHelper::safe($row["rek_ket"]); + $amt = (int)$row["rek_total"]; + + $sum += $amt; + + $list .= "- " . $bln . "/" . $thn . " (" . $ket . ") - Rp " . number_format($amt, 0, ',', '.') . "\n"; + } + + $msg = "Tagihan PDAM Tirta Intan\n\n" . + "Nama: $nama\n" . + "Alamat: $alamat\n\n" . + "Daftar Tagihan:\n" . + $list . "\n" . + "Total: Rp " . number_format($sum, 0, ',', '.') . ""; + + TelegramHelper::sendMenu($chatId, $msg); + } +} diff --git a/src/Helpers/SessionHelper.php b/src/Helpers/SessionHelper.php new file mode 100644 index 0000000..2b20cd6 --- /dev/null +++ b/src/Helpers/SessionHelper.php @@ -0,0 +1,73 @@ + []], JSON_PRETTY_PRINT)); + } + + $json = json_decode(file_get_contents($file), true); + return $json["sessions"] ?? []; + } + + /** + * Save all sessions + */ + public static function saveSessions($sessions) + { + $file = self::getSessionFile(); + file_put_contents($file, json_encode(["sessions" => $sessions], JSON_PRETTY_PRINT)); + } + + /** + * Get session for a chat ID + */ + public static function getSession($chatId) + { + $sessions = self::loadSessions(); + return $sessions[$chatId] ?? null; + } + + /** + * Set session for a chat ID + */ + public static function setSession($chatId, $value) + { + $sessions = self::loadSessions(); + $sessions[$chatId] = $value; + self::saveSessions($sessions); + } + + /** + * Clear session for a chat ID + */ + public static function clearSession($chatId) + { + $sessions = self::loadSessions(); + unset($sessions[$chatId]); + self::saveSessions($sessions); + } +} diff --git a/src/Helpers/TelegramHelper.php b/src/Helpers/TelegramHelper.php index b190624..04b25a2 100644 --- a/src/Helpers/TelegramHelper.php +++ b/src/Helpers/TelegramHelper.php @@ -4,108 +4,160 @@ namespace App\Helpers; class TelegramHelper { - private static $botToken = null; - private static $adminTransaction = []; - private static $adminGangguan = []; + private static $apiURL; + private static $botToken; - /** - * Initialize Telegram config from environment - */ - private static function init() + public static function init() { - if (self::$botToken === null) { - self::$botToken = $_ENV['TELEGRAM_BOT_TOKEN'] ?? '8325211525:AAGPN-Ko2UZr-OIshu54jvi_7wzaMClR8SA'; - self::$adminTransaction = explode(',', $_ENV['TELEGRAM_ADMIN_TRANSACTION'] ?? '1128050689'); - self::$adminGangguan = explode(',', $_ENV['TELEGRAM_ADMIN_GANGGUAN'] ?? '237213251,257394015'); - } + self::$botToken = $_ENV['TELEGRAM_BOT_TOKEN'] ?? ''; + self::$apiURL = "https://api.telegram.org/bot" . self::$botToken . "/"; } /** - * Send Telegram message + * Clean UTF-8 text */ - public static function sendTelegram($pesan, $chatIds = null) + public static function cleanUtf8($text) + { + if (!is_string($text)) { + $text = (string)$text; + } + + // Remove carriage return + $text = str_replace("\r", '', $text); + + // Ensure UTF-8 + if (function_exists('mb_detect_encoding')) { + if (!mb_detect_encoding($text, 'UTF-8', true)) { + $text = mb_convert_encoding($text, 'UTF-8', 'UTF-8,ISO-8859-1,Windows-1252'); + } + } else { + $text = iconv('UTF-8', 'UTF-8//IGNORE', $text); + } + + // Remove control characters (except newline and tab) + $text = preg_replace('/[^\P{C}\n\t]+/u', '', $text); + + return $text; + } + + /** + * Safe string for HTML + */ + public static function safe($str) + { + $str = self::cleanUtf8($str ?? ""); + return htmlspecialchars($str, ENT_QUOTES, 'UTF-8'); + } + + /** + * Send text message + */ + public static function sendText($chatId, $text) { self::init(); + + $text = self::cleanUtf8($text); - if (empty($pesan)) { - return false; - } + $params = [ + "chat_id" => $chatId, + "text" => $text, + "parse_mode" => "HTML" + ]; - if ($chatIds === null) { - $chatIds = self::$adminTransaction; - } + $ch = curl_init(self::$apiURL . "sendMessage"); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + $res = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); - if (!is_array($chatIds)) { - $chatIds = [$chatIds]; - } + self::log("SEND TEXT - Chat ID: $chatId, HTTP: $httpCode, Response: $res"); - $url = 'https://api.telegram.org/bot' . self::$botToken . '/sendMessage'; - $successCount = 0; - $failedCount = 0; + return json_decode($res, true); + } - foreach ($chatIds as $chatId) { - $data = [ - 'chat_id' => $chatId, - 'text' => $pesan, - 'parse_mode' => 'Markdown' + /** + * Send message with inline keyboard + */ + public static function sendMenu($chatId, $text, $keyboard = null) + { + self::init(); + + $text = self::cleanUtf8($text); + + if ($keyboard === null) { + $keyboard = [ + "inline_keyboard" => [ + [ + ["text" => "Cek Tagihan", "callback_data" => "menu_tagihan"] + ], + [ + ["text" => "Cek ID Telegram", "callback_data" => "menu_cekid"] + ], + [ + ["text" => "Bantuan", "callback_data" => "menu_bantuan"] + ] + ] ]; - - $ch = curl_init(); - curl_setopt_array($ch, [ - CURLOPT_URL => $url, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_POST => true, - CURLOPT_POSTFIELDS => http_build_query($data), - CURLOPT_TIMEOUT => 30, - CURLOPT_CONNECTTIMEOUT => 10, - CURLOPT_SSL_VERIFYPEER => false, - CURLOPT_SSL_VERIFYHOST => false, - ]); - - $response = curl_exec($ch); - $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); - $error = curl_error($ch); - curl_close($ch); - - if ($error) { - error_log('Telegram API - cURL Error for Chat ID ' . $chatId . ': ' . $error); - $failedCount++; - continue; - } - - if ($httpCode == 200) { - $result = json_decode($response, true); - if (isset($result['ok']) && $result['ok'] === true) { - error_log('Telegram API - Message sent successfully to Chat ID: ' . $chatId); - $successCount++; - } else { - error_log('Telegram API - Error for Chat ID ' . $chatId . ': ' . ($result['description'] ?? 'Unknown error')); - $failedCount++; - } - } else { - error_log('Telegram API - HTTP Error ' . $httpCode . ' for Chat ID ' . $chatId); - $failedCount++; - } } - return $successCount > 0; + $params = [ + "chat_id" => $chatId, + "text" => $text, + "parse_mode" => "HTML", + "reply_markup" => json_encode($keyboard) + ]; + + $ch = curl_init(self::$apiURL . "sendMessage"); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + $res = curl_exec($ch); + $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); + curl_close($ch); + + self::log("SEND MENU - Chat ID: $chatId, HTTP: $httpCode, Response: $res"); + + return json_decode($res, true); } /** - * Send to transaction admin + * Answer callback query */ - public static function sendToTransactionAdmin($pesan) + public static function answerCallback($callbackQueryId, $text = null, $showAlert = false) { self::init(); - return self::sendTelegram($pesan, self::$adminTransaction); + + $params = [ + "callback_query_id" => $callbackQueryId, + "text" => $text, + "show_alert" => $showAlert + ]; + + $ch = curl_init(self::$apiURL . "answerCallbackQuery"); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $params); + $res = curl_exec($ch); + curl_close($ch); + + return json_decode($res, true); } /** - * Send to gangguan admin + * Log message (public static untuk bisa dipanggil dari controller) */ - public static function sendToGangguanAdmin($pesan) + public static function log($message) { - self::init(); - return self::sendTelegram($pesan, self::$adminGangguan); + $logFile = __DIR__ . "/../../logs/telegram_bot.log"; + $logDir = dirname($logFile); + + if (!file_exists($logDir)) { + mkdir($logDir, 0777, true); + } + + $timestamp = date("Y-m-d H:i:s"); + file_put_contents($logFile, "[$timestamp] $message\n", FILE_APPEND); } }