Payments

Stripe handles every payment in Midsummer — registration tiers, vendor tables, shop items, and donations. There is no alternate payment backend.

The model

  • Each Event has an associated Stripe API key (utility.StripeKeydjstripe APIKey). Events run in either test or live mode; the key determines which.

  • Products and prices are auto-managed. When you save a model that maps to a Stripe object (e.g. a RegistrationLevel with a price), the model’s save() override creates/updates the corresponding Stripe Product/Price through the API. You generally don’t manage Stripe objects by hand.

  • Checkout is Stripe Checkout. A registration/cart checkout produces a stripe_checkout_id stored on the record; the user completes payment on Stripe and returns.

  • Confirmation is webhook-driven. Stripe sends events to the webhook endpoint; the handler marks records paid (is_paid = True) and triggers downstream effects (confirmation email with QR, etc.).

Separate modes

  • UFLS_STRIPE_TEST=true selects test keys (config in .env). Use test mode for all local/sandbox work.

  • Items created in Stripe sandbox/test mode do not transfer to live Stripe — recreating them later is awkward. Sandbox keys are for sandbox deployments only.

Warning

Restricted Stripe keys will fail. Use an unrestricted API key. This matters when onboarding tenants (see Add a new tenant).

Reconciliation & reporting

  • register__check_unfinished / register__checkpaid / register__oops — operational commands that reconcile a registration’s is_paid flag against the live Stripe checkout/payment-intent state (e.g. catch “marked paid but not actually paid” or “paid but flagged unpaid”). See Management commands.

  • Superadmin Stripe transactions — a per-event live charge report (list/detail/export) across register/vendor/shop sources, with a cents-based summary cached for 300s. Superadmin-gated; lives in register/services/stripe_transactions_service.py.

Payment & the data snapshot

Payment success is what finalizes a Registration and triggers the snapshot of tier-merch into Registration.data. Editing a tier’s included_merch later does not change existing paid registrations — that’s the snapshot pattern. Mutating a Registration via admin tools (merch adjustment, tier upgrade) does not touch Stripe directly, so those operations are Stripe-safe by construction.

Where to look

  • Payment connection utilities: ufls/

  • Per-event keys: utility/models.py (StripeKey)

  • Webhook + checkout views: register/views.py, vendors/views.py, shop/views.py

  • Transactions report: register/services/stripe_transactions_service.py