Keycloak × Stripe: Unsichtbares Marktplatz-Onboarding mit ereignisgesteuerter Architektur aufbauen
Das Onboarding auf Marktplätzen ist oft eine fragmentierte Erfahrung: Benutzer erstellen ein Konto, durchlaufen zusätzliche Registrierungsschritte und verknüpfen Zahlungsfunktionen manuell. Jeder zusätzliche Schritt erhöht die Reibung.
In diesem Artikel zeigen wir, wie wir Keycloak und Stripe Connect integriert haben, um große Teile des Onboarding-Prozesses zu automatisieren. Mithilfe einer ereignisgesteuerten Architektur, eines reaktiven Kotlin-Backends und zuverlässigem AMQP-Messaging werden neue Benutzer automatisch systemübergreifend bereitgestellt – für ein nahtloses Onboarding-Erlebnis ohne zusätzliche Benutzerinteraktion.
Warum dieser Ansatz? Unsere Kernprinzipien
Bevor wir in das „Wie“ eintauchen, lassen Sie uns das „Warum“ untersuchen. Unser Architekturdesign wurde von vier Schlüsselprinzipien für unseren Marktplatz geleitet:
Mühelose Benutzererfahrung (User Experience): Unser Ziel war es, Reibungspunkte zu eliminieren. Die Registrierung und die Vorbereitung auf Zahlungen sollten sich wie eine einzige, fließende und natürliche Aktion anfühlen.
Unerschütterliche Markenkonsistenz (Whitelabeling): Obwohl wir leistungsstarke Drittanbieter-Tools wie Stripe Connect nutzen, sollten unsere Nutzer immer das Gefühl haben, sich in der Umgebung unserer eigenen Plattform zu bewegen.
Unbeugsame Sicherheit: Betrachten Sie Keycloak als unseren vertrauenswürdigen Wächter – es ist unsere zentrale "Source of Truth" (Quelle der Wahrheit) für Identität und Autorisierung.
Architektonische Flexibilität: Wir haben ein modulares System aufgebaut, in dem Komponenten aktualisiert oder ausgetauscht werden können, ohne dass größere Generalüberholungen erforderlich sind.
Diese Kernprinzipien haben uns ganz natürlich zu einem ereignisgesteuerten (event-driven) Modell geführt, bei dem die identitätsbezogenen Aktionen von Keycloak nahtlos zahlungsspezifische Prozesse auslösen.
Das Gesamtbild: Eine detaillierte User Journey & Backend-Magie
Um den „unsichtbaren“ Aspekt wirklich zu verstehen, lassen Sie uns eine typische Benutzerregistrierung nachverfolgen und beobachten, wie die Frontend-Erfahrung und die Backend-Prozesse über drei verschiedene Phasen hinweg fehlerfrei miteinander tanzen.
Phase 1: Benutzerregistrierung & Event-Emission
In dieser ersten Phase interagieren die Benutzer mit dem Frontend und dem Keycloak-Authentifizierungssystem. Dies gipfelt darin, dass Keycloak das entscheidende USER_CREATED-Event ausgibt.
1graph TD2U[User] -->|"1- Initiates Signup"| F[Next.js Frontend]3F -->|2- Redirects for Authentication| KC["Keycloak (Auth/Register)"]4KC -->|3- User Completes Registration| F5F -->|4- Receives JWT & Logs In| U6KC -->|5- Emits USER_CREATED Event| W[Keycloak Webhook Plugin]7W -->|6- Publishes AMQP Message| MQ[AMQP Message Broker]

Erklärung:
Benutzer kommt an: Der Benutzer startet den Registrierungsprozess über unser Next.js-Frontend.
Auth-Weiterleitung: Das Frontend leitet sicher zu Keycloak für die Authentifizierung/Registrierung weiter.
Keycloak-Magie: Der Benutzer schließt seine Registrierung auf den Standardseiten von Keycloak ab.
Zurück zur App: Keycloak leitet den Benutzer mit einem JWT für den Login zurück zu unserem Frontend.
Keycloak-Event: Keycloak generiert intern ein
USER_CREATED-Event, wenn die Registrierung erfolgreich war.Webhook & AMQP: Unser Keycloak-Webhook-Plugin lauscht auf dieses Event und sendet es als AMQP-Nachricht an einen Broker.
Phase 2: Asynchrone Backend-Verarbeitung
Diese Phase beschreibt den Weg des Events vom Message Broker zum Payment Service sowie dessen Interaktion mit Stripe und unserer Datenbank, um das Zahlungskonto bereitzustellen.
// language: mermaid
// title: /Asynchronous-Backend-Processing
// copy: true
// lines: true
// maxLines: 10
graph TD
MQ[AMQP Message Broker] -->|7- Payment Service Consumes Event| PS["Payment Service (Spring Boot Kotlin)"] PS -->|8- Calls Stripe API to Create Account| S[Stripe]
S -->|Stripe Account ID| PS
PS -->|9- Saves KeycloakUser ID : StripeAccount ID Mapping| DB[DynamoDB]

Erklärung:
Service lauscht: Unser Payment Service überwacht und verarbeitet das
USER_CREATED-Event aus der AMQP-Warteschlange.Erstellung des Stripe-Kontos: Unter Verwendung der Benutzerinformationen aus dem Event erstellt der Payment Service über die Stripe-API ein neues Stripe-Connect-Konto.
Datenhaltung: Das System speichert die neue Stripe-Account-ID in DynamoDB und verknüpft sie direkt mit der Keycloak-User-ID.
Phase 3: Anschließende Einrichtung der Benutzerzahlungen
Diese letzte Phase zeigt, wie Benutzer ihre Zahlungsdaten über die Frontend-Oberfläche vervollständigen. Dies baut nahtlos auf den Vorarbeiten des Backends auf, um ein konsistentes Markenerlebnis zu gewährleisten.
1graph TD2U[User] -->|10- Navigates to Payment Setup Section| F[Next.js Frontend]3F -->|11- Frontend Requests Payment Status API Call| PS[Payment Service]4PS -->|12- Fetches Stripe Account ID| DB[DynamoDB]5DB -->|Stripe Account ID| PS6PS -->|Returns Stripe Account ID| F7F -->|13- Embeds Stripe Elements Guided Onboarding within UI| S[Stripe via Frontend]

Erklärung:
Benutzer erkundet & konfiguriert: Wenn er bereit ist, besucht der Benutzer den Bereich für die Zahlungseinrichtung in unserem Frontend.
Frontend prüft Status: Das Frontend sendet eine sichere API-Anfrage an den Payment Service, um den Status der Zahlungskonfiguration zu überprüfen.
Backend liefert: Der Payment Service ruft die zuvor erstellte Stripe-Account-ID aus der DynamoDB ab.
Geführtes Onboarding: Unter Verwendung der Stripe-Account-ID implementiert unser Next.js-Frontend Stripe Elements, um den Benutzer durch die verbleibenden Schritte (wie Bankverbindung und KYC) innerhalb unserer gebrandeten UI zu führen. Der Benutzer bleibt während des gesamten Prozesses in unserer Anwendung.
Dieser phasenweise Ansatz bedeutet: Wenn die Benutzer bereit sind, sich um die Zahlungen zu kümmern, ist der Großteil der Einrichtungsarbeit hinter den Kulissen bereits erledigt, was eine reibungslose und effiziente Erfahrung schafft.
Keycloaks Event-Superkraft: Die Webhook- und AMQP-Brücke
Der Schlüssel zu unserer Hintergrundmagie liegt in Keycloaks leistungsstarkem Event-System, das Benachrichtigungen für verschiedene Aktionen im Lebenszyklus eines Benutzers ausgibt. Das Keycloak-Webhook-Plugin ist so konfiguriert, dass es diese spezifischen Ereignisse erfasst.
Wenn ein Event wie USER_CREATED eintritt, führt das Plugin keinen direkten, blockierenden HTTP-Aufruf an unseren Payment Service aus. Stattdessen wandelt es die Event-Daten in eine Nachricht um und veröffentlicht sie auf einem AMQP-Broker (wie RabbitMQ).
Warum AMQP? Eine strategische Entscheidung für Robustheit:
Entkopplung: Keycloak läuft unabhängig, ohne die Netzwerkadresse oder den Verfügbarkeitsstatus des Payment Service kennen zu müssen.
Resilienz: Wenn der Payment Service ausfällt, warten die Nachrichten sicher im AMQP-Broker und werden automatisch verarbeitet, sobald der Dienst wieder läuft – es gehen keine Events verloren.
Skalierbarkeit: Mehrere Instanzen des Payment Service können aus derselben Warteschlange konsumieren, was die horizontale Skalierung extrem einfach macht.
Der grundlegende Ablauf für diese Event-Weiterleitung ist elegant und einfach:
1graph TD2KC[Keycloak: Event Occurs] --> Plugin[Webhook Plugin]3Plugin -- Publishes Event --> AMQP[AMQP Message Broker]4AMQP -- Delivers Message --> PS[Payment Service: AMQP Consumer]5PS --> Logic[Processes Event]

Automatisierung von Stripe Connect: Die Kernlogik
Da die Keycloak-Events zuverlässig über AMQP fließen, übernimmt unser Payment Service die Rolle des Orchestrators für die Verwaltung der Stripe-Connect-Konten.
Szenario 1: Benutzererstellung oder -aktualisierung
Wenn ein USER_CREATED-Event (oder ein USER_UPDATED-Event, falls wir Änderungen synchronisieren) eintrifft:
Der Payment Service empfängt die Event-Daten aus der AMQP-Warteschlange.
Er extrahiert die relevanten Benutzerdaten (wie die Keycloak-User-ID und die E-Mail-Adresse) aus dem Event-Payload.
Er ruft die Stripe-API auf, um ein neues Connect-Konto zu erstellen (in der Regel ein Express-Konto) und füllt die Informationen aus Keycloak und den Marktplatz-Standardeinstellungen vorab aus.
Nach erfolgreicher Erstellung speichert er die Stripe-Account-ID sicher in der DynamoDB, gemappt auf die Keycloak-User-ID.
Dieser optimierte Prozess sorgt für eine effiziente und nahtlose Integration:
1sequenceDiagram2 participant KPlugin as Keycloak Webhook via AMQP3 participant PaySvc as Payment Service4 participant StripeAPI as Stripe5 participant DB as DynamoDB6 KPlugin->>PaySvc: USER_CREATED Event7 activate PaySvc8 PaySvc->>StripeAPI: Create Connect Account (User Details)9 activate StripeAPI10 StripeAPI-->>PaySvc: Stripe Account ID11 deactivate StripeAPI12 PaySvc->>DB: Save (KeycloakUserID, StripeAccountID)13 activate DB14 DB-->>PaySvc: Confirmation15 deactivate DB16 deactivate PaySvc

Szenario 2: Benutzerlöschung
Wenn ein USER_DELETED-Event empfangen wird:
Der Payment Service fragt DynamoDB ab, um die entsprechende Stripe-Account-ID des Benutzers anhand seiner Keycloak-User-ID abzurufen.
Wenn ein Konto gefunden wird, ruft er die Stripe-API auf, um das Connect-Konto zu löschen oder zu deaktivieren (basierend auf Compliance-Anforderungen und Datenrückhalterichtlinien).
Schließlich entfernt er den Mapping-Eintrag aus der DynamoDB, um einen sauberen und konsistenten Zustand zu wahren.
Der Ablauf für die Löschung ist ebenso präzise:
1sequenceDiagram2 participant KPlugin as Keycloak Webhook via AMQP3 participant PaySvc as Payment Service4 participant StripeAPI as Stripe5 participant DB as DynamoDB6 KPlugin->>PaySvc: USER_DELETED Event7 activate PaySvc8 PaySvc->>DB: Get StripeAccountID for KeycloakUserID9 activate DB10 DB-->>PaySvc: Stripe Account ID (or null)11 deactivate DB12 alt Stripe Account ID Found13 PaySvc->>StripeAPI: Delete Connect Account (StripeAccountID)14 activate StripeAPI15 StripeAPI-->>PaySvc: Confirmation16 deactivate StripeAPI17 PaySvc->>DB: Delete Mapping (KeycloakUserID)18 activate DB19 DB-->>PaySvc: Confirmation20 deactivate DB21 end22 deactivate PaySvc

Unter der Haube: Der Payment Service (Spring Boot Kotlin)
Unser Payment Service ist eine Spring Boot-Anwendung, die in Kotlin geschrieben ist und Coroutines für effiziente asynchrone Operationen nutzt. Dieser nicht-blockierende Ansatz ist essenziell für die Verarbeitung von I/O-gebundenen Aufgaben wie AMQP-Messaging, DynamoDB-Zugriffen und Stripe-API-Aufrufen – was eine optimale Performance und Reaktionsfähigkeit garantiert.
AMQP-Event-Listener: Der dedizierte Consumer
Im Herzen unseres Dienstes überwacht der KeycloakEventListener die zugewiesene AMQP-Warteschlange auf eingehende
1@Component2class KeycloakEventListener(3 private val paymentAccountOrchestrator: PaymentAccountOrchestrator4) {5 @RabbitListener(queues = ["\\\\${app.amqp.keycloak-events-queue}"]) // Configured queue name6 suspend fun handleKeycloakEvent(eventMessage: KeycloakEventPayload) { // Assuming deserialized payload7 logger.info("Received Keycloak event: ${eventMessage.type} for user ${eventMessage.details.userId}")8 when (eventMessage.type) {9 "USER_CREATED" -> paymentAccountOrchestrator.createAccountForUser(eventMessage.details.userId)10 "USER_DELETED" -> paymentAccountOrchestrator.deleteAccountForUser(eventMessage.details.userId)11 // Handle USER_UPDATED if necessary for syncing profile changes12 else -> logger.warn("Unhandled Keycloak event type: ${eventMessage.type}")13 }14 }15}
Kern-Logik des Services (Vereinfachtes createAccountForUser): Der Konto-Alchemist
Diese Methode kapselt die wesentliche Logik für die Erstellung eines Stripe-Kontos, einschließlich einer wichtigen Idempotenzprüfung, um Duplikate zu verhindern:
1@Service2class PaymentAccountOrchestrator(3 private val stripeService: StripeService, // Robust wrapper for all Stripe API calls4 private val userRepository: UserRepository // Our DynamoDB repository for user-Stripe mappings5) {6 suspend fun createAccountForUser(keycloakUserId: String) {7 // Idempotency check: Crucial to avoid recreating existing accounts8 if (userRepository.findStripeAccountId(keycloakUserId) != null) {9 logger.info("Stripe account mapping already exists for Keycloak user: $keycloakUserId. Skipping creation.")10 return11 }12 // Build the request for an Express account with sensible defaults13 val accountCreationRequest = StripeAccountCreateRequest(14 type = "express",15 country = "DE", // Example default country (e.g., for a German marketplace)16 email = "user-$keycloakUserId@example.com" // Placeholder; ideally fetched from Keycloak user details17 // Add other required capabilities (e.g., card_payments, transfers) as needed18 )19 val stripeAccount = stripeService.createAccount(accountCreationRequest)20 userRepository.saveStripeMapping(keycloakUserId, stripeAccount.id)21 logger.info("Successfully created Stripe account ${stripeAccount.id} for Keycloak user $keycloakUserId.")22 }23 // ... Implement other core methods like deleteAccountForUser to complete the lifecycle24}
Die Frontend-Erfahrung: Whitelabeling in Aktion
Wie in der gesamten User Journey bereits hervorgehoben, wird der Endnutzer akribisch davor geschützt, rohe Stripe-Seiten zu sehen. Nach der initialen, stillen Kontoerstellung im Hintergrund passiert Folgendes:
Unser Next.js-Frontend ruft die Stripe-Account-ID des Benutzers sicher ab (über die geschützte API unseres Backends).
Es nutzt dann strategisch Stripe Elements oder andere eingebettete UIs, die von Stripe.js bereitgestellt werden, um alle weiteren erforderlichen Informationen zu sammeln (z. B. Bankdaten für Auszahlungen oder Identifikationsdokumente für die KYC/KYB-Compliance).
Entscheidend ist, dass dieser gesamte Datenerfassungsprozess innerhalb der UI unserer Anwendung stattfindet. Das bewahrt eine nahtlose Markenkonsistenz und bietet eine geführte, vertraute Benutzererfahrung.Dieser akribische Ansatz ist die Essenz unseres „Whitelabeling“-Ziels: die Nutzung der mächtigen Backend-Zahlungsverarbeitung von Stripe, ohne Kompromisse bei unserer sorgfältig gestalteten Frontend-User-Experience einzugehen.
Das Ergebnis: Nahtlos, sicher und flexibel
Unsere ereignisgesteuerte, entkoppelte Architektur erfüllt unsere ursprünglichen Designprinzipien:
Mühelose UX: Die Benutzerregistrierung löst die automatische Erstellung des Zahlungskontos aus, wodurch Reibungsverluste minimiert werden und eine reaktionsschnelle Plattform entsteht.
Markenkonsistenz: Das Frontend behält die vollständige Kontrolle über die Stripe-Interaktionspunkte, sodass alle Touchpoints des Nutzers innerhalb unserer gebrandeten UI verbleiben.
Robuste Sicherheit: Keycloak fungiert als zentraler Gatekeeper für das Identitäts- und Zugriffsmanagement, während alle sensiblen Zahlungsoperationen sicher auf der Serverseite abgewickelt werden.
Außergewöhnliche Flexibilität: Die AMQP-Brücke hält Keycloak und den Payment Service lose gekoppelt. Alle Stripe-Interaktionen sind im Payment Service gekapselt, was zukünftige Änderungen oder einen Wechsel des Anbieters vereinfacht.
Dieser Ansatz des „unsichtbaren Onboardings“ optimiert die erste Benutzererfahrung und sorgt dafür, dass sich unsere Plattform von Anfang an polierter, professioneller und intuitiver anfühlt.
Abschließende Gedanken
Seien wir ehrlich – das Verknüpfen von Identitätsmanagement mit Zahlungssystemen ist ein bisschen so, als würde man versuchen, einer Katze beizubringen, die Steuererklärung zu machen. Aber wir haben es geknackt! Indem wir Keycloak und unsere asynchrone Architektur ihren Tanz aufführen lassen (denken Sie an Fred Astaire trifft auf Distributed Computing), haben wir etwas erschaffen, das so reibungslos läuft, als würden Ihre Zahlungen von Ninja-Buchhaltern verarbeitet. Klar, das Ganze einzurichten hat ungefähr so viel Spaß gemacht, wie Code zu debuggen, der von einem koffeingetriebenen Eichhörnchen geschrieben wurde, aber die Ergebnisse sind es wert. Wir haben das, was leicht eine Erfahrung auf dem Niveau eines Straßenverkehrsamtes hätte werden können, in etwas so Unsichtbares verwandelt, dass Harry Potters Tarnumhang dagegen wie Amateurenwerk aussieht. Jetzt können Nutzer unserer Plattform schneller beitreten, als Sie „Blockchain“ sagen können – und das will was heißen!
Keywords