Payments
A connector framework with two production methods + reserved slots for hosted gateways.
Connector contract
Every payment method implements three async ops:
class PaymentConnector(ABC):
name: str # 'cod', 'bank_transfer', 'card_stripe', ...
display_name: str
requires_redirect: bool
supports_refund: bool
async def start_payment(...) -> StartResult: ...
async def confirm_payment(...) -> ConfirmResult: ...
async def refund(...) -> RefundResult: ... # optional
Connectors register at module import. The checkout service calls
get_connector(method_name) to dispatch.
Production methods (Phase 1)
COD (cod) — Dobírka
The customer pays the courier on delivery. From the system:
start_payment→ synthetic intent ID,requires_inline_confirm=true, no external callconfirm_payment→ always succeeds, status=awaiting_delivery- Order created with
payment_status='unpaid' - Order's
payment_statusflips topaidwhen the courier confirms cash receipt (separate flow via fulfillment update or manual mark-paid)
Bank transfer (bank_transfer) — Bankovní převod s VS
Customer wires money manually using a Variabilní Symbol (typically the order number). From the system:
start_payment→ instant success, returns IBAN + VS for the customer to useconfirm_payment→ instant success, status=awaiting_transfer- Order's
payment_statusflips topaidwhen:- Staff manually marks paid in admin
- Bank statement import (apps/api banks module) reconciles
- Open Banking webhook reports the deposit (future)
carrier_config for bank_transfer:
{
"iban": "CZ...",
"bic": "...",
"beneficiary_name": "Acme s.r.o.",
"qr_payment_url": "https://qr.example.com/pay/..."
}
Reserved slots (future iterations)
- Stripe (
card_stripe) — generic card payments via Stripe Checkout / PaymentIntents - Comgate (
card_comgate) — CZ-native card gateway - GoPay (
card_gopay) — alternative CZ gateway
The connector contract is designed to slot in any of these — requires_redirect=true,
start_payment returns a redirect_url, the customer pays on the
gateway's hosted page, the gateway calls back to your storefront's
return_url, and your storefront calls POST /confirm.json with
the callback payload.
Payment attempts ledger
checkout_payment_attempts records every attempt with:
| Field | Notes |
|---|---|
method | Connector name |
provider | Gateway adapter (same as method for now) |
provider_intent_id | Gateway-side reference |
status | `started → redirected |
amount_cents, currency | Amount being charged |
provider_request / provider_response | Full audit |
error_code, error_message | On failure |
A checkout can have multiple attempts — failed retries each get a new row.
Refunds
The refund flow is part of the Orders module
(via payments table on the order). The connector's refund()
op is called when staff issues a refund in admin.
Phase 1: refund support depends on the gateway. COD doesn't support
refund() (refunds happen out of band). Bank transfer same.
Stripe / Comgate support real refunds when those connectors land.
Next steps
Orders — what complete produces.