From abb778e09003f424e81428087db20553616bb6b6 Mon Sep 17 00:00:00 2001 From: adonis Date: Thu, 30 Jul 2026 15:46:11 +0330 Subject: [PATCH] added chat --- .../Controllers/Customer/ChatController.php | 68 +++++++++++++++++++ app/Models/Customer.php | 2 + ...01_add_chat_columns_to_customers_table.php | 53 +++++++++++++++ database/sql/deploy_settings_const.sql | 61 +++++++++++++++-- routes/customer.php | 2 + 5 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 app/Http/Controllers/Customer/ChatController.php create mode 100644 database/migrations/2026_07_30_000001_add_chat_columns_to_customers_table.php diff --git a/app/Http/Controllers/Customer/ChatController.php b/app/Http/Controllers/Customer/ChatController.php new file mode 100644 index 0000000..eaccb9d --- /dev/null +++ b/app/Http/Controllers/Customer/ChatController.php @@ -0,0 +1,68 @@ +id()); + + if (!empty($user->chat_room_id)) { + return response()->json([ + 'message' => 'چت از قبل ساخته شده', + 'user' => $user, + ]); + } + + $chatApi = self::Config('chat_api'); + $chatApiKey = self::Config('chat_api_key'); + + if (!$chatApi || !$chatApiKey) { + return response()->json([ + 'message' => 'تنظیمات گفتگو تنظیم نشده است.', + ], 422); + } + + $host = preg_replace('#^https?://#', '', rtrim((string) $chatApi, '/')); + $userChatId = 'user_'.$user->id; + $url = 'https://'.$host.'/api/rooms/create'; + + try { + $response = Http::post($url, [ + 'api_key' => $chatApiKey, + 'name' => $user->name, + 'type' => 'SUPPORT', + 'members' => [ + 'admin', + $userChatId, + ], + ]); + + if (!$response->successful()) { + return response()->json([ + 'message' => $response->body(), + 'url' => $url, + ], 422); + } + + $data = $response->json(); + $user->chat_room_id = $data['room_id'] ?? null; + $user->chat_user_id = $userChatId; + $user->save(); + + return response()->json([ + 'message' => 'چت ساخته شد', + 'user' => $user, + ]); + } catch (\Exception $exception) { + return response()->json([ + 'message' => $exception->getMessage(), + ], 422); + } + } +} diff --git a/app/Models/Customer.php b/app/Models/Customer.php index 23c9ae8..2fe1908 100644 --- a/app/Models/Customer.php +++ b/app/Models/Customer.php @@ -43,6 +43,8 @@ class Customer extends Authenticatable implements JWTSubject 'trade_active',//آیا امکان معامله دارد؟ 'conditional_order_active',//آیا سفارش شرطی مجاز است؟ 'conditional_order_limit',//سقف تعداد pending (null = نامحدود) + 'chat_room_id', + 'chat_user_id', 'type', 'referral_id', 'referral_to_id', diff --git a/database/migrations/2026_07_30_000001_add_chat_columns_to_customers_table.php b/database/migrations/2026_07_30_000001_add_chat_columns_to_customers_table.php new file mode 100644 index 0000000..d00cb03 --- /dev/null +++ b/database/migrations/2026_07_30_000001_add_chat_columns_to_customers_table.php @@ -0,0 +1,53 @@ +addCustomerColumnIfMissing('chat_room_id', 'VARCHAR(255) NULL DEFAULT NULL', 'conditional_order_limit'); + $this->addCustomerColumnIfMissing('chat_user_id', 'VARCHAR(255) NULL DEFAULT NULL', 'chat_room_id'); + } + + public function down(): void + { + // عمداً خالی — rollback ستون را حذف نمی‌کند + } + + private function customersTable(): string + { + return DB::getTablePrefix().'customers'; + } + + private function customerColumnExists(string $column): bool + { + $result = DB::selectOne( + 'SELECT COUNT(*) AS cnt FROM information_schema.COLUMNS + WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ? AND COLUMN_NAME = ?', + [DB::connection()->getDatabaseName(), $this->customersTable(), $column] + ); + + return (int) $result->cnt > 0; + } + + private function addCustomerColumnIfMissing(string $column, string $definition, ?string $after = null): void + { + if ($this->customerColumnExists($column)) { + return; + } + + $table = $this->customersTable(); + $afterClause = ($after !== null && $this->customerColumnExists($after)) + ? " AFTER `{$after}`" + : ''; + + DB::statement("ALTER TABLE `{$table}` ADD COLUMN `{$column}` {$definition}{$afterClause}"); + } +}; diff --git a/database/sql/deploy_settings_const.sql b/database/sql/deploy_settings_const.sql index de94cae..70dbf77 100644 --- a/database/sql/deploy_settings_const.sql +++ b/database/sql/deploy_settings_const.sql @@ -694,6 +694,36 @@ INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `de SELECT 'support_messenger', '', 'پیام‌رسان پشتیبانی', 1, 1, 'bale,telegram,whatsapp,rubika,eitaa,soroush' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'support_messenger' LIMIT 1); +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'show_to_users_chat', 'deactivate', 'نمایش چت به کاربران', 0, 1, + 'روشن: قابلیت چت پشتیبانی برای این دیپلوی فعال است (منوی ادمین و پیش‌نیاز نمایش به کاربر). خاموش: چت در ادمین و اپ کاربر مخفی است. سوییچ مشتری (has_chat) جداست.', 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'show_to_users_chat' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'chat_api', '', 'API چت', 0, 1, + 'هاست سرور چت جدا (بدون https)، مثلاً chat.example.ir — برای WS و ساخت روم.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'chat_api' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'chat_api_key', '', 'کلید API چت', 0, 1, + 'کلید API سرور چت جدا.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'chat_api_key' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'chat_upload_url', '', 'آدرس آپلود فایل چت', 0, 1, + 'URL کامل آپلود مدیا برای چت پشتیبانی.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'chat_upload_url' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'chat_download_url', '', 'آدرس دانلود فایل چت', 0, 1, + 'پایهٔ URL دانلود/نمایش فایل‌های چت پشتیبانی.', 'text' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'chat_download_url' LIMIT 1); + +INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) +SELECT 'has_chat', 'true', 'چت پشتیبانی', 1, 1, + 'روشن: چت پشتیبانی در اپ مشتری نمایش داده می‌شود (اگر show_to_users_chat هم روشن باشد). خاموش: دکمه و صفحه چت برای کاربر مخفی است. این سوییچ را خود مشتری در تنظیمات عادی عوض می‌کند.', 'switch' +WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'has_chat' LIMIT 1); + INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) SELECT 'deposit_sms_support_number', '', 'شماره تماس پشتیبانی', 1, 1, 'شماره تماس پشتیبانی که در صفحه واریز، درباره ما و قوانین به مشتری نشان داده می‌شود. با کلیک، تماس تلفنی برقرار می‌شود.', 'number' @@ -1154,7 +1184,7 @@ DELETE FROM `settings` WHERE `key` IN ( 'melted_product_id', 'display_montzar', 'tabanGohar_price', 'etehadie_api_url', 'price_method', 'price_primary_source', 'has_page_fund', 'has_page_permission', 'has_page_physical_gold', - 'has_chat', 'product_update_price_on_list', 'product_auto_close_open_on_list', + 'product_update_price_on_list', 'product_auto_close_open_on_list', 'referral_count_for_gift', 'store_status', 'name_en', 'bace_url', 'server_url', 'key', 'color_primary', 'color_secondary', 'price_from_nasiryan', @@ -1572,7 +1602,28 @@ UPDATE `settings` SET `title_fa` = 'پاداش معرف‌شونده' WHERE `key UPDATE `settings` SET `title_fa` = 'پاداش معرف' WHERE `key` = 'gift_for_referrer'; UPDATE `settings` SET `title_fa` = 'پیامک گروهی' WHERE `key` = 'group_sms'; UPDATE `settings` SET `title_fa` = 'پنل پیامک (کیف پول)' WHERE `key` = 'sms_panel'; -UPDATE `settings` SET `title_fa` = 'چت پشتیبانی' WHERE `key` = 'has_chat'; +UPDATE `settings` SET + `title_fa` = 'چت پشتیبانی', + `type` = 'switch', + `can_edit` = 1, + `description` = 'روشن: چت پشتیبانی در اپ مشتری نمایش داده می‌شود (اگر نمایش چت به کاربران هم روشن باشد). خاموش: دکمه و صفحه چت برای کاربر مخفی است.' +WHERE `key` = 'has_chat'; + +UPDATE `settings` SET + `title_fa` = 'نمایش چت به کاربران', + `type` = 'switch', + `description` = 'روشن: قابلیت چت پشتیبانی برای این دیپلوی فعال است (منوی ادمین و پیش‌نیاز نمایش به کاربر). خاموش: چت در ادمین و اپ کاربر مخفی است. سوییچ مشتری (has_chat) جداست.', + `can_edit` = 0 +WHERE `key` = 'show_to_users_chat'; +UPDATE `settings` SET `title_fa` = 'API چت', `type` = 'text', `can_edit` = 0 +WHERE `key` = 'chat_api'; +UPDATE `settings` SET `title_fa` = 'کلید API چت', `type` = 'text', `can_edit` = 0 +WHERE `key` = 'chat_api_key'; +UPDATE `settings` SET `title_fa` = 'آدرس آپلود فایل چت', `type` = 'text', `can_edit` = 0 +WHERE `key` = 'chat_upload_url'; +UPDATE `settings` SET `title_fa` = 'آدرس دانلود فایل چت', `type` = 'text', `can_edit` = 0 +WHERE `key` = 'chat_download_url'; + UPDATE `settings` SET `title_fa` = 'صفحه کسب درآمد' WHERE `key` = 'has_page_earn_money'; UPDATE `settings` SET `title_fa` = 'صفحه صندوق' WHERE `key` = 'has_page_fund'; UPDATE `settings` SET `title_fa` = 'صفحه مجوزها' WHERE `key` = 'has_page_permission'; @@ -1721,7 +1772,8 @@ UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( 'unit', 'up_price', 'down_price', 'wss_enabled', - 'zaarbox_api_url' + 'zaarbox_api_url', + 'show_to_users_chat', 'chat_api', 'chat_api_key', 'chat_upload_url', 'chat_download_url' ); -- قابل ویرایش در پنل (can_edit = 1) @@ -1754,7 +1806,8 @@ UPDATE `settings` SET `can_edit` = 1 WHERE `key` IN ( 'show_product_trade_status', 'show_product_card_meta', 'products_site_link_enabled', 'products_site_link_url', 'products_site_link_text', 'startDay', - 'support_messenger', 'support_messenger_id', 'support_messenger_text', + 'support_messenger', 'support_messenger_id', 'support_messenger_text', 'support_messengers', + 'has_chat', 'deposit_support_message_text', 'deposit_account_holder', 'deposit_card_number', 'deposit_sheba', 'text_about', 'text_rule', 'price_channel_enabled', 'price_channel_messengers', 'price_channel_diff', diff --git a/routes/customer.php b/routes/customer.php index 7bb0c7d..8e4a374 100644 --- a/routes/customer.php +++ b/routes/customer.php @@ -20,6 +20,7 @@ use App\Services\ConfigService; use App\Http\Controllers\Customer\havaleController; use App\Http\Controllers\Customer\CartController; use App\Http\Controllers\Admin\CategoryController; +use App\Http\Controllers\Customer\ChatController; //----------gateway-verify @@ -79,6 +80,7 @@ Route::middleware(['auth:customer', 'customer.active'])->group(function () use ( //--------------Customer Route::get('/me', [CustomerController::class, 'me']); Route::post('/me/update', [CustomerController::class, 'updateMe']); + Route::get('/start-chat', [ChatController::class, 'StartSupportChat']); //----------------code Route::post('/im_from/{code}', [CustomerController::class, 'imFrom']);