Files
clinicpro/docs/api/settlement.md
T
hamed c2c6ae4d02 feat(migrations): add national_code_verified flag to users and normalize bank_account representation
- 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.
2026-06-25 19:38:47 +03:30

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/mebank_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)