Skip to main content

FastAPI payment checkout library — Python port of awesome-node-checkout

Project description

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

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

awesome_python_checkout-0.1.0.tar.gz (20.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

awesome_python_checkout-0.1.0-py3-none-any.whl (17.2 kB view details)

Uploaded Python 3

File details

Details for the file awesome_python_checkout-0.1.0.tar.gz.

File metadata

  • Download URL: awesome_python_checkout-0.1.0.tar.gz
  • Upload date:
  • Size: 20.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for awesome_python_checkout-0.1.0.tar.gz
Algorithm Hash digest
SHA256 16614a4ba9ae3f32112f06e9eddd855d642df07491c1be895d27e9ad0248d503
MD5 6cac450ca70048f0b3880edd792b0b99
BLAKE2b-256 0c3ae5b31519c73ed0712db4d139fcb25044360909c41d6a47cbf40739d8b63d

See more details on using hashes here.

Provenance

The following attestation bundles were made for awesome_python_checkout-0.1.0.tar.gz:

Publisher: publish.yml on nik2208/awesome-python-checkout

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file awesome_python_checkout-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for awesome_python_checkout-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 90fe56be5065a4885f299d7630e74f70e3fe911cc6744b36ed4269c3c98f640d
MD5 294e58ba70844a0ef80fa7e6e8a0db6a
BLAKE2b-256 2d3019a5b3c26b6a9c6efce8e43628f51f64d88a9b07588989cb237355ba3279

See more details on using hashes here.

Provenance

The following attestation bundles were made for awesome_python_checkout-0.1.0-py3-none-any.whl:

Publisher: publish.yml on nik2208/awesome-python-checkout

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page