TransactKit-Litev1.0.0
TransactKit-Lite architecture
Understand TransactKit-Lite's direct Stripe client boundary, Checkout-first lifecycle, local persistence, idempotency, and host responsibilities.
Updated
System boundary
The code is organized package-by-feature. Controllers accept application DTOs, services own payment lifecycle decisions, the official StripeClient performs outbound calls, and Spring Data repositories persist only application-relevant projections. There is no custom Stripe HTTP client or generic gateway/adapter layer.
Host application / browser tester
-> Controller -> feature Service -> official StripeClient -> Stripe API
|
-> Spring Data JPA -> H2 or MySQL
Stripe webhook
-> raw-body verification -> durable event claim -> transactional handler
-> Payment / RefundRecord projectionCheckout-first payment lifecycle
- A Payment represents one logical application payment and is unique by businessReference.
- The Payment stores only its latest Checkout Session ID and attemptReference.
- An open Session is returned for accidental retries instead of creating another Session.
- An expired or asynchronously failed attempt can be replaced only with a new attemptReference.
- A completed unpaid Session remains processing until asynchronous success or failure.
- A paid, partially refunded, or refunded Payment cannot start another Checkout attempt.
- Checkout creates the PaymentIntent; Lite does not expose direct PaymentIntent creation.
Request idempotency
Checkout uses the Stripe idempotency key checkout:<paymentId>:<attemptReference>. This ties idempotency to one logical payment attempt without permanently binding a business reference to an expired Session.
Refund creation uses refund:<paymentId>:<reference>. The host must generate a stable, unique reference for each intended refund operation and prevent unauthorized callers from choosing arbitrary references.
The configured StripeClient also enables two automatic network retries for outbound Stripe requests. Those SDK retries are separate from Checkout/refund idempotency and from Stripe's webhook redelivery behavior.
Local persistence model
Money uses long integer minor units. Payment UUIDs are stored as VARCHAR for H2/MySQL portability. Flyway owns DDL and Hibernate runs in validate mode. The default H2 URL uses MySQL compatibility mode; DB_URL, DB_USERNAME, and DB_PASSWORD select external MySQL without a separate Java profile.
| Table | Purpose | Important constraints |
|---|---|---|
| payments | Logical payment and latest Checkout projection | Unique business reference, Checkout Session ID, and PaymentIntent ID |
| refunds | Stripe Refund projection associated with a local Payment | Unique Stripe Refund ID and foreign key to payments |
| webhook_events | Durable event claim and processing status | Unique Stripe event ID and bounded error detail |
Webhook transaction model
A short independent transaction inserts the event as RECEIVED. The main handler locks the claim and applies a supported state transition transactionally. On failure, business writes roll back and a second independent transaction marks the event FAILED. PROCESSED and IGNORED are terminal; RECEIVED and FAILED can be retried.
Testing architecture
- The default suite uses H2, mocked StripeClient boundaries, MVC tests, transaction tests, and deterministic signed webhook fixtures.
- The optional stripe-mock profile starts four live contract tests through the official Stripe SDK for Customers, Checkout, Refunds, serialization, and local writes.
- The project-hosted browser tester exercises safe interactive flows without a frontend framework or raw card fields.
- Stripe Test Mode remains necessary for hosted Checkout, card processing, lifecycle transitions, webhook delivery, realistic errors, and Dashboard state.
Host application responsibilities
- Authenticate callers and authorize Customer, Checkout, Payment, and Refund access.
- Bind businessReference and Payment ownership to the host domain model.
- Approve refunds through host policy rather than exposing the endpoint directly.
- Fulfill orders only from an intentional, idempotent business workflow.
- Protect keys, enforce HTTPS, add edge rate limits, and prevent sensitive logging.
- Operate durable MySQL, backups, monitoring, alerting, reconciliation, and incident procedures.