This commit marks the completion of phase 3.11 (UAT Ready) and includes significant updates to deployment automation, testing, and documentation. Key changes: - Implement `ifnex:smoke-test` command for E2E post-deployment validation - Implement `ifnex:preflight` command for environment audit before migration - Implement `ifnex:import-fx-rates` for automated multi-source currency rate imports (Exir.io and FreeCurrencyAPI) - Update `CurrencySeeder` to support base currencies (USD, AED, EUR, CNY, IRR) - Enhance `IfnexSmokeTest` with improved environment-aware checks and robust HTTP mocking in tests - Update project documentation (Roadmap, README, AGENT, Handoff) to reflect completed phases 3.7 through 3.11 - Add UAT checklist and installation guides for recent hotfixes - Update project statistics (models, migrations, endpoints, and test counts)
20 KiB
راهنمای استقرار IFNEX — ویژهٔ تیم IT کارفرما
مخاطب: مسئول IT شرکت IFNEX تاریخ تحویل: ۲۰۲۶-۱۰-۰۴ آخرین بهروزرسانی: ۲۰۲۶-۱۱-۰۱ (فاز ۳.۱۱) نسخه: ۱.۱ تهیهکننده: VernaSoft Group — Kazem Alghasi
۱. معماری استقرار
این سیستم از دو بخش مستقل تشکیل شده است که هرکدام روی دامنهٔ جداگانه میزبانی میشوند و فقط از طریق REST API با هم ارتباط دارند.
| بخش | دامنه | روش تحویل | مسیر وبسرور |
|---|---|---|---|
| لاراول (API + پنل مدیریت Filament) | system.ifnex.ir |
کلون گیت | /var/www/system.ifnex.ir/public |
| وردپرس (وبسایت + پورتال مشتری) | ifnex.ir |
فایل ZIP + فایل SQL | /var/www/ifnex.ir |
پیشنیازهای هر دو بخش:
- PHP 8.2 یا بالاتر با اکستنشنهای
pdo_mysql،mbstring،xml،gd،zip - MySQL 8 یا بالاتر
- Composer 2.x (فقط برای لاراول)
- Nginx یا Apache + PHP-FPM
- گواهی SSL از Let's Encrypt برای هر دو دامنه
۲. استقرار لاراول — system.ifnex.ir
۲.۱ کلون مخزن
cd /var/www/system.ifnex.ir
git clone https://www.git.vernahost.ir/gitmodir110/ifnex.git tmp
cp -r tmp/04_Laravel/* .
cp tmp/04_Laravel/.env.example .env
rm -rf tmp
۲.۲ نصب پکیجها
composer install --no-dev --optimize-autoloader
۲.۳ تنظیم فایل .env
nano .env
مقادیر زیر را حتماً تنظیم کنید:
APP_NAME=IFNEX
APP_ENV=production
APP_DEBUG=false
APP_URL=https://system.ifnex.ir
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=ifnex_laravel
DB_USERNAME=YOUR_DB_USER
DB_PASSWORD=YOUR_DB_PASSWORD
IFNEX_API_KEY=change-this-secret-key
IFNEX_BRIDGE_API_KEY=change-this-secret-key
CORS_ALLOWED_ORIGINS=https://ifnex.ir
ZARINPAL_SANDBOX=false
ZARINPAL_MERCHANT_ID=YOUR_REAL_MERCHANT_ID
ZARINPAL_CALLBACK_URL=https://system.ifnex.ir/api/v1/payment/callback
ZARINPAL_FRONTEND_FAILURE_URL=https://ifnex.ir/wallet
KAVENEGAR_API_KEY=
KAVENEGAR_SENDER=
⚠️ نکتهٔ امنیتی — الزامی: هر دو مقدار
IFNEX_API_KEYوIFNEX_BRIDGE_API_KEYباید پیش از استقرار با یک رشتهٔ تصادفی و طولانی (مثلاً خروجیopenssl rand -hex 32) جایگزین شوند.مقدار
change-this-secret-keyعمداً انتخاب شده است، چون کد سمت لاراول (BridgeAuthController) دقیقاً همین مقدار را رد میکند و خطای ۵۰۰ میدهد. یعنی اگر جایگزینی فراموش شود، سیستم بیسروصدا کار نمیکند و بهجای آن لو میدهد. هر مقدار دیگری — از جمله مواردی که شبیه placeholder باشند — بهعنوان یک کلید معتبر پذیرفته میشود.
IFNEX_BRIDGE_API_KEYباید عیناً در پلاگین وردپرس هم تنظیم شود.IFNEX_API_KEYکلید عمومی بخش رهگیری است و آن هم باید در پلاگین تنظیم شود.
۲.۴ راهاندازی اولیه
# فاز ۳.۱۰ — پیشاز-همه: بررسی سختسازی محیط (fail-fast)
php artisan ifnex:preflight --skip-db
php artisan key:generate
php artisan migrate --force
# دادههای مرجع — بدون این مراحل قیمتگذاری و فرم سفارش کار نمیکنند
php artisan db:seed --class=CountriesTableSeeder --force
php artisan db:seed --class=SystemSettingSeeder --force
php artisan db:seed --class=CurrencySeeder --force # فاز ۳.۱۰ — پنج ارز پایه
php artisan db:seed --class=RoleAndPermissionSeeder --force
# دریافت نرخ ارز اولیه (auto-approve) — فاز ۳.۱۰
php artisan ifnex:import-fx-rates --source=all --auto-approve
# بررسی نهایی preflight (شامل currencies)
php artisan ifnex:preflight
php artisan storage:link
php artisan config:cache
php artisan route:cache
php artisan view:cache
ℹ️ دربارهٔ seedها: جدول
countriesفقط توسطCountriesTableSeederپر میشود و موتور قیمتگذاری باCountry::where('iso_code', …)->firstOrFail()کشور را پیدا میکند؛ اگر این seed اجرا نشود، همهٔ استعلامهای قیمت با خطای 404 مواجه میشوند و لیست کشورها در فرم سفارش وردپرس خالی میماند. جدولsystem_settingsنیز فقط توسطSystemSettingSeederپر میشود.⚠️ فاز ۳.۱۰ — جدول
currencies:CurrencySeederپنج ارز پایه (USD/AED/EUR/CNY/IRR) را با نرخ صفر (یا ۱ برای ریال) ایجاد میکند تاExchangeRateService::getCurrentRate()خطای RuntimeException ندهد. سپسifnex:import-fx-rates --source=all --auto-approveنرخهای واقعی را از Exir.io (USD/AED) و FreeCurrencyAPI (EUR/CNY) دریافت و درcurrencies.rate_to_rialمینویسد.⚠️ دربارهٔ
DatabaseSeeder: فایلDatabaseSeeder.phpدر فاز ۳.۱۰ بهروزرسانی شد تا در محیط Production، حساب super_admin با رمز عبورpasswordنساخته شود (درlocal/testing/stagingهمچنان ساخته میشود). برای ساخت ادمین Production ازmake:filament-user+assignRoleاستفاده کنید.
💡 اسکریپت خودکار: میتوانید بهجای اجرای دستی همهٔ مراحل بالا، از اسکریپت
scripts/deploy.shاستفاده کنید:bash scripts/deploy.shاین اسکریپت همهٔ مراحل بالا را بهترتیب اجرا میکند و در صورت شکست هر مرحله با کد غیرصفر متوقف میشود.
تنظیم دسترسی پوشهها:
chown -R www-data:www-data storage bootstrap/cache
chmod -R 775 storage bootstrap/cache
۲.۵ ساخت حساب ادمین پنل
پنل مدیریت فقط به کاربرانی اجازهٔ ورود میدهد که نقش Spatie یکی از super_admin، admin یا staff را داشته باشند. برای ساخت اولین مدیر:
php artisan make:filament-user
سپس در یک محیط تعاملی (Tinker) نقش را اعطا کنید:
php artisan tinker
$user = User::where('email', 'admin@ifnex.ir')->first();
$user->assignRole('super_admin');
⚠️ اگر این مرحله انجام نشود، صفحهٔ
/panel/loginباز میشود ولی هیچ حسابی نمیتواند وارد شود.
۲.۶ همگامسازی کاربران وردپرس
ورود مشتری از طریق Bridge انجام میشود و کاربر را بر اساس ایمیل در دیتابیس لاراول پیدا میکند. برای اینکه مشتریان وردپرس بتوانند وارد شوند، باید یکبار کاربران را همگام کنید (این دستور پس از راهاندازی هر دو دیتابیس اجرا میشود):
php artisan ifnex:sync-wp-users \
--wp-db-host=127.0.0.1 \
--wp-db-name=ifnex_wordpress \
--wp-db-user=YOUR_WP_DB_USER \
--wp-db-pass=YOUR_WP_DB_PASSWORD
اگر پیشوند جدولهای وردپرس شما
wp_نیست، گزینهٔ--wp-table-prefixرا هم اضافه کنید.
۲.۷ تنظیمات پیامک (کاوهنگار)
ارسال پیامک در این سیستم از جدول system_settings خوانده میشود، نه از فایل .env. بنابراین مقداردهی KAVENEGAR_API_KEY در .env بهتنهایی کافی نیست و باید از پنل مدیریت وارد شود:
پنل ادمین ← تنظیمات سیستم ← سرویس پیامک
| فیلد | مقدار |
|---|---|
| Kavenegar API Key | کلید دریافتی از پنل کاوهنگار |
| Kavenegar Sender | شمارهٔ فرستندهٔ تأییدشده |
پس از وارد کردن، سوییچهای ارسال برای هر رویداد (تأیید سفارش، رد سفارش، پرداخت موفق، تغییر ترکینگ) را نیز در همان صفحه فعال کنید.
۲.۸ تنظیم Cron
این پروژه در حال حاضر هیچ زمانبندی ثبتشدهای (Schedule) ندارد. تنها وظیفهٔ زمانبندیشده، بهروزرسانی نرخ ارز است که باید مستقیم صدا زده شود:
# فاز ۳.۱۰ — دستور ارتقایافته (جایگزین ifnex:update-rates):
# - USD و AED از Exir.io
# - EUR و CNY از FreeCurrencyAPI (نیازمند CURRENCY_API_KEY)
# - auto-approve نرخهای با تغییر زیر ۵٪
0 2 * * * cd /var/www/system.ifnex.ir && bash scripts/cron-exir-rates.sh >> storage/logs/cron.log 2>&1
⚠️ دستور قبلی
ifnex:update-ratesهمچنان برای backward compatibility موجود است، اما فقط USD و AED را پشتیبانی میکند و auto-approve ندارد. توصیه میشود ازifnex:import-fx-ratesاستفاده کنید.📋 اسکریپت کرون:
scripts/cron-exir-rates.shبهصورت wrapper برایifnex:import-fx-rates --source=all --auto-approveکار میکند. متغیر محیطیIFNEX_PROJECT_DIRرا اگر پروژه در مسیر دیگری نصب است، در crontab تنظیم کنید.
ℹ️ دربارهٔ صف: در نسخهٔ فعلی هیچ Job یا اعلانی که
ShouldQueueرا پیادهسازی کند وجود ندارد وQUEUE_CONNECTIONرویdatabaseاست. بنابراین نیازی بهqueue:workنیست. اگر در آینده صف اضافه شد، آن را با systemd یا supervisor مدیریت کنید، نه با کرون.
۲.۹ تست E2E پس از دیپلوی (فاز ۳.۱۱)
پس از تکمیل مراحل §۲.۴ و چرخش کلیدها، دستور زیر را اجرا کنید تا اتصال DB، ارزها، کشورها، نقشها، ادمین، storage، config/route cache و ۴ endpoint API (شامل health check و endpoint محافظتشده) تأیید شود:
php artisan ifnex:smoke-test
# یا با دامنهٔ سفارشی:
php artisan ifnex:smoke-test --url=https://system.ifnex.ir
این دستور ۲۵+ بررسی انجام میدهد و اگر حتی یکی قرمز باشد، با کد غیرصفر خارج میشود.
⚠️ اگر هر بررسی قرمز شد، UAT کارفرما را شروع نکنید — ابتدا مشکل را رفع کنید. برای جزئیات، فایل لاگ
storage/logs/laravel.logرا ببینید.
پس از سبز شدن smoke-test، چکلیست ۴۳ موردی UAT-3.11.md آمادهٔ اجرا توسط کارفرماست.
۳. استقرار وردپرس — ifnex.ir
۳.۱ نصب فایلها
- فایل ZIP وردپرس را در
/var/www/ifnex.irاکسترکت کنید. - فایل SQL دیتابیس را ایمپورت کنید.
۳.۲ تنظیم wp-config.php
define('DB_NAME', 'ifnex_wordpress');
define('DB_USER', 'YOUR_WP_DB_USER');
define('DB_PASSWORD', 'YOUR_WP_DB_PASSWORD');
define('DB_HOST', '127.0.0.1');
define('DB_CHARSET', 'utf8mb4');
define('DB_COLLATE', '');
define('WP_HOME', 'https://ifnex.ir');
define('WP_SITEURL', 'https://ifnex.ir');
// غیرفعال کردن دیباگ در Production
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);
// امنیت پیشخوان
define('DISALLOW_FILE_EDIT', true);
define('DISALLOW_FILE_MODS', true);
define('FS_METHOD', 'direct');
ساخت کلیدها و Saltهای اختصاصی — الزامی:
فایل wp-config.php که همراه بسته تحویل داده میشود دارای WP_DEBUG = true و کلیدها و Saltهای ثابت است که در مخزن گیت قرار دارند. این مقادیر نباید در Production استفاده شوند. پیش از راهاندازی، مقادیر AUTH_KEY، SECURE_AUTH_KEY، LOGGED_IN_KEY، NONCE_KEY، AUTH_SALT، SECURE_AUTH_SALT، LOGGED_IN_SALT و NONCE_SALT را با مقادیر تصادفی اختصاصی جایگزین کنید. سادهترین روش، دریافت هشت مقدار آماده از سرویس رسمی وردپرس است:
https://api.wordpress.org/secret-key/1.1/salt/
⚠️ استفاده از Saltهای مشترک بین چند نصب، امنیت کوکیهای احراز هویت را بهطور کامل از بین میبرد.
۳.۳ فعالسازی قالب و پلاگین
قالب IFNEX Theme و پلاگین IFNEX Bridge را از بخش افزونههای وردپرس فعال کنید.
۳.۴ تنظیمات پلاگین IFNEX Bridge
از مسیر پنل وردپرس → تنظیمات IFNEX، هر سه فیلد زیر را پر کنید:
| تنظیم | مقدار |
|---|---|
| API URL | https://system.ifnex.ir/api/v1 |
| API Key (عمومی) | همان مقدار IFNEX_API_KEY در فایل .env لاراول |
| Bridge API Key | همان مقدار IFNEX_BRIDGE_API_KEY در فایل .env لاراول |
⚠️ اگر
API Key (عمومی)خالی بماند، صفحهٔ/tracking/خطای «API Key تنظیم نشده است» نشان میدهد و اندپوینت رهگیری کار نمیکند. این مقدار را با یک رشتهٔ تصادفی در.envتنظیم کنید.
۳.۵ اصلاح آدرسها در دیتابیس
اگر سایت از محیط لوکال به سرور منتقل میشود، آدرسهای ذخیرهشده را اصلاح کنید:
UPDATE wp_options
SET option_value = REPLACE(option_value, 'http://localhost/IFNEX-Logistics/03_WordPress', 'https://ifnex.ir')
WHERE option_name IN ('home', 'siteurl');
UPDATE wp_posts
SET guid = REPLACE(guid, 'http://localhost/IFNEX-Logistics/03_WordPress', 'https://ifnex.ir');
UPDATE wp_posts
SET post_content = REPLACE(post_content, 'http://localhost/IFNEX-Logistics/03_WordPress', 'https://ifnex.ir');
UPDATE wp_postmeta
SET meta_value = REPLACE(meta_value, 'http://localhost/IFNEX-Logistics/03_WordPress', 'https://ifnex.ir');
سپس کش وردپرس را پاک کنید (اگر افزونهٔ کش دارید) و یکبار به پیشخوان وردپرس بروید.
۴. تنظیمات وبسرور
۴.۱ لاراول — system.ifnex.ir
- Document Root:
/var/www/system.ifnex.ir/public
۴.۲ وردپرس — ifnex.ir
- Document Root:
/var/www/ifnex.ir
۴.۳ گواهی SSL
هر دو دامنه به گواهی SSL از Let's Encrypt نیاز دارند. پس از نصب گواهی، مطمئن شوید ریدایرکت HTTP به HTTPS فعال است.
۴.۴ 🔐 چکلیست امنیتی سختسازی (فاز ۳.۸.۱ — اجباری قبل از انتشار)
زمینه: در فاز سختسازی Production این تغییرات امنیتی اعمال شد. پیش از رفتن روی سرور، موارد زیر را انجام دهید:
| # | اقدام | چرا؟ |
|---|---|---|
| ۱ | چرخش کلیدها — IFNEX_API_KEY و IFNEX_BRIDGE_API_KEY با رشتهٔ تصادفی جدید (هر دو طرف لاراول و وردپرس یکسان) |
مقادیر قبلی در تاریخچهٔ گیت ثبت شدهاند و باید لورفته فرض شوند: php -r "echo bin2hex(random_bytes(32));" |
| ۲ | Saltهای وردپرس — همهٔ ۸ کلید/salt را از api.wordpress.org/secret-key بازتولید کنید | wp-config.php با saltهای لوکال قبلاً در مخزن کامیت شده بود — اکنون از گیت حذف شده و دیگر کامیت نمیشود |
| ۳ | درگاه پرداخت — ZARINPAL_MERCHANT_ID واقعی + ZARINPAL_SANDBOX=false |
اکنون کد در APP_ENV=production اگر درگاه تستی باشد، با خطای صریح از پردازش جلوگیری میکند (Log::critical در لاگ) |
| ۴ | لاگ Production — LOG_STACK=daily، LOG_LEVEL=warning، LOG_DAILY_DAYS=14، APP_DEBUG=false |
لاگ روزانه و بدون اطلاعات حساس |
| ۵ | کشها — config:cache + route:cache + view:cache |
سرعت + عدم افشای متغیرهای محیطی |
| ۶ | حذف فایلهای دیباگ — مطمئن شوید نسخهٔ جدید پلاگین (ifnex-bridge ≥ 2.1.0) روی سرور است |
هکهای opcache_reset() / header() / cache-buster با time() حذف شدند و با filemtime جایگزین شدند |
۵. چکلیست نهایی
۵.۱ لاراول
- کلون مخزن انجام شد
composer installاجرا شد- فایل
.envتنظیم شد (دیتابیس،APP_URL، CORS، Zarinpal) IFNEX_API_KEYوIFNEX_BRIDGE_API_KEYبا رشتهٔ تصادفی جایگزین شدند (مقدارchange-this-secret-keyباقی نمانده)php artisan key:generateاجرا شدphp artisan migrateاجرا شد (شامل مایگریشن جدیدdiscount_code_usages— سختسازی فاز ۳.۸.۱)- تست کد تخفیف: ثبت سفارش با کد فعال →
used_countافزایش یافت؛ سفارش دوم با کد تکمصرف → خطای 422 - seedها اجرا شدند (
CountriesTableSeeder،SystemSettingSeeder،RoleAndPermissionSeeder) - جدول
countriesپر است (۱۹۲ کشور) - حساب ادمین با نقش
super_adminساخته شد php artisan storage:linkاجرا شد- دسترسی
storage/وbootstrap/cache/تنظیم شد php artisan config:cacheاجرا شد- کاوهنگار در «تنظیمات سیستم» پنل تنظیم شد
- کرون بهروزرسانی نرخ ارز اضافه شد
php artisan ifnex:smoke-testسبز است (تست E2E post-deploy — فاز ۳.۱۱)- آدرس
https://system.ifnex.ir/panel/loginباز میشود و ورود ادمین کار میکند
۵.۲ وردپرس
- فایلها اکسترکت شدند
- دیتابیس ایمپورت شد
wp-config.phpتنظیم شدWP_DEBUGرویfalseتنظیم شد- کلیدها و Saltهای وردپرس با مقادیر اختصاصی جایگزین شدند
- آدرسها در دیتابیس جایگزین شدند
- قالب و پلاگین IFNEX Bridge فعال شدند
- پلاگین تنظیم شد (API URL + API Key عمومی + Bridge API Key)
ifnex:sync-wp-usersاجرا شد و کاربران مشتری به لاراول منتقل شدند- آدرس
https://ifnex.irباز میشود - لاگین مشتری کار میکند
۵.۳ ارتباط بینسامانهای
- وردپرس به API لاراول وصل میشود (تست: لاگین مشتری)
- خطای CORS داده نمیشود
- صفحهٔ
/tracking/با یک شمارهٔ AWB نتیجه برمیگرداند - پرداخت درگاه کار میکند (
ZARINPAL_MERCHANT_IDتنظیم شده وZARINPAL_SANDBOX=false) — توجه: از فاز ۳.۸.۱ کد در Production با درگاه تستی اصلاً اجرا نمیشود (گارد سختسازی) - ارسال پیامک Kavenegar تست شد
- بارگذاری فایل (آپلود تعهدنامه) کار میکند
- بکاپ دیتابیس تنظیم شده است
۶. اطلاعات تماس
| مورد | مقدار |
|---|---|
| توسعهدهنده | VernaSoft Group — Kazem Alghasi |
| ایمیل | kazem@vernasoft.group |
| مخزن گیت | git.vernahost.ir/gitmodir110/ifnex |