docs: فاز ۱۱ — فیکسهای پرداخت ZarinPal + تصحیح تومان/ریال + امنیت Callback URL
- CHANGELOG: Phase 11 (11a-11f) — ZarinPal verify fix, تومان/ریال مدل, صفحه موفقیت, حذف ×۱۰ دوبار, callback URL امنیت - BUSINESS-02: تصحیح مدل ارزی (DB=تومان نه ریال), ZarinPal verify fix, جدول callback URL امنیت - TECH-01: اضافه CmsBaseUrl/FrontOfficeBaseUrl به appsettings, توضیح امنیت Open Redirect - TECH-02: اضافه PaymentCallback.razor, وضعیتهای جدید - ROADMAP: بروزرسانی Payment 97→99%, اضافه فاز ۱۱ به DONE list
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
# 💰 سیستم مالی، پرداخت و درگاهها
|
||||
|
||||
> **منابع ادغامشده:** `payment-gateway.md`, `payment-architecture-pyms.md`, `daya-loan-integration.md`, `manual-payment-system.md`, `discount-shop-business.md`
|
||||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: فیکس Toman/Rial + PackagePurchaseDialog + اعمال migrations بر staging)
|
||||
> **آخرین بروزرسانی:** اسفند ۱۴۰۴ (بروزرسانی: تصحیح مدل تومان/ریال + فیکس ZarinPal Verify + امنیت Callback URL)
|
||||
|
||||
---
|
||||
|
||||
@@ -47,27 +47,41 @@ flowchart TD
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A["کاربر → انتخاب محصول\nدرخواست پرداخت"] --> B["CMS → CreatePaymentRequest\ngRPC to PYMS"]
|
||||
B --> C["PYMS → ZarinPal API\nدریافت Authority"]
|
||||
B --> C["PYMS → ZarinPal API\nمبلغ ×۱۰ (تومان→ریال)\nدریافت Authority"]
|
||||
C --> D["Redirect کاربر\nصفحه پرداخت ZarinPal"]
|
||||
D --> E["بازگشت با Authority\nCMS VerifyPayment"]
|
||||
D --> E["بازگشت با Authority\nCMS VerifyPayment (مبلغ ×۱۰)"]
|
||||
E -->|موفق| F["✅ ثبت سفارش\n+ شارژ کیفپول"]
|
||||
E -->|ناموفق| G["❌ نمایش پیام خطا"]
|
||||
```
|
||||
|
||||
> **✅ فیکس ZarinPal Verify (اسفند ۱۴۰۴ — `721661a`):**
|
||||
> - **باگ:** `VerifyPaymentAsync(authority)` با ۲ آرگومان → amount=0 → ZarinPal Code=-1
|
||||
> - **فیکس:** lookup `PaymentTransaction.Amount` از DB + استفاده از overload ۳ آرگومانه `VerifyPaymentAsync(authority, orderId, amount)`
|
||||
> - `IPaymentGatewayService` — default impl ۳ آرگومانه اضافه شد
|
||||
> - ۷ فایل تغییر: PackageService, TransactionsService, VerifyDiscountWalletChargeCommandHandler, VerifyPackagePurchaseCommandHandler, IPaymentGatewayService, MockPaymentGatewayService, DayaPaymentService
|
||||
|
||||
### ۲.۲ تنظیمات ZarinPal
|
||||
|
||||
| پارامتر | مقدار |
|
||||
|----------|-------|
|
||||
| `MerchantId` | `4225d555-5fa9-4df0-9b61-1ce152cbbba8` |
|
||||
| `CallbackUrl` | `/payment/callback` |
|
||||
| `CallbackUrl` | از `appsettings.json` خوانده میشود (نه از ورودی کاربر) |
|
||||
| `Sandbox` | `true` (staging) / `false` (production) |
|
||||
| `Currency` | IRR (ریال → تبدیل به تومان در UI) |
|
||||
| `Currency` | DB: تومان — ZarinPal: ریال (×۱۰ هنگام ارسال) |
|
||||
|
||||
> **✅ توضیح تبدیل Rial → Toman:**
|
||||
> - **DB:** `Package.Price` به **ریال** ذخیره میشود (`/// قیمت پکیج (ریال)`)
|
||||
> - **CMS → ZarinPal:** مستقیم ریال ارسال میشود (`Amount = package.Price` → `amountInRials = (long)request.Amount`)
|
||||
> - **FrontOffice UI:** `PackageDto.FormattedPrice` = `Price / 10` + «تومان» (فیکس شد در `3c1a8ff`)
|
||||
> - **باگ قبلی:** FO مقدار خام ریال را با برچسب «تومان» نمایش میداد (مثلاً ۵۶۰،۰۰۰،۰۰۰ تومان بجای ۵۶،۰۰۰،۰۰۰ تومان)
|
||||
> **✅ مدل ارزی (تصحیح اسفند ۱۴۰۴):**
|
||||
> - **DB:** `Package.Price` و همه مبالغ مالی به **تومان** ذخیره میشوند
|
||||
> - **CMS → ZarinPal:** `ZarinPalPaymentService` مبلغ را ×۱۰ میکند (`amountInRials = amount * 10`)
|
||||
> - **FrontOffice UI:** مبالغ مستقیم به تومان نمایش داده میشوند (بدون تبدیل)
|
||||
> - **FrontOffice → CMS:** مبالغ به تومان ارسال میشوند (FO هیچ تبدیلی انجام نمیدهد)
|
||||
> - **باگ قبلی ۱:** FO مبلغ تومان را ×۱۰ تبدیل میکرد + CMS/ZarinPal دوباره ×۱۰ → مبلغ ۱۰۰ برابر (فیکس: `2f9ef15`)
|
||||
> - **باگ قبلی ۲:** `FormattedPrice = Price / 10` اشتباه بود — Price از قبل تومان است (فیکس: `3c1a8ff` اصلاح شد)
|
||||
|
||||
> **✅ امنیت Callback URL (اسفند ۱۴۰۴):**
|
||||
> - هیچ callback URL از ورودی کاربر خوانده نمیشود — همه از `appsettings.json` خوانده میشوند
|
||||
> - `PackageService` و `TransactionsService`: از `FrontOfficeBaseUrl` config
|
||||
> - `MagicWallet` و `DiscountWallet`: از `CmsBaseUrl` config
|
||||
> - جلوگیری از حمله Open Redirect
|
||||
|
||||
> **تنظیمات محیطی:**
|
||||
> - `appsettings.json` + `appsettings.Staging.json`: `UseSandbox: true` (تست)
|
||||
@@ -245,12 +259,15 @@ service PaymentService {
|
||||
| ماژول | وضعیت | یادداشت |
|
||||
|-------|--------|---------|
|
||||
| ZarinPal IPG | ✅ کامل | **Production فعال** — MerchantId: `4225d555...` |
|
||||
| ZarinPal Verify | ✅ فیکس شده | رفع amount=0 با overload ۳ آرگومانه (`721661a`) |
|
||||
| Callback URL امنیت | ✅ فیکس شده | همه از config خوانده میشوند — جلوگیری از Open Redirect |
|
||||
| وام دایا | ✅ کامل | Mock mode فعال در staging |
|
||||
| پرداخت ترکیبی | ✅ کامل | Discount + IPG |
|
||||
| Pool هفتگی | ✅ کامل | SP + Hangfire |
|
||||
| WalletChangeLog | ✅ فیکس شده | لاگ تغییرات کیفپول در ۳ هندلر اضافه شد |
|
||||
| Validation کیفپول اعتباری | ✅ فیکس شده | ارور اگر موجودی کافی نباشد |
|
||||
| Toman/Rial تبدیل نمایش | ✅ فیکس شده | `Price / 10` در FO — درگاه ریال میگیرد، UI تومان نمایش میدهد |
|
||||
| Toman/Rial مدل | ✅ تصحیح شده | DB=تومان، فقط ZarinPal ریال (×۱۰) — FO بدون تبدیل |
|
||||
| صفحه موفقیت پرداخت | ✅ بهبود | TransactionId + موجودی واقعی + دکمه بازگشت |
|
||||
| PackagePurchaseDialog | ✅ کامل | دیالوگ داینامیک کاشیای با انتخاب روش پرداخت |
|
||||
| پرداخت دستی | ⬜ طراحی | نیاز به تصمیم مدیریت |
|
||||
| Refund | ⬜ طراحی | فقط در PYMS تعریفشده |
|
||||
|
||||
Reference in New Issue
Block a user