# ADR-020: Independent Enterprise Payment Platform Service (Torbat Pay)

| Field | Value |
| --- | --- |
| Status | Accepted |
| Date | 2026-07-27 |
| Deciders | Platform Architecture |
| Supersedes | — |
| Superseded by | — |

## Context

Every TorbatYar vertical — Accounting, CRM, Hospitality, Sports Center, Marketplace, Delivery, Experience, Healthcare, Beauty Business, Automation, and future services — needs payment capture without embedding PSP credentials, callback handling, or transaction ledgers inside each service.

Tenants require two commercial modes:

1. **Bring Your Own PSP (BYO-PSP)** — connect tenant-owned gateways (ZarinPal, IDPay, NextPay, Pay.ir, Mellat, Parsian, Saman, …).
2. **Torbat Pay Merchant** — Torbat Pay acts as payment facilitator; tenants onboard as sub-merchants under platform settlement rules.

TorbatYar already isolates shared platforms as independent services (Communication [ADR-012](ADR-012.md), Loyalty [ADR-011](ADR-011.md), Delivery [ADR-015](ADR-015.md)). Payment capture, PSP routing, verification, and payment-domain ledger must follow the same pattern. Accounting owns financial journals via Posting Engine [ADR-010](ADR-010.md); Payment must never create journal entries locally.

International PSP expansion is **not** in current scope but the provider adapter architecture must allow future regions without vertical changes.

Commercial product name: **Torbat Pay**.

## Decision

1. Introduce `payment` as an **independent Enterprise Payment Platform service** with sole ownership of `payment_db` ([ADR-001](ADR-001.md)).
2. Permission prefix: `payment.*`. Publish-only domain events: `payment.*`.
3. Row-level multi-tenancy via `tenant_id` ([ADR-003](ADR-003.md)).
4. PSP implementations sit behind **provider protocols/adapters** owned by Payment; verticals never call PSP APIs directly.
5. Consume Accounting, CRM, Loyalty, Communication, Core, and all vertical services **only** via REST API and Events — never shared tables or foreign model imports.
6. Financial journals only through Accounting Posting Engine ([ADR-010](ADR-010.md)). Payment emits settlement/reconciliation **intents**; Accounting posts externally.
7. Customer payment notifications (receipt SMS/email) only through Communication ([ADR-012](ADR-012.md)).
8. Vertical services (Hospitality POS, Marketplace checkout, Sports Center membership, Experience widgets, etc.) hold **commercial context refs only** (`order_ref`, `invoice_ref`, `checkout_session_ref`) and delegate capture to Payment APIs.
9. Implementation phases registered as **`payment-14.0`–`payment-14.10`** in [phase-manifest.yaml](../../ai-framework/phase-manifest.yaml); roadmap in [payment-roadmap.md](../../payment-roadmap.md). Phase numeric **14.x** is the Payment **track** identifier; it is distinct from Beauty Business phases (`beauty-business-14.x`).
10. API port **8012** reserved; service path `backend/services/payment`.
11. UI for checkout, merchant admin, and reconciliation dashboards lives in `frontend/` only ([ADR-002](ADR-002.md)); this service exposes APIs and events.
12. No international PSP implementation in initial HIGH-priority phases; adapter registry and credential schema must be region-aware for future expansion.

## Consequences

### Positive

- One reusable payment platform for all current and future TorbatYar services
- Enforceable PSP credential isolation and callback verification in one place
- BYO-PSP and Torbat Pay Merchant modes without duplicating integration code per vertical
- Clear boundary with Accounting (money movement vs financial posting)

### Negative

- Additional deployable service and database
- Eventual consistency between payment status and vertical order state
- PCI scope management for facilitator mode requires operational discipline (documented, not implemented in registration)

### Neutral

- Registration (this ADR + manifests) precedes business code; `payment-14.0` implements the scaffold
- Loyalty wallet/gift-card money flows remain in Loyalty; Payment handles external PSP money-in only unless explicitly integrated later

## Alternatives Considered

1. Payment subsystem inside Core — rejected (violates business-module boundaries; couples platform billing with tenant commerce payments).
2. Payment tables inside Accounting — rejected (Accounting owns posting semantics, not PSP routing/callbacks).
3. Per-vertical PSP integrations — rejected (duplicates credentials, callbacks, idempotency, and audit across Hospitality/Marketplace/Sports Center).
4. Third-party payment orchestration SaaS only — rejected for primary path (tenant BYO-PSP and facilitator control require owned platform).

## Related Documents

- [Payment Roadmap](../../payment-roadmap.md)
- [Phase Area — Payment](../../phases/Payment/README.md)
- [Module Boundaries](../module-boundaries.md)
- [Module Registry — payment](../../module-registry.md#payment)
- [Payment Contracts Reference](../../reference/payment-contracts.md)
- [Phase Manifest](../../ai-framework/phase-manifest.yaml)
- [Service Manifest](../../ai-framework/service-manifest.yaml)
- [ADR-001](ADR-001.md) · [ADR-002](ADR-002.md) · [ADR-003](ADR-003.md) · [ADR-006](ADR-006.md) · [ADR-010](ADR-010.md) · [ADR-011](ADR-011.md) · [ADR-012](ADR-012.md) · [ADR-021](ADR-021.md)
