SaaS · Abrechnung und CRM
Synchronisierung von Stripe Billing mit dem CRM: Abonnements, Zahlungen und MRR als Deals, ohne verlorene oder doppelte Ereignisse
Eine Marketplace-App, die Kunden, Abonnements und Zahlungen aus Stripe als Kontakte und Deals ins CRM spiegelt, gestützt auf ein Ledger signierter Webhooks, Row-Level Security pro Mandant und einen täglichen Abgleich.
- Branche
- SaaS · Abrechnung und CRM
- Technologien
- TypeScript · NestJS · PostgreSQL 16 + Drizzle
Ausgangslage
Unternehmen, die über Stripe abrechnen, wollten in ihrem CRM sehen, wer zahlt, mit welchem Plan und mit welchem Monatswert, ohne manuelle Nachträge. Stripe-Webhooks treffen nicht in der richtigen Reihenfolge ein, können doppelt ankommen und enthalten einen Snapshot, der bereits veraltet sein kann; eine Synchronisierung, die ihnen einfach vertraut, schreibt falsche Phasen und doppelte Deals. Zudem bedient die App viele Unternehmen gleichzeitig und verwaltet deren Stripe-Schlüssel, deshalb gehörten Isolation und der Umgang mit Secrets vom ersten Tag an zum Auftrag.
Lösung
Wir haben ein gehostetes Backend gebaut, das drei Prozesse aus einem Image betreibt: API, Worker und Scheduler. Der Eingang prüft die Stripe-Signatur auf dem unveränderten Request-Body, identifiziert den Mandanten ausschliesslich über das Endpoint-Token und antwortet mit 2xx, ohne Geschäftslogik auszuführen. Jedes Ereignis landet in einer einzigen Transaktion im Ledger und in der Warteschlange, mit einer Outbox, damit nichts verloren geht, falls Redis ausfällt. Vor jedem Schreibvorgang holt der Worker das aktuelle Objekt bei Stripe und verwirft veraltete Ereignisse; danach bildet er Abonnements auf Deals ab, mit Phase, MRR, Währung und Kontakt. Ein täglicher Abgleich erfasst alles, was die Webhooks verpasst haben.
Wie es zusammenhängt
- 01 Webhook prüfen
- 02 Ledger & Warteschlange
- 03 Aktuellen Stand abrufen
- 04 Auf Deal abbilden
- 05 Ins CRM schreiben
- 06 Täglich abgleichen
Was wir geliefert haben
- Webhook-Eingang mit Signaturprüfung auf dem Raw Body und Zuordnung des Mandanten über das Endpoint-Token
- Ereignis-Ledger mit transaktionalem Einreihen und einem Outbox-Drainer
- Warteschlangen mit Retry-Policy, Circuit Breaker und Sperren pro Objekt
- Abbildung von Abonnements auf Deals mit Phase, MRR (markiert, wenn unvollständig), Währung und Kontakten
- Deal-Suche, die ihren eigenen Treffer prüft, bevor sie schreibt
- Erstimport der Historie in fortsetzbaren Abschnitten sowie ein täglicher Abgleich
- Einrichtungsassistent in vier Schritten und 11 Sprachen, der die CRM-Felder und Pipeline-Phasen selbst anlegt
- Mehrere Stripe-Konten pro Benutzer, Jobs für die Datenaufbewahrung und Installationsstatistiken
- Rund 590 automatisierte Testfälle
Funktionen
- Row-Level Security in PostgreSQL auf jeder Geschäftstabelle; eindeutige Schlüssel enthalten den Mandanten und das Stripe-Konto
- Envelope Encryption für gespeicherte Secrets
- Felder und Phasen, die Personen im CRM von Hand setzen, werden nie überschrieben
- Fehler, die auch bei einer Wiederholung nicht gelingen können, gehen in den Status «Handlungsbedarf», statt endlos wiederholt zu werden
- Die Einrichtungsseite lädt keine Skripte von Drittanbietern, weil Nutzer dort einen Stripe-Schlüssel einfügen
- Tägliche Backups, geprüft mit Test-Wiederherstellungen
- Strukturierte Logs ohne Personendaten
Integrationen
- Stripe Billing API und Webhooks
- CRM-API des Kunden: Kontakte, Deals, Pipelines und benutzerdefinierte Felder
- App-Marketplace des Kunden
Technologien
Ergebnis
Auf einem gehosteten Staging-Server deployt und in der Abnahme mit einem Stripe-Konto im Live-Modus. Abnahmetests und ein Security-Review haben Mängel aufgezeigt; jene innerhalb der App sind behoben und erneut getestet. Die Veröffentlichung im Marketplace folgt nach der Abnahme.
Warum vor jedem Schreibvorgang bei Stripe nachfragen?
Ein Webhook sagt, dass sich etwas geändert hat, nicht, was jetzt gilt. Zwei Ereignisse zum selben Abonnement können in falscher Reihenfolge eintreffen, und das ältere würde den neueren Stand überschreiben. Deshalb liest die App aus dem Webhook nur die Ereignis-ID, den Typ und die Objekt-ID und holt das aktuelle Objekt bei Stripe, bevor sie etwas ins CRM schreibt. Das Ledger macht ein wiederholtes Ereignis wirkungslos, und der tägliche Abgleich schliesst jede Lücke, die eine verpasste Zustellung hinterlassen hat.
Projekt besprechen
Erzählen Sie uns von Ihrem Projekt