Stripe payment gateway integration for python-getpaid ecosystem.
Project description
python-getpaid-stripe
Stripe payment processor for the
python-getpaid
ecosystem, wrapping Stripe Checkout Sessions (payment mode) via the
official stripe-python SDK.
Design and rationale live in SPEC.md; research backing in
docs/research/.
Key features
- Hosted checkout —
prepare_transaction()creates a payment-mode Checkout Session and returns a redirect URL - Webhook handling — signature verification via
stripe.Webhook.construct_eventover the raw body; semantic mapping wherepayment_intent.*events are authoritative for money-state - Pre-auth / manual capture —
charge()(full or partial capture, remainder auto-released) andrelease_lock(); the first getpaid plugin to exercise core's pre-auth FSM states - Refunds — full and multiple partial refunds; status-driven webhook mapping handles late failures and Stripe-generated expiry refunds
- Radar fraud reviews —
review.opened/closedmap to coreFraudEvents - Status polling —
fetch_payment_status()PULL flow, doubling as the authorization-expiry backstop - Simulator plugin — a local Stripe stand-in for
python-getpaid-simulatorwith a fake hosted checkout, real HMAC webhook signatures, and time-travel ops
Installation
pip install python-getpaid-stripe
With the local simulator plugin:
pip install python-getpaid-stripe[simulator]
Configuration
| Setting | Type | Required | Default | Notes |
|---|---|---|---|---|
api_key |
str | yes | — | sk_test_… / sk_live_… / rk_…; validated at construction |
webhook_secret |
str | yes | — | whsec_…, per-endpoint, test/live distinct; validated at construction |
success_url |
str template | yes | — | {payment_id} is formatted by the plugin; Stripe's literal {CHECKOUT_SESSION_ID} is passed through |
cancel_url |
str template | yes | — | same semantics |
capture_method |
"automatic" | "manual" |
no | "automatic" |
per-payment override: prepare_transaction(capture_method="manual") |
session_expires_in |
int minutes (30–1440) | no | Stripe's 24 h | maps to Checkout expires_at |
max_network_retries |
int | no | 2 |
safe: the SDK auto-generates idempotency keys |
There is no publishable key setting (nothing in a hosted-Checkout
flow consumes one) and no sandbox flag: test vs live mode is
derived from the API key prefix (processor.is_sandbox). A flag that
can contradict the key is a lie waiting to happen.
accepted_currencies is a broad default list of Stripe presentment
currencies; availability is per account country — subclass the
processor to narrow it.
Webhook endpoint (Stripe Dashboard)
Point a webhook endpoint at your framework adapter's callback URL and enable exactly these events:
checkout.session.completed
checkout.session.expired
payment_intent.amount_capturable_updated
payment_intent.succeeded
payment_intent.payment_failed
payment_intent.canceled
refund.created
refund.updated
refund.failed
review.opened
review.closed
The framework adapter must pass the raw request body to
verify_callback(..., raw_body=...) — Stripe signatures are computed
over the raw bytes. Only classic v1 snapshot payloads are supported;
v2 "thin" events are rejected.
Manual capture (pre-auth)
Opt in per configuration or per payment. The flow:
prepare_transaction(capture_method="manual")— the buyer authorizes;payment_intent.amount_capturable_updatedlocks the payment (LOCKED).charge()captures the full locked amount;charge(amount)captures partially and Stripe auto-releases the remainder. Returnsasync_call=True— the authoritativePAYMENT_CAPTUREDarrives viapayment_intent.succeeded.release_lock()cancels the intent and returns the full locked amount;payment_intent.canceledconfirmsLOCK_RELEASED.
Operator note — authorization expiry: card authorizations are
valid for ~7 days (variance: Visa MIT 5 days, some in-person 2, Japan
30). The lock's provider_data["locked_at"] timestamp is stamped when
LOCKED is applied, so your application can schedule
capture-or-release. There is no reliable expiry webhook; the
deterministic detection path is fetch_payment_status() (a canceled
manual-capture intent maps to LOCK_RELEASED). Polling cadence
belongs to the application — this plugin ships no scheduler. Note that
manual capture also narrows the payment methods Stripe offers (cards,
Klarna, PayPal yes; ACH, iDEAL no).
Refunds
start_refund() refunds the full captured amount,
start_refund(amount) a part of it (multiple partials allowed). The
refund id is stored in provider_data["refund_id"] (latest refund
only). Refund reason is deliberately not exposed — Stripe's
fraudulent value has card-block side effects.
cancel_refund() effectively always returns False for card
payments: only refunds in requires_action (bank-transfer-style
methods) are API-cancelable; card refunds can only be canceled from
the Stripe Dashboard.
Simulator plugin
With the simulator extra installed, python-getpaid-simulator
auto-discovers the stripe plugin. Configuration via environment:
SIMULATOR_STRIPE_API_KEY (default sk_test_sim_stripe_key)
SIMULATOR_STRIPE_WEBHOOK_SECRET (default whsec_sim_stripe_secret)
SIMULATOR_STRIPE_NOTIFY_URL (webhook delivery target)
Point the processor at the simulator with the internal api_base
config key. The fake hosted checkout offers pay / pay-delayed /
decline / abandon; POST /sim/stripe/ops/{order_id} forces
transitions with no natural actor (expire_session, expire_auth
time-travel, settle_delayed / fail_delayed, fail_refund,
set_refund_mode, open_review / close_review). Webhooks carry genuine HMAC
Stripe-Signature headers plus deliberate ignore-list traffic
(charge.*, checkout.session.async_payment_*) so the processor's
ignore behavior is exercised under realistic fire.
Development
uv sync --all-extras
uv run pytest
uv run ruff check .
uv run ty check
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file python_getpaid_stripe-0.1.0.tar.gz.
File metadata
- Download URL: python_getpaid_stripe-0.1.0.tar.gz
- Upload date:
- Size: 157.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
13a2ce2d972dffc82e1769fad79467d9cb65ebcab0d1ee520a8e2abdd2d79685
|
|
| MD5 |
0744469a0f62df2d78ccd279a515aea1
|
|
| BLAKE2b-256 |
ad8ae85ef0ed4f8fc7ca5aa3930ed1d9b246cd875bfd686a5fad60808fec2ecb
|
File details
Details for the file python_getpaid_stripe-0.1.0-py3-none-any.whl.
File metadata
- Download URL: python_getpaid_stripe-0.1.0-py3-none-any.whl
- Upload date:
- Size: 23.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0787e8a7512c2eb24425a41f7a297bff21d3d5366c3cc3ec4a17aeb0c49959b0
|
|
| MD5 |
5e766ceee7aec88a8e2865d9ed081e52
|
|
| BLAKE2b-256 |
36954eeff5dc5a507596835bac424c3e35dd17b0ad5c9b9937fa8725d681c7be
|