8. Payments & Escrow

← Business Requirements

(a) Business requirements

  • The family pays the gross booking price through the platform by card via a licensed PSP's IPG. The platform is the merchant-of-record; the payment lands net of provider/Shaparak fees.
  • Escrow is an internal ledger state, not platform-held cash. The platform models money state with a minimal double-entry ledger_entries ledger: each money event posts balanced legs grouped by a transaction group. Account types: escrow_held, platform_revenue, nurse_payable, refund_payable, bnpl_fee_expense, nurse_clawback_receivable. The ledger is the single source of truth for "how much is held," "how much do we owe nurses now," and "what is our commission income" — replacing fragile inference from scattered status booleans.
    • On a successful card payment: debit escrow_held (gross), credit platform_revenue (Balinyaar commission), credit nurse_payable (nurse payout).
  • Settlement-sharing (تسهیم). The compliant marketplace primitive is splitting one incoming card payment across multiple registered IBANs (the nurse's share and the platform's commission) at settlement, performed by Shaparak/the provider — the platform never touches the actual split. The internal ledger mirrors this split; the per-booking fee snapshot freezes it.
  • Per-booking the three amounts are stored separately and never conflated: gross_price_irr (what the customer is charged), balinyaar_commission_irr (platform's cut — drives the nurse payout), and (for BNPL) bnpl_commission_irr (the provider's merchant discount — a platform expense). nurse_payout_amount = gross_price_irr − balinyaar_commission_irr.
  • Webhook idempotency is mandatory before money moves. Every PSP/BNPL callback is stored raw and deduplicated by a unique external event id in payment_webhook_events before any money state mutates — preventing double-confirmed bookings and double-settlements from at-least-once, retried callbacks.
  • Payment uniqueness: at most one succeeded payment transaction per booking, and the Shaparak reference is unique — enforced so a retried success webhook cannot double-confirm.
  • Multi-provider failover. Provider settlement cut-offs are a real continuity risk (the Toman/Jibit Nov-2024 suspensions cut businesses off mid-cycle). The payment layer abstracts the provider behind configuration so a blocked provider can be swapped, and the reconciliation ledger survives a provider being cut off.

(b) Iran-specific considerations

  • The load-bearing legal constraint: a پرداخت‌یار may not hold customer deposits, run wallets, or move money between merchants; the Shaparak ban on inter-merchant/inter-facilitator transfers means the "delay the تسهیم and redistribute later from a platform pool" pattern is regulatory grey-to-prohibited. The compliant posture is: collect via the provider, model escrow as an internal ledger over funds custodied at the licensed provider/partner bank, and pay out by provider-side settlement to verified, registered nurse IBANs. A bank-grade escrow product (e.g., Vandar میندو / معاملات امن) is the only true hold/release/refund mechanism, and its EVV-triggered hold is unverified — so the platform never assumes it can lawfully custody the cash itself.
  • PSP received ≠ cash in bank. Iranian PAYA settlement is cyclic (T+0/T+1, holiday-deferred), so the ledger separates a clearing/receivable state from settled cash, making bank reconciliation possible.
  • Toman/PSP units differ from internal Rials; convert only at the API boundary. Amounts are BIGINT IRR internally to avoid float/rounding bugs.

(c) MVP vs DEFERRED

  • MVP: card payment via one licensed PSP; internal double-entry ledger_entries escrow; per-booking three-way amount split; تسهیم-style commission/nurse-share modeling; payment_webhook_events idempotency; single-succeeded-transaction-per-booking guard; provider abstraction for failover.
  • DEFERRED: a nurse-facing wallet with on-demand withdrawal (facilitator wallet prohibition risk); multiple simultaneous live PSPs at launch (abstraction is built, second provider added later); bank-grade EVV-triggered escrow product integration.

(d) Supporting database entities

payment_gateways, payment_transactions (unique Shaparak ref, single-succeeded-per-booking), payment_webhook_events, ledger_entries, bookings (gross_price_irr, balinyaar_commission_irr, platform_fee_rate, nurse_payout_amount), refunds, nurse_bank_accounts (verified registered IBANs).

Related: Deep fintech detail — Escrow Ledger. Data model — Payments Ledger & Refunds.

↑ Back to top