Files
docs/business/BUSINESS-02-PAYMENT-FINANCE.md
T
masoodafar-web 3c729304db docs: fix all discrepancies based on comprehensive code audit
Corrections verified against actual CMS/BackOffice/FrontOffice source code:

- ClubActivationFee: 25,200,000 (not 25,000,000)
- Tree depth: no limit (15 is commission calculation depth only)
- IPG wallet charge: Balance=56M + Discount=56M
- DayaLoan wallet charge: Balance=56M + Discount=112M (2×)
- Discount: per-product MaxDiscountPercent (not fixed 30%)
- VAT: 10% (ShopVAT) vs 9% (discount store PlaceOrder)
- Kavenegar template: 'Afrino' only (not verify-foursat)
- SMS sender: 1000001110100
- DayaLoan job: every 20min (not 15min)
- Commission job: Sunday 00:05 (not Saturday)
- Network tree: on User entity (not separate NetworkNode table)
- UserWallets entity (not UserWalletBalances)
- OTP: 6 digits, 5 attempts, 2min TTL, 60s cooldown
- Removed non-existent constants (ClubJoiningPercentage, ClubActivationThreshold)
- Fixed Hangfire Chatika interval: every 5min
- Removed InventorySync from recurring jobs list
2026-02-18 22:58:40 +03:30

232 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 💰 سیستم مالی، پرداخت و درگاه‌ها
> **منابع ادغام‌شده:** `payment-gateway.md`, `payment-architecture-pyms.md`, `daya-loan-integration.md`, `manual-payment-system.md`, `discount-shop-business.md`
> **آخرین بروزرسانی:** اسفند ۱۴۰۴
---
## ۱. معماری کلی مالی
```
┌──────────────────────────────────────────────────────────────────┐
│ FourSat Payment Architecture │
├──────────────┬──────────────┬──────────────┬─────────────────────┤
│ ZarinPal │ Daya Loan │ Manual Pay │ Discount Wallet │
│ (IPG) │ (API) │ (Card2Card) │ (Internal) │
├──────────────┴──────────────┴──────────────┴─────────────────────┤
│ PYMS (Payment Service) │
│ gRPC ←→ CMS ←→ FrontOffice/BackOffice │
├──────────────────────────────────────────────────────────────────┤
│ 3 Wallet System │
│ Balance (نقدی) │ NetworkBalance (شبکه) │ DiscountBalance │
└──────────────────────────────────────────────────────────────────┘
```
---
## ۲. درگاه ZarinPal (IPG)
### ۲.۱ فلوی پرداخت
```
کاربر → انتخاب محصول → درخواست پرداخت
CMS → CreatePaymentRequest (gRPC to PYMS)
PYMS → ZarinPal API → دریافت Authority
Redirect کاربر → صفحه پرداخت ZarinPal
بازگشت با Authority → CMS VerifyPayment
├─→ موفق: ثبت سفارش + شارژ کیف‌پول (در صورت نیاز)
└─→ ناموفق: نمایش پیام خطا
```
### ۲.۲ تنظیمات ZarinPal
| پارامتر | مقدار |
|----------|-------|
| `MerchantId` | از appsettings |
| `CallbackUrl` | `/payment/callback` |
| `Sandbox` | true (staging) / false (production) |
| `Currency` | IRR (ریال → تبدیل به تومان در UI) |
---
## ۳. سیستم وام دایا (DayaLoan)
### ۳.۱ معماری
```
Hangfire Recurring Job (هر ۲۰ دقیقه — cron: */20 * * * *)
DayaLoanProcessorJob.Execute()
بررسی LoanRequests با Status=Pending
برای هر درخواست:
├─→ ارسال به DayaLoan API ([AutomaticRetry(Attempts=3)])
├─→ در صورت تأیید: Balance += 56M, DiscountBalance += 112M (2×)
├─→ ثبت Transaction + Log
└─→ در صورت رد: Status=Rejected + ارسال SMS
```
### ۳.۲ Mock Mode
```csharp
// appsettings.json
"DayaLoan": {
"UseMock": true, // staging
"BaseUrl": "https://api.dayaloan.ir",
"ApiKey": "***",
"AutoApproveInMock": true
}
```
### ۳.۳ مقادیر
| آیتم | مقدار |
|------|-------|
| مبلغ وام (DayaLoanAmount) | ۵۶,۰۰۰,۰۰۰ ریال |
| شارژ Balance | ۵۶,۰۰۰,۰۰۰ ریال |
| شارژ DiscountBalance | ۱۱۲,۰۰۰,۰۰۰ ریال (دو برابر — DayaLoanAmount × 2) |
| مجموع شارژ | ۱۶۸,۰۰۰,۰۰۰ ریال |
| NetworkBalance | شارژ نمی‌شود |
| بازپرداخت | طبق شرایط دایا |
---
## ۴. پرداخت دستی (کارت‌به‌کارت)
> ⚠️ **وضعیت: طراحی‌شده — پیاده‌سازی نشده**
```
فلوی پیشنهادی:
کاربر → انتخاب "کارت‌به‌کارت"
نمایش شماره‌کارت مقصد + مبلغ
کاربر → واریز + آپلود تصویر رسید
ادمین BackOffice → مشاهده لیست درخواست‌ها
تأیید/رد → شارژ خودکار کیف‌پول
```
**موجودیت‌های مورد نیاز:**
- `ManualPaymentRequest` (UserId, Amount, ReceiptImage, Status, AdminNote)
- `ManualPaymentStatus` enum: Pending, Approved, Rejected
---
## ۵. پرداخت ترکیبی فروشگاه تخفیفی (Hybrid Payment)
### ۵.۱ فرمول
```
قیمت محصول = 1,000,000 ریال
MaxDiscountPercent محصول = 40% (هر محصول درصد تخفیف مخصوص خود را دارد)
سهم تخفیف = MIN(1,000,000 × 40%, DiscountBalanceکاربر) = 400,000
پرداخت نقدی (IPG) = 1,000,000 - 400,000 = 600,000
─────────
مجموع = 1,000,000
ℹ️ تخفیف ثابت ۳۰% نیست — فیلد Product.MaxDiscountPercent (0-100) تعیین‌کننده است.
```
### ۵.۲ فلوی خرید فروشگاه تخفیفی
```
کاربر (عضو باشگاه) → مشاهده محصول
قیمت تخفیف‌خورده نمایش داده می‌شود
افزودن به سبد → بررسی DiscountBalance
├─→ DiscountBalance کافی:
│ سهم تخفیف از DiscountBalance کسر
│ باقیمانده → IPG (ZarinPal)
└─→ DiscountBalance ناکافی:
فقط به اندازه موجودی از تخفیف
باقیمانده بیشتر → IPG
```
### ۵.۳ دسترسی فروشگاه تخفیفی
| شرط | نتیجه |
|------|--------|
| `IsClubMember = true` | دسترسی به Discount Store |
| `IsClubMember = false` | فقط Regular Store |
| `DiscountBalance > 0` | می‌تواند از تخفیف استفاده کند |
| `DiscountBalance = 0` | پرداخت ۱۰۰% نقدی |
---
## ۶. PYMS — سرویس پرداخت مرکزی
### ۶.۱ gRPC Services
```protobuf
service PaymentService {
rpc CreatePayment (CreatePaymentRequest) returns (CreatePaymentResponse);
rpc VerifyPayment (VerifyPaymentRequest) returns (VerifyPaymentResponse);
rpc GetPaymentStatus (GetPaymentStatusRequest) returns (PaymentStatusResponse);
rpc RefundPayment (RefundPaymentRequest) returns (RefundPaymentResponse);
}
```
### ۶.۲ Transaction Types
| نوع | کد | توضیح |
|-----|-----|--------|
| PackagePurchase | 1 | خرید پکیج طلایی |
| StorePurchase | 2 | خرید از فروشگاه |
| DiscountStorePurchase | 3 | خرید از فروشگاه تخفیفی |
| CommissionPayout | 4 | واریز کمیسیون هفتگی |
| WalletCharge | 5 | شارژ مستقیم کیف‌پول |
| ActivationFee | 6 | هزینه فعالسازی |
| DayaLoanCharge | 7 | شارژ از وام دایا |
---
## ۷. مالیات و VAT
```
دو نرخ VAT در کد:
SystemConstants.ShopVAT = 0.1 (10%) — تنظیم سیستمی
VAT_RATE = 0.09 (9%) — در فروشگاه تخفیفی (DiscountShop PlaceOrder)
قیمت نمایشی = قیمت پایه × (1 + VAT)
در صورتحساب: قیمت پایه + مالیات جداگانه نمایش داده می‌شود
```
---
## ۸. خلاصه وضعیت پیاده‌سازی
| ماژول | وضعیت | یادداشت |
|-------|--------|---------|
| ZarinPal IPG | ✅ کامل | Production ready |
| وام دایا | ✅ کامل | Mock mode فعال در staging |
| پرداخت ترکیبی | ✅ کامل | Discount + IPG |
| Pool هفتگی | ✅ کامل | SP + Hangfire |
| پرداخت دستی | ⬜ طراحی | نیاز به تصمیم مدیریت |
| Refund | ⬜ طراحی | فقط در PYMS تعریف‌شده |