feat: implement tax calculations for subscription and SMS wallet payments

- Updated SubscriptionPeriod interface to include tax-related fields: tax_percent, tax_rials, and payable_rials.
- Modified payment API documentation to reflect changes in tax handling for subscriptions and SMS wallet charges.
- Adjusted PaymentController to calculate payment amounts based on subscription period details instead of client input.
- Enhanced PaymentManager to handle net amounts for SMS wallet charges, ensuring tax is not credited to the wallet.
- Created PaymentTaxCalculator and SubscriptionTaxCalculator services to manage tax calculations consistently across payment types.
- Added tests for tax calculations in both subscription and SMS wallet contexts, ensuring correct behavior with and without tax enabled.
- Updated frontend components to display tax information appropriately during payment processes.
This commit is contained in:
hamed
2026-08-09 16:51:22 +03:30
parent 2471c90cbb
commit 7716b40f6a
18 changed files with 762 additions and 45 deletions
+25 -1
View File
@@ -349,13 +349,37 @@ Updated template with `status: "rejected"`.
"data": {
"payment_uuid": "...",
"pay_url": "{APP_BASE_URL}/api/v1/payment/pay/ORD-...",
"order_id": "ORD-..."
"order_id": "ORD-...",
"net_rials": 50000,
"tax_percent": 10,
"tax_rials": 5000,
"payable_rials": 55000
}
}
```
> این endpoint فقط `Payment` (type=`sms_wallet`) می‌سازد و `pay_url` می‌دهد؛ **ارتباط با بانک اینجا انجام نمی‌شود** و از flow واحد پرداخت (`GET /payment/pay/{orderId}` → callback → `PaymentManager`) عبور می‌کند. کلاینت باید مرورگر را به `pay_url` هدایت کند. پس از پرداخت موفق، `PaymentManager` موجودی کیف را خودکار شارژ می‌کند.
#### مالیات
`amount_rials` ورودی **خالص** است — همان اعتباری که به کیف پول می‌نشیند. مالیات رویش
**اضافه** می‌شود و مبلغی که به بانک می‌رود `payable_rials` است.
| فیلد | معنی |
|------|------|
| `net_rials` | اعتباری که بعد از پرداخت موفق به کیف پول اضافه می‌شود |
| `tax_percent` | درصد مؤثر؛ با `tax_enabled=0` برابر `0` |
| `tax_rials` | `round(net_rials × tax_percent / 100)` |
| `payable_rials` | `net_rials + tax_rials` — مبلغ رکورد `Payment` و مبلغ درگاه |
نرخ از همان کلیدهای سراسری `tax_enabled` / `tax_percent` می‌آید؛ محاسبه در
`App\Payment\Service\PaymentTaxCalculator`.
**اعتبار کیف پول هرگز شامل مالیات نیست.** مقدار خالص در `metadata.net_rials` رکورد پرداخت
ذخیره می‌شود و `PaymentManager::handleSmsWalletCharge` همان را شارژ می‌کند — نه
`amount_rials` را. استرداد هم قرینهٔ همین است. پرداخت‌های قدیمی که `net_rials` ندارند به
مبلغ کلشان fallback می‌کنند.
### GET /api/v1/sms/wallet/logs
تراکنش‌های کیف پیامک (paginated).