Redirect-Flow, Authorization vs. Direct Sale, Webhooks, Refunds – was Entwickler bei der Wero-Integration wirklich wissen müssen
SerieWero: Europas digitaler Bezahldienst
Teil 4 von 5
Im dritten Teil dieser Serie ging es um PSP-Wahl und Code-Einstieg. Dieser Artikel geht tiefer: Wie sieht der technische Checkout-Flow wirklich aus? Welche Operationen unterstützt welcher PSP – und welche nicht? Wo lauern die Stolperfallen, die kein Marketing-Dokument erwähnt?
Architektur in 30 Sekunden
Wero ist ein Redirect-Zahlverfahren. Der Kern ist überall gleich: Payment anlegen, Redirect, Bestätigung, Webhook. Was sich je nach PSP und Gerät unterscheidet, ist der konkrete Wero-Flow-Schritt.
Die eine Regel, die alles bestimmt
Die Return-URL ist nur UX. Der Webhook ist die Wahrheit.
Der Redirect zurück zum Shop ist nicht garantiert. Nutzer schließen den Browser, verlieren die Verbindung, navigieren weg. Ein System, das den Zahlungsstatus aus dem Return-Redirect ableitet, produziert stille Fehler: bezahlte Bestellungen, die nicht als bezahlt markiert werden – oder schlimmer, umgekehrt.
Die einzige verlässliche Statusquelle ist der Webhook vom PSP. Die Bestellung wird erst als bezahlt markiert, wenn der Webhook eintrifft und die Signatur valide ist.
Der Wero-Flow im Detail
Desktop: QR-Code-Flow
Auf Desktop zeigt das Wero-Portal einen QR-Code. Der Kunde scannt ihn mit dem Smartphone und bestätigt die Zahlung in der Banking-App. Das setzt ein zweites Gerät voraus – ein UX-Bruch, den du mit einem kurzen Hinweis im Checkout abfangen solltest: „Bitte halten Sie Ihr Smartphone bereit.”
Mobile: Redirect-Flow je nach PSP
Auf dem Smartphone führt der Redirect in den Wero-Flow – aber wie der genau aussieht, hängt vom PSP und Setup ab: Je nach Anbieter kann sich eine Banking-App per Deep-Link öffnen, ein Browser-Flow starten oder ein alphanumerischer Wero-Code angezeigt werden, den der Nutzer in seiner Banking-App eingibt. Nicht jeder PSP implementiert das gleich. Das Ergebnis ist dasselbe – der Unterschied liegt im Komfort.
Payment-States: nicht binär denken
Der kritischste Denkfehler bei Redirect-Zahlarten: in „bezahlt” und „nicht bezahlt” zu denken. In der Praxis gibt es mindestens diese Zustände:
| Status | Bedeutung | Aktion im Shop |
|---|---|---|
pending | Payment angelegt, Kunde noch unterwegs | Bestellung reserviert, nicht bestätigt |
authorized | Betrag reserviert, noch nicht gebucht | Warten auf Capture |
captured / paid | Geld gebucht | Bestellung als bezahlt markieren |
failed | Zahlung fehlgeschlagen | Kunde informieren, Retry anbieten |
expired | Timeout – Kunde hat nicht bestätigt | Bestellung stornieren |
cancelled | Kunde hat abgebrochen | Bestellung stornieren |
refunded | Rückerstattung gebucht | Buchung stornieren |
Ein System, das nur success und failed kennt, ist nicht produktionsreif. Gerade pending und expired sorgen für stille Fehler, wenn sie nicht explizit behandelt werden.
Capability-Matrix: Was welcher PSP für Wero unterstützt
Nicht jeder PSP unterstützt dieselben Operationen. Das ist einer der wichtigsten Unterschiede – und einer der am wenigsten dokumentierten.
| Funktion | PAYONE | Worldline | Unzer | Stripe |
|---|---|---|---|---|
| Charge (Direct Sale) | ✓ | ✓ | ✓ | ✓ |
| Authorize | ✓ | ✓ | ✗ | ✗ |
| Manual Capture | ✓ | ✓ | ✗ | ✗ |
| Partial Refund | ✓ | ✓ | ✓ | ✓ |
| Multiple Refunds | ✓ | ✓ | ✓ | ✓ |
| Recurring / Subscriptions | In Planung | In Planung | ✗ | ✗ |
| Dispute-Support (PSP-seitig) | Ja | Ja | Ja | ✗ |
Das Authorization-Fenster bei PAYONE und Worldline beträgt 7–10 Tage. Danach verfällt die Reservierung automatisch. Für Backorder-Szenarien mit langer Lieferzeit ist Wero im Auth-Modus daher nicht geeignet.
Die PSP-APIs im Detail
PAYONE Commerce Platform (JSON-API)
PAYONE betreibt zwei API-Systeme. Die neue Commerce Platform API basiert auf der Worldline-Plattform und nutzt JSON. Wero hat die paymentProductId 900.
Endpunkte:
- Test:
https://payment.preprod.payone.com - Live:
https://payment.payone.com
Authentifizierung: HMAC-SHA256 mit API Key und API Secret.
Authorization: GCS v1HMAC:{API_Key}:{base64-encoded-signature}
Payment erstellen (Direct Sale):
{
"order": {
"amountOfMoney": { "currencyCode": "EUR", "amount": 4999 },
"references": { "merchantReference": "order-12345", "descriptor": "ShopName" }
},
"redirectPaymentMethodSpecificInput": {
"paymentProductId": 900,
"requiresApproval": false
}
}
Payment erstellen (Authorization + Capture):
{
"order": {
"amountOfMoney": { "currencyCode": "EUR", "amount": 4999 },
"references": { "merchantReference": "order-12345" }
},
"redirectPaymentMethodSpecificInput": {
"paymentProductId": 900,
"requiresApproval": true,
"paymentProduct900SpecificInput": { "captureTrigger": "Shipping" }
}
}
Die captureTrigger-Werte bestimmen, wann die Buchung erfolgt:
| Wert | Anwendungsfall |
|---|---|
Shipping | Physische Ware, Capture bei Versand |
Delivery | Capture bei Zustellung |
Availability | Digitale Güter |
ServiceFulfilment | Dienstleistungen |
Other | Sonstige |
Refund:
{
"amountOfMoney": { "currencyCode": "EUR", "amount": 4999 },
"references": { "merchantReference": "refund-12345" },
"refundRedirectPaymentMethodSpecificInput": {
"refundRedirectPaymentProduct900SpecificInput": {
"refundReason": "ReturnedGoods"
}
}
}
refundReason ist Pflicht. Erlaubte Codes: ReturnedGoods, WrongAmountCorrection, PreDisputeRefund, SubscriptionRefund, ServiceLateCancellation, Other. Ohne den Parameter schlägt der Call fehl.
PAYONE Server API (Legacy, URL-encoded)
Die ältere Server API nutzt URL-encoded POST-Requests. Wero wird über clearingtype=wlt und wallettype=WRO identifiziert.
request=preauthorization
clearingtype=wlt
wallettype=WRO
mode=test
amount=10000
currency=EUR
reference=order-12345
successurl=https://shop.example.com/success
errorurl=https://shop.example.com/error
backurl=https://shop.example.com/back
Unzer REST API
Unzer nutzt einen zweistufigen Ansatz: Payment-Type anlegen, dann Charge ausführen. Authorize ist bei Unzer für Wero nicht verfügbar.
Authentifizierung: HTTP Basic Auth mit Private Key als Username (s-priv-xxxxxxxxxx), leeres Passwort.
Schritt 1 – Wero Payment Type anlegen:
POST /v1/types/wero
Gibt eine ID wie s-wro-xxxxxxxxxx zurück.
Schritt 2 – Charge (Direct Sale):
{
"amount": "49.99",
"currency": "EUR",
"returnUrl": "https://shop.example.com/return",
"orderId": "order-12345",
"resources": { "typeId": "s-wro-xxxxxxxxxx" }
}
Refund:
POST /v1/payments/{paymentId}/charges/{chargeId}/cancels
{ "amount": "20.00", "paymentReference": "Refund for order 12345" }
Chargeback: Unzer unterstützt Chargeback-Handling über sein Dispute-System – im Gegensatz zu Stripe.
Stripe
Wer bereits Stripe nutzt, hat es am einfachsten: Wero im Dashboard aktivieren, keine Code-Änderung bei Nutzung von Stripe Checkout oder Payment Element.
const session = await stripe.checkout.sessions.create({
payment_method_types: ['wero'],
line_items: [{
price_data: {
currency: 'eur',
product_data: { name: 'Bestellung #456' },
unit_amount: 2990,
},
quantity: 1,
}],
mode: 'payment',
success_url: `${BASE_URL}/success?session_id={CHECKOUT_SESSION_ID}`, // nur UX
cancel_url: `${BASE_URL}/cancel`,
});
Bei automatic_payment_methods erscheint Wero automatisch für deutsche Kunden in EUR.
Einschränkungen bei Stripe – wichtig:
- Kein Manual Capture – Wero bei Stripe ist nur als Direct Sale verfügbar
- Kein Dispute-Support über das normale Stripe-Dispute-System – Konflikte werden außerhalb des Stripe-Rahmens abgewickelt
- Keine Subscriptions mit Wero
- Express Checkout Element unterstützt kein Wero
- Höhere Gebühren als PAYONE oder VR Payment
Worldline Direct API
Die Worldline Direct API ist nahezu identisch mit der PAYONE Commerce Platform API – beide basieren auf derselben Plattform. paymentProductId für Wero: ebenfalls 900.
Endpunkte:
- Test:
https://payment.preprod.direct.worldline-solutions.com - Live:
https://payment.direct.worldline-solutions.com
| Operation | Methode | Pfad |
|---|---|---|
| Payment erstellen | POST | /v2/{PSPID}/payments |
| Hosted Checkout | POST | /v2/{PSPID}/hostedcheckouts |
| Payment-Details | GET | /v2/{PSPID}/payments/{paymentId} |
| Capture | POST | /v2/{PSPID}/payments/{paymentId}/approve |
| Cancel | POST | /v2/{PSPID}/payments/{paymentId}/cancel |
| Refund | POST | /v2/{PSPID}/payments/{paymentId}/refund |
JSON-Strukturen für Payment, Capture und Refund sind identisch mit der PAYONE Commerce Platform API. Server-SDKs für Java, .NET, Python, Node.js, PHP und Ruby verfügbar.
Webhooks: Signaturen, Idempotenz und Retries
Signaturprüfung pro PSP
PAYONE Commerce Platform:
- Algorithmus: HMAC-SHA-512
- Event-Types:
payment.captured,payment.rejected,payment.refunded,payment.cancelled - Retry-Schedule: 10min, 1h, 2h, 8h, 24h (5 Retries)
PAYONE Legacy (TransactionStatus):
- Prüfung:
key-Parameter muss dem MD5-Hash des Portal Keys entsprechen - Format: URL-encoded POST
- Erwartete Antwort: exakt
TSOK(4 Zeichen, kein HTML, kein Whitespace) - Timeout: 10 Sekunden
Stripe:
- Algorithmus: HMAC-SHA256
- Header:
Stripe-Signature(Format:t={timestamp},v1={signature}) - Replay-Schutz durch Timestamp-Toleranz (Standard: 300s)
const event = stripe.webhooks.constructEvent(
requestBody,
req.headers['stripe-signature'],
endpointSecret // whsec_...
);
Worldline Direct:
- Algorithmus: HMAC-SHA256
- Headers:
X-GCS-Signature(Base64),X-GCS-KeyId - Endpoint-Verifizierung: GET-Request mit
X-GCS-Webhooks-Endpoint-Verification-Header muss als Plain Text zurückgegeben werden
Idempotenz: konkret umgesetzt
PSPs senden Webhooks im Fehlerfall mehrfach – das ist kein Bug, sondern At-least-once-Delivery. Ohne Idempotenz können Bestellungen doppelt als bezahlt markiert werden. Die Lösung: jede Event-ID persistieren und vor der Verarbeitung prüfen.
State-Transitions dürfen nur in erlaubter Richtung laufen: pending → paid ist gültig, paid → pending nicht. Implementiere das als Zustandsmaschine, nicht als freie Zustandsmutation.
app.post('/webhooks/wero', verifyPSPSignature, async (req, res) => {
const { id: eventId, status, reference, amount } = req.body;
// Idempotenz: Event bereits verarbeitet?
if (await isEventProcessed(eventId)) {
return res.sendStatus(200);
}
switch (status) {
case 'CAPTURED':
case 'PAID':
await transitionOrder(reference, 'paid'); // erlaubte Transition prüfen
await markEventProcessed(eventId);
break;
case 'CANCELLED':
case 'EXPIRED':
case 'REJECTED':
await transitionOrder(reference, 'failed', status);
await markEventProcessed(eventId);
break;
case 'REFUNDED':
await processRefund(reference, amount);
await markEventProcessed(eventId);
break;
default:
logger.warn({ eventId, status }, 'Unbekannter Wero-Status');
}
res.sendStatus(200);
});
Was du monitoren musst
Der Unterschied zwischen „funktioniert im Demo-Flow” und „läuft im echten Shop” ist Observability:
- Webhook-Signaturfehler – sofortiger Alert, kein normaler Betrieb
- Webhook-Latenz – wenn der PSP Stunden braucht für einen Retry
- Offene
pending-Zahlungen – cron-Job, der altepending-States aufräumt - Redirect-Abbrüche – Checkout-Funnel tracken, Wero-Abbruchrate vs. andere Methoden
- Capture-Timeouts bei Auth-Flows – Authorization-Fenster (7–10 Tage) per Job überwachen
- Refund-Fehler – fehlgeschlagene
refundReason-Calls - Doppelverarbeitung – Alarm wenn dieselbe Order zweimal den Status
paidbekommt
Wero in Shop-Systemen
Shopware 6
| PSP | Plugin | Wero seit | Hinweis |
|---|---|---|---|
| PAYONE | payone-gmbh/shopware-6 | v7.1.0 (Dez 2024) | Composer-Install |
| Unzer | unzerdev/shopware6 | v7.1.3 | Unzer Private Key konfigurieren |
| Mollie | Shopware Store Plugin | Aktiv | Wero im Mollie Dashboard aktivieren |
| Computop | FATCHIP Payment Connector | Über Paygate | Kontakt zu Computop nötig |
WooCommerce
| PSP | Plugin | Hinweis |
|---|---|---|
| Mollie | mollie-payments-for-woocommerce | Wero per Checkbox aktivierbar |
| Stripe | WooCommerce Stripe Plugin | Wero bei automatic_payment_methods automatisch |
| PAYONE | WooCommerce Integration | Server API mit clearingtype=wlt |
| Pronamic Pay | Multi-PSP-Plugin | Wero-Support vorhanden |
Shopify
Hier gilt es, zwei Dinge zu trennen:
iDEAL | Wero (Niederlande, Shopify Payments): In den Niederlanden migriert iDEAL seit Januar 2026 zu Wero. Shopify Payments unterstützt diese lokale Zahlungsmethode direkt – allerdings gebunden an NL-Händler, EUR und die iDEAL-Wero-Infrastruktur. Das ist ein Sonderfall der niederländischen Migration, kein allgemeines Wero-Feature für Shopify.
Wero für andere Märkte (DE, BE, FR) via Shopify: Shopify Payments selbst unterstützt kein allgemeines Wero. Die Integration läuft über Drittanbieter:
- CartDNA – Shopify Payment App für Wero in DE, FR, BE. Refunds inklusive. Erfordert lokale Geschäftseinheit im Zielmarkt.
- Stripe – wenn dein Shopify-Store Stripe als Payment-Backend nutzt, kann Wero über Dynamic Payment Methods erscheinen.
Magento / Adobe Commerce
| PSP | Extension |
|---|---|
| PAYONE | payone-gmbh/magento-2 |
| Worldline | Adobe Commerce Marketplace |
| Mollie | Magento 2 Plugin |
| Computop | Packagist |
Headless / Custom
Bei Headless-Shops integrierst du direkt gegen die PSP-REST-API. Backend sendet CreatePayment, PSP gibt redirectUrl, Frontend leitet weiter, Webhook liefert definitiven Status. Kein SDK nötig – ein HTTP-Client reicht.
PSP-Abdeckung im Überblick
| PSP | Shopware 6 | WooCommerce | Shopify | Magento 2 | Direct API |
|---|---|---|---|---|---|
| PAYONE | Ab v7.1.0 | Ja | Nein | Ja | Server API + Commerce Platform |
| Unzer | Ab v7.1.3 | Über Plugins | Geplant | Geplant | REST API |
| Worldline | Über Saferpay | Über Plugins | Nein | Marketplace | Direct API v2 |
| Mollie | Ja | Ja | Über Mollie App | Ja | REST API |
| Stripe | Über Stripe Plugin | Ja | Via Dynamic PM | Über Stripe Module | PaymentIntent API |
| Computop | FATCHIP Plugin | Über Paygate | Nein | FATCHIP Plugin | Paygate API |
| Adyen | Über Adyen Plugin | Über Adyen Plugin | Über Adyen App | Über Adyen Module | iDEAL-Wero-Migration |
iDEAL-Wero-Transition: Exkurs für Adyen-Nutzer
Adyen ist kein allgemeiner Wero-PSP, sondern der Hauptanbieter für die niederländische iDEAL-Wero-Migration. Bestehende iDEAL-Checkout-Seiten mussten zwischen dem 29. Januar 2026 und 31. März 2026 auf „iDEAL | Wero” umgestellt werden – Co-Branding, neues Logo, neue API-Parameter. Wer iDEAL bereits über Adyen nutzt, bekommt Wero als technisches Upgrade; die API-Grundstruktur bleibt weitgehend gleich.
Sandbox und Testen
Die Sandbox bildet den Redirect-Flow gut ab – aber nicht alle Realweltprobleme. Was die Sandbox nicht zuverlässig abbildet: eine nicht installierte Banking-App, echte Deep-Link-Varianten je nach Betriebssystem, Device-Wechsel-Timing und echte Bankreaktionen auf Grenzfälle. Plane Zeit für Tests im Production-ähnlichen Staging ein.
PAYONE Sandbox: Login unter https://portal.preprod.payone.com, Acquirer „Simulation_APM”, Wero aktivieren. Im Test-Modus leitet die PSP-API auf einen Wero-Simulator weiter, der Approve und Decline ermöglicht.
Stripe Sandbox: Standard-Test-Keys (sk_test_...) reichen. Wero funktioniert in Stripes normalem Testmodus; der Flow ist nahezu identisch mit Produktion – der nächste Testumgebung an der Realität.
Unzer Sandbox: Sandbox-Keys erkennt man am Prefix s-priv-. Testresponse-Code: COR.000.100.112.
Worldline Sandbox: https://payment.preprod.direct.worldline-solutions.com, Keys im Merchant Portal (Test-Environment). Teilt sich den Wero-Simulator mit PAYONE.
Was du testen solltest:
- Desktop-QR-Flow und Mobile-Redirect-Flow getrennt
- Webhook-Empfang mit allen relevanten Status
- Fehlerszenarien: Kunde bricht ab, Timeout, App nicht installiert
- Refund: Teil-Refund und Voll-Refund
- Auth + Capture (wo unterstützt): Autorisieren, dann capturen
- Idempotenz: denselben Webhook zweimal senden, kein Doppel-Update
Gebühren und Chargebacks
Gebührenvergleich
| Zahlart | Typische Gebühr |
|---|---|
| Wero (PAYONE/VR Payment) | 0,1–0,5 % |
| Wero (Stripe) | ca. 1,1–1,4 % + Fix |
| Kreditkarte | 1,5–3,0 % |
| PayPal | ca. 1,6–2,99 % + Fix |
Bei PAYONE oder VR Payment spart Wero gegenüber Kreditkarten 75–80 % an Transaktionskosten. Bei Stripe schmilzt dieser Vorteil.
Chargebacks und Disputes
Das Chargeback-Modell unterscheidet sich je nach PSP:
PAYONE und Worldline: Dispute-Handling ist Teil der PSP-Infrastruktur. Als Händler bekommst du eine Benachrichtigung und hast 24–72 Stunden, um Nachweise zu liefern oder freiwillig zurückzuerstatten.
Unzer: Chargeback-Handling vorhanden – Konflikte laufen über das Unzer-Dispute-System.
Stripe: Stripe unterstützt für Wero kein standardmäßiges Dispute-Handling. Das bedeutet nicht, dass es keine Konflikte geben kann – aber das bekannte Stripe-Dispute-System greift bei Wero nicht. Konfliktfälle sind außerhalb des Stripe-Rahmens zu klären.
Das Grundprinzip bei allen PSPs: Wero ist eine SEPA-Instant-Zahlung, kein klassisches Kartenmodell. Es gibt keinen automatischen Chargeback wie bei Visa oder Mastercard. Rückerstattungen müssen Händler aktiv anstoßen.
Technische Grenzen – Stand April 2026
- Nur EUR. Keine Fremdwährungen.
- Keine Recurring Payments. Abos und wiederkehrende Zahlungen in Planung, noch nicht live.
- Redirect-Zahlverfahren. Wero ist aus Kundensicht ein Redirect; die Einbindung kann je nach PSP über gehostete Checkout-Seiten oder eingebettete Payment-UI des PSP erfolgen – aber der Wero-Flow selbst läuft immer auf dem Wero-Portal.
- Geografisch begrenzt. E-Commerce live in Deutschland, Belgien und Frankreich. Luxemburg seit Mitte 2025 aktiv. Niederlande: iDEAL-Migration läuft seit Januar 2026. NFC an POS-Terminals auf 2027 verschoben – QR-Code-Zahlungen im stationären Handel kommen 2026.
- Authorization-Fenster begrenzt. 7–10 Tage zwischen Auth und Capture. Nur bei PAYONE und Worldline verfügbar, nicht bei Stripe oder Unzer.
- Stripe: eingeschränkte Capabilities. Kein Manual Capture, kein Dispute-Support – wichtig wenn du die PSP-Wahl noch nicht getroffen hast.
Checkliste für die Integration
- PSP wählen – Capabilities-Matrix prüfen (Auth/Capture, Dispute-Support, Gebühren)
- Sandbox einrichten – Testumgebung, Zugänge beim PSP anfragen
- State Machine implementieren – alle Status behandeln, nicht nur
paid - Webhook-Endpunkt – mit Signaturprüfung und idempotenter Verarbeitung
- Return-URL – nur für UX nutzen, niemals für Zahlungsbestätigung
- Auth vs. Direct Sale entscheiden – abhängig vom Liefermodell und PSP-Support
- Refund-Logik – Reason-Codes nicht vergessen (PAYONE/Worldline), teilweise ohne Reason (Unzer/Stripe)
- Monitoring – Webhook-Fehler, Pending-Timeouts, Capture-Deadlines
- Checkout-Hinweis – für Desktop-Nutzer „Smartphone bereithalten”
- Testen – Desktop-QR, Mobile-Flow, alle Fehlerfälle, Idempotenz
- Live schalten – API-Keys auf Production, erste Zahlungen buchen sofort auf Girokonto
Einordnung
Der Grundflow ist bekannt und technisch beherrschbar. Die eigentliche Komplexität steckt nicht im Redirect selbst, sondern in der Statusverarbeitung, den Fehlerfällen, den PSP-spezifischen Capabilities und stabilem Monitoring.
Wer bereits einen PSP nutzt und dessen Plugin hat, kann Wero technisch in wenigen Stunden aktivieren – organisatorisch hängt das aber am PSP-Onboarding, an Vertragsfreischaltung und Sandbox-Tests. Wer von Null startet, plant realistisch eine Woche.
Der wichtigste Unterschied zwischen PSPs ist nicht der API-Stil, sondern was sie für Wero unterstützen: Authorize und Manual Capture bei PAYONE und Worldline, Direct-Sale-only bei Stripe und Unzer. Wer einen Auth+Capture-Flow braucht – zum Beispiel für physische Ware mit variablem Versanddatum – muss das bei der PSP-Wahl berücksichtigen.
Und mit der iDEAL-Migration in den Niederlanden wird Wero bald auch dort Standard – wer jetzt integriert, ist vorbereitet.
Im fünften Teil geht es um Kosten, Conversion und die Frage, wann Wero für einen Shop wirklich lohnenswert ist.