Skip to main content

awesome-python-checkout

Python FastAPI License: MIT PyPI version

FastAPI payment checkout library — a faithful Python port of awesome-node-checkout.

Drop-in payment orchestration for FastAPI — connect any payment provider through a single interface.
Inspired by awesome-python-auth. Same philosophy: no framework lock-in, no DB lock-in, implement one interface and you're done.


Installation

pip install awesome-python-checkout

Quick Start

Standalone (no HTTP framework)

import asyncio
from awesome_python_checkout import CheckoutConfigurator, PayPalProvider, PayPalConfig, PaymentRequest

checkout = CheckoutConfigurator()
checkout.register_provider(
    PayPalProvider(PayPalConfig(
        client_id="YOUR_CLIENT_ID",
        client_secret="YOUR_CLIENT_SECRET",
        environment="sandbox",
    ))
)

async def main():
    result = await checkout.create_payment(
        "paypal",
        PaymentRequest(
            amount=49.99,
            currency="EUR",
            description="Order #1234",
            return_url="https://myapp.com/payment/success",
            cancel_url="https://myapp.com/payment/cancel",
            order_id="ORD-1234",
        ),
    )
    print(result.redirect_url)  # redirect user to this URL

asyncio.run(main())

FastAPI router mounting

import os
from fastapi import FastAPI
from awesome_python_checkout import (
    CheckoutConfigurator,
    PayPalProvider, PayPalConfig,
    NexiProvider, NexiConfig,
    SatispayProvider, SatispayConfig,
)

checkout = CheckoutConfigurator()

checkout \
    .register_provider(PayPalProvider(PayPalConfig(
        client_id=os.environ["PAYPAL_CLIENT_ID"],
        client_secret=os.environ["PAYPAL_CLIENT_SECRET"],
        environment="sandbox",
    ))) \
    .register_provider(NexiProvider(NexiConfig(
        merchant_id=os.environ["NEXI_MERCHANT_ID"],
        mac_key=os.environ["NEXI_MAC_KEY"],
        environment="sandbox",
    ))) \
    .register_provider(SatispayProvider(SatispayConfig(
        key_id=os.environ["SATISPAY_KEY_ID"],
        private_key=open("private.pem").read(),
        environment="sandbox",
        server_url="https://myapp.com",
    )))

app = FastAPI()
app.include_router(checkout.router(), prefix="/checkout")

CheckoutConfig Reference

PayPalConfig

Field Type Default Description
client_id str required PayPal OAuth2 client ID
client_secret str required PayPal OAuth2 client secret
environment "sandbox" | "live" "sandbox" Target environment

NexiConfig

Field Type Default Description
merchant_id str required Nexi merchant alias
mac_key str required Nexi MAC key for SHA-1 signature
environment "sandbox" | "live" "sandbox" Target environment

SatispayConfig

Field Type Default Description
key_id str required Satispay RSA key ID
private_key str required RSA private key (PEM string)
environment "sandbox" | "live" "sandbox" Target environment
server_url str "" Public base URL of your server (used to build the webhook callback URL)
store ITransactionStore InMemoryTransactionStore() Transaction store for correlating webhooks

Routes

All routes are mounted under the prefix you choose (e.g. /checkout).

Method Path Description
POST /{provider} Create a payment
POST /{provider}/execute Execute / capture a payment
GET /{provider}/redirect Handle provider redirect callback
GET /{provider}/{id} Get payment details
POST /{provider}/refund Refund a payment
POST /{provider}/webhook Handle provider webhook

Payment Flows

Flow Providers Description
redirect PayPal, Nexi User is redirected to the provider page, then returns with query params
webhook Satispay Provider calls the webhook URL asynchronously after confirmation
direct (future) Synchronous processing (card tokenisation, etc.)

Events

Subscribe to lifecycle events with checkout.on():

checkout \
    .on("payment.created",   lambda p: print("created",   p["paymentId"])) \
    .on("payment.completed", lambda p: print("completed", p["paymentId"])) \
    .on("payment.failed",    lambda p: print("failed",    p["error"])) \
    .on("payment.refunded",  lambda p: print("refunded",  p["paymentId"])) \
    .on("webhook.received",  lambda p: print("webhook",   p["data"]))

Async callbacks are also supported:

async def on_completed(payload):
    await notify_order_service(payload["paymentId"])

checkout.on("payment.completed", on_completed)
Event Payload keys Fired when
payment.created provider, paymentId create_payment succeeds
payment.completed provider, paymentId execute / redirect / webhook confirms success
payment.failed provider, error payment fails
payment.refunded provider, paymentId refund succeeds
webhook.received provider, data webhook body arrives

Custom Transaction Store

Implement ITransactionStore to persist transactions in your database:

from awesome_python_checkout import ITransactionStore, TransactionData

class RedisTransactionStore(ITransactionStore):
    async def save(self, key: str, data: TransactionData) -> None:
        await redis.set(key, data.model_dump_json(), ex=3600)

    async def get(self, key: str) -> TransactionData | None:
        raw = await redis.get(key)
        return TransactionData.model_validate_json(raw) if raw else None

    async def delete(self, key: str) -> None:
        await redis.delete(key)

Pass the store to the provider config:

from awesome_python_checkout import SatispayProvider, SatispayConfig

provider = SatispayProvider(SatispayConfig(
    key_id="...",
    private_key="...",
    store=RedisTransactionStore(),
))

Custom Provider

Extend BasePaymentProvider to add your own payment gateway:

from awesome_python_checkout import BasePaymentProvider, PaymentRequest, PaymentResult
from typing import Any, Literal

class StripeProvider(BasePaymentProvider):
    @property
    def name(self) -> str:
        return "stripe"

    @property
    def flow(self) -> Literal["redirect"]:
        return "redirect"

    async def create_payment(self, request: PaymentRequest) -> PaymentResult:
        # call Stripe API …
        return PaymentResult(
            payment_id="pi_xxx",
            status="pending",
            provider=self.name,
            redirect_url="https://checkout.stripe.com/pay/…",
        )

    async def execute_payment(self, payment_id: str, data: dict[str, Any]) -> PaymentResult: ...
    async def get_payment(self, payment_id: str) -> PaymentResult: ...
    async def refund_payment(self, payment_id: str, amount: float | None = None) -> PaymentResult: ...
    async def handle_webhook(self, body: Any, headers: dict[str, str]) -> PaymentResult: ...
    async def handle_redirect(self, query: dict[str, str]) -> PaymentResult: ...

checkout.register_provider(StripeProvider())

Built-in Providers

Provider Flow Notes
PayPalProvider redirect PayPal Orders API v2
NexiProvider redirect Nexi eCommerce DispatcherServlet, MAC SHA-1
SatispayProvider webhook Satispay Business API v1, RSA-SHA256 signing

Angular Integration

Point your Angular app (using ng-awesome-node-auth or any HTTP client) at the FastAPI server:

// Call the checkout API directly from Angular
const result = await http.post('/checkout/paypal', {
  amount: 49.99,
  currency: 'EUR',
  order_id: 'ORD-1234',
  return_url: 'https://myapp.com/success',
  cancel_url: 'https://myapp.com/cancel',
}).toPromise();

window.location.href = result.redirect_url;

No other changes needed — the FastAPI server handles all provider communication.


Flutter Integration

Call the checkout endpoints from your Flutter app:

final response = await http.post(
  Uri.parse('https://your-server.com/checkout/paypal'),
  headers: {'Content-Type': 'application/json'},
  body: jsonEncode({
    'amount': 49.99,
    'currency': 'EUR',
    'order_id': 'ORD-1234',
    'return_url': 'https://your-server.com/success',
    'cancel_url': 'https://your-server.com/cancel',
  }),
);
final data = jsonDecode(response.body);
// Open data['redirect_url'] in a WebView or browser

License

MIT

Release files for awesome-python-checkout 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for awesome-python-checkout 0.1.0
File Size Uploaded
awesome_python_checkout-0.1.0.tar.gz 20.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for awesome-python-checkout 0.1.0
File Interpreter ABI Platform
awesome_python_checkout-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 37.3 kB

Release files / awesome_python_checkout-0.1.0.tar.gz

Download URL awesome_python_checkout-0.1.0.tar.gz
Size 20.1 kB
Tags Source
SHA-256 checksum
How to use checksums
16614a4ba9ae3f32112f06e9eddd855d642df07491c1be895d27e9ad0248d503
BLAKE2b-256 checksum
How to use checksums
0c3ae5b31519c73ed0712db4d139fcb25044360909c41d6a47cbf40739d8b63d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 7, 2026.

Transparency log

Release files / awesome_python_checkout-0.1.0-py3-none-any.whl

Download URL awesome_python_checkout-0.1.0-py3-none-any.whl
Size 17.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
90fe56be5065a4885f299d7630e74f70e3fe911cc6744b36ed4269c3c98f640d
BLAKE2b-256 checksum
How to use checksums
2d3019a5b3c26b6a9c6efce8e43628f51f64d88a9b07588989cb237355ba3279
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 7, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page