make the domain configuration, not code: two env vars move everything
A domain change is coming (the Zarinpal terminal rejects the current callback domain). ALLOWED_HOSTS, CSRF_TRUSTED_ORIGINS, CORS defaults, the Bazaar redirect URI and deploy.sh's public health URL each spelled the domain out. They now derive from PUBLIC_BASE_URL and FRONTEND_URL, which keep today's domain as their default; env values for the three lists are still added on top, so the old domain can stay allowed while DNS moves. ZARINPAL_CALLBACK_URL used os.environ.get(key, default), so an empty key in .env produced an empty callback and every payment would fail closed. It now uses the same `.strip() or` fallback as its neighbours; the new test caught it. config/tests_domains.py loads settings in a subprocess with a new domain and fails if any derived value still mentions the old one. docs/operations.md gains the step-by-step domain move (DNS, .env, Zarinpal/Bazaar panels, frontend config.js, verification). CLAUDE.md records that the frontend is now ours and where the rebuild stands. 624 tests green. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -101,13 +101,13 @@ curl https://api.math.tadrisino2.ir/api/health
|
||||
|---|---|
|
||||
| `DJANGO_DEBUG` | خاموش (`0`) — که حالتِ درستِ پروداکشن است |
|
||||
| `DJANGO_SECRET_KEY` | یک کلیدِ تصادفیِ قوی ساخته و در `.django_secret_key` (مجوز `0600`) ذخیره میشود |
|
||||
| `DJANGO_ALLOWED_HOSTS` | دامنههای خودمان پیشفرضاند |
|
||||
| `CSRF_TRUSTED_ORIGINS` · `CORS_ALLOWED_ORIGINS` · `PUBLIC_BASE_URL` | پیشفرضِ درست دارند |
|
||||
| `PUBLIC_BASE_URL` · `FRONTEND_URL` | دامنهی فعلی (`api.math.tadrisino2.ir` / `math.tadrisino2.ir`). بقیهی تنظیمهای دامنه از همین دو ساخته میشوند؛ بخشِ «عوض کردنِ دامنه» |
|
||||
| `DJANGO_ALLOWED_HOSTS` · `CSRF_TRUSTED_ORIGINS` · `CORS_ALLOWED_ORIGINS` | از دو آدرسِ بالا ساخته میشوند؛ مقدارِ env فقط دامنهی *اضافه* است |
|
||||
| `CACHE_URL` | سرویس بالا میآید ولی نرخ بینِ workerها مشترک نیست؛ `/api/health` هشدار میدهد |
|
||||
| `KAVENEGAR_API_KEY` | `POST /api/auth/otp/request` خطای صریحِ `503` میدهد، نه موفقیتِ ساختگی |
|
||||
| `ZARINPAL_MERCHANT_ID` | مسیرِ پرداخت fail-closed میماند (`503`) |
|
||||
| `gunicorn.conf.py` (در ریپو، نه env) | gunicorn خودش از پوشهی کاری میخواندش: workerهای `gthread` با ۸ نخ و timeoutِ ۱۲۰. بدونِ آن، سه استریمِ همزمانِ دستیار کلِ API را قفل میکرد |
|
||||
| `FRONTEND_URL` · `ZARINPAL_REDIRECT_URL` | بعد از پرداخت کاربر به `https://math.tadrisino2.ir/?orderId=…&status=paid\|failed` برمیگردد. `ZARINPAL_REDIRECT_URL=-` یعنی همان پاسخِ JSONِ قدیمی |
|
||||
| `ZARINPAL_REDIRECT_URL` | بعد از پرداخت کاربر به `FRONTEND_URL/?orderId=…&status=paid\|failed` برمیگردد. `ZARINPAL_REDIRECT_URL=-` یعنی همان پاسخِ JSONِ قدیمی |
|
||||
| `BAZAAR_PISHKHAN_API_SECRET` (روشِ جدید) یا `BAZAAR_CLIENT_ID` · `BAZAAR_CLIENT_SECRET` (روشِ قدیمی)، بهعلاوهی `BAZAAR_PACKAGE_NAME` | `POST /api/payment/bazaar/verify` هر خرید را نامعتبر میداند (fail-closed)؛ `/api/health` → `bazaar: false` |
|
||||
| `OPENAI_API_KEY` · `QDRANT_API_KEY` | `POST /api/ai/ask` همان پاسخِ stub را میدهد |
|
||||
| `TEST_LOGIN_PHONES` | هیچ حسابِ تستی باز نیست (بخشِ بعد) |
|
||||
@@ -145,6 +145,35 @@ pendingِ همان کاربر را دوباره با زرینپال میس
|
||||
> روشن میکند که هر شمارهای را بهعنوانِ ورودِ معتبر میپذیرد، و صفحههای خطا
|
||||
> کلِ تنظیمات را نشان میدهند. جایش فقط `.env` است، نه یونیتِ systemd.
|
||||
|
||||
## عوض کردنِ دامنه
|
||||
|
||||
دامنه در کد فقط یکجا آمده: پیشفرضِ `PUBLIC_BASE_URL` و `FRONTEND_URL` در
|
||||
`config/settings.py`. `ALLOWED_HOSTS`، `CSRF_TRUSTED_ORIGINS`، `CORS_ALLOWED_ORIGINS`،
|
||||
callbackِ زرینپال، برگشت از پرداخت، `BAZAAR_REDIRECT_URI` و آدرسِ سلامت در
|
||||
`deploy.sh` همه از همین دو ساخته میشوند (۲۰۲۶-۰۹-۲۶). فرانت هم دامنه را در کد
|
||||
ندارد (README همان ریپو).
|
||||
|
||||
ترتیبِ کار، از بیرون به داخل:
|
||||
|
||||
1. **DNS، آروان و گواهی** برای دامنههای تازه، رو به همین سرور، و `server_name`ِ
|
||||
nginx — کارِ ادمینِ سرور، نه ما.
|
||||
2. **بکاند:** در `.env` سرور `PUBLIC_BASE_URL` و `FRONTEND_URL` را عوض کنید. تا DNS
|
||||
کامل جابهجا شود، دامنههای قبلی را هم نگه دارید:
|
||||
`DJANGO_ALLOWED_HOSTS=api.math.tadrisino2.ir,math.tadrisino2.ir` و
|
||||
`CORS_ALLOWED_ORIGINS=https://math.tadrisino2.ir`. بعد ریاستارت.
|
||||
3. **زرینپال:** دامنهی تازهی API را در پنلِ ترمینال ثبت کنید. خطای `-14` («دامنهی
|
||||
callback با دامنهی ثبتشده نمیخواند») دقیقاً نبودنِ همین است.
|
||||
**بازار** (اگر استفاده شود): Redirect URI در پنل باید عیناً
|
||||
`PUBLIC_BASE_URL/api/payment/bazaar/verify` شود.
|
||||
4. **فرانت:** روی سرورِ فرانت در `dist/config.js` بنویسید
|
||||
`apiBaseUrl: "https://<دامنهی تازهی API>/api"` (یا `.env.production` را عوض و
|
||||
build کنید)، و کشِ آروان را برای `config.js` و `index.html` پاک کنید.
|
||||
5. **وارسی:** `curl https://<دامنهی تازهی API>/api/health` (در `clientIp` باید IPِ
|
||||
خودتان باشد) و یک بار ورود و باز کردنِ یک درس در اپ.
|
||||
|
||||
مرحلهی ۳ را فقط یک پرداختِ واقعی ثابت میکند؛ تا آن انجام نشده، پرداخت را
|
||||
«کار میکند» ننویسید.
|
||||
|
||||
## ورودِ توسعهدهندهها (بدونِ سرویسِ پیامک)
|
||||
|
||||
تا وقتی `KAVENEGAR_API_KEY` ست نشده، با `DEBUG=0` هیچکس نمیتواند با شماره
|
||||
|
||||
Reference in New Issue
Block a user