Initial SMM panel implementation
This commit is contained in:
@@ -0,0 +1,303 @@
|
||||
# AGENTS.md — SMM Panel Project
|
||||
|
||||
> ملف تعليمات للوكيل البرمجي (AI Agent). اقرأه بالكامل قبل كتابة أي كود.
|
||||
> الهدف: بناء موقع SMM Panel لبيع خدمات السوشال ميديا عبر API مزوّد خارجي،
|
||||
> مع محفظة رصيد (Wallet) ونظام مستخدمين ولوحة أدمن.
|
||||
>
|
||||
> ⚠️ راجع أيضاً `WALLET.md` — فيه تفاصيل إلزامية عن نظام تسجيل الدخول وصحة المحفظة،
|
||||
> و`TASKS.md` — فيه خطة تنفيذ مرحلية بالترتيب.
|
||||
|
||||
---
|
||||
|
||||
## 1. نظرة عامة على المشروع (Project Overview)
|
||||
|
||||
منصة ويب تبيع خدمات سوشال ميديا (متابعين، لايكات، مشاهدات … إلخ).
|
||||
المستخدم:
|
||||
1. يسجّل حساب ويسجّل دخول.
|
||||
2. يشحن محفظته (Wallet) برصيد.
|
||||
3. يتصفّح الخدمات المتاحة.
|
||||
4. ينشئ طلب (Order): يختار خدمة + يحط الرابط/الـ ID + الكمية.
|
||||
5. النظام يخصم من رصيده ويرسل الطلب لمزوّد الخدمة عبر API، ثم يتابع حالته.
|
||||
|
||||
الموقع **وسيط**: يشتري من مزوّد بسعر منخفض ويبيع للمستخدم بسعر أعلى (هامش ربح يحدده الأدمن).
|
||||
|
||||
---
|
||||
|
||||
## 2. المصطلحات (Glossary)
|
||||
|
||||
- **Provider / المزوّد**: الجهة الخارجية اللي تملك الـ API الحقيقي وتنفّذ الخدمات.
|
||||
- **Service / الخدمة**: عنصر قابل للبيع (مثال: "1000 متابع انستقرام")، له `service_id` وسعر وحد أدنى وأقصى.
|
||||
- **Wallet / المحفظة**: رصيد المستخدم داخل الموقع.
|
||||
- **Order / الطلب**: عملية شراء خدمة من قبل المستخدم.
|
||||
- **Transaction / المعاملة**: أي حركة على الرصيد (شحن، خصم، استرجاع).
|
||||
- **Markup / الهامش**: نسبة أو مبلغ يُضاف على سعر المزوّد ليصير سعر البيع.
|
||||
|
||||
---
|
||||
|
||||
## 3. التقنيات (Tech Stack)
|
||||
|
||||
> ⚠️ هذه افتراضات قابلة للتغيير — راجع "قرارات مفتوحة" في الأسفل.
|
||||
|
||||
- **Backend**: Node.js + Express
|
||||
- **Database**: MySQL (أو MariaDB)
|
||||
- **Auth**: JWT + bcrypt لتشفير كلمات المرور
|
||||
- **Frontend**: (اختر واحد) React / EJS templates بسيطة للبداية
|
||||
- **HTTP client** للتواصل مع المزوّد: `axios`
|
||||
- **Validation**: `zod` أو `express-validator`
|
||||
- **Env config**: `dotenv`
|
||||
|
||||
هيكل المجلدات المقترح:
|
||||
```
|
||||
/src
|
||||
/config (اتصال قاعدة البيانات، متغيرات البيئة)
|
||||
/models (استعلامات قاعدة البيانات)
|
||||
/services (منطق العمل: wallet, orders, provider API)
|
||||
/controllers (معالجة الطلبات)
|
||||
/routes (المسارات)
|
||||
/middleware (auth, admin-check, error handler)
|
||||
/utils
|
||||
/public (الواجهة)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. مخطط قاعدة البيانات (Database Schema)
|
||||
|
||||
### جدول users
|
||||
| العمود | النوع | ملاحظات |
|
||||
|---|---|---|
|
||||
| id | BIGINT PK AUTO_INCREMENT | |
|
||||
| username | VARCHAR(50) UNIQUE | |
|
||||
| email | VARCHAR(120) UNIQUE | |
|
||||
| password_hash | VARCHAR(255) | bcrypt |
|
||||
| balance | DECIMAL(12,4) DEFAULT 0 | رصيد المحفظة |
|
||||
| role | ENUM('user','admin') DEFAULT 'user' | |
|
||||
| status | ENUM('active','banned') DEFAULT 'active' | |
|
||||
| created_at | TIMESTAMP | |
|
||||
|
||||
### جدول services
|
||||
| العمود | النوع | ملاحظات |
|
||||
|---|---|---|
|
||||
| id | BIGINT PK | |
|
||||
| provider_service_id | VARCHAR(50) | الـ ID عند المزوّد |
|
||||
| name | VARCHAR(255) | |
|
||||
| category | VARCHAR(100) | |
|
||||
| provider_price | DECIMAL(12,4) | سعر المزوّد لكل 1000 |
|
||||
| sell_price | DECIMAL(12,4) | سعر البيع لكل 1000 (بعد الهامش) |
|
||||
| min | INT | أقل كمية |
|
||||
| max | INT | أكبر كمية |
|
||||
| is_active | BOOLEAN DEFAULT true | |
|
||||
| updated_at | TIMESTAMP | |
|
||||
|
||||
### جدول orders
|
||||
| العمود | النوع | ملاحظات |
|
||||
|---|---|---|
|
||||
| id | BIGINT PK | |
|
||||
| user_id | BIGINT FK → users.id | |
|
||||
| service_id | BIGINT FK → services.id | |
|
||||
| link | VARCHAR(500) | الرابط/الـ ID المستهدف |
|
||||
| quantity | INT | |
|
||||
| charge | DECIMAL(12,4) | المبلغ المخصوم من المستخدم |
|
||||
| provider_order_id | VARCHAR(80) | رقم الطلب عند المزوّد |
|
||||
| status | ENUM('pending','processing','in_progress','completed','partial','canceled','failed') DEFAULT 'pending' | |
|
||||
| created_at | TIMESTAMP | |
|
||||
|
||||
### جدول transactions
|
||||
| العمود | النوع | ملاحظات |
|
||||
|---|---|---|
|
||||
| id | BIGINT PK | |
|
||||
| user_id | BIGINT FK | |
|
||||
| type | ENUM('deposit','order','refund') | |
|
||||
| amount | DECIMAL(12,4) | موجب = إضافة، سالب = خصم |
|
||||
| balance_after | DECIMAL(12,4) | الرصيد بعد العملية (للتدقيق) |
|
||||
| reference | VARCHAR(120) | مرجع (رقم الطلب / رقم الإيداع) |
|
||||
| note | VARCHAR(255) | |
|
||||
| created_at | TIMESTAMP | |
|
||||
|
||||
### جدول deposits (طلبات الشحن اليدوي)
|
||||
| العمود | النوع | ملاحظات |
|
||||
|---|---|---|
|
||||
| id | BIGINT PK | |
|
||||
| user_id | BIGINT FK | |
|
||||
| amount | DECIMAL(12,4) | |
|
||||
| method | VARCHAR(50) | usdt / manual … |
|
||||
| tx_ref | VARCHAR(200) | إثبات التحويل (hash / رقم عملية) |
|
||||
| status | ENUM('pending','approved','rejected') DEFAULT 'pending' | |
|
||||
| reviewed_by | BIGINT NULL | id الأدمن |
|
||||
| created_at | TIMESTAMP | |
|
||||
|
||||
---
|
||||
|
||||
## 5. تكامل API المزوّد (Provider Integration)
|
||||
|
||||
معظم مزوّدي SMM يتبعون نفس المعيار (Perfect Panel standard). كل الطلبات
|
||||
عبارة عن POST إلى نقطة نهاية واحدة مع `key` و `action`.
|
||||
|
||||
**متغيرات البيئة المطلوبة:**
|
||||
```
|
||||
PROVIDER_API_URL=https://provider.example/api/v2
|
||||
PROVIDER_API_KEY=xxxxxxxx
|
||||
```
|
||||
|
||||
**العمليات:**
|
||||
```
|
||||
# جلب كل الخدمات
|
||||
POST { key, action: "services" }
|
||||
|
||||
# إنشاء طلب
|
||||
POST { key, action: "add", service, link, quantity }
|
||||
→ يرجّع { order: <provider_order_id> }
|
||||
|
||||
# متابعة حالة طلب
|
||||
POST { key, action: "status", order: <provider_order_id> }
|
||||
→ يرجّع { charge, start_count, status, remains }
|
||||
|
||||
# رصيدك أنت عند المزوّد
|
||||
POST { key, action: "balance" }
|
||||
```
|
||||
|
||||
> ⚠️ تحقّق من توثيق المزوّد الفعلي: بعض الحقول قد تختلف بالتسمية.
|
||||
> اجعل طبقة `provider.service.js` قابلة للتعديل من مكان واحد.
|
||||
|
||||
---
|
||||
|
||||
## 6. المنطق الحرج: المحفظة والطلبات (Critical Logic)
|
||||
|
||||
> التفاصيل الكاملة (race conditions، idempotency، تسوية دورية) موجودة في `WALLET.md`. هذا ملخص سريع فقط.
|
||||
|
||||
### قاعدة ذهبية: كل عملية على الرصيد داخل Transaction من قاعدة البيانات (atomic)
|
||||
لا تسمح أبداً بخصم الرصيد وإرسال الطلب في خطوات منفصلة غير محمية.
|
||||
|
||||
**تدفق إنشاء الطلب (order flow):**
|
||||
```
|
||||
1. تحقّق أن المستخدم مسجّل دخول ونشِط.
|
||||
2. تحقّق أن الخدمة موجودة و is_active.
|
||||
3. تحقّق quantity ضمن [min, max].
|
||||
4. احسب charge = (sell_price / 1000) * quantity.
|
||||
5. ابدأ DB Transaction:
|
||||
a. اقفل صف المستخدم (SELECT ... FOR UPDATE).
|
||||
b. تحقّق balance >= charge، وإلا ارفض (رصيد غير كافٍ).
|
||||
c. اخصم: balance -= charge.
|
||||
d. أنشئ صف order بحالة pending.
|
||||
e. أنشئ صف transaction (type=order, amount=-charge).
|
||||
f. Commit.
|
||||
6. أرسل الطلب لـ API المزوّد.
|
||||
7. إذا نجح: خزّن provider_order_id وحدّث status=processing.
|
||||
8. إذا فشل الإرسال: أعِد الرصيد (refund) وحدّث status=failed.
|
||||
```
|
||||
|
||||
**تدفق الشحن اليدوي:**
|
||||
```
|
||||
1. المستخدم يقدّم طلب إيداع (amount + tx_ref) → deposits(status=pending).
|
||||
2. الأدمن يراجع ويوافق.
|
||||
3. عند الموافقة (داخل DB Transaction):
|
||||
- balance += amount
|
||||
- transaction (type=deposit)
|
||||
- deposit.status = approved
|
||||
```
|
||||
|
||||
**متابعة الحالات (cron/job):**
|
||||
مهمة دورية تمرّ على الطلبات غير المكتملة وتستعلم عن حالتها من المزوّد وتحدّثها.
|
||||
|
||||
---
|
||||
|
||||
## 7. المسارات (API Routes)
|
||||
|
||||
### عامة / مصادقة
|
||||
```
|
||||
POST /auth/register
|
||||
POST /auth/login
|
||||
POST /auth/logout
|
||||
POST /auth/forgot-password
|
||||
```
|
||||
|
||||
### المستخدم (يتطلب تسجيل دخول)
|
||||
```
|
||||
GET /me → بيانات الحساب + الرصيد
|
||||
GET /services → قائمة الخدمات النشطة (بسعر البيع)
|
||||
POST /orders → إنشاء طلب
|
||||
GET /orders → طلباتي
|
||||
GET /orders/:id → تفاصيل طلب
|
||||
GET /transactions → كشف حساب المحفظة
|
||||
POST /deposits → طلب شحن يدوي
|
||||
GET /deposits → طلبات الشحن الخاصة بي
|
||||
```
|
||||
|
||||
### الأدمن (يتطلب role=admin)
|
||||
```
|
||||
GET /admin/users
|
||||
PATCH /admin/users/:id → حظر/رفع حظر، تعديل رصيد يدوي
|
||||
GET /admin/deposits → طلبات الشحن المعلّقة
|
||||
PATCH /admin/deposits/:id → موافقة/رفض
|
||||
GET /admin/orders → كل الطلبات
|
||||
POST /admin/services/sync → سحب الخدمات من المزوّد
|
||||
PATCH /admin/services/:id → تعديل السعر/الهامش/التفعيل
|
||||
GET /admin/stats → إحصائيات (أرباح، مبيعات)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. متطلبات الأمان (Security — إلزامي)
|
||||
|
||||
- تشفير كلمات المرور بـ **bcrypt** (لا تخزّنها نصّاً أبداً).
|
||||
- مفتاح API المزوّد في **متغيرات البيئة فقط**، لا يُرسل للواجهة إطلاقاً.
|
||||
- كل حسابات المال بـ `DECIMAL` وليس `FLOAT`.
|
||||
- التحقق من صحة كل المدخلات (server-side validation).
|
||||
- حماية من SQL Injection عبر prepared statements / ORM.
|
||||
- Rate limiting على مسارات auth و orders.
|
||||
- التحقق من الصلاحيات (middleware) على كل مسار أدمن.
|
||||
- **السعر يُحسب دائماً في الخادم** — لا تثق بأي سعر قادم من الواجهة.
|
||||
|
||||
---
|
||||
|
||||
## 9. متغيرات البيئة (.env)
|
||||
|
||||
```
|
||||
PORT=3000
|
||||
DATABASE_URL=mysql://user:pass@localhost:3306/smm
|
||||
JWT_SECRET=change_me_long_random
|
||||
PROVIDER_API_URL=https://provider.example/api/v2
|
||||
PROVIDER_API_KEY=your_provider_key
|
||||
DEFAULT_MARKUP_PERCENT=25
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. ترتيب البناء (Build Order / Milestones)
|
||||
|
||||
1. **الإعداد**: مشروع Node + Express + اتصال MySQL + الهجرات (migrations).
|
||||
2. **المصادقة**: register / login / JWT / middleware.
|
||||
3. **المحفظة**: جداول transactions + عرض الرصيد + كشف حساب.
|
||||
4. **الشحن اليدوي**: deposits + موافقة الأدمن.
|
||||
5. **الخدمات**: سحب من المزوّد + عرضها بسعر البيع + إدارة الأدمن.
|
||||
6. **الطلبات**: تدفق الطلب الكامل (atomic) + الإرسال للمزوّد.
|
||||
7. **متابعة الحالات**: مهمة دورية لتحديث حالات الطلبات.
|
||||
8. **لوحة الأدمن**: الإحصائيات والإدارة.
|
||||
9. **الواجهة**: ربط كل شيء بواجهة نظيفة.
|
||||
|
||||
سلّم كل مرحلة قابلة للتشغيل والاختبار قبل الانتقال للتالية.
|
||||
|
||||
> 📋 للتنفيذ الفعلي خطوة بخطوة، اتّبع `TASKS.md`.
|
||||
|
||||
---
|
||||
|
||||
## 11. قرارات مفتوحة (Open Decisions — املأها)
|
||||
|
||||
هذه القرارات محسومة للنسخة الحالية، ومفصلة في `DECISIONS.md`:
|
||||
|
||||
- [x] **طريقة الشحن**: شحن يدوي عبر قنوات قابلة للإدارة، مع PayPal وشام كاش وUSDT كبداية.
|
||||
- [x] **اللغة/التقنية**: Node.js + Express + MySQL/MariaDB.
|
||||
- [x] **الواجهة**: HTML/CSS/JavaScript ثابتة داخل `public/` وتخدمها Express.
|
||||
- [x] **العملة المعتمدة**: USD بأربع خانات عشرية.
|
||||
- [x] **الهامش**: هامش افتراضي من `DEFAULT_MARKUP_PERCENT` مع تخزين `markup_percent` لكل خدمة ودعم تعديل الأدمن.
|
||||
- [x] **رابط ومفتاح API المزوّد الفعلي**: عبر `PROVIDER_API_URL` و`PROVIDER_API_KEY` في متغيرات البيئة فقط.
|
||||
- [x] **دعم متعدد اللغات**: الواجهة والرسائل عربية حالياً، وتعليقات الكود والداخليات بالإنجليزية.
|
||||
|
||||
---
|
||||
|
||||
## 12. ملاحظات للوكيل (Agent Notes)
|
||||
|
||||
- اطلب توثيق المزوّد الحقيقي قبل كتابة طبقة `provider.service.js`.
|
||||
- لا تفترض تفاصيل الدفع؛ إن كانت غير محسومة اسأل المالك.
|
||||
- اكتب اختبارات لمنطق المحفظة (أهم جزء حسّاس) — راجع `WALLET.md` قسم 4.
|
||||
- علّق الكود بالإنجليزية، والرسائل للمستخدم بالعربية (أو حسب إعداد اللغة).
|
||||
Reference in New Issue
Block a user