Stripe webhook ignores promo registration payments — signup_method filter too strict #400

Open
opened 2026-04-08 21:53:52 +00:00 by forgejo_admin · 0 comments
Contributor

Type

Bug

Lineage

Discovered during Stripe/DB reconciliation on 2026-04-08. kevin porja paid $15 via Stripe but DB shows pending.

Repo

forgejo_admin/basketball-api

What Broke

The Stripe webhook handler for checkout.session.completed at src/basketball_api/routes/webhooks.py:360 filters registrations by signup_method == "stripe". Promo discount registrations have signup_method = "promo_discount" even though they pay through Stripe checkout at a discounted price. The webhook arrives, the filter excludes the registration, payment is never recorded.

Result: player shows as unpaid in the CRM even though Stripe charged them. Marcus sees incorrect payment status.

Repro Steps

  1. Register with a promo code (creates registration with signup_method=promo_discount)
  2. Complete Stripe checkout at discounted price
  3. Stripe sends checkout.session.completed with type=tryout_registration metadata
  4. Webhook handler queries Registration.signup_method == "stripe" — no match
  5. Payment never recorded, registration stays pending

Expected Behavior

The webhook handler should match registrations regardless of signup_method. Any registration with matching registration_id from the Stripe metadata should be updated to paid when the checkout completes.

Fix: change line ~360 from:

Registration.signup_method == "stripe",

to either remove the filter entirely, or expand it:

Registration.signup_method.in_(["stripe", "promo_discount", "promo"]),

Environment

  • Cluster/namespace: prod / basketball-api
  • Affected: kevin porja (registration #182, player #198) — paid $15 on Stripe, DB shows pending
  • Signup methods in DB: stripe(48), cash(3), form(2), promo(2), promo_discount(1)

Acceptance Criteria

  • Webhook handler matches registrations by registration_id without filtering on signup_method
  • kevin porja's registration updated to paid (manual fix or webhook replay)
  • Test coverage for promo registration webhook flow
  • No regression on standard Stripe registration flow
  • project-westside-basketball
  • story:WS-S17 — parent registration
  • forgejo_admin/basketball-api#350 — webhook fix (same handler)
  • Key files: src/basketball_api/routes/webhooks.py:360
### Type Bug ### Lineage Discovered during Stripe/DB reconciliation on 2026-04-08. kevin porja paid $15 via Stripe but DB shows pending. ### Repo `forgejo_admin/basketball-api` ### What Broke The Stripe webhook handler for `checkout.session.completed` at `src/basketball_api/routes/webhooks.py:360` filters registrations by `signup_method == "stripe"`. Promo discount registrations have `signup_method = "promo_discount"` even though they pay through Stripe checkout at a discounted price. The webhook arrives, the filter excludes the registration, payment is never recorded. Result: player shows as unpaid in the CRM even though Stripe charged them. Marcus sees incorrect payment status. ### Repro Steps 1. Register with a promo code (creates registration with `signup_method=promo_discount`) 2. Complete Stripe checkout at discounted price 3. Stripe sends `checkout.session.completed` with `type=tryout_registration` metadata 4. Webhook handler queries `Registration.signup_method == "stripe"` — no match 5. Payment never recorded, registration stays `pending` ### Expected Behavior The webhook handler should match registrations regardless of `signup_method`. Any registration with matching `registration_id` from the Stripe metadata should be updated to `paid` when the checkout completes. Fix: change line ~360 from: ```python Registration.signup_method == "stripe", ``` to either remove the filter entirely, or expand it: ```python Registration.signup_method.in_(["stripe", "promo_discount", "promo"]), ``` ### Environment - Cluster/namespace: prod / basketball-api - Affected: kevin porja (registration #182, player #198) — paid $15 on Stripe, DB shows pending - Signup methods in DB: stripe(48), cash(3), form(2), promo(2), promo_discount(1) ### Acceptance Criteria - [ ] Webhook handler matches registrations by `registration_id` without filtering on `signup_method` - [ ] kevin porja's registration updated to `paid` (manual fix or webhook replay) - [ ] Test coverage for promo registration webhook flow - [ ] No regression on standard Stripe registration flow ### Related - `project-westside-basketball` - `story:WS-S17` — parent registration - `forgejo_admin/basketball-api#350` — webhook fix (same handler) - Key files: `src/basketball_api/routes/webhooks.py:360`
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
ldraney/basketball-api#400
No description provided.