Skip to content

Python SDK — Django integration

The Django adapter ships in the same wheel as paylera-fastapi — install with the django extra and import from paylera_django. It’s a thin URL-pattern factory that delegates to the same RelayCore the FastAPI router uses, so the wire shape stays identical across frameworks.

Terminal window
pip install "paylera-fastapi[django]"

Requires Django 4.2 or newer.

Wire it into urls.py

urls.py
from django.conf import settings
from django.http import HttpRequest
from django.urls import include, path
from paylera_django import paylera_relay_urls
from paylera_fastapi import PayleraCustomerIdentity
def identify(request: HttpRequest) -> PayleraCustomerIdentity:
user = request.user
if not user.is_authenticated:
return PayleraCustomerIdentity()
return PayleraCustomerIdentity(
customer_id=getattr(user, "paylera_customer_id", None),
email=user.email,
name=user.get_full_name(),
)
urlpatterns = [
path(
"api/paylera/",
include(paylera_relay_urls(
api_token=settings.PAYLERA_API_TOKEN,
identify=identify,
auto_create_customer=True,
csrf=True,
)),
),
]

paylera_relay_urls(...) returns a list[URLPattern] you can drop into include(...). The router names every pattern (paylera-attach, paylera-check, …) so you can reverse() them in tests.

Routes

MethodPathURL name
GETcsrf-tokenpaylera-csrf-token
POSTattachpaylera-attach
POSTcheckpaylera-check
POSTtrackpaylera-track
GETentitlementspaylera-entitlements
GETmepaylera-me
GETplanspaylera-plans (anonymous-friendly)
GETinvoicespaylera-invoices
POSTbilling-portalpaylera-billing-portal
POSTsubscriptions/<sub_id>/upgradepaylera-subscription-upgrade
POSTsubscriptions/<sub_id>/cancelpaylera-subscription-cancel

CSRF

The factory installs the Paylera double-submit-cookie middleware (Paylera-CSRF-Token header + paylera_csrf cookie). That’s separate from Django’s built-in CSRF — you don’t need @csrf_exempt on these views, and you shouldn’t reuse Django’s csrftoken cookie for the relay. The two middlewares coexist if you mount Django’s CSRF on the rest of your app.

Tune with paylera_fastapi.PayleraCsrfOptions:

from paylera_fastapi import PayleraCsrfOptions
paylera_relay_urls(
...,
csrf=PayleraCsrfOptions(
cookie_path="/api/paylera",
cookie_secure=True,
cookie_samesite="strict",
),
)

Auth — read request.user

identify runs after Django’s middleware chain, so request.user is already populated by your auth backend. The example above maps an authenticated user; an anonymous user falls back to an empty identity, which means routes that need a customer (everything except /plans) will return 401.

Webhook receiver

paylera_webhook_urls is the inbound twin:

from paylera_django import paylera_webhook_urls
from paylera_fastapi import InvoicePaidEvent
async def handle_invoice_paid(event: InvoicePaidEvent) -> None:
# event.data.id, event.data.amount_paid, ... typed
...
urlpatterns += [
path("webhooks/paylera/", include(paylera_webhook_urls(
signing_secret=settings.PAYLERA_WEBHOOK_SECRET,
accepted_secrets=[settings.PAYLERA_WEBHOOK_SECRET_PREVIOUS]
if settings.PAYLERA_WEBHOOK_SECRET_PREVIOUS else None,
handlers={"invoice.paid": handle_invoice_paid},
))),
]

Handlers can be async or sync; the dispatcher accepts both. See webhooks for the verification rules.

Settings

Add to settings.py (read from environment in production):

import os
PAYLERA_API_TOKEN = os.environ["PAYLERA_API_TOKEN"]
PAYLERA_WEBHOOK_SECRET = os.environ["PAYLERA_WEBHOOK_SECRET"]
PAYLERA_WEBHOOK_SECRET_PREVIOUS = os.environ.get("PAYLERA_WEBHOOK_SECRET_PREVIOUS", "")

No INSTALLED_APPS entry is required — paylera_django is an adapter package, not a Django app.

Async views

The factory always wraps handlers with async_to_sync so they work under WSGI or ASGI. If you’re on ASGI (Daphne / Uvicorn / Hypercorn) and want true concurrency for webhook delivery, mount under asgi.application and your async handlers will run on the running event loop.

Full example

A runnable Django 4.2 project is at examples/python/django-app/ in the monorepo. manage.py runserver 8001 boots a service with both the relay (/api/paylera/) and webhook receiver (/webhooks/paylera/) mounted.