Skip to content

Club Billing Runbook

Stand: 2026-03-22
Gilt für: beta.targetshot.app, staging, Club-Plus-Billing mit Stripe + Keygen

Dieses Runbook beschreibt den normalen Club-Billing-Lifecycle und die wichtigsten Recovery-Fälle für Admins und Support.

Normaler Ablauf

  1. Im Bereich Club Billing die primäre Aktion Club Plus kaufen starten.
  2. Stripe öffnet den Checkout und leitet danach mit stripe=success zurück auf /club-billing.
  3. Das Backend versucht zuerst finalize-session und fällt bei Bedarf auf reconcile zurück.
  4. Die Club-Lizenz wird auf denselben Club gebucht und danach nach Keygen synchronisiert.
  5. Sobald billingProvider = stripe plus billingCustomerId oder billingSubscriptionId vorhanden sind, wechselt die UI auf Billing verwalten.
  6. Wenn ein Admin aus TargetShot heraus Abo kündigen startet, setzt TargetShot cancel_at_period_end = true direkt über die Backend-API bei Stripe und gleicht die Vereinslizenz anschließend sofort neu ab.
  7. Wenn eine vorgemerkte Kündigung wieder zurückgenommen werden soll, nutzt der Admin in TargetShot die Aktion Kündigung zurücknehmen. Diese setzt cancel_at_period_end = false direkt über Stripe und gleicht die Vereinslizenz anschließend sofort neu ab.
  8. Zusätzlich läuft serverseitig ein periodischer Stripe-Reconcile-Pass, der Stripe-Status, Club-Lizenz und Keygen regelmäßig still gegeneinander abgleicht.

Sichtbare Admin-Zustände

  • Bereit für neuen Checkout Bedeutung: Es gibt noch keinen aktiven Stripe-Lifecycle für diesen Club. Aktion: Club Plus kaufen

  • Checkout oder Recovery offen Bedeutung: Es existiert bereits ein Checkout- oder Recovery-Fall, aber Stripe und Club-Lizenz sind noch nicht vollständig synchron. Aktion: Stripe synchronisieren

  • Stripe verwaltet Billing Bedeutung: Stripe-Referenzen sind vollständig vorhanden und das Billing-Portal kann genutzt werden. Aktion: Billing verwalten

  • Kündigung vorgemerkt Bedeutung: Die Kündigung ist in Stripe bereits zum Laufzeitende hinterlegt, Club Plus bleibt bis validUntil aktiv. Aktion: Kündigung zurücknehmen oder Billing verwalten

  • Synchronisierung läuft Bedeutung: Der Return-Flow oder ein manueller Recovery-Lauf ist noch in Arbeit. Aktion: warten, danach Status neu laden

Recovery-Fälle

1. Rückkehr von Stripe, aber Lizenz bleibt unvollständig

  • Im Club-Billing bleibt die Hauptaktion auf Stripe synchronisieren.
  • Diese Aktion prüft, ob ein offener Checkout fortgesetzt werden muss oder ob Stripe bereits abgeschlossen wurde und nur noch in die Club-Lizenz zurückgeschrieben werden muss.
  • Zusätzlich sollte der serverseitige Reconcile-Pass denselben Drift später automatisch wieder einfangen, auch wenn ein Webhook verspätet war.

2. Alter Checkout ist abgelaufen

  • Stripe synchronisieren gibt den Zustand stripe_checkout_expired zurück.
  • Danach kann ein neuer Checkout gestartet werden.

3. Stripe ist gebucht, Keygen aber fehlgeschlagen

  • billingProvider ist bereits stripe, aber provisioningState = failed.
  • In diesem Fall nicht noch einmal kaufen.
  • Stattdessen im Keygen-Bereich Keygen erneut synchronisieren verwenden.

4. Billing-Portal öffnet nicht

  • Das Portal steht nur bereit, wenn billingCustomerId vorhanden ist.
  • Wenn die UI statt Billing verwalten wieder Stripe synchronisieren zeigt, zuerst den Recovery-Lauf durchziehen.

5. Kündigung wurde in Stripe bestätigt, aber der Status bleibt unverändert

  • Bevorzugt die In-App-Aktion Abo kündigen verwenden. Sie setzt die Kündigung direkt in Stripe und liefert die neu reconciled Vereinslizenz zurück, ohne Portal-Redirect.
  • Wenn die Kündigung stattdessen im generischen Billing-Portal vorgenommen wurde und der Status danach unverändert bleibt, Stripe synchronisieren manuell starten.
  • Danach prüfen, ob accessState = cancel_scheduled und eine Restlaufzeit sichtbar sind.

6. Kündigung wurde zurückgenommen, aber TargetShot zeigt weiter Kündigung vorgemerkt

  • Bevorzugt direkt die In-App-Aktion Kündigung zurücknehmen verwenden. Sie aktualisiert Stripe und reconciled die Vereinslizenz sofort im selben Flow.
  • Wenn die Rücknahme außerhalb von TargetShot im generischen Billing-Portal erfolgt ist, ist return_url dort nur ein Rück-Link. Danach in TargetShot Stripe synchronisieren oder Neu laden ausführen.
  • Danach prüfen, ob accessState = active oder trial ist und cancelAtPeriodEnd nicht mehr gesetzt ist.

7. Checkout/Subscription an falschen Club gebunden

  • Fehlerbilder wie stripe_checkout_attached_to_other_club oder stripe_checkout_conflicts_with_existing_club_billing nicht lokal überschreiben.
  • Stripe-Referenzen und Club-Zuordnung auf Backend-/Stripe-Seite prüfen, bevor weitergeschrieben wird.

Staging-Smoke

  1. Auf staging mit einem Club-Admin einen Checkout starten.
  2. Stripe erfolgreich abschließen.
  3. Nach Return prüfen:
  4. Hauptaktion wechselt von Club Plus kaufen auf Billing verwalten oder kurzzeitig Stripe synchronisieren
  5. billingProvider = stripe
  6. billingCustomerId oder billingSubscriptionId sind gesetzt
  7. provisioningState ist provisioned oder zeigt klar einen Recovery-Bedarf
  8. Stripe synchronisieren einmal manuell ausführen und sicherstellen, dass kein zweiter Checkout erzeugt wird.
  9. Billing verwalten öffnen und verifizieren, dass das Portal für denselben Club aufgeht.
  10. Abo kündigen aus TargetShot starten und verifizieren:
  11. es erscheint nur die In-App-Bestätigung, kein Stripe-Redirect
  12. der Status zeigt Kündigung vorgemerkt bzw. Endet zum Laufzeitende
  13. Club Plus bleibt bis validUntil weiter aktiv
  14. Danach in TargetShot Kündigung zurücknehmen verwenden und verifizieren:
  15. der Status springt wieder auf Aktiv
  16. Kündigung vorgemerkt verschwindet
  17. Club Plus bleibt ohne neuen Checkout nutzbar
  18. Falls Keygen absichtlich gestört wurde, Keygen erneut synchronisieren testen.

Nicht über dieses Runbook lösen

  • Produktbegriff-/Plan-Mapping (Free, Pro, Club Plus)
  • allgemeine Notification-Probleme
  • mobile Push-/Inbox-Themen

Diese Themen liegen in separaten Sprint-Tasks.