Skip to content

Payment gateway

Payment operations, normalised once

Every processor implements the same handful of ideas with different names, different state machines and different failure modes. The gateway module exists so that a platform learns those ideas once rather than once per integration.

Planned — no payment operation is available

State of the work

Operations callable
None. No endpoint exists.
Processors connected
None, in production or otherwise.
Design fixed
Idempotency on every mutation; accepted and settled never collapse.
Sequence
Follows the vault. A gateway with nothing to reference is not useful.

Intended operations

These are the operations the module is designed around. None is currently callable.

authorize

Reserve funds against a payment method without moving them. The step that makes a guarantee real.

capture

Take an authorised amount. Separated from authorisation because the two rarely happen at the same moment.

partial capture

Take less than was authorised, which is the normal case whenever the final amount is not known up front.

void

Release an authorisation that will not be captured, instead of letting it expire against the cardholder's available balance.

refund

Return a captured amount, in full or in part, with the original payment as its lineage.

retrieve

Read the current state of a payment, including what the processor actually said rather than what was assumed.

A payment has a lifecycle, and provider acceptance is not the end of it

Treating an accepted request as a completed payment is how reconciliation breaks. The state model is designed to keep those separate.

  1. attempted

  2. accepted

    Provider took the request

  3. authorized

    Funds reserved

  4. captured

    Funds taken

  5. settled

    Money actually moved

Diagram · Intended state model. Terminal states — refunded, disputed, failed — branch from this sequence and are not shown.

The distinction between accepted and settled is the one that costs money when it is collapsed. A platform that treats acceptance as settlement will report revenue that has not arrived and cannot explain the gap at month end.

Design commitments

Idempotency
Every mutating operation takes an idempotency key. A retried request after a timeout must not become a second charge — the failure mode where a customer is billed twice by a network blip is a design defect, not bad luck.
Replay resistance
Requests are bound to a merchant, a scope and a window, so that a captured request cannot be replayed later or against a different tenant.
Deterministic audit
Every payment mutation produces an audit record with a correlation identifier that survives across the gateway, the processor response and the reconciliation event.
Sanitised errors
Processor reason codes are normalised and stripped before they reach a caller, so that diagnosing a decline never becomes a way of extracting card data.