Add independent payment-service (port 8012, payment_db) with foundation licensing, BYO-PSP, merchant accounts, idempotent requests, callbacks, and immutable ledger. Co-authored-by: Cursor <cursoragent@cursor.com>
554 lines
21 KiB
Markdown
554 lines
21 KiB
Markdown
# Payment Platform — Integration & Contract Reference
|
|
|
|
> **Normative contract reference** for Torbat Pay (`payment` service).
|
|
> Architecture: [ADR-020](../architecture/adr/ADR-020.md), [ADR-021](../architecture/adr/ADR-021.md)
|
|
> Roadmap: [payment-roadmap.md](../payment-roadmap.md)
|
|
|
|
All contracts are **versioned**. Implementations MUST accept unknown additive JSON fields. Breaking changes require a new major version and a registered phase.
|
|
|
|
---
|
|
|
|
## 1. Architectural verification checklist
|
|
|
|
| Requirement | How Torbat Pay satisfies it |
|
|
| --- | --- |
|
|
| **API-first** | All vertical integration via REST `/api/v1/*` and token-gated `/internal/v1/*`; no shared DB |
|
|
| **Event-first** | Domain transitions publish `payment.*` via transactional outbox ([ADR-006](../architecture/adr/ADR-006.md)) |
|
|
| **Database-per-service** | Sole owner of `payment_db` ([ADR-001](../architecture/adr/ADR-001.md)) |
|
|
| **Feature toggles** | L3 `PaymentFeatureToggle` in Payment; operational flags within bundles |
|
|
| **Permission tree** | `payment.*` bundle-gated leaves; see §8 |
|
|
| **Bundle isolation** | Inactive bundles → hidden APIs, capabilities, permissions ([ADR-021](../architecture/adr/ADR-021.md)) |
|
|
| **Multi-tenant isolation** | `tenant_id` on all rows; callback routing validated ([ADR-003](../architecture/adr/ADR-003.md)) |
|
|
| **Tenant enable/disable** | Core L1 + PaymentWorkspace.status |
|
|
| **Choose own PSP** | BYO `PspConnection` + `PaymentProviderAssignment` |
|
|
| **Choose Torbat Pay Merchant** | `default_payment_mode=torbat_pay_merchant` + `MerchantAccount` |
|
|
| **Change provider without code** | Update `PaymentProviderAssignment` / `PspRoutingPolicy` only |
|
|
|
|
---
|
|
|
|
## 2. Three-layer licensing model
|
|
|
|
### L1 — Core service entitlement
|
|
|
|
| Feature key | Meaning |
|
|
| --- | --- |
|
|
| `payment.module.enabled` | Tenant may use Torbat Pay at all |
|
|
|
|
Check: `POST /api/v1/tenants/{tenant_id}/features/check` (Core) — see [services-contracts.md](services-contracts.md).
|
|
|
|
Payment caches result; invalidates on `feature_access.changed`.
|
|
|
|
### L2 — Payment bundles (owned by Payment)
|
|
|
|
| Bundle code | Capabilities unlocked | Typical mode |
|
|
| --- | --- | --- |
|
|
| `payment.byo_psp.basic` | PSP connections, routing, payment requests, callbacks, ledger | BYO-PSP |
|
|
| `payment.torbat_pay.merchant` | Merchant accounts, facilitator routing, payment requests, callbacks, ledger | Torbat Pay Merchant |
|
|
| `payment.marketplace.splits` | Split rules, settlement batches | Facilitator + marketplace |
|
|
| `payment.advanced.refunds` | Refund APIs (14.6+) | Either mode |
|
|
| `payment.advanced.reconciliation` | Reconciliation + accounting intents (14.9+) | Either mode |
|
|
| `payment.future.subscriptions` | SubscriptionBillingContract (reserved) | Either mode |
|
|
| `payment.future.installments` | InstallmentPlanContract (reserved) | Either mode — **Payment schedule shell only** |
|
|
| `payment.future.credit_provider` | CREDIT_PROVIDER routing via external credit adapters | Either mode — **not implemented** |
|
|
| `payment.future.wallet_topup` | WalletTopUpContract with Loyalty (reserved) | Either mode |
|
|
|
|
Aggregates: `PaymentBundleDefinition`, `TenantPaymentBundle` (activation refs Core entitlement only).
|
|
|
|
### L3 — Payment feature toggles (owned by Payment)
|
|
|
|
| Toggle key | Default | Requires bundle |
|
|
| --- | --- | --- |
|
|
| `payment.capture.enabled` | true when workspace enabled | any active L2 |
|
|
| `payment.refunds.enabled` | false | `payment.advanced.refunds` |
|
|
| `payment.splits.enabled` | false | `payment.marketplace.splits` |
|
|
| `payment.installments.enabled` | false | `payment.future.installments` |
|
|
| `payment.subscriptions.enabled` | false | `payment.future.subscriptions` |
|
|
| `payment.wallet_topup.enabled` | false | `payment.future.wallet_topup` |
|
|
| `payment.credit_provider.enabled` | false | `payment.future.credit_provider` |
|
|
| `payment.fraud_hooks.enabled` | false | any active L2 |
|
|
|
|
---
|
|
|
|
## 3. Provider assignment & routing
|
|
|
|
### PaymentProviderAssignment
|
|
|
|
Links a workspace (and optional scope) to the active payment source:
|
|
|
|
```json
|
|
{
|
|
"assignment_id": "uuid",
|
|
"tenant_id": "uuid",
|
|
"payment_workspace_id": "uuid",
|
|
"scope_type": "workspace|branch|vertical",
|
|
"scope_ref_id": "uuid|null",
|
|
"source_type": "psp_connection|merchant_account",
|
|
"source_id": "uuid",
|
|
"priority": 1,
|
|
"is_active": true
|
|
}
|
|
```
|
|
|
|
**Changing PSP or credit provider:** deactivate old assignment, activate new — routing policy selects at request time. No adapter code change in verticals.
|
|
|
|
### Payment source types (routing — reserved)
|
|
|
|
| Value | Description | Adapter | Status |
|
|
| --- | --- | --- | --- |
|
|
| `PSP` | BYO payment gateway | `PspAdapter` | Phase 14.1+ |
|
|
| `MERCHANT_FACILITATOR` | Torbat Pay Merchant | Facilitator adapter | Phase 14.2+ |
|
|
| `CREDIT_PROVIDER` | External credit/BNPL/financing | `CreditProviderAdapter` | **Reserved — not implemented** |
|
|
|
|
When `payment_source=CREDIT_PROVIDER`, Payment routes to an external **Credit Provider** (primary reserved: **Torbat Credit**) using the same assignment and adapter registry pattern as PSPs.
|
|
|
|
### Credit provider architectural references (opaque refs only)
|
|
|
|
| Field | Type | Owner of truth |
|
|
| --- | --- | --- |
|
|
| `credit_provider_id` | uuid | Payment registry → external provider |
|
|
| `financing_reference` | string | Torbat Credit |
|
|
| `credit_authorization_reference` | string | Torbat Credit |
|
|
| `installment_contract_reference` | string | Torbat Credit |
|
|
|
|
### PspRoutingPolicy
|
|
|
|
```json
|
|
{
|
|
"policy_id": "uuid",
|
|
"tenant_id": "uuid",
|
|
"rules": [
|
|
{
|
|
"priority": 1,
|
|
"provider_assignment_id": "uuid",
|
|
"conditions": {
|
|
"currency": ["IRR"],
|
|
"payment_source": ["PSP", "MERCHANT_FACILITATOR", "CREDIT_PROVIDER"],
|
|
"min_amount_minor": 0,
|
|
"max_amount_minor": null,
|
|
"channel": ["web", "mobile", "pos"]
|
|
}
|
|
}
|
|
],
|
|
"failover_enabled": true
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 4. Contract catalog
|
|
|
|
### 4.1 PaymentIntentContract v1 (Phase 14.3+)
|
|
|
|
**Purpose:** Vertical initiates payment; Payment returns redirect/token payload.
|
|
|
|
**HTTP:** `POST /api/v1/payment-requests`
|
|
**Headers:** `Authorization`, `X-Tenant-ID`, `Idempotency-Key` (required)
|
|
|
|
```json
|
|
{
|
|
"contract_version": "payment_intent.v1",
|
|
"amount_minor": 150000,
|
|
"currency": "IRR",
|
|
"idempotency_key": "string",
|
|
"source": {
|
|
"service": "hospitality|marketplace|sports_center|experience|crm|delivery|accounting|other",
|
|
"ref_type": "pos_ticket|order|membership|invoice|checkout_session|quote|other",
|
|
"ref_id": "uuid"
|
|
},
|
|
"payer": {
|
|
"contact_ref": "uuid|null",
|
|
"user_ref": "uuid|null",
|
|
"mobile": "string|null"
|
|
},
|
|
"payment_mode": "byo_psp|torbat_pay_merchant|default",
|
|
"payment_source": "PSP|MERCHANT_FACILITATOR|CREDIT_PROVIDER",
|
|
"provider_assignment_id": "uuid|null",
|
|
"credit_provider_id": "uuid|null",
|
|
"financing_reference": "string|null",
|
|
"credit_authorization_reference": "string|null",
|
|
"installment_contract_reference": "string|null",
|
|
"return_url": "https://...",
|
|
"metadata": {},
|
|
"line_items": [
|
|
{ "description": "string", "amount_minor": 150000, "quantity": 1 }
|
|
]
|
|
}
|
|
```
|
|
|
|
**Response 201:**
|
|
|
|
```json
|
|
{
|
|
"payment_request_id": "uuid",
|
|
"status": "pending|redirect_issued",
|
|
"redirect_url": "https://...",
|
|
"token": "string|null",
|
|
"expires_at": "ISO-8601"
|
|
}
|
|
```
|
|
|
|
**Notes:**
|
|
|
|
- `payment_source` defaults from routing policy when omitted.
|
|
- `CREDIT_PROVIDER` fields are **ignored** until bundle `payment.future.credit_provider` is active and Torbat Credit adapter is registered — validators reject if source is `CREDIT_PROVIDER` before implementation.
|
|
- Verticals pass refs only; Torbat Credit owns authorization lifecycle.
|
|
|
|
**Events:** `payment.request.created`, `payment.request.redirect_issued`, `payment.request.paid`, `payment.request.failed`
|
|
|
|
---
|
|
|
|
### 4.2 CheckoutSessionContract v1 (Phase 14.8+)
|
|
|
|
**Purpose:** Higher-level checkout wrapper for embeddable/widget flows.
|
|
|
|
**HTTP:** `POST /api/v1/checkout-sessions`
|
|
|
|
```json
|
|
{
|
|
"contract_version": "checkout_session.v1",
|
|
"source": { "service": "string", "ref_type": "string", "ref_id": "uuid" },
|
|
"amount_minor": 0,
|
|
"currency": "IRR",
|
|
"success_url": "https://...",
|
|
"cancel_url": "https://...",
|
|
"metadata": {},
|
|
"payment_intent_overrides": {}
|
|
}
|
|
```
|
|
|
|
Completing session creates/links a PaymentIntent internally. Verticals SHOULD prefer CheckoutSession for UX flows; low-level verticals MAY call PaymentIntent directly.
|
|
|
|
---
|
|
|
|
### 4.3 CallbackIngressContract v1 (Phase 14.4+)
|
|
|
|
**Purpose:** PSP → Payment webhook ingress (adapter-normalized).
|
|
|
|
**HTTP:** `POST /api/v1/callbacks/{provider_code}/{connection_id}`
|
|
|
|
Adapter normalizes to:
|
|
|
|
```json
|
|
{
|
|
"contract_version": "callback_ingress.v1",
|
|
"provider_code": "zarinpal|idpay|...",
|
|
"connection_id": "uuid",
|
|
"provider_transaction_id": "string",
|
|
"payment_request_id": "uuid|null",
|
|
"raw_status": "string",
|
|
"normalized_status": "paid|failed|pending",
|
|
"amount_minor": 0,
|
|
"currency": "IRR",
|
|
"signature": "string",
|
|
"received_at": "ISO-8601"
|
|
}
|
|
```
|
|
|
|
**Events:** `payment.callback.received`, `payment.callback.verified`, `payment.request.paid`
|
|
|
|
---
|
|
|
|
### 4.4 SettlementIntentContract v1 (Phase 14.9+)
|
|
|
|
**Purpose:** Payment → Accounting (no journal in Payment).
|
|
|
|
**Event:** `payment.accounting_intent.created`
|
|
|
|
```json
|
|
{
|
|
"contract_version": "settlement_intent.v1",
|
|
"intent_id": "uuid",
|
|
"tenant_id": "uuid",
|
|
"intent_type": "capture|fee|facilitator_payout|reconciliation_adjustment",
|
|
"payment_transaction_id": "uuid",
|
|
"amount_minor": 0,
|
|
"currency": "IRR",
|
|
"accounting_refs": {
|
|
"customer_ref": "uuid|null",
|
|
"revenue_account_code_ref": "string|null"
|
|
},
|
|
"idempotency_key": "string",
|
|
"occurred_at": "ISO-8601"
|
|
}
|
|
```
|
|
|
|
Accounting consumes and posts via Posting Engine ([ADR-010](../architecture/adr/ADR-010.md)).
|
|
|
|
---
|
|
|
|
### 4.5 RefundIntentContract v1 (Phase 14.6+ — schema reserved)
|
|
|
|
**HTTP:** `POST /api/v1/refund-requests`
|
|
|
|
```json
|
|
{
|
|
"contract_version": "refund_intent.v1",
|
|
"payment_transaction_id": "uuid",
|
|
"amount_minor": 0,
|
|
"reason": "string",
|
|
"source_ref": { "service": "string", "ref_type": "string", "ref_id": "uuid" },
|
|
"idempotency_key": "string"
|
|
}
|
|
```
|
|
|
|
**Events:** `payment.refund.requested`, `payment.refund.succeeded`, `payment.refund.failed`
|
|
|
|
---
|
|
|
|
### 4.6 SplitAllocationContract v1 (Phase 14.7+ — schema reserved)
|
|
|
|
Embedded in capture or post-capture allocation:
|
|
|
|
```json
|
|
{
|
|
"contract_version": "split_allocation.v1",
|
|
"payment_transaction_id": "uuid",
|
|
"allocations": [
|
|
{
|
|
"party_ref": { "type": "merchant_account|seller_ref|platform", "id": "uuid" },
|
|
"amount_minor": 0,
|
|
"description": "string"
|
|
}
|
|
],
|
|
"remainder_to": "platform|primary_merchant"
|
|
}
|
|
```
|
|
|
|
**Events:** `payment.split.allocated`, `payment.settlement_batch.created`
|
|
|
|
---
|
|
|
|
### 4.7 SubscriptionBillingContract v1 (Future — schema reserved)
|
|
|
|
```json
|
|
{
|
|
"contract_version": "subscription_billing.v1",
|
|
"subscription_ref": { "service": "string", "ref_id": "uuid" },
|
|
"billing_cycle": "monthly|annual|custom",
|
|
"amount_minor": 0,
|
|
"currency": "IRR",
|
|
"payment_method_assignment_id": "uuid",
|
|
"trial_days": 0
|
|
}
|
|
```
|
|
|
|
Recurring charge execution deferred to future Payment phase; contract stable for Marketplace/CRM/Experience planning.
|
|
|
|
---
|
|
|
|
### 4.8 WalletTopUpContract v1 (Future — schema reserved)
|
|
|
|
Payment captures external money; Loyalty owns wallet ledger ([ADR-011](../architecture/adr/ADR-011.md)).
|
|
|
|
```json
|
|
{
|
|
"contract_version": "wallet_topup.v1",
|
|
"loyalty_wallet_account_ref": "uuid",
|
|
"amount_minor": 0,
|
|
"currency": "IRR",
|
|
"payment_intent_id": "uuid"
|
|
}
|
|
```
|
|
|
|
**Event (handoff):** `payment.transaction.recorded` with `metadata.intent_kind=wallet_topup` — Loyalty subscribes.
|
|
|
|
---
|
|
|
|
### 4.9 InstallmentPlanContract v1 (Future — Payment schedule shell only)
|
|
|
|
> **Not the Credit Engine.** Installment **calculation**, credit **scoring**, **KYC**, **BNPL** underwriting, and financing agreements are exclusive to the future **Torbat Credit** service (`credit`). This contract is a Payment-side **schedule shell** linked to a payment request or `installment_contract_reference` from Torbat Credit.
|
|
|
|
```json
|
|
{
|
|
"contract_version": "installment_plan.v1",
|
|
"source_ref": { "service": "string", "ref_type": "order|invoice", "ref_id": "uuid" },
|
|
"total_amount_minor": 0,
|
|
"currency": "IRR",
|
|
"installments": [
|
|
{ "sequence": 1, "due_at": "ISO-8601", "amount_minor": 0, "payment_request_ref": "uuid|null" }
|
|
],
|
|
"provider_assignment_id": "uuid",
|
|
"payment_source": "PSP|CREDIT_PROVIDER",
|
|
"credit_provider_id": "uuid|null",
|
|
"installment_contract_reference": "string|null"
|
|
}
|
|
```
|
|
|
|
Payment records due dates and links to capture requests; Torbat Credit owns financing terms and authorization.
|
|
|
|
---
|
|
|
|
### 4.10 CreditProviderAdapter pattern (Future — architecture reserved)
|
|
|
|
Torbat Credit (`credit` service, commercial product **Torbat Credit**) integrates as an **external Credit Provider** — invoked by Payment identically to a PSP adapter:
|
|
|
|
| Adapter method | Purpose |
|
|
| --- | --- |
|
|
| `authorize_financing()` | Reserve credit / BNPL authorization |
|
|
| `capture_financing()` | Capture against authorization |
|
|
| `verify_authorization()` | Reconcile status |
|
|
| `parse_callback()` | Normalize credit provider webhooks |
|
|
|
|
Registry entry example:
|
|
|
|
```json
|
|
{
|
|
"provider_code": "torbat_credit",
|
|
"provider_family": "credit_bnpl",
|
|
"service_ref": "credit",
|
|
"adapter_version": "1",
|
|
"supports_payment_source": "CREDIT_PROVIDER"
|
|
}
|
|
```
|
|
|
|
Payment calls Torbat Credit via **internal service API + adapter protocol** — never direct DB access.
|
|
|
|
---
|
|
|
|
### 4.11 Reserved event namespace — `credit.*` (Torbat Credit only)
|
|
|
|
The **`credit.*` event namespace is reserved** for the future independent **Torbat Credit** service. Payment **does not** publish or consume `credit.*` events in current or HIGH-priority phases.
|
|
|
|
Examples (documentation only — no implementation):
|
|
|
|
| event_type | Owner |
|
|
| --- | --- |
|
|
| `credit.application.submitted` | Torbat Credit |
|
|
| `credit.authorization.approved` | Torbat Credit |
|
|
| `credit.authorization.declined` | Torbat Credit |
|
|
| `credit.financing.created` | Torbat Credit |
|
|
| `credit.installment.due` | Torbat Credit |
|
|
| `credit.installment.paid` | Torbat Credit |
|
|
|
|
Payment integrates via adapter callbacks and opaque refs; cross-service coordination uses `payment.*` events on the Payment side.
|
|
|
|
---
|
|
|
|
## 5. Service compatibility matrix
|
|
|
|
| Service | Consumes (API) | Consumes (Events) | Provides to Payment | Compatible | Notes |
|
|
| --- | --- | --- | --- | --- | --- |
|
|
| **Core** | — | `feature_access.changed` | Entitlement check API | ✅ | L1 gate; service registry |
|
|
| **Identity** | — | — | `user_ref` validation (optional) | ✅ | Payer refs only |
|
|
| **Tenant (Core)** | — | `tenant.suspended` | Tenant id context | ✅ | Suspend → workspace suspend |
|
|
| **Accounting** | Posting intent ingest (future) | `payment.accounting_intent.created` | COA/account refs | ✅ | No journal in Payment |
|
|
| **CRM** | — | optional | `contact_ref` | ✅ | Payer linkage |
|
|
| **Communication** | Send notify (client) | — | Templates | ✅ | Receipt/refund SMS |
|
|
| **Hospitality** | PaymentIntent/Checkout | `payment.request.paid` | `pos_ticket` refs | ✅ | Replace POS PSP embed long-term |
|
|
| **Delivery** | PaymentIntent (optional) | `payment.request.paid` | COD job refs | ✅ | Optional COD |
|
|
| **Sports Center** | PaymentIntent | `payment.request.paid` | membership refs | ✅ | No local PSP |
|
|
| **Marketplace** | Checkout + Split | `payment.*` | seller/order refs | ✅ | Splits need bundle L2 |
|
|
| **Experience** | CheckoutSession | `payment.request.paid` | form/checkout refs | ✅ | Paid forms/widgets |
|
|
| **Loyalty** | WalletTopUp (future) | `payment.transaction.recorded` | wallet refs | ✅ | Wallet ledger stays Loyalty |
|
|
| **Torbat Credit** (future) | CreditProviderAdapter from Payment | `credit.*` (Credit service only) | authorization/financing refs | ✅ | Scoring/KYC/BNPL exclusive to Credit |
|
|
| **Healthcare** | PaymentIntent (future) | `payment.request.paid` | appointment refs | ✅ | Same pattern as Beauty |
|
|
| **Beauty Business** | PaymentIntent (future) | `payment.request.paid` | appointment refs | ✅ | Same pattern |
|
|
| **Automation** | — | `payment.transaction.recorded` | — | ✅ | Trigger workflows |
|
|
|
|
**No breaking changes required** in listed services before `payment-14.0`; vertical connector phases adopt contracts incrementally (Payment 14.8).
|
|
|
|
---
|
|
|
|
## 6. Event catalog (Payment — planned)
|
|
|
|
| event_type | When | Primary consumers |
|
|
| --- | --- | --- |
|
|
| `payment.workspace.enabled` | Workspace activated | Core audit |
|
|
| `payment.workspace.disabled` | Payment disabled for tenant | Verticals cache |
|
|
| `payment.bundle.activated` | L2 bundle on | Frontend capabilities |
|
|
| `payment.feature_toggle.changed` | L3 toggle | Internal |
|
|
| `payment.psp_connection.activated` | BYO PSP live | — |
|
|
| `payment.merchant_account.activated` | Facilitator ready | — |
|
|
| `payment.provider_assignment.changed` | PSP switch | — |
|
|
| `payment.request.created` | Intent created | Vertical |
|
|
| `payment.request.paid` | Verified paid | Hospitality, Marketplace, … |
|
|
| `payment.request.failed` | Failed/expired | Vertical |
|
|
| `payment.transaction.recorded` | Ledger write | Accounting prep, Loyalty |
|
|
| `payment.refund.succeeded` | Refund done | Vertical, Communication |
|
|
| `payment.split.allocated` | Split computed | Marketplace |
|
|
| `payment.accounting_intent.created` | Settlement intent | Accounting |
|
|
| `payment.reconciliation.completed` | Recon done | Admin |
|
|
|
|
Full envelope: [event-catalog.md](event-catalog.md#payment-platform-planned).
|
|
|
|
---
|
|
|
|
## 7. Internal service API (token-gated)
|
|
|
|
| Scope | Path | Purpose |
|
|
| --- | --- | --- |
|
|
| `payment.requests.create` | POST `/internal/v1/payment-requests` | Vertical server-side initiate |
|
|
| `payment.transactions.read` | GET `/internal/v1/payment-transactions/{id}` | Status poll |
|
|
| `payment.capabilities.read` | GET `/internal/v1/capabilities` | Service discovery |
|
|
|
|
Requires Internal Service Token ([services-contracts.md](services-contracts.md)) + `X-Tenant-ID`.
|
|
|
|
---
|
|
|
|
## 8. Permission tree (foundation + growth)
|
|
|
|
```
|
|
payment.*
|
|
├── payment.workspaces.{view,manage,enable,disable}
|
|
├── payment.bundles.{view,manage}
|
|
├── payment.feature_toggles.{view,manage}
|
|
├── payment.configurations.{view,manage}
|
|
├── payment.settings.{view,manage}
|
|
├── payment.psp_providers.view
|
|
├── payment.psp_connections.{view,create,update,delete,test,manage} [bundle: byo_psp.basic]
|
|
├── payment.psp_routing.{view,manage} [bundle: byo_psp.basic]
|
|
├── payment.provider_assignments.{view,manage}
|
|
├── payment.merchant_accounts.{view,create,update,submit,activate,suspend,close,manage} [bundle: torbat_pay.merchant]
|
|
├── payment.requests.{view,create,cancel,manage}
|
|
├── payment.callbacks.view
|
|
├── payment.transactions.{view,export}
|
|
├── payment.ledger.view
|
|
├── payment.refunds.{view,create,manage} [bundle: advanced.refunds]
|
|
├── payment.splits.{view,manage} [bundle: marketplace.splits]
|
|
├── payment.settlement_batches.{view,manage}
|
|
├── payment.connectors.manage
|
|
├── payment.checkout_sessions.{view,create}
|
|
├── payment.reconciliation.{view,run,manage} [bundle: advanced.reconciliation]
|
|
├── payment.accounting_intents.view
|
|
├── payment.analytics.{view,refresh}
|
|
├── payment.fraud_rules.manage
|
|
└── payment.audit.view
|
|
```
|
|
|
|
---
|
|
|
|
## 9. Capability discovery (`GET /capabilities`)
|
|
|
|
Response includes (when implemented):
|
|
|
|
```json
|
|
{
|
|
"service": "payment",
|
|
"phase": "14.x",
|
|
"workspace_status": "enabled|disabled",
|
|
"default_payment_mode": "byo_psp|torbat_pay_merchant",
|
|
"active_bundles": ["payment.byo_psp.basic"],
|
|
"feature_toggles": { "payment.refunds.enabled": false },
|
|
"contract_versions": {
|
|
"payment_intent": "v1",
|
|
"checkout_session": "v1",
|
|
"settlement_intent": "v1",
|
|
"installment_plan": "v1",
|
|
"credit_authorization": "v1"
|
|
},
|
|
"payment_sources_supported": ["PSP", "MERCHANT_FACILITATOR"],
|
|
"payment_sources_reserved": ["CREDIT_PROVIDER"],
|
|
"credit_providers_registered": [],
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 10. Related documents
|
|
|
|
- [Payment Roadmap](../payment-roadmap.md)
|
|
- [ADR-020](../architecture/adr/ADR-020.md) · [ADR-021](../architecture/adr/ADR-021.md)
|
|
- [Module Registry — payment](../module-registry.md#payment)
|
|
- [Provider Reference](provider-reference.md) (PSP entries added at 14.1)
|
|
- [Event Catalog](event-catalog.md)
|