Skip to main content

Python SDK: oid4pay-oid4ac

The Python SDK targets CPython 3.11+. It pins cryptography for Ed25519, pydantic v2 for request and response models, and httpx for the AS round trips.

Install

pip install oid4pay-oid4ac
# or
uv pip install oid4pay-oid4ac

API reference

verify_offer(body, headers, jwks, *, expected_target_uri=None)

Verifies an RFC 9421 signed offer. Raises OfferVerifyError with a code attribute that mirrors the Node / Go / CDN SDKs.

verify_mandate(sd_jwt_vc, kb_jwt, as_jwks, *, expected_audience, expected_nonce)

Verifies an SD-JWT VC mandate plus KB-JWT pair. Returns a VerifiedMandate Pydantic model with the disclosed claims.

charge(*, access_token, dpop_key, offer_digest, idempotency_key)

Settles a charge against the AS. The dpop_key is a cryptography private key whose public JWK thumbprint must match the JWT-AT cnf.jkt.

Example: FastAPI storefront route

from fastapi import APIRouter
from oid4pay_oid4ac import verify_offer, charge, OfferVerifyError
from uuid import uuid4

router = APIRouter()

@router.post("/charge")
async def settle(req: ChargeRequest) -> ChargeResponse:
    merchant_jwks = await fetch_jwks(req.merchant_id)
    try:
        v = verify_offer(
            req.offer_body,
            req.signed_headers,
            merchant_jwks,
            expected_target_uri=f"https://shop.example.com/oid4ac/offer/{req.offer_body.sku}",
        )
    except OfferVerifyError as exc:
        raise HTTPException(status_code=400, detail=exc.code)

    return await charge(
        access_token=req.access_token,
        dpop_key=load_dpop_key(),
        offer_digest=v.body_digest,
        idempotency_key=str(uuid4()),
    )

Algorithm whitelist

Identical to the Node SDK: ed25519 and ecdsa-p256-sha256 for signed offers; EdDSA for JWT-AT verification.