From b366baa64cec12237f8231279d38d8f59d4ed8d5 Mon Sep 17 00:00:00 2001 From: hamed <15238-genius.ha@users.noreply.drupalcode.org> Date: Wed, 1 Jul 2026 11:53:16 +0330 Subject: [PATCH] feat(sms): simplify SMS settings to use only KAVENEGAR_API_KEY from env, remove other SMS-related fields from config --- .../prompt/sms-settings-apikey-env-only.md | 311 ++++++++++++++++++ .env.coolify.example | 7 +- .env.example | 6 +- .env.liara.example | 4 +- assets/admin/pages/SettingsPage.tsx | 66 +--- config/services.yaml | 6 - docs/api/sms.md | 12 +- .../Controller/SiteConfigController.php | 12 +- .../Repository/SiteConfigRepository.php | 7 - src/Sms/Controller/SmsWalletController.php | 4 +- src/Sms/Provider/KavehNegarProvider.php | 9 +- 11 files changed, 352 insertions(+), 92 deletions(-) create mode 100644 .claude/prompt/sms-settings-apikey-env-only.md diff --git a/.claude/prompt/sms-settings-apikey-env-only.md b/.claude/prompt/sms-settings-apikey-env-only.md new file mode 100644 index 00000000..ebf66df7 --- /dev/null +++ b/.claude/prompt/sms-settings-apikey-env-only.md @@ -0,0 +1,311 @@ +# ساده‌سازی «تنظیمات پیامک (SMS)» — فقط API Key از env + +## پروژه + +`clinicpro` (Backend Symfony + پنل ادمین React) + +## زمینه + +در پنل ادمین (`https://clinic-pro.ddev.site/admin` → صفحه تنظیمات) بخش **«تنظیمات پیامک (SMS)»** الان چهار مورد قابل‌ویرایش دارد که همه در جدول DB `site_config` ذخیره می‌شوند: + +- `sms_provider` (انتخاب سرویس: کاوه‌نگار / رنگینه) +- `sms_price_rials` (قیمت هر پیامک) +- `kavenegar_api_key` (کلید API) +- `kavenegar_sender` (شماره فرستنده) + +مقدار API Key عملاً باید یک راز (secret) باشد و جای آن env است، نه دیتابیس یا فرم قابل‌ویرایش پنل. تصمیم نهایی: + +- **تنها `KAVENEGAR_API_KEY` در env بماند.** بقیه env های SMS حذف شوند. +- در پنل، کلید فقط **read-only** نمایش داده شود (وضعیت «تنظیم‌شده / تنظیم‌نشده») و از env خوانده شود؛ دیگر در DB ذخیره نشود. +- سه مورد دیگر (provider، price، sender) از **UI و Backend به‌طور کامل حذف** شوند. +- خودِ کارت/بخش «تنظیمات پیامک (SMS)» باقی بماند. + +## هدف + +1. API Key فقط از env (`KAVENEGAR_API_KEY`) — read-only در پنل، بدون ذخیره در DB. +2. حذف کامل `sms_provider`، `sms_price_rials`، `kavenegar_sender` (و کلیدهای rangineh) از UI و Backend config. +3. Provider همیشه `kavenegar`. Sender خالی → کاوه‌نگار از خط پیش‌فرض حساب استفاده می‌کند. +4. `sms_price_rials` که قبلاً از config خوانده می‌شد، تبدیل به ثابت (constant) شود تا کیف‌پول پیامک نشکند. +5. همه فایل‌های env به‌روزرسانی شوند: فقط `KAVENEGAR_API_KEY` بماند. + +## فایل‌های مرتبط + +| فایل | نقش | تغییر | +|------|-----|-------| +| `assets/admin/pages/SettingsPage.tsx` | فرم تنظیمات پنل | حذف ۳ فیلد، تبدیل API Key به read-only status | +| `assets/admin/types/index.ts` | تایپ‌ها | حذف `sms_price_rials` | +| `src/Config/Controller/SiteConfigController.php` | endpoint `/api/v1/admin/settings` | حذف کلیدهای SMS از `ALLOWED_KEYS`؛ افزودن flag read-only | +| `src/Config/Repository/SiteConfigRepository.php` | مقادیر پیش‌فرض config | حذف کلیدهای SMS از `DEFAULTS` | +| `src/Sms/Provider/KavehNegarProvider.php` | provider کاوه‌نگار | خواندن key/sender فقط از env، نه configRepo | +| `src/Sms/Controller/SmsWalletController.php` | balance/price | `sms_price_rials` از ثابت به‌جای config | +| `config/services.yaml` | wiring provider | تنظیم binding های env | +| `.env` و بقیه `.env.*` | متغیرهای محیطی | فقط `KAVENEGAR_API_KEY` | +| `docs/api/sms.md` | مستندات | ذکر منبع جدید API Key | + +--- + +## وضعیت فعلی (کد واقعی) + +### ۱. فرم پنل — `assets/admin/pages/SettingsPage.tsx` + +Zod schema (خطوط ۴۰–۴۳): + +```tsx + sms_provider: z.string(), + kavenegar_api_key: z.string(), + kavenegar_sender: z.string(), + sms_price_rials: z.string(), +``` + +interface (خطوط ۶۵–۶۸) + reset defaults (۱۲۳–۱۲۶) + reset onClick (۵۴۴–۵۴۷) هم همین ۴ کلید را دارند. + +بخش UI (خطوط ۴۷۱–۵۲۰): + +```tsx + {/* تنظیمات پیامک */} +
+ {/* ... هدر «تنظیمات پیامک (SMS)» ... */} +
+
+ + +
+
+ + +
+
+
+
تنظیمات کاوه‌نگار
+
+
+ + + {/* دکمه نمایش/پنهان */} +
+
+ + +
+
+
+
+``` + +### ۲. `src/Config/Repository/SiteConfigRepository.php` — `DEFAULTS` (خطوط ۳۲–۳۷) + +```php + // sms provider + 'sms_provider' => 'kavenegar', + 'kavenegar_api_key' => '', + 'kavenegar_sender' => '', + 'rangineh_api_key' => '', + 'rangineh_sender' => '', + 'sms_price_rials' => '500', +``` + +### ۳. `src/Config/Controller/SiteConfigController.php` — `ALLOWED_KEYS` (خطوط ۳۸–۴۴) + +```php + // sms provider + 'sms_provider', + 'kavenegar_api_key', + 'kavenegar_sender', + 'rangineh_api_key', + 'rangineh_sender', + 'sms_price_rials', +``` + +### ۴. `src/Sms/Provider/KavehNegarProvider.php` (خطوط ۱۳–۲۴) + +```php + public function __construct( + private readonly HttpClientInterface $httpClient, + private readonly SiteConfigRepository $configRepo, + private readonly LoggerInterface $logger, + private readonly ?string $apiKey = null, + private readonly ?string $sender = null, + ) {} + + private function key(): string { return $this->configRepo->get('kavenegar_api_key') ?: ($this->apiKey ?? ''); } + private function sender(): string { return $this->configRepo->get('kavenegar_sender') ?: ($this->sender ?? ''); } +``` + +### ۵. `src/Sms/Controller/SmsWalletController.php` (خط ۵۶) + +```php + $smsPriceRials = (int) ($this->configRepo->get('sms_price_rials') ?? 500); +``` + +### ۶. `config/services.yaml` (خطوط ۹۲–۹۹) + +```yaml + App\Sms\Provider\KavehNegarProvider: + arguments: + $apiKey: '%env(default::KAVENEGAR_API_KEY)%' + $sender: '%env(default::KAVENEGAR_SENDER)%' + + App\Sms\Provider\RanginehProvider: + arguments: + $apiKey: '%env(default::RANGINEH_API_KEY)%' + $sender: '%env(default::RANGINEH_SENDER)%' +``` + +### ۷. env فعلی — `.env` (خطوط ۳۸–۴۲ و ۶۰–۶۴) + +``` +###> SMS ### +KAVENEGAR_API_KEY=change_me +RANGINEH_API_KEY=change_me +SMS_PROVIDER=kavenegar +###< SMS ### +... +# SMS +KAVENEGAR_API_KEY=test_key +KAVENEGAR_SENDER=1000596446 +RANGINEH_API_KEY=test_key +RANGINEH_SENDER=3000 +``` + +> توجه: `.env` هم بلوک `###> SMS ###` دارد هم یک بخش دوم پایین فایل. هر دو باید یکی شوند. + +--- + +## وظایف + +### ۱. Backend — provider کاوه‌نگار فقط از env + +در `src/Sms/Provider/KavehNegarProvider.php`: + +- متد `key()` و `sender()` دیگر از `configRepo` نخوانند؛ فقط از env (constructor): + +```php + private function key(): string { return $this->apiKey ?? ''; } + private function sender(): string { return $this->sender ?? ''; } +``` + +- چون `SiteConfigRepository` دیگر در این کلاس استفاده نمی‌شود، `use App\Config\Repository\SiteConfigRepository;` و پارامتر `private readonly SiteConfigRepository $configRepo,` از constructor حذف شود. +- کامنت خطوط ۱۷–۱۸ («the real key normally comes from DB site config») هم اصلاح شود که حالا فقط از env می‌آید. + +### ۲. Backend — حذف کلیدهای SMS از config + +- `src/Config/Repository/SiteConfigRepository.php`: کل بلوک `// sms provider` (۶ کلید: `sms_provider`, `kavenegar_api_key`, `kavenegar_sender`, `rangineh_api_key`, `rangineh_sender`, `sms_price_rials`) از `DEFAULTS` حذف شود. +- `src/Config/Controller/SiteConfigController.php`: همان ۶ کلید از `ALLOWED_KEYS` حذف شوند (دیگر از طریق PATCH قابل ذخیره نیستند). + +### ۳. Backend — قیمت پیامک به ثابت + +در `src/Sms/Controller/SmsWalletController.php`، چون `sms_price_rials` دیگر در config نیست، آن را ثابت کن: + +```php +class SmsWalletController extends BaseController +{ + private const SMS_PRICE_RIALS = 500; + ... + // به‌جای config: + $smsPriceRials = self::SMS_PRICE_RIALS; +``` + +> `SmsWalletPage.tsx` (خط ۱۲۶) مقدار `balance.sms_price_rials` را از پاسخ همین endpoint می‌خواند؛ چون همچنان در پاسخ برگردانده می‌شود، نیازی به تغییر ندارد. + +### ۴. Backend — نمایش وضعیت read-only کلید در پنل + +چون API Key دیگر در DB نیست، برای اینکه پنل بتواند «تنظیم‌شده/نشده» را نشان دهد، در `SiteConfigController::get()` یک flag محاسبه‌شده اضافه کن (بدون افشای خودِ کلید): + +```php + #[Route('/api/v1/admin/settings', methods: ['GET'])] + public function get(): JsonResponse + { + $config = $this->configRepo->getAll(); + // API Key پیامک فقط از env؛ فقط وضعیت تنظیم‌بودن برگردانده می‌شود نه مقدار. + $config['sms_api_key_configured'] = ($_ENV['KAVENEGAR_API_KEY'] ?? '') !== ''; + return $this->success($config); + } +``` + +> اگر پروژه برای خواندن env از سرویس/پارامتر خاصی استفاده می‌کند، از همان الگو استفاده کن؛ اگر نه، خواندن مستقیم از `$_ENV` قابل‌قبول است. + +### ۵. `config/services.yaml` + +- برای `KavehNegarProvider` فقط `$apiKey` از env بماند؛ خط `$sender` حذف شود (constructor مقدار پیش‌فرض `null` دارد → خط پیش‌فرض کاوه‌نگار): + +```yaml + App\Sms\Provider\KavehNegarProvider: + arguments: + $apiKey: '%env(default::KAVENEGAR_API_KEY)%' +``` + +- binding های `RanginehProvider` (خطوط ۹۶–۹۹) که به env حذف‌شده اشاره می‌کنند حذف شوند. کلاس `RanginehProvider` و تزریق آن در `SmsService` دست‌نخورده بماند (فقط دیگر انتخاب نمی‌شود؛ `resolveProvider()` به‌صورت پیش‌فرض `kavenegar` برمی‌گرداند). + +### ۶. Frontend — `assets/admin/pages/SettingsPage.tsx` + +- از Zod schema (۴۰–۴۳): حذف `sms_provider`، `kavenegar_sender`، `sms_price_rials`. کلید `kavenegar_api_key` هم چون دیگر ارسال نمی‌شود از schema حذف شود. +- از interface تنظیمات (۶۵–۶۸)، reset defaults (۱۲۳–۱۲۶) و reset onClick (۵۴۴–۵۴۷): همان کلیدها حذف شوند. +- state مربوط به `showKavenegarKey` حذف شود (دیگر input رمزی نداریم). +- کارت «تنظیمات پیامک (SMS)» بماند اما محتوایش به یک نمایش read-only تبدیل شود که وضعیت را از `settings.sms_api_key_configured` می‌خواند: + +```tsx + {/* تنظیمات پیامک */} +
+
+
+ 📱 +
+

تنظیمات پیامک (SMS)

+
+ +
+ +
+ {settings?.sms_api_key_configured + ? ✓ تنظیم‌شده (از متغیر محیطی KAVENEGAR_API_KEY) + : ✗ تنظیم‌نشده — مقدار KAVENEGAR_API_KEY را در فایل env قرار دهید} +
+

+ کلید API فقط از طریق متغیر محیطی سرور مدیریت می‌شود و در این پنل قابل ویرایش نیست. +

+
+
+``` + +- `assets/admin/types/index.ts` خط ۴۱۵: `sms_price_rials: number;` حذف شود. اگر تایپ تنظیمات، `sms_provider`/`kavenegar_api_key`/`kavenegar_sender` هم دارد، آن‌ها هم حذف و در صورت لزوم `sms_api_key_configured: boolean;` اضافه شود. + +### ۷. به‌روزرسانی همه فایل‌های env + +در **همه** این فایل‌ها فقط `KAVENEGAR_API_KEY` بماند و `KAVENEGAR_SENDER`، `RANGINEH_API_KEY`، `RANGINEH_SENDER`، `SMS_PROVIDER` حذف شوند: + +`.env`, `.env.example`, `.env.dev`, `.env.local`, `.env.test`, `.env.coolify.example`, `.env.liara.example` + +الگوی نهایی بلوک SMS (در `.env`): + +``` +###> SMS ### +KAVENEGAR_API_KEY=change_me +###< SMS ### +``` + +- در `.env` بخش تکراری پایین فایل (خطوط ۶۰–۶۴) هم پاک‌سازی شود؛ فقط یک `KAVENEGAR_API_KEY` باقی بماند. +- در `.env.example` کامنت خط ۴۱ اصلاح شود به این مضمون: «کلید کاوه‌نگار فقط از env خوانده می‌شود» (نه از DB). +- برای فایل‌های نمونه (`*.example`) مقدار placeholder مثل `KAVENEGAR_API_KEY=` یا `change_me` بگذار؛ در `.env.test` مقدار تستی (مثلاً `test_key`). + +### ۸. مستندات — `docs/api/sms.md` + +- ذکر شود API Key کاوه‌نگار فقط از env `KAVENEGAR_API_KEY` خوانده می‌شود. +- ذکر شود endpoint `/api/v1/admin/settings` دیگر کلیدهای `sms_provider`، `kavenegar_api_key`، `kavenegar_sender`، `rangineh_*`، `sms_price_rials` را نمی‌پذیرد؛ در پاسخ GET فیلد read-only `sms_api_key_configured` اضافه شده. +- provider ثابت `kavenegar` و قیمت پیامک ثابت `SMS_PRICE_RIALS = 500` مستند شود. + +--- + +## نکات مهم + +- **پاک‌سازی DB (اختیاری):** ردیف‌های قدیمی این کلیدها ممکن است در جدول `site_config` مانده باشند. حذفشان ضروری نیست (دیگر خوانده نمی‌شوند) اما برای تمیزی می‌توان با یک کوئری آن‌ها را حذف کرد. migration لازم نیست چون Entity تغییر نکرده. +- **Sender خالی:** با حذف `kavenegar_sender`، متد `send()` مقدار `sender=''` می‌فرستد؛ کاوه‌نگار در این حالت از خط پیش‌فرض حساب استفاده می‌کند. اگر خط اختصاصی لازم شد، بعداً می‌توان `KAVENEGAR_SENDER` را به env و binding برگرداند — طبق درخواست فعلی فقط API Key در env می‌ماند. +- **سازگاری پاسخ:** ساختار پاسخ‌ها با `$this->success()` حفظ شود (BaseController). +- **بررسی تایپ فرانت:** بعد از تغییر، `ddev exec npx tsc --noEmit --project tsconfig.json` خطا ندهد (کلیدهای حذف‌شده جایی رفرنس نشده باشند — خصوصاً `showKavenegarKey`). +- **بیلد:** `ddev exec yarn dev` برای تأیید بیلد JS/TS. +- **پاک کردن کش بعد از تغییر services.yaml/env:** `ddev exec php bin/console cache:clear`. +- **graphify:** بعد از پایان تغییرات `graphify update .` اجرا شود. diff --git a/.env.coolify.example b/.env.coolify.example index 5a5e9e0c..505f4772 100644 --- a/.env.coolify.example +++ b/.env.coolify.example @@ -55,9 +55,12 @@ TRUSTED_PROXIES=10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,127.0.0.1 API_IR_BASE_URL=https://s.api.ir API_IR_TOKEN= +# ── SMS ── +# Kavenegar API key is read ONLY from this env (not the DB). +KAVENEGAR_API_KEY= + # ── Notes ── -# • SMS keys (kavenegar/rangineh) and payment gateway keys (mellat/sep) are read -# from the DB ("Site Settings"), NOT from env. No need to set them here. +# • Payment gateway keys (mellat/sep) are read from the DB ("Site Settings"), NOT from env. # • REFRESH_TOKEN_TTL / OTP_TTL / MAX_FILE_SIZE_BYTES are fixed in the compose file. # • MariaDB & Redis are separate Coolify resources — see DATABASE_URL/REDIS_URL above. diff --git a/.env.example b/.env.example index 8536c991..a9b24d2b 100644 --- a/.env.example +++ b/.env.example @@ -38,8 +38,10 @@ REFRESH_TOKEN_TTL=2592000 OTP_TTL=1200 ###< Auth ### -# SMS keys (kavenegar/rangineh) از پنل «تنظیمات سایت» (DB) خوانده می‌شوند، نه env. -# env فقط fallback اختیاری است؛ نیازی به تعریف اینجا نیست. +###> SMS ### +# کلید API کاوه‌نگار فقط از همین env خوانده می‌شود (نه DB). +KAVENEGAR_API_KEY= +###< SMS ### ###> api.ir Identity Inquiry (Shahkar + IbanMatch) ### # استعلام هویت نماینده: تطبیق کد ملی با موبایل (شاهکار) و تطبیق شبا با کد ملی. diff --git a/.env.liara.example b/.env.liara.example index cd10089a..a0ad96ee 100644 --- a/.env.liara.example +++ b/.env.liara.example @@ -58,7 +58,7 @@ UPLOAD_DIR=var/uploads # ── Notes ── # • Do NOT set RUN_INIT — entrypoint.sh defaults it to 1, and this is a single app, # so JWT keygen + doctrine migrations run once on boot (correct). -# • SMS keys (kavenegar/rangineh) and payment gateway keys (mellat/sep) are read -# from the DB ("Site Settings"), NOT from env. No need to set them here. +# • Kavenegar API key is read ONLY from env — set KAVENEGAR_API_KEY below. +# • Payment gateway keys (mellat/sep) are read from the DB ("Site Settings"), NOT from env. # • Liara exposes only ONE external HTTP port (8080, from liara.json). MariaDB/Redis # are reachable on the private network only. diff --git a/assets/admin/pages/SettingsPage.tsx b/assets/admin/pages/SettingsPage.tsx index 0ed9e46b..ac48ae2f 100644 --- a/assets/admin/pages/SettingsPage.tsx +++ b/assets/admin/pages/SettingsPage.tsx @@ -36,11 +36,6 @@ const schema = z.object({ mellat_username: z.string(), mellat_password: z.string(), sep_terminal_id: z.string(), - // sms - sms_provider: z.string(), - kavenegar_api_key: z.string(), - kavenegar_sender: z.string(), - sms_price_rials: z.string(), }); type FormValues = z.infer; @@ -62,10 +57,7 @@ interface Settings { mellat_username: string; mellat_password: string; sep_terminal_id: string; - sms_provider: string; - kavenegar_api_key: string; - kavenegar_sender: string; - sms_price_rials: string; + sms_api_key_configured: boolean; } // ── Component ───────────────────────────────────────────────────────────── @@ -73,7 +65,6 @@ interface Settings { export default function SettingsPage() { const qc = useQueryClient(); const [showMellatPassword, setShowMellatPassword] = useState(false); - const [showKavenegarKey, setShowKavenegarKey] = useState(false); const { data, isLoading } = useQuery({ queryKey: ['admin-settings'], @@ -120,10 +111,6 @@ export default function SettingsPage() { mellat_username: settings.mellat_username ?? '', mellat_password: settings.mellat_password ?? '', sep_terminal_id: settings.sep_terminal_id ?? '', - sms_provider: settings.sms_provider ?? 'kavenegar', - kavenegar_api_key: settings.kavenegar_api_key ?? '', - kavenegar_sender: settings.kavenegar_sender ?? '', - sms_price_rials: settings.sms_price_rials ?? '500', }); } }, [settings, reset]); @@ -477,45 +464,16 @@ export default function SettingsPage() {

تنظیمات پیامک (SMS)

-
-
- - -
-
- - -
-
- -
-
تنظیمات کاوه‌نگار
-
-
- -
- - -
-
-
- - -
+
+ +
+ {settings?.sms_api_key_configured + ? ✓ تنظیم‌شده (از متغیر محیطی KAVENEGAR_API_KEY) + : ✗ تنظیم‌نشده — مقدار KAVENEGAR_API_KEY را در فایل env قرار دهید}
+

+ کلید API فقط از طریق متغیر محیطی سرور مدیریت می‌شود و در این پنل قابل ویرایش نیست. +

@@ -541,10 +499,6 @@ export default function SettingsPage() { mellat_username: settings.mellat_username, mellat_password: settings.mellat_password, sep_terminal_id: settings.sep_terminal_id, - sms_provider: settings.sms_provider, - kavenegar_api_key: settings.kavenegar_api_key, - kavenegar_sender: settings.kavenegar_sender, - sms_price_rials: settings.sms_price_rials, })} disabled={!isDirty || mutation.isPending} > diff --git a/config/services.yaml b/config/services.yaml index f7855a97..584329e9 100644 --- a/config/services.yaml +++ b/config/services.yaml @@ -91,12 +91,6 @@ services: App\Sms\Provider\KavehNegarProvider: arguments: $apiKey: '%env(default::KAVENEGAR_API_KEY)%' - $sender: '%env(default::KAVENEGAR_SENDER)%' - - App\Sms\Provider\RanginehProvider: - arguments: - $apiKey: '%env(default::RANGINEH_API_KEY)%' - $sender: '%env(default::RANGINEH_SENDER)%' App\Blog\Controller\BlogController: arguments: diff --git a/docs/api/sms.md b/docs/api/sms.md index 4ad58e69..c10025fa 100644 --- a/docs/api/sms.md +++ b/docs/api/sms.md @@ -1,9 +1,17 @@ # SMS API > **Prefix:** `/api/v1/sms` -> **Providers:** `kavenegar` (default) | `rangineh` +> **Provider:** همیشه `kavenegar` (پیش‌فرض و تنها گزینه فعال). > All send operations are dispatched **asynchronously** via Symfony Messenger → Redis queue. +## Configuration + +- **کلید API کاوه‌نگار فقط از متغیر محیطی `KAVENEGAR_API_KEY` خوانده می‌شود** — نه از دیتابیس و نه از پنل. در پنل ادمین فقط وضعیت read-only «تنظیم‌شده/نشده» نمایش داده می‌شود. +- شماره فرستنده تنظیم نمی‌شود؛ کاوه‌نگار از خط پیش‌فرض حساب استفاده می‌کند. +- endpoint `GET /api/v1/admin/settings` یک فیلد read-only به نام `sms_api_key_configured` (boolean) برمی‌گرداند. +- `PATCH /api/v1/admin/settings` دیگر کلیدهای `sms_provider`، `kavenegar_api_key`، `kavenegar_sender`، `rangineh_api_key`، `rangineh_sender`، `sms_price_rials` را نمی‌پذیرد (از `ALLOWED_KEYS` حذف شده‌اند). +- قیمت هر پیامک ثابت است: `SmsWalletController::SMS_PRICE_RIALS = 500` ریال. + --- ## POST `/api/v1/sms/send` @@ -25,7 +33,7 @@ Send a direct SMS message (free text). |-------|------|----------|-------------| | `mobile` | string | ✅ | Recipient mobile (`09XXXXXXXXX`) | | `message` | string | ✅ | Message text | -| `provider` | string | ❌ | `"kavenegar"` or `"rangineh"` (default from env) | +| `provider` | string | ❌ | نادیده گرفته می‌شود؛ همیشه `kavenegar` استفاده می‌شود | ### Response `200` ```json diff --git a/src/Config/Controller/SiteConfigController.php b/src/Config/Controller/SiteConfigController.php index 69968689..bc73c1e6 100644 --- a/src/Config/Controller/SiteConfigController.php +++ b/src/Config/Controller/SiteConfigController.php @@ -35,13 +35,6 @@ class SiteConfigController extends BaseController 'mellat_username', 'mellat_password', 'sep_terminal_id', - // sms provider - 'sms_provider', - 'kavenegar_api_key', - 'kavenegar_sender', - 'rangineh_api_key', - 'rangineh_sender', - 'sms_price_rials', ]; public function __construct( @@ -53,7 +46,10 @@ class SiteConfigController extends BaseController #[Route('/api/v1/admin/settings', methods: ['GET'])] public function get(): JsonResponse { - return $this->success($this->configRepo->getAll()); + $config = $this->configRepo->getAll(); + // کلید API پیامک فقط از env؛ فقط وضعیت تنظیم‌بودن برگردانده می‌شود نه مقدار. + $config['sms_api_key_configured'] = ($_ENV['KAVENEGAR_API_KEY'] ?? '') !== ''; + return $this->success($config); } #[Route('/api/v1/admin/settings', methods: ['PATCH'])] diff --git a/src/Config/Repository/SiteConfigRepository.php b/src/Config/Repository/SiteConfigRepository.php index 81865529..54f7434f 100644 --- a/src/Config/Repository/SiteConfigRepository.php +++ b/src/Config/Repository/SiteConfigRepository.php @@ -28,13 +28,6 @@ class SiteConfigRepository extends ServiceEntityRepository 'mellat_username' => '', 'mellat_password' => '', 'sep_terminal_id' => '', - // sms provider - 'sms_provider' => 'kavenegar', - 'kavenegar_api_key' => '', - 'kavenegar_sender' => '', - 'rangineh_api_key' => '', - 'rangineh_sender' => '', - 'sms_price_rials' => '500', ]; public function __construct(ManagerRegistry $registry) diff --git a/src/Sms/Controller/SmsWalletController.php b/src/Sms/Controller/SmsWalletController.php index 91eb039a..6267b14e 100644 --- a/src/Sms/Controller/SmsWalletController.php +++ b/src/Sms/Controller/SmsWalletController.php @@ -29,6 +29,8 @@ use OpenApi\Attributes as OA; #[IsGranted('IS_AUTHENTICATED_FULLY')] class SmsWalletController extends BaseController { + private const SMS_PRICE_RIALS = 500; + public function __construct( private readonly SmsWalletService $walletService, private readonly SmsWalletRepository $walletRepo, @@ -53,7 +55,7 @@ class SmsWalletController extends BaseController } $balanceRials = $this->walletService->getBalance($entityType, $entityId); - $smsPriceRials = (int) ($this->configRepo->get('sms_price_rials') ?? 500); + $smsPriceRials = self::SMS_PRICE_RIALS; $estimatedSms = $smsPriceRials > 0 ? (int) floor($balanceRials / $smsPriceRials) : 0; return $this->success([ diff --git a/src/Sms/Provider/KavehNegarProvider.php b/src/Sms/Provider/KavehNegarProvider.php index e5341d6a..4b49307c 100644 --- a/src/Sms/Provider/KavehNegarProvider.php +++ b/src/Sms/Provider/KavehNegarProvider.php @@ -2,7 +2,6 @@ namespace App\Sms\Provider; -use App\Config\Repository\SiteConfigRepository; use Psr\Log\LoggerInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; @@ -12,16 +11,14 @@ class KavehNegarProvider implements SmsProviderInterface public function __construct( private readonly HttpClientInterface $httpClient, - private readonly SiteConfigRepository $configRepo, private readonly LoggerInterface $logger, - // Nullable: env `%env(default::KAVENEGAR_API_KEY)%` resolves to null when unset - // (the real key normally comes from DB site config below, not env). + // API key comes only from env `%env(default::KAVENEGAR_API_KEY)%`; null when unset. private readonly ?string $apiKey = null, private readonly ?string $sender = null, ) {} - private function key(): string { return $this->configRepo->get('kavenegar_api_key') ?: ($this->apiKey ?? ''); } - private function sender(): string { return $this->configRepo->get('kavenegar_sender') ?: ($this->sender ?? ''); } + private function key(): string { return $this->apiKey ?? ''; } + private function sender(): string { return $this->sender ?? ''; } public function getName(): string { return 'kavenegar'; }