Package-level declarations

Types

Link copied to clipboard

Android realization of PaymentHost. Providers cast the opaque host to this to reach the ComponentActivity (some SDKs — Razorpay, Cashfree — require an Activity to open their sheet) and to register ActivityResult contracts (Stripe, UPI intent) without owning the registry themselves.

Link copied to clipboard

Feature a gateway supports — drives capability-filtered lookups and Lab badges.

Link copied to clipboard
data class ConnectAccount(val accountId: String, val status: ConnectAccountStatus)
Link copied to clipboard
interface ConnectBackend

The app's view of the server's Stripe Connect payout onboarding rail (roadmap #11) — mirrors PayoutBackend's shape: onboard/completeOnboarding do the server round-trips, status polls server-authoritative state. Implemented in core:network against core:protocol DTOs.

Link copied to clipboard
data class ConnectOnboarding(val onboardingId: String, val hostedOAuthUrl: String, val accountId: String)
Link copied to clipboard
data class CreatedOrder(val order: OrderRef, val gatewayId: GatewayId, val providerParams: Map<String, String>)

Result of order creation: the order plus the provider-specific session material for the SDK.

Link copied to clipboard

Normalized failure taxonomy — every provider maps its own SDK error zoo into these.

Link copied to clipboard
value class GatewayId(val value: String)

Stable identifier for a payment provider, e.g. razorpay, upi_intent, stripe.

Link copied to clipboard
data class GatewayMeta(val displayName: String, val status: GatewayStatus, val capabilities: Set<Capability>, val region: String, val docsPath: String, val blurb: String)

Catalog metadata for a gateway — everything the Lab home needs without touching the impl.

Link copied to clipboard

Whether a provider can be exercised end-to-end in this showcase.

Link copied to clipboard
data class InstrumentCharge(val chargeId: String, val customerId: String, val instrumentId: String, val amount: Money, val status: PaymentStatus)
Link copied to clipboard

Thrown by WalletLedgerPort.debit when the wallet balance can't cover the requested amount.

Link copied to clipboard
data class Money(val amountMinor: Long, val currency: String)

An amount of money in the smallest indivisible unit of currency (paise for INR, cents for USD).

Link copied to clipboard
data class OrderRef(val orderId: String, val catalogItemId: String, val amount: Money)

A server-created order the client is about to pay. The client never sets the amount — it sends a catalog item id and the backend resolves the price (the trust boundary this whole app exists to demonstrate). This is what the backend returns from POST /orders.

Link copied to clipboard
data class PaymentApiConfig(val baseUrl: String = DEFAULT_BASE_URL)

Where the app finds its payments backend server.

Link copied to clipboard
interface PaymentBackend

The app's view of the server. Implemented in core:network (Ktor) against the core:protocol DTOs; consumed by the orchestrator in domain terms only, so the orchestrator never sees a DTO or an HTTP concern. This is the seam that lets the tested core run against a fake backend.

Link copied to clipboard
interface PaymentGateway

The single contract every payment provider implements. Deliberately tiny and platform-agnostic: the messy, Activity-callback-era SDK reality is confined to each provider's androidMain impl and bridged back into a coroutine by PaymentHost.

Link copied to clipboard

The collected set of gateways available in the app. Each provider:* module contributes one PaymentGateway into DI; the app assembles them here. Features depend only on this registry, so adding provider N+1 touches no existing feature code.

Link copied to clipboard
interface PaymentHost

Platform handle a PaymentGateway needs to launch its SDK/UI. Deliberately opaque in commonMain — it carries no platform types, so the contract stays multiplatform. On Android the concrete host (see AndroidPaymentHost in androidMain) owns the ComponentActivity + ActivityResult plumbing and bridges the SDK's callback back into the suspending PaymentGateway.pay call.

Link copied to clipboard
class PaymentPreparationException(val message: String, val cause: Throwable? = null) : Exception

Thrown by PaymentGateway.prepare when the order/session could not be created.

Link copied to clipboard
sealed interface PaymentResult

The terminal (or near-terminal) outcome of a payment attempt, as reported by the client SDK.

Link copied to clipboard
data class PaymentSnapshot(val orderId: String, val paymentId: String?, val status: PaymentStatus, val providerRef: String? = null)

A point-in-time snapshot of server-side payment state.

Link copied to clipboard

Server-authoritative payment state — the domain mirror of PaymentStatusDto.

Link copied to clipboard
sealed interface PaymentStep

One observable step in a payment's lifecycle, emitted by the orchestrator as a stream. The Lab screen renders these as a live timeline (order created → launching → client result → verifying → terminal), each carrying its RedactedPayload so the user sees the actual data at every hop.

Link copied to clipboard
interface PayoutBackend

The app's view of the server's Transfers/payout rail (roadmap #4) — mirrors PaymentBackend's shape: initiate does the server round-trip, status polls the server-authoritative state a mock settlement webhook updates. Implemented in core:network against core:protocol DTOs.

Link copied to clipboard
data class PayoutSnapshot(val payoutId: String, val gatewayId: GatewayId, val recipientRef: String, val amount: Money, val status: PayoutStatus)
Link copied to clipboard

Payout lifecycle — the domain mirror of PayoutStatusDto.

Link copied to clipboard
data class PendingPayment(val orderId: String, val catalogItemId: String, val gatewayId: GatewayId, val amount: Money, val createdAtEpochMs: Long, val status: PaymentStatus, val paymentId: String? = null)

A durable record of one payment attempt.

Link copied to clipboard

The process-death insurance policy. A pending row is written here before the SDK launches, so if the app is killed mid-payment (OEM battery kill, user swipe, low memory during the bank's 3DS WebView) the orchestrator can, on next cold start, find unresolved payments and reconcile them against the server. Implemented by core:data (Room).

Link copied to clipboard

Why a payment is not yet terminal.

Link copied to clipboard
data class PreparedPayment(val gatewayId: GatewayId, val orderId: String, val amount: Money, val params: Map<String, String>)

Opaque, provider-specific data produced by PaymentGateway.prepare and handed to PaymentGateway.pay. Each provider stuffs its own session material into params: Razorpay → order_id + key_id; Cashfree → payment_session_id; Stripe → client_secret; UPI intent → the constructed upi:// reference fields.

Link copied to clipboard
data class RedactedPayload(val label: String, val entries: List<Pair<String, String>>)

A key/value snapshot of an SDK request or response that has already passed the redaction allowlist — safe to render in the Lab timeline and to log. Constructing one asserts "these fields are non-secret". Secrets and PII never reach this type; the redactor drops them upstream.

Link copied to clipboard
object Redactor

Turns an arbitrary provider request/response map into a RedactedPayload safe to render and log.

Link copied to clipboard
data class SavedInstrument(val instrumentId: String, val customerId: String, val brand: String, val last4: String)

A saved instrument as the app ever sees it — masked, never the raw card token.

Link copied to clipboard

The scripted outcome a SimulatedPayment run should settle to.

Link copied to clipboard

Stands in for a real SDK round-trip when a gateway has no live sandbox credentials (GatewayStatus.MOCK_MODE). A short suspend delay mimics the SDK hop; the outcome is scripted (not random) so the Lab timeline is deterministic and every mock-mode gateway can be demoed end-to-end with zero credentials.

Link copied to clipboard

Which leg of a split payment a PaymentStep.LegSettled belongs to.

Link copied to clipboard

A Tier-4 "stub/docs-only" catalog entry: real enough to appear in the Lab list with an honest GatewayStatus.COMING_SOON badge and a web-researched doc, but with no working integration behind it (no backend adapter, no real or mock SDK call). pay always fails — nothing should ever actually invoke it in normal use since the UI badges it as not-yet-available, but the contract still has to return something rather than throw if it somehow is.

Link copied to clipboard
data class StubGatewayConfig(val id: GatewayId, val displayName: String, val region: String, val docsPath: String, val blurb: String, val capabilities: Set<Capability> = setOf(Capability.ONE_TIME_PAYMENT))

Everything a Tier-4 catalog-only entry needs: identity + the research-backed blurb/docs link.

Link copied to clipboard
interface VaultBackend

The app's view of the server's Stripe Customer + vault rail (roadmap #7) — mirrors PayoutBackend's shape: save/list/charge each do a server round-trip against core:protocol DTOs. Implemented in core:network.

Link copied to clipboard
data class VerificationRequest(val gatewayId: GatewayId, val orderId: String, val paymentId: String? = null, val signature: String? = null, val extra: Map<String, String> = emptyMap())
Link copied to clipboard
@Serializable
data class WalletBalanceResponse(val accountId: String, val balanceMinor: Long)

GET /wallet/{accountId}/balance response.

Link copied to clipboard
@Serializable
data class WalletDebitRequest(val idempotencyKey: String, val amountMinor: Long)

POST /wallet/{accountId}/debit request — the ledger "pay" movement, carries an idempotency key.

Link copied to clipboard

Slim port onto the wallet's double-entry ledger, used ONLY by the orchestrator (see PaymentOrchestrator.paySplit) for the split-payment wallet leg's compensating credit. Deliberately separate from PaymentGateway — refund/compensation is an orchestration concern (per the split-payment design), not part of the gateway contract every provider implements.

Link copied to clipboard
@Serializable
data class WalletRefundRequest(val idempotencyKey: String, val amountMinor: Long)

POST /wallet/{accountId}/refund request — the ledger "refund" movement (a credit back).

Link copied to clipboard
@Serializable
data class WalletTransactionResponse(val txnId: String, val accountId: String, val balanceMinor: Long)