Repository navigation
Releases
Releases · AkibUllah/fastapi-payment-gateway
v0.2.0
Race-safe idempotency keys
Two requests carrying the same new Idempotency-Key could previously both reach the payment provider before the unique constraint caught the second one. Keys are now reserved before the provider is called:
- A duplicate that arrives while the first request is still running gets
409 idempotency_key_in_progresswithRetry-After, and the provider is called once. - A request that fails releases its key, so the client can retry straight away.
- A request that crashes frees its key when
IDEMPOTENCY_LOCK_SECONDS(new setting, default 60) runs out. - A new CI job races 8 concurrent requests for one key on PostgreSQL and checks that exactly one wins.
Also in this release: CodeQL scanning, Dependabot, README screenshots, and a read-only CI token.
Upgrading from v0.1.0
ALTER TABLE idempotency_keys ADD COLUMN state VARCHAR(16) NOT NULL DEFAULT 'completed';
ALTER TABLE idempotency_keys ADD COLUMN locked_until TIMESTAMPTZ;
ALTER TABLE idempotency_keys ALTER COLUMN status_code DROP NOT NULL;
ALTER TABLE idempotency_keys ALTER COLUMN response_body DROP NOT NULL;Full changelog: v0.1.0...v0.2.0 · PR #13
v0.1.0
First public release of FastAPI Payment Gateway.
Highlights
- Provider adapter pattern:
BkashAdapter,SSLCommerzAdapter,StripeAdapter(sandbox) and aMockProviderfor tests, all behind onePaymentProviderprotocol - Payment lifecycle state machine (
CREATED → AUTHORIZED → CAPTURED → PARTIALLY_REFUNDED/REFUNDED, plusFAILED/CANCELLED); illegal transitions are rejected with HTTP 409 and never persisted Idempotency-Keyheader on create/capture/refund: stored responses are replayed byte-for-byte, reuse with a different body is rejected- Merchant API keys stored as SHA-256 hashes with a lookup prefix; per-merchant data isolation
- Outgoing merchant webhooks signed with HMAC-SHA256 (
X-Gateway-Signature: t=…,v1=…), bounded retries, delivery log queryable via the API - Inbound provider webhook verification (bare HMAC for bKash/SSLCommerz, timestamped Stripe-style signature with replay window) with idempotent event application
- Fee-aware routing: cheapest provider for a currency/method pair, overridable per request; fees computed in basis points with half-up integer rounding, no floats anywhere near money
- Full and partial refunds with refundable-balance enforcement; partial captures re-quote the fee
- Daily settlement batches per provider and currency, CSV export, reconciliation that diffs the provider report against the ledger (mismatches, missing, unexpected) and a
PAIDclose-out - Health endpoint, request-id middleware, structured error envelope, OpenAPI docs at
/docs
Getting started
- Quick start (Docker and local): see the README.
- Live demo / API reference: https://akibullah.github.io/fastapi-payment-gateway/
- Run it in your browser: Open in GitHub Codespaces
Quality
- Full test suite, lint and build run in CI on every push and pull request.
- MIT licensed.