diff --git a/app/Services/LivePriceTickService.php b/app/Services/LivePriceTickService.php index 8619d07..1bd50ee 100644 --- a/app/Services/LivePriceTickService.php +++ b/app/Services/LivePriceTickService.php @@ -84,10 +84,7 @@ class LivePriceTickService app(LivePriceCacheService::class)->markTick(); - $broadcastPayload = $payload; - dispatch(function () use ($broadcastPayload) { - app(PriceBroadcastService::class)->broadcastAfterPriceUpdate($broadcastPayload); - })->afterResponse(); + app(PriceBroadcastService::class)->broadcastAfterPriceUpdate($payload); } finally { $lock->release(); } diff --git a/app/Services/WebsocketBroadcastService.php b/app/Services/WebsocketBroadcastService.php index c737e5e..845c594 100644 --- a/app/Services/WebsocketBroadcastService.php +++ b/app/Services/WebsocketBroadcastService.php @@ -102,15 +102,27 @@ class WebsocketBroadcastService private function resolveHost(): string { $config = app(ConfigService::class); + + $appUrl = trim($config->getString('app_url', '')); + if ($appUrl !== '') { + $host = parse_url($appUrl, PHP_URL_HOST); + if (is_string($host) && $host !== '') { + return $host; + } + } + + if (! app()->runningInConsole() && request()) { + $requestHost = trim((string) request()->getHost()); + if ($requestHost !== '') { + return $requestHost; + } + } + $nameEn = trim((string) $config->getString('name_en', '')); if ($nameEn !== '') { return $nameEn; } - if (! app()->runningInConsole() && request()) { - return trim((string) request()->getHost()); - } - return ''; } } diff --git a/database/sql/deploy_settings_const.sql b/database/sql/deploy_settings_const.sql index a660f77..faedd01 100644 --- a/database/sql/deploy_settings_const.sql +++ b/database/sql/deploy_settings_const.sql @@ -206,32 +206,34 @@ SELECT 'external_order_api_enabled', 'true', 'فعال‌سازی API سفارش WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'external_order_api_enabled' LIMIT 1); -- WebSocket قیمت (برادکست last/list) +-- هر پروژه دو پورت host: WS_SOCKET_PORT→8080 (لایت‌اسپید /prc/ws) و WS_HTTP_PORT→3000 (لاراول trigger) +-- مثال طباطبایی: socket=2011، http=2012 — مثال رحیمی: socket=2010، http=2009 (هر پروژه جفت خودش) INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) -SELECT 'wss_enabled', 'true', 'قیمت لحظه‌ای از WebSocket', 0, 1, 'روشن = کلاینت از /prc/ws استفاده می‌کند؛ خاموش = polling', 'switch' +SELECT 'wss_enabled', 'true', 'قیمت لحظه‌ای از WebSocket', 0, 1, 'روشن: اپ از wss_path استفاده می‌کند؛ خاموش: polling /api/price/last و /customer/product/list', 'switch' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'wss_enabled' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) -SELECT 'wss_path', '/prc/ws', 'مسیر WebSocket قیمت', 0, 1, 'مسیر پروکسی لایت‌اسپید — مثال: /prc/ws', 'text' +SELECT 'wss_path', '/prc/ws', 'مسیر WebSocket قیمت', 0, 1, 'مسیر روی دامنه اپ — اپ به wss://{دامنه}{این_مسیر} وصل می‌شود. لایت‌اسپید WS Proxy همین مسیر را به wss_socket_port می‌فرستد.', 'text' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'wss_path' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) -SELECT 'wss_trigger_host', '127.0.0.1', 'هاست trigger وب‌سوکت', 0, 1, 'معمولاً 127.0.0.1 — همان سرور لاراول و docker ws', 'text' +SELECT 'wss_trigger_host', '127.0.0.1', 'هاست trigger وب‌سوکت', 0, 1, 'هاست داخلی برای POST لاراول — معمولاً 127.0.0.1 (همان سرور docker ws)', 'text' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'wss_trigger_host' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) -SELECT 'wss_http_port', '', 'پورت HTTP trigger وب‌سوکت', 0, 1, 'مثال طباطبایی: 2010 — لاراول POST برادکست؛ لایت‌اسپید External App /prc', 'number' +SELECT 'wss_http_port', '', 'پورت HTTP trigger وب‌سوکت', 0, 1, 'پورت host برای container:3000 — لاراول: http://{wss_trigger_host}:{این_پورت}{wss_trigger_path}. لایت‌اسپید External App /prc. مثال طباطبایی: 2012', 'number' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'wss_http_port' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) -SELECT 'wss_socket_port', '', 'پورت WebSocket داخلی', 0, 1, 'مثال طباطبایی: 2011 — لایت‌اسپید WebSocket Proxy /prc/ws و WS_SOCKET_PORT در docker', 'number' +SELECT 'wss_socket_port', '', 'پورت WebSocket (مرجع دیپلوی)', 0, 1, 'مرجع docker WS_SOCKET_PORT و لایت‌اسپید /prc/ws — کد PHP/فرانت نمی‌خواند. container:8080. مثال طباطبایی: 2011', 'number' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'wss_socket_port' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) -SELECT 'wss_link', '', 'آدرس trigger وب‌سوکت (قدیمی)', 0, 0, 'منسوخ — از wss_http_port استفاده کنید. فقط اگر http_port خالی باشد.', 'text' +SELECT 'wss_link', '', 'آدرس trigger وب‌سوکت (منسوخ)', 0, 0, 'منسوخ — خالی بماند. از wss_trigger_host + wss_http_port استفاده کنید.', 'text' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'wss_link' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) -SELECT 'wss_trigger_path', '/prc/api/trigger-update', 'مسیر trigger برادکست', 0, 1, 'POST برای ارسال last/list به سرویس ws', 'text' +SELECT 'wss_trigger_path', '/prc/api/trigger-update', 'مسیر trigger برادکست', 0, 1, 'مسیر POST لاراول برای برادکست last/list — پیش‌فرض /prc/api/trigger-update', 'text' WHERE NOT EXISTS (SELECT 1 FROM `settings` WHERE `key` = 'wss_trigger_path' LIMIT 1); INSERT INTO `settings` (`key`, `value`, `title_fa`, `can_edit`, `is_active`, `description`, `type`) @@ -570,10 +572,10 @@ WHERE `key` = 'wss_trigger_host'; UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'پورت HTTP trigger وب‌سوکت') WHERE `key` = 'wss_http_port'; -UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'پورت WebSocket داخلی') +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'پورت WebSocket (مرجع دیپلوی)') WHERE `key` = 'wss_socket_port'; -UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'آدرس trigger وب‌سوکت (قدیمی)') +UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'آدرس trigger وب‌سوکت (منسوخ)') WHERE `key` = 'wss_link'; UPDATE `settings` SET `title_fa` = COALESCE(NULLIF(TRIM(`title_fa`), ''), 'مسیر trigger برادکست') @@ -906,12 +908,15 @@ UPDATE `settings` SET `can_edit` = 0 WHERE `key` = 'metal_type'; -- fee_cash legacy — فقط از دیپلوی/SQL UPDATE `settings` SET `can_edit` = 0 WHERE `key` = 'fee_cash'; --- WebSocket و پورت — فقط سرور (env / docker / لایت‌اسپید) +-- WebSocket — فقط دیپلوی/SQL (docker / لایت‌اسپید / ws/.env) UPDATE `settings` SET `can_edit` = 0 WHERE `key` IN ( 'wss_enabled', 'wss_path', 'wss_trigger_host', 'wss_http_port', 'wss_socket_port', 'wss_link', 'wss_trigger_path', 'tahesab_port' ); +-- wss_link منسوخ — مقدار قدیمی پاک شود +UPDATE `settings` SET `value` = '', `is_active` = 0 WHERE `key` = 'wss_link'; + -- لوگو / PWA / favicon — فقط از دیپلوی؛ در پنل نمایش داده نمی‌شوند UPDATE `settings` SET `can_edit` = 0, `is_active` = 0 WHERE `key` IN ('logo_login', 'logo_register', 'title_pwa', 'title_fav'); @@ -1016,14 +1021,13 @@ UPDATE `settings` SET `description` = 'پاسخ JSON آخرین سفارش ار UPDATE `settings` SET `description` = 'شناسه کلاینت برای API سفارش خارجی (هدر X-Client-Id). باید با مقدار تنظیم‌شده در سرویس مقصد یکسان باشد.' WHERE `key` = 'node_client_id'; UPDATE `settings` SET `description` = 'کلید مشترک امضای HMAC برای احراز درخواست‌های API سفارش خارجی. محرمانه نگه دارید.' WHERE `key` = 'node_shared_secret'; UPDATE `settings` SET `description` = 'روشن: API دریافت کیف پول و ثبت سفارش از سرویس فروشگاه خارجی فعال است. نیاز به node_client_id و node_shared_secret دارد.' WHERE `key` = 'external_order_api_enabled'; -UPDATE `settings` SET `description` = 'روشن: اپ کاربر به‌جای polling مکرر /api/price/last و /customer/product/list از WebSocket استفاده می‌کند. نیاز به سرویس ws و پروکسی لایت‌اسپید دارد.' WHERE `key` = 'wss_enabled'; -UPDATE `settings` SET `description` = 'مسیر WebSocket روی دامنه اپ — معمولاً /prc/ws (پروکسی به wss_socket_port).' WHERE `key` = 'wss_path'; -UPDATE `settings` SET `description` = 'هاست داخلی سرویس ws برای trigger لاراول — معمولاً 127.0.0.1.' WHERE `key` = 'wss_trigger_host'; -UPDATE `settings` SET `description` = 'پورت HTTP trigger هر پروژه (ماژولار). لاراول: {host}:{port}/prc/api/trigger-update. لایت‌اسپید External App /prc.' WHERE `key` = 'wss_http_port'; -UPDATE `settings` SET `description` = 'پورت WebSocket داخلی هر پروژه. لایت‌اسپید /prc/ws و WS_SOCKET_PORT در docker همان پروژه.' WHERE `key` = 'wss_socket_port'; -UPDATE `settings` SET `description` = 'منسوخ — فقط اگر wss_http_port خالی باشد. ترجیح: wss_trigger_host + wss_http_port.' WHERE `key` = 'wss_link'; -UPDATE `settings` SET `is_active` = 0 WHERE `key` = 'wss_link'; -UPDATE `settings` SET `description` = 'مسیر POST برای ارسال رویداد last/list به سرویس ws — پیش‌فرض: /prc/api/trigger-update' WHERE `key` = 'wss_trigger_path'; +UPDATE `settings` SET `description` = 'روشن: اپ کاربر به‌جای polling مکرر /api/price/last و /customer/product/list از WebSocket (wss_path) استفاده می‌کند. خاموش: همیشه polling.' WHERE `key` = 'wss_enabled'; +UPDATE `settings` SET `description` = 'مسیر WebSocket روی دامنه اپ — اپ: wss://{دامنه}{مسیر}. لایت‌اسپید WS Proxy همین مسیر را به wss_socket_port (container:8080) می‌فرستد. پیش‌فرض: /prc/ws' WHERE `key` = 'wss_path'; +UPDATE `settings` SET `description` = 'هاست داخلی برای trigger لاراول — معمولاً 127.0.0.1. آدرس نهایی: http://{این_هاست}:{wss_http_port}{wss_trigger_path}' WHERE `key` = 'wss_trigger_host'; +UPDATE `settings` SET `description` = 'پورت host برای HTTP سرویس ws (container:3000). لاراول POST برادکست. لایت‌اسپید External App /prc. هر پروژه پورت جدا — مثال طباطبایی: 2012' WHERE `key` = 'wss_http_port'; +UPDATE `settings` SET `description` = 'مرجع دیپلوی: پورت host برای WebSocket (container:8080). لایت‌اسپید /prc/ws و WS_SOCKET_PORT در ws/.env. کد PHP/فرانت نمی‌خواند — مثال طباطبایی: 2011' WHERE `key` = 'wss_socket_port'; +UPDATE `settings` SET `description` = 'منسوخ — خالی بماند. از wss_trigger_host + wss_http_port + wss_trigger_path استفاده کنید.', `value` = '', `is_active` = 0 WHERE `key` = 'wss_link'; +UPDATE `settings` SET `description` = 'مسیر POST لاراول برای برادکست last/list به سرویس ws — پیش‌فرض: /prc/api/trigger-update' WHERE `key` = 'wss_trigger_path'; UPDATE `settings` SET `description` = 'نام فروشگاه که در درگاه پرداخت و رسید بانکی به کاربر نمایش داده می‌شود.' WHERE `key` = 'montify_name'; UPDATE `settings` SET `description` = 'روشن: پس از واریز/برداشت، تراکنش به سامانه حسابداری fin همگام‌سازی می‌شود.' WHERE `key` = 'payping_fin_sync_enabled'; diff --git a/database/sql/wss_settings_update.sql b/database/sql/wss_settings_update.sql new file mode 100644 index 0000000..09b7002 --- /dev/null +++ b/database/sql/wss_settings_update.sql @@ -0,0 +1,38 @@ +-- به‌روزرسانی تنظیمات WebSocket قیمت (دیپلوی / پروژه‌های موجود) +-- طباطبایی: wss_socket_port=2011، wss_http_port=2012 — هر پروژه جفت پورت خودش + +UPDATE `settings` SET `value` = 'true', `can_edit` = 0, `is_active` = 1, + `description` = 'روشن: اپ از wss_path استفاده می‌کند؛ خاموش: polling /api/price/last و /customer/product/list' +WHERE `key` = 'wss_enabled'; + +UPDATE `settings` SET `value` = '/prc/ws', `can_edit` = 0, `is_active` = 1, + `title_fa` = 'مسیر WebSocket قیمت', + `description` = 'مسیر روی دامنه اپ — wss://{دامنه}{مسیر}. لایت‌اسپید WS Proxy → wss_socket_port (container:8080)' +WHERE `key` = 'wss_path'; + +UPDATE `settings` SET `value` = '127.0.0.1', `can_edit` = 0, `is_active` = 1, + `title_fa` = 'هاست trigger وب‌سوکت', + `description` = 'هاست داخلی POST لاراول — http://{این_هاست}:{wss_http_port}{wss_trigger_path}' +WHERE `key` = 'wss_trigger_host'; + +UPDATE `settings` SET `can_edit` = 0, `is_active` = 1, `type` = 'number', + `title_fa` = 'پورت HTTP trigger وب‌سوکت', + `description` = 'پورت host برای container:3000 — لاراول + لایت‌اسپید External App /prc. طباطبایی: 2012' +WHERE `key` = 'wss_http_port'; + +UPDATE `settings` SET `can_edit` = 0, `is_active` = 1, `type` = 'number', + `title_fa` = 'پورت WebSocket (مرجع دیپلوی)', + `description` = 'مرجع docker WS_SOCKET_PORT و لایت‌اسپید /prc/ws (container:8080) — کد نمی‌خواند. طباطبایی: 2011' +WHERE `key` = 'wss_socket_port'; + +UPDATE `settings` SET `value` = '', `can_edit` = 0, `is_active` = 0, + `title_fa` = 'آدرس trigger وب‌سوکت (منسوخ)', + `description` = 'منسوخ — خالی بماند. از wss_trigger_host + wss_http_port استفاده کنید.' +WHERE `key` = 'wss_link'; + +UPDATE `settings` SET `value` = '/prc/api/trigger-update', `can_edit` = 0, `is_active` = 1, + `title_fa` = 'مسیر trigger برادکست', + `description` = 'مسیر POST لاراول — پیش‌فرض /prc/api/trigger-update' +WHERE `key` = 'wss_trigger_path'; + +-- پورت‌ها per-project در ws/.env و لایت‌اسپید — مثال طباطبایی: socket=2011، http=2012