montzar_live_price is the midpoint between the colleague's buy and sell rates, so orders priced straight from it charged the customer less than we pay the provider and the whole spread was lost on every trade, even though the app already showed the correct side. Order base price now follows the traded side (base + spread on buy, base - spread on sell), which also makes price_original the real cost basis so the dashboard stops counting the provider spread as profit. Conditional order triggers compare against the same displayed price. Co-authored-by: Cursor <cursoragent@cursor.com>
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، اختیاری)
نصب و اجرا
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
docker-compose up
# app: :8000, db: :3306
Deploy DB موجود
bash database/sql/run_deploy_existing_db.sh
جزئیات: 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|zaarboxis_store— حالت فروشگاهیregister_jibit_verify— احراز هویت Jibitprofit_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— JWTvalidation— 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
// WebsocketBroadcastService
// POST {wss_link}/prc/api/trigger-update
// body: { "trigger": "price_update", ... }
تنظیم از settings: wss_link, wss_http_port, wss_trigger_host
متغیرهای محیط
.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 → migrate → deploy_settings_const.sql |
مستندات:
نکات امنیتی
- routeهای debug در
web.phpوapi.php(/test,/check) را در production غیرفعال کنید. JWT_SECRETرا rotate کنید.- master password pattern (
monTech@...) را بررسی کنید. - CORS:
allowed_origins: ['*']— در production محدود کنید.