Remove service_charge_percentage alias and config/fee.php fallback (empty → 0). Move code-managed Montzar/price runtime keys to can_edit=1 in deploy SQL. Add settings:deploy and deploy:tenant artisan commands for server deploy. Advanced admin settings merge runtime keys from local DB; block manual edits. Co-authored-by: Cursor <cursoragent@cursor.com>
330 lines
10 KiB
Markdown
330 lines
10 KiB
Markdown
# Khanegi — سرور API (Laravel)
|
|
|
|
**API اصلی** پلتفرم معاملات طلا و آبشده با تمرکز بر مشتریان خانگی. تمام منطق کسبوکار، احراز هویت، دیتابیس، کیف پول و یکپارچهسازی با سیستمهای خارجی در این پروژه قرار دارد.
|
|
|
|
| مورد | مقدار |
|
|
|------|--------|
|
|
| فریمورک | Laravel 8.75 |
|
|
| PHP | ^7.3 \| ^8.0 |
|
|
| Auth | JWT (`tymon/jwt-auth`) + Sanctum |
|
|
| DB | MySQL 8 |
|
|
| پکیج داخلی | `Rooyesh\Wallet` |
|
|
| تاریخ شمسی | `morilog/jalali`, `hekmatinasser/verta` |
|
|
|
|
---
|
|
|
|
## نقش در معماری Khanegi
|
|
|
|
```
|
|
Khanegi/
|
|
├── userModular/ ← پنل مشتری (مصرفکننده /customer, /auth)
|
|
├── admin/ ← پنل مدیریت (مصرفکننده /admin, /auth)
|
|
└── server/ ← این پروژه
|
|
```
|
|
|
|
کلاینتها REST + JWT به این سرور متصل میشوند. برای رویدادهای لحظهای قیمت، SSE از `/api/price/stream` استفاده میشود. broadcast اختیاری WebSocket از طریق `WebsocketBroadcastService` انجام میشود.
|
|
|
|
---
|
|
|
|
## پیشنیازها
|
|
|
|
- PHP 7.3+ یا 8.x
|
|
- Composer
|
|
- MySQL 8
|
|
- Node.js (فقط برای Laravel Mix، اختیاری)
|
|
|
|
---
|
|
|
|
## نصب و اجرا
|
|
|
|
```bash
|
|
cd server
|
|
composer install
|
|
# ایجاد .env و تنظیم DB_*, JWT_SECRET, APP_KEY
|
|
php artisan key:generate
|
|
php artisan jwt:secret
|
|
php artisan migrate
|
|
php artisan serve # http://localhost:8000
|
|
```
|
|
|
|
### Docker
|
|
|
|
```bash
|
|
docker-compose up
|
|
# app: :8000, db: :3306
|
|
```
|
|
|
|
### Deploy DB موجود
|
|
|
|
```bash
|
|
bash database/sql/run_deploy_existing_db.sh
|
|
```
|
|
|
|
جزئیات: [database/sql/DEPLOY_CHECKLIST.md](./database/sql/DEPLOY_CHECKLIST.md)
|
|
|
|
---
|
|
|
|
## ساختار پروژه
|
|
|
|
```
|
|
server/
|
|
├── app/
|
|
│ ├── Http/Controllers/
|
|
│ │ ├── Admin/ # بکآفیس
|
|
│ │ ├── Customer/ # اپ مشتری
|
|
│ │ ├── Auth/ # ورود، ثبتنام
|
|
│ │ ├── Site/ # قیمت، شهر، گزارش
|
|
│ │ ├── pay/ # PayPing
|
|
│ │ ├── Finance/ # مالی
|
|
│ │ └── Single/ # سفارشات تک
|
|
│ ├── Models/ # 30 مدل Eloquent
|
|
│ └── Services/ # 22 سرویس
|
|
├── packages/rooyesh/wallet/ # کیف پول داخلی
|
|
├── routes/
|
|
│ ├── api.php
|
|
│ ├── auth.php
|
|
│ ├── admin.php
|
|
│ ├── customer.php
|
|
│ └── web.php
|
|
├── config/
|
|
│ ├── auth.php, jwt.php
|
|
│ ├── price_providers.php
|
|
│ ├── payment.php, fee.php
|
|
│ └── validation.php
|
|
├── database/
|
|
│ ├── migrations/ # 21 migration (2026_*)
|
|
│ ├── schema/mysql-schema.sql.reference
|
|
│ └── sql/ # deploy scripts
|
|
├── docker-compose.yml
|
|
└── Dockerfile
|
|
```
|
|
|
|
---
|
|
|
|
## گروههای Route
|
|
|
|
بارگذاری در `RouteServiceProvider`:
|
|
|
|
| Prefix | Middleware | File | مخاطب |
|
|
|--------|------------|------|--------|
|
|
| `/api` | api | `api.php` | عمومی (قیمت، شهر، تنظیمات) |
|
|
| `/auth` | api + validation | `auth.php` | ورود |
|
|
| `/admin` | api | `admin.php` | پنل مدیریت |
|
|
| `/customer` | api | `customer.php` | اپ مشتری |
|
|
| `/` | web | `web.php` | views, cron |
|
|
|
|
Rate limit: **60 req/min** روی `api`.
|
|
|
|
---
|
|
|
|
## API Endpoints (خلاصه)
|
|
|
|
### `/auth` — احراز هویت
|
|
|
|
| Method | Path | توضیح |
|
|
|--------|------|--------|
|
|
| POST | `/auth/login` | ورود (رمز/SMS) |
|
|
| POST | `/auth/verify` | تأیید OTP |
|
|
| POST | `/auth/register` | ثبتنام مشتری |
|
|
|
|
### `/api` — عمومی
|
|
|
|
| Endpoint | عملکرد |
|
|
|----------|--------|
|
|
| GET `/api/candle` | نمودار شمعی |
|
|
| GET/POST `/api/price/last` | آخرین قیمت |
|
|
| GET `/api/price/stream` | SSE قیمت لحظهای |
|
|
| GET `/api/city/*` | استان/شهر |
|
|
| GET `/api/get_settings` | تنظیمات عمومی |
|
|
| GET `/api/const/key/{key}` | ثابتها |
|
|
| POST `/api/price_triggers/table` | جدول هشدار قیمت |
|
|
| Store: `/api/cart/*`, `/api/categories` | سبد خرید بدون لاگین |
|
|
|
|
### `/admin` — مدیریت (JWT: `auth:user`)
|
|
|
|
| Domain | Endpoints |
|
|
|--------|-----------|
|
|
| Profile | `GET /admin/me`, `POST /admin/me/update` |
|
|
| Users | `resource /admin/user`, `POST /admin/user/table` |
|
|
| Customers | `resource /admin/customer`, archive, assets, referrals |
|
|
| Products | `resource /admin/product`, quick actions, categories |
|
|
| Prices | `POST /admin/price`, `/admin/prices/chart`, sync logs |
|
|
| Orders | `POST /admin/order/table`, single orders |
|
|
| Wallet | charge, withdraw, transactions |
|
|
| Dashboard | `GET/POST /admin/dashboard`, finance |
|
|
| Tahesab | sync, register, retry |
|
|
| Settings | `GET/POST /admin/get_settings` |
|
|
| Messages | `resource /admin/messages` |
|
|
| Gift Card | `POST /admin/giftcard/generate` |
|
|
| Offer Codes | `resource /admin/offer_code` |
|
|
|
|
### `/customer` — مشتری (JWT: `auth:customer`)
|
|
|
|
| Domain | Endpoints |
|
|
|--------|-----------|
|
|
| Profile | `GET /customer/me`, `POST /customer/me/update` |
|
|
| Wallet | `GET /customer/wallet/me`, withdraw, transactions |
|
|
| Orders | `POST /customer/order`, `POST /customer/order/table` |
|
|
| Fund | `resource /customer/fund`, deposit/withdraw |
|
|
| Product | `POST /customer/wallet/product/deposit` |
|
|
| Bank Account | `resource /customer/account` |
|
|
| Gateway | `POST /customer/charge_account` |
|
|
| Referral | `POST /customer/im_from/{code}` |
|
|
| Price Trigger | `resource /customer/price_triggers` |
|
|
| Address | `resource /customer/address` |
|
|
| Gift Card | `POST /customer/giftcard/use` |
|
|
| Store | `POST /customer/havale`, `POST /customer/cart/checkout` |
|
|
|
|
---
|
|
|
|
## مدلها و دامنههای کسبوکار
|
|
|
|
| دامنه | Models |
|
|
|--------|--------|
|
|
| کاربران | `User` |
|
|
| مشتریان | `Customer`, `CustomersSetting` |
|
|
| کاتالوگ | `Product`, `Category`, `Price`, `PriceCandle`, `PriceTrigger` |
|
|
| معاملات | `Order` |
|
|
| مالی | `Fund`, `Withdraw`, `BankAccount` |
|
|
| کیف پول | `Wallet`, `Transaction` (Rooyesh) |
|
|
| فروشگاه | `Cart`, `CartItem` |
|
|
| کارت هدیه | `GiftCard`, `GiftCardCodes`, `OfferCode` |
|
|
| حسابداری | `Tahesab`, `TransactionsAdmin` |
|
|
| سیستم | `Setting`, `Cnt`, `Message`, `Log`, `File`, `City` |
|
|
| Sync | `PriceSyncLog`, `PriceSyncLogItem` |
|
|
|
|
**تنظیمات runtime** در جدول `settings` ذخیره میشود (`ConfigService`).
|
|
|
|
کلیدهای رایج در `config/price_providers.php`:
|
|
|
|
- `price_provider` — `montzar` \| `main_product` \| `zaarbox`
|
|
- `is_store` — حالت فروشگاهی
|
|
- `register_jibit_verify` — احراز هویت Jibit
|
|
- `profit_gold_api_enabled` — API سود طلا
|
|
- `external_order_api_enabled` — API سفارش خارجی
|
|
|
|
---
|
|
|
|
## احراز هویت
|
|
|
|
### Guards
|
|
|
|
| Guard | Model | کاربرد |
|
|
|-------|-------|--------|
|
|
| `user` | `User` | ادمین |
|
|
| `customer` | `Customer` | مشتری خانگی |
|
|
|
|
### Login Flow
|
|
|
|
- Provider: `user` یا `customer`
|
|
- روشها: password، SMS OTP (4 رقمی)، master password
|
|
- TTL JWT: **43200 دقیقه** (30 روز)
|
|
- بررسی: `active`, `is_archive` (مشتری)
|
|
|
|
### Middleware
|
|
|
|
- `auth:user` / `auth:customer` — JWT
|
|
- `validation` — rules از `config/validation.php` + تبدیل اعداد فارسی
|
|
- `throttle:api` — 60 req/min
|
|
|
|
---
|
|
|
|
## سرویسهای کلیدی
|
|
|
|
| سرویس | کاربرد |
|
|
|--------|--------|
|
|
| `ConfigService` | تنظیمات از DB + fallback |
|
|
| `ProductPriceService` | قیمتگذاری محصولات |
|
|
| `PriceStreamService` | SSE قیمت لحظهای |
|
|
| `MontzarService` | منبع قیمت Montzar |
|
|
| `ZaarboxPriceService` | منبع قیمت Zaarbox |
|
|
| `TahesabSyncService` | همگامسازی تهحساب |
|
|
| `WalletBalanceService` | مانده کیف پول |
|
|
| `AssetSummaryService` | خلاصه دارایی |
|
|
| `WebsocketBroadcastService` | trigger WebSocket اختیاری |
|
|
| `NotificationService` | SMS و اعلان |
|
|
| `ReferralGiftService` | پاداش معرف |
|
|
| `AccountingLedgerService` | دفتر حسابداری |
|
|
|
|
---
|
|
|
|
## پکیج کیف پول (Rooyesh)
|
|
|
|
```
|
|
packages/rooyesh/wallet/
|
|
├── WalletInterface
|
|
├── TransactionInterface
|
|
└── Models: Wallet, Transaction, TransactionMeta
|
|
```
|
|
|
|
مدیریت موجودی `cash` (ریال) و `gold` (طلا) per owner.
|
|
|
|
---
|
|
|
|
## یکپارچهسازیهای خارجی
|
|
|
|
| سرویس | کاربرد |
|
|
|--------|--------|
|
|
| **تهحساب** | حسابداری، مانده، اسناد |
|
|
| **PayPing** | درگاه پرداخت |
|
|
| **Montzar / Zaarbox** | منبع قیمت |
|
|
| **Jibit** | احراز هویت ثبتنام |
|
|
| **WebSocket (اختیاری)** | realtime trigger |
|
|
|
|
### Trigger WebSocket
|
|
|
|
```php
|
|
// WebsocketBroadcastService
|
|
// POST {wss_link}/prc/api/trigger-update
|
|
// body: { "trigger": "price_update", ... }
|
|
```
|
|
|
|
تنظیم از `settings`: `wss_link`, `wss_http_port`, `wss_trigger_host`
|
|
|
|
---
|
|
|
|
## متغیرهای محیط
|
|
|
|
### `.env` استاندارد
|
|
|
|
```env
|
|
APP_NAME, APP_ENV, APP_KEY, APP_DEBUG, APP_URL
|
|
DB_CONNECTION=mysql
|
|
DB_HOST, DB_PORT, DB_DATABASE, DB_USERNAME, DB_PASSWORD
|
|
JWT_SECRET
|
|
```
|
|
|
|
**توجه:** بیشتر credentialهای یکپارچهسازی در جدول `settings` است، نه `.env`.
|
|
|
|
---
|
|
|
|
## Deploy
|
|
|
|
| روش | توضیح |
|
|
|------|--------|
|
|
| PHP-FPM + Nginx | production استاندارد |
|
|
| Docker | `docker-compose.yml` — app + MySQL |
|
|
| DB موجود | `baseline_migrations.sql` → `php artisan deploy:tenant` |
|
|
|
|
مستندات:
|
|
|
|
- [database/sql/DEPLOY_CHECKLIST.md](./database/sql/DEPLOY_CHECKLIST.md)
|
|
- [database/schema/README.md](./database/schema/README.md)
|
|
|
|
---
|
|
|
|
## نکات امنیتی
|
|
|
|
1. routeهای debug در `web.php` و `api.php` (`/test`, `/check`) را در production غیرفعال کنید.
|
|
2. `JWT_SECRET` را rotate کنید.
|
|
3. master password pattern (`monTech@...`) را بررسی کنید.
|
|
4. CORS: `allowed_origins: ['*']` — در production محدود کنید.
|
|
|
|
---
|
|
|
|
## مستندات مرتبط
|
|
|
|
- [README اپ مشتری](../userModular/README.md)
|
|
- [README پنل ادمین](../admin/README.md)
|
|
- [README نمای کلی](../README.md)
|