Xircuit Blog

Produkt-Updates, Entwickler-Logs und Neuigkeiten aus der Entwicklung von Xircuit.

Abrechnung, die trägt: Stripe-Plattform-Billing cover image

Abrechnung, die trägt: Stripe-Plattform-Billing


Abrechnung, die trägt: Stripe-Plattform-Billing

Bezahlung als Sinnbild für Abrechnung Foto: Words as Pictures · StockSnap (CC0 1.0), via Openverse

Irgendwann muss jede Plattform die unbequeme Frage beantworten, wie sie sich finanziert. Bei Xircuit war das lange ein Randthema, das ich vor mir hergeschoben habe, weil der Aufbau der eigentlichen Funktionen wichtiger schien. Diese Woche ließ sich die Frage nicht mehr aufschieben: Wer die Plattform ernsthaft nutzt, muss dafür bezahlen können, und zwar so unkompliziert, dass die Bezahlung nie der Grund ist, warum jemand abspringt.

Ich habe mir dafür bewusst Zeit genommen, weil Abrechnung eine dieser Komponenten ist, die man genau einmal richtig bauen sollte. Ein halbgares Billing-System rächt sich später mit doppelten Buchungen, verlorenen Kündigungen und Support-Tickets, die niemand lösen kann. Dieser Post beschreibt, wie das Plattform-Billing bei Xircuit jetzt funktioniert und welche Entscheidungen dahinterstecken.

Warum Stripe und ein Plattform-Modell

Die naheliegende Entscheidung war, Zahlungen nicht selbst abzuwickeln. Kartendaten, Compliance, wiederkehrende Abbuchungen, Steuersätze, gescheiterte Zahlungen mit Wiederholungslogik: Das ist ein eigenes Produkt, und es gibt bereits eines, das es gut macht. Xircuit rechnet Abonnements deshalb über Stripe ab, und Stripe hält alles, was mit dem eigentlichen Geldfluss zu tun hat.

Wichtiger als die Wahl des Anbieters war die Struktur. Xircuit bedient sehr unterschiedliche Branchen, vom Fitnessstudio über die Praxis bis zum Verein, und ich wollte nicht für jede davon ein eigenes Abrechnungsmodell pflegen. Das Plattform-Billing deckt daher alle Branchen mit demselben Fundament ab. Ein Produktkatalog, eine Abo-Logik, ein Satz an Zuständen, den jede Organisation durchläuft. Was sich zwischen den Branchen unterscheidet, ist der Funktionsumfang, nicht die Mechanik der Abrechnung.

Diese Einheitlichkeit ist mehr als eine Bequemlichkeit für mich als Entwickler. Sie bedeutet, dass jede Verbesserung an der Abrechnung sofort allen Branchen zugutekommt und dass ein Fehler, den ich an einer Stelle behebe, überall behoben ist. Ein pro Branche kopiertes Billing hätte genau das Gegenteil bedeutet: fünf leicht abweichende Varianten, von denen jede ihre eigenen Sonderfälle und ihre eigenen stillen Bugs mitbringt.

Webhooks als Quelle der Wahrheit

Der heikelste Teil eines jeden Stripe-Integrationsprojekts sind die Webhooks. Stripe teilt asynchron mit, was passiert ist: Ein Abonnement wurde angelegt, eine Zahlung ging durch, eine Karte wurde abgelehnt, ein Abo gekündigt. Diese Ereignisse sind die einzige verlässliche Quelle dafür, in welchem Zustand ein Konto wirklich ist. Wer stattdessen dem Redirect nach dem Checkout vertraut, baut auf Sand.

Ich habe die Webhook-Verarbeitung deshalb in einen dedizierten Dienst gelegt, statt sie irgendwo im Web-Frontend mitlaufen zu lassen. Das entkoppelt den Empfang der Ereignisse von der Nutzeroberfläche und passt zur übrigen Aspire-Topologie, in der jede Verantwortlichkeit ihren eigenen klar umrissenen Dienst bekommt. Der Dienst nimmt die Ereignisse entgegen, prüft die Signatur und verarbeitet sie im Hintergrund.

Entscheidend ist dabei die Idempotenz. Stripe garantiert nicht, dass ein Ereignis genau einmal ankommt; es kann dasselbe Ereignis mehrfach zustellen, etwa nach einem Timeout oder einem erneuten Versuch. Die Verarbeitung ist deshalb so gebaut, dass ein doppelt eintreffendes Ereignis nichts kaputt macht. Jedes Ereignis wird anhand seiner Identität erkannt, und was bereits verbucht wurde, wird kein zweites Mal verbucht. Das klingt unspektakulär, ist aber der Unterschied zwischen einem Billing-System, dem man vertrauen kann, und einem, das bei jedem Netzwerkschluckauf still doppelt abrechnet.

Eine Rechnung als Sinnbild für Abonnements Foto: Words as Pictures · StockSnap (CC0 1.0), via Openverse

Selbstverwaltung über das Stripe-Kundenportal

Sobald Geld regelmäßig fließt, entsteht ein zweites Problem: Menschen wollen ihre Zahlungsdaten ändern, ihr Abo umstellen oder kündigen, und sie wollen das tun, ohne eine E-Mail schreiben zu müssen. Jede dieser Interaktionen selbst zu bauen, wäre viel Aufwand für etwas, das Stripe bereits sauber löst.

Ich habe deshalb das Stripe-Kundenportal angebunden. Über einen einzigen Einstiegspunkt in Xircuit gelangt eine Organisation in ein von Stripe gehostetes Portal, in dem sie ihre Zahlungsmittel aktualisieren, vergangene Rechnungen einsehen und ihr Abonnement selbst verwalten kann. Was dort passiert, kommt über dieselben Webhooks wieder bei uns an, sodass der Zustand in Xircuit automatisch nachgeführt wird. Selbstverwaltung heißt hier also nicht, dass zwei Systeme auseinanderlaufen, sondern dass Stripe die Oberfläche stellt und Xircuit über die Ereignisse konsistent bleibt.

Funktionsumfang an den Abo-Status koppeln

Ein Abonnement ist nur dann sinnvoll, wenn der bezahlte Zustand tatsächlich einen Unterschied macht. Bei Xircuit ist der Funktionsumfang deshalb an den Abo-Status gekoppelt. Dieses Gating baut nicht auf einem eigenen Sonderweg auf, sondern auf der Feature-Flag-Infrastruktur, die ohnehin schon im System steckt und über die einzelne Fähigkeiten der Plattform an- und abgeschaltet werden.

Der Vorteil dieser Wiederverwendung ist, dass Gating und Feature-Steuerung dieselbe Sprache sprechen. Der Abo-Status entscheidet, welche Flags für eine Organisation greifen, und die Anwendung fragt an genau den Stellen, an denen sie schon vorher Fähigkeiten abgefragt hat. Es gibt keine zweite, parallele Logik, die man getrennt pflegen und testen müsste. Ändert sich der Status durch ein Stripe-Ereignis, verschiebt sich der verfügbare Funktionsumfang mit, ohne dass irgendwo manuell eingegriffen werden muss.

Bewusst noch im Testmodus

Ein Punkt, der mir wichtig ist, weil er leicht übersehen wird: In Produktion laufen aktuell bewusst die Stripe-TEST-Schlüssel. Die gesamte Kette steht, vom Checkout über die Webhooks bis zum Kundenportal, aber es wird noch kein echtes Geld bewegt. Das ist kein Versehen, sondern eine Entscheidung.

Ich möchte die Abrechnung erst unter realen Bedingungen beobachten, bevor sie tatsächlich abrechnet. Mit Testschlüsseln kann ich Abos anlegen, Zahlungen simulieren, gescheiterte Karten durchspielen und die Idempotenz der Webhooks unter Last prüfen, ohne dass ein Fehler jemandem echtes Geld kostet. Der Wechsel auf Live-Schlüssel ist deshalb bewusst eine eigene, spätere Entscheidung. Erst wenn ich sicher bin, dass jeder Zustandsübergang sauber sitzt, wird umgeschaltet. Bis dahin ist der TEST-Modus kein Provisorium, sondern eine Sicherheitsleine.

Was ich aus dieser Woche mitnehme

Rückblickend war das Aufwendige an dieser Woche nicht der glückliche Pfad, in dem jemand ein Abo abschließt und alles funktioniert. Aufwendig waren die Ränder: das doppelt zugestellte Ereignis, die abgelehnte Karte, die Kündigung, die im Portal ausgelöst und in Xircuit nachvollzogen werden muss. Genau diese Ränder entscheiden aber darüber, ob ein Billing-System trägt oder nur so lange hält, bis es das erste Mal ernst wird.

Dass die Abrechnung branchenübergreifend auf demselben Fundament steht, dass Webhooks idempotent in einem eigenen Dienst laufen, dass die Selbstverwaltung an Stripe delegiert ist und das Gating auf der vorhandenen Feature-Flag-Infrastruktur aufsetzt, ergibt zusammen ein System, das ich guten Gewissens scharf schalten kann, sobald der Zeitpunkt stimmt.

Was kommt als Nächstes?

Nächste Woche: wie Organisationen ihre eigenen Mitglieder abrechnen — über Stripe Connect.


Kommentare

Noch keine Kommentare. Teilen Sie als Erste(r) Ihre Gedanken!

Kommentar hinterlassen