Online Transaction Service
Overview
gateway-online-txn owns the e-commerce edge plus merchant-operated payment
entry points: checkout sessions, hosted payment flows, typed virtual-terminal
sale/auth/force-auth, authenticated setup-intent confirmation, shopper payment
submission, storefront resources, API-key records, webhook delivery attempts,
and checkout-facing subscription actions. It delegates payment execution to the
internal processing service.
Production traffic uses https://pay.peakgateway.co; staging uses
https://staging-pay.peakgateway.co. Both hosts default to online-txn and also
route /online-txn/* with the prefix removed.
| Area | Responsibility |
|---|---|
| Checkout | Create, read, cancel, expire, and pay checkout sessions |
| Virtual terminal | Validate typed card/ACH credentials, enforce scope/App Check/impersonation and idempotency, canonicalize requests, and delegate sale/auth/force-auth |
| Setup intents | Confirm authenticated setup intents on the pay host; management retains PAN-free metadata and lifecycle operations |
| Shopper payment | Validate session credentials and submit card or wallet payment data |
| Hosted payments | Payment links, buttons, iframe flows, and appearance configuration |
| Storefront | Products, prices, coupons, promotion codes, shipping, and customers |
| API keys | Persist merchant API keys and exchange them through auth for scoped OAuth tokens |
| Webhooks | Create delivery attempts, sign payloads, retry failures, and expose replay controls |
| Fraud controls | Endpoint rate limits and optional reCAPTCHA Enterprise assessment |
| Subscriptions | Checkout-facing create and lifecycle operations delegated to processing |
Authentication Modes
| Caller | Credential |
|---|---|
| Server integration | OAuth2 Bearer token from the auth service |
| API-key integration | Raw key exchanged at /auth/oauth2/api-key/token; downstream calls use the returned Bearer token |
| Checkout shopper | Session token/secret bound to one checkout session |
| Portal BFF | Firebase-authenticated management call forwarded through an internal service client |
A raw API key is not a long-lived Bearer credential for arbitrary online-txn routes. The auth service validates it and issues a short-lived, scoped OAuth token.
API Contracts
The public OpenAPI specification is the source of truth for checkout, wallet, subscription, storefront, and typed virtual-terminal request/response bodies:
- Public API reference
websites/docs/openapi/public-api.yamlservices/online-txn/src/main/kotlin/.../controller/
The pay host owns the credential-bearing transaction and setup-intent confirmation routes:
POST /api/v1/transactions/salePOST /api/v1/transactions/authPOST /api/v1/transactions/force-authPOST /api/v1/setup-intents/{setupIntentId}/confirm
Do not duplicate endpoint schemas in this page. The generated reference covers current fields such as line items, minor-unit amounts, Apple Pay and Google Pay payloads, session-token headers, idempotency headers, and subscription mutation responses.
Checkout Lifecycle
OPEN --pay approved--> COMPLETED
| |
| +--declined/validation failure--> OPEN (when retry remains allowed)
+--cancel-------------------------------> CANCELLED
+--expiry-------------------------------> EXPIRED
The persisted session is authoritative. Shopper redirects and browser state are presentation concerns and cannot mark a payment successful. A session moves to its terminal success state only after processing has returned a durable payment outcome and online-txn has persisted the corresponding session transition.
Fast repeated /pay calls are rate limited. Certification automation that
receives 429 RATE_LIMITED must honor the retry window and resume the failed
step rather than recreate the full run.
Wallet Payments
Apple Pay and Google Pay requests preserve provider payloads and merchant configuration through the checkout boundary. The service validates the session and wallet-specific request shape before delegating payment execution. Wallet certificates, merchant identifiers, and domain verification are documented in Digital Wallets.
Webhook Delivery
Webhook ownership is intentionally split:
- management owns durable subscription/configuration records and operator actions;
- online-txn owns per-destination delivery attempts, retries, and dispatch state;
- domain services persist their transition before publishing an event.
Delivery uses HMAC-SHA256 over the exact timestamp and raw request body. SDK helpers are the preferred verification path. Consumers must verify against the raw bytes before JSON parsing and enforce an age window to limit replay.
Webhook delivery is downstream of the payment transition. Exhausted delivery retries enter DLQ/operator recovery; they never reverse an approved payment. See Event Log and Replay.
Data Ownership
Online-txn owns the tables for:
- checkout sessions and shopper-session state
- hosted-payment configuration
- storefront catalog and promotion resources
- merchant API-key records owned by this service
- webhook delivery attempts and retry state
Processing owns transactions, customers/payment methods where designated by the processing contract, subscriptions, and monetary outcomes. Management owns merchant/operator configuration and tenant authorization. Cross-service writes to another service's single-owner tables are prohibited.
The SQLDelight definitions under libs/schema/src/main/sqldelight/ are the
schema source of truth.
Reliability and Security
- Resolve location ownership before reading or mutating a session.
- Require OAuth scope and applicable Firebase App Check/impersonation checks on merchant-operated payment routes.
- Require idempotency on externally retryable monetary actions.
- Never log PAN, CVV, raw bank account data, raw wallet cryptograms, session secrets, API keys, or webhook secrets.
- Persist delivery attempts and terminal payment outcomes independently.
- Treat an unknown processing result as in-doubt, not as a safe retry.
- Keep shopper routes narrowly scoped to the session credential.
Runtime
| Component | Technology |
|---|---|
| Language | Kotlin 2.2 on Java 25 |
| Framework | Spring Boot 4.0.5 |
| Database | Cloud Spanner PostgreSQL dialect through SQLDelight/PGAdapter |
| Messaging | Cloud Pub/Sub |
| Payment execution | Internal call to processing with Cloud Run IAM |
| Public host | pay.peakgateway.co / staging-pay.peakgateway.co |
Health endpoint: GET /health on the service, publicly reachable as
/online-txn/health on the payment host.