- Added a new column `national_code_verified` to the `users` table. - Normalized the `bank_account` field in the `representations` table from a single object to an array of IBANs with a default `verified` status of false. feat(ApiIrService): implement identity verification client for api.ir - Created `ApiIrService` to handle identity verification via api.ir. - Implemented methods for matching national code with mobile and IBAN with national code and birth date. - Added error handling and logging for external API requests.
9.1 KiB
Settlement & Wallet API
Prefix:
/api/v1/wallet,/api/v1/settlement
GET /api/v1/wallet/balance
Get authenticated user's wallet balance.
Permission: AUTH
Response 200
{
"success": true,
"data": {
"balance_rials": 2500000,
"recent_transactions": [
{
"uuid": "...",
"type": "credit",
"amount_rials": 500000,
"balance_after": 2500000,
"description": "دریافت از نوبت شماره ...",
"created_at": 1717000000
}
]
}
}
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
GET /api/v1/wallet/transactions
Get wallet transaction history for the authenticated user.
Permission: AUTH
Response 200
{
"success": true,
"data": [
{
"uuid": "...",
"type": "credit",
"amount_rials": 500000,
"balance_after": 2500000,
"description": "دریافت از نوبت",
"created_at": 1717000000
},
{
"uuid": "...",
"type": "debit",
"amount_rials": 200000,
"balance_after": 2300000,
"description": "تسویهحساب",
"created_at": 1716900000
}
]
}
Transaction Type Values:
| Value | Description |
|---|---|
credit |
Money added to wallet |
debit |
Money removed from wallet |
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
POST /api/v1/settlement
Request a settlement (withdrawal from wallet to bank account).
Permission: AUTH
Request Body (application/json)
{
"amount_rials": 1000000,
"iban_id": "iban-uuid-..."
}
| Field | Type | Required | Description |
|---|---|---|---|
amount_rials |
integer | ✅ | Amount to withdraw (must be ≤ wallet balance) |
iban_id |
string | ✅ | شناسهی یکی از شباهای تأییدشدهی نماینده (از GET /api/v1/representation/me → bank_account[].id) |
شبای انتخابی بهصورت snapshot (
iban,bank_name,owner_name) داخل خود رکورد تسویه ذخیره میشود؛ حذف بعدی شبا در پروفایل، این رکورد را تغییر نمیدهد. مبلغ همان لحظهی ثبت از کیفپول کسر (debit) میشود.
Response 201
{
"success": true,
"data": {
"uuid": "settle-uuid-...",
"amount_rials": 1000000,
"status": "pending",
"bank_account": {
"iban": "IR...",
"bank_name": "بانک ملت",
"owner_name": "علی احمدی"
},
"created_at": 1717000000
}
}
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
ERR_VALIDATION_001 |
422 | مبلغ نامعتبر/بیش از موجودی، یا شبا تأییدنشده/نامعتبر (field: iban_id) |
ERR_VALIDATION_002 |
422 | iban_id ارسال نشده (field: iban_id) |
ERR_CONFLICT_001 |
422 | موجودی کافی نیست |
GET /api/v1/settlement
Get authenticated user's settlement requests.
Permission: AUTH
Response 200
{
"success": true,
"data": [
{
"uuid": "...",
"amount_rials": 1000000,
"status": "pending",
"note": null,
"created_at": 1717000000,
"processed_at": null
}
]
}
Settlement Status Values:
| Value | Description |
|---|---|
pending |
Awaiting admin review |
approved |
Approved, payment sent |
rejected |
Rejected by admin |
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
GET /api/v1/settlement/{uuid}
Get a single settlement.
Permission: AUTH — must be the owner or ROLE_ADMIN
Response 200
Settlement object with full details including bank_account.
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
ERR_FORBIDDEN_001 |
403 | Not the owner |
ERR_NOT_FOUND_001 |
404 | Settlement not found |
POST /api/v1/settlement/{uuid}/approve
Approve a settlement request. Marks it as paid and debits the wallet.
Permission: ROLE_ADMIN
Path Parameters
| Param | Type | Description |
|---|---|---|
uuid |
string (UUID) | Settlement UUID |
Request Body (application/json)
{
"note": "پرداخت شد — شناسه پیگیری: 123456"
}
| Field | Type | Required |
|---|---|---|
note |
string | ❌ |
Response 200
Updated settlement object with status: "approved".
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
ERR_AUTH_006 |
403 | Not admin |
ERR_NOT_FOUND_001 |
404 | Settlement not found |
ERR_VALIDATION_001 |
422 | Already processed |
POST /api/v1/settlement/{uuid}/reject
Reject a settlement request. Returns the amount back to wallet.
Permission: ROLE_ADMIN
Request Body
{
"note": "حساب بانکی نادرست است"
}
| Field | Type | Required |
|---|---|---|
note |
string | ✅ |
Response 200
Updated settlement object with status: "rejected".
Errors
| Code | HTTP | Description |
|---|---|---|
ERR_AUTH_001 |
401 | Missing token |
ERR_AUTH_006 |
403 | Not admin |
ERR_NOT_FOUND_001 |
404 | Settlement not found |
ERR_VALIDATION_002 |
422 | Missing note |
FinancialBreakdown (لاگ مالی)
علاوه بر تسویهحساب دستی، کیفپول نماینده بهصورت خودکار از طریق CommissionService هنگام پرداخت موفقِ نوبت/اشتراک شارژ میشود (WalletTransaction credit). هر واریز یک ردیف FinancialBreakdown ثبت میکند که تفکیک کامل تراکنش (ناخالص، هزینه پیامک، مالیات، خالص، درصد و سهم پورسانت، سهم سیستم) را نگه میدارد. ثبت idempotent است (بر اساس payment_id). گزارشها از طریق GET /api/v1/admin/financial-breakdowns و GET /api/v1/admin/financial-summary در دسترساند — جزئیات در docs/api/admin.md.
رسید پرداخت و ثبت پرداخت نهایی (ROLE_ADMIN)
منطق کیفپول: مبلغ هنگام ثبت درخواست از کیفپول نماینده کسر (reserve/debit) میشود؛ رد آن را برمیگرداند (credit). تأیید و پرداختِ نهایی کیفپول را دوباره دست نمیزنند (جلوگیری از double-debit).
POST /file/upload/clinic_pro/settlement/receipt
آپلود تصویر رسید پرداخت. بدنه = محتوای خام فایل؛ هدر Content-Disposition: filename="...". Permission: ROLE_ADMIN
Response 200:
{ "success": true, "data": { "uuid": "...", "url": "/uploads/settlements/receipts/2026-06/...", "filename": "...", "filemime": "image/jpeg" } }
POST /api/v1/settlement/{uuid}/receipt
ذخیرهی رسید پرداخت بدون نهاییسازی. فقط روی تسویهی approved؛ وضعیت تغییر نمیکند (همچنان approved). پس از این مرحله دکمهی «تکمیل» در پنل فعال میشود. Permission: ROLE_ADMIN
Request Body:
{ "receipt": "/uploads/settlements/receipts/2026-06/..." }
| Field | Type | Required | Description |
|---|---|---|---|
receipt |
string | ✅ | URL رسیدِ آپلودشده |
Response 200: آبجکت تسویه (با receipt ذخیرهشده، status: "approved").
Errors:
| Code | HTTP | Description |
|---|---|---|
ERR_NOT_FOUND_001 |
404 | درخواست یافت نشد |
ERR_VALIDATION_001 |
422 | تسویه approved نیست |
ERR_VALIDATION_002 |
422 | receipt خالی (field: receipt) |
POST /api/v1/settlement/{uuid}/paid
«تکمیل» — ثبت پرداخت نهایی. فقط روی تسویهی approved. وضعیت → paid و receipt ذخیره میشود. کیفپول تغییر نمیکند (مبلغ هنگام ثبت درخواست کسر شده). پس از تکمیل، آن مبلغ دیگر قابل درخواست تسویه نیست. Permission: ROLE_ADMIN
Request Body:
{ "receipt": "/uploads/settlements/receipts/2026-06/..." }
| Field | Type | Required | Description |
|---|---|---|---|
receipt |
string | ✅ | URL رسیدِ آپلودشده |
Response 200: آبجکت تسویه (شامل receipt و status: "paid").
Errors:
| Code | HTTP | Description |
|---|---|---|
ERR_NOT_FOUND_001 |
404 | درخواست یافت نشد |
ERR_VALIDATION_001 |
422 | تسویه approved نیست |
ERR_VALIDATION_002 |
422 | receipt خالی (field: receipt) |