8. Payments & Escrow
(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_entriesledger: 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), creditplatform_revenue(Balinyaar commission), creditnurse_payable(nurse payout).
- On a successful card payment: debit
- 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_eventsbefore any money state mutates — preventing double-confirmed bookings and double-settlements from at-least-once, retried callbacks. - Payment uniqueness: at most one
succeededpayment 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_entriesescrow; per-booking three-way amount split; تسهیم-style commission/nurse-share modeling;payment_webhook_eventsidempotency; 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).
↑ Back to topRelated: Deep fintech detail — Escrow Ledger. Data model — Payments Ledger & Refunds.