App "ShopwarePayments" did not provide checkout gateway response: Ursache finden in Shopware 6
Die Meldung steht im Shopware-Log, meistens mehrfach am Tag, und sie verrät fast nichts. Kein Stacktrace, kein Kontext, nur zwei leere Klammern am Ende. Mal merkt im Checkout niemand etwas, mal fehlen Zahlarten, mal dauert die Bestellseite auffällig lange. Genau dieses „mal so, mal so“ haben wir in einem Kundenshop gesehen.
Vorweg: Für diesen Fall haben wir noch keinen bestätigten Fix. Der Artikel ist deshalb eine Diagnose-Anleitung. Er erklärt, was im Core passiert, warum die Meldung so leer ist und wo die echte Fehlermeldung steht. Sobald die Ursache in unserem Fall feststeht, ergänzen wir sie hier.
Die Fehlermeldung
app.ERROR: App "ShopwarePayments" did not provide checkout gateway response [] []
Was dahintersteckt
Seit Shopware 6.6.3.0 gibt es das Checkout Gateway. Apps können darüber im Checkout mitentscheiden, zum Beispiel Zahl- oder Versandarten ausblenden oder Warenkorbfehler setzen. Dafür trägt eine App im manifest.xml eine URL ein, und Shopware schickt bei jedem Checkout-Schritt einen POST mit Warenkorb, SalesChannelContext und den verfügbaren Zahl- und Versandarten an den App-Server. Shopware Payments ist so eine App, deshalb taucht ihr technischer Name ShopwarePayments in der Meldung auf.
Aufgerufen wird das Gateway an mehreren Stellen: beim Laden von Warenkorb- und Confirm-Seite, bei der Versandkostenberechnung, beim Abschicken der Bestellung (CartOrderRoute) und beim Ändern der Zahlart einer bestehenden Bestellung. Wer eine Headless-Storefront betreibt, kennt außerdem die Store-API-Route /store-api/checkout/gateway.
Die Meldung selbst kommt aus AppCheckoutGateway::process(). Der Ablauf, gekürzt aus dem Core:
// src/Core/Framework/App/Checkout/Payload/AppCheckoutGatewayPayloadService.php
try {
$response = $this->client->post($url, $optionRequest->jsonSerialize());
// ...
} catch (GuzzleException $e) {
$this->logger->logOrThrowException($e); // 1. Log-Eintrag: die echte Ursache
return null;
}
// src/Core/Framework/App/Checkout/Gateway/AppCheckoutGateway.php
if (!$appResponse) {
$this->logger->logOrThrowException(
CheckoutGatewayException::emptyAppResponse($app->getName()) // 2. Log-Eintrag: unsere Meldung
);
return;
}
„Did not provide checkout gateway response“ heißt also nicht, dass die App eine leere Antwort geschickt hat. Es heißt: Der Request an den App-Server ist gescheitert, egal warum. Die Meldung ist nur die Folge.
Die leeren [] [] erklären sich auch. Der ExceptionLogger schreibt nur $e->getMessage() ins Log, ohne Kontext und ohne Trace. Deshalb sieht die Zeile so nackt aus.
Und das wechselhafte Verhalten? Auch das steckt im ExceptionLogger. Im prod-Environment wird nur geloggt, der Checkout läuft weiter, nur eben ohne die Anpassungen der App für diesen Request. Welche das bei Shopware Payments konkret sind, legt Shopware nicht offen. Läuft der Shop dagegen mit APP_ENV=dev oder ist LOGGER_ENFORCE_THROW_EXCEPTION=1 gesetzt, wird die Exception geworfen, und der Checkout bricht mit einem 400er ab. Eine Staging-Instanz kann sich also ganz anders verhalten als Live.
Dazu kommt das Timing. Der HTTP-Client für Apps hat im Core einen connect_timeout von 1 Sekunde und einen timeout von 5 Sekunden. Hängt der App-Server, kann jeder Gateway-Aufruf bis zu fünf Sekunden kosten. Bei Warenkorb, Confirm und Bestellabschluss summiert sich das spürbar.
Prüfen, was wirklich schiefgeht
Der wichtigste Schritt: Schau dir die Zeile direkt davor an. Dort steht die Guzzle-Exception mit der eigentlichen Ursache.
grep -h -B1 'did not provide checkout gateway response' var/log/prod-*.log | tail -n 20
Je nachdem, was dort auftaucht, liegt der Fall woanders:
cURL error 28: Operation timed out ...: Der App-Server antwortet zu langsam oder gar nicht innerhalb der fünf Sekunden.cURL error 6odercURL error 7: DNS oder Verbindung vom Webserver nach außen klappt nicht. Bei manchen Hostern blockiert eine Firewall ausgehende Requests, oder ein Proxy fehlt.Could not verify the authenticity of the response: Die Antwort kam an, aber die Signatur passt nicht. Shopware prüft Antworten von Gateway-Requests mit dem App-Secret.Server error: ... 5xxoderClient error: ... 401: Der App-Server lehnt den Request ab oder hat selbst ein Problem.
Welche Gateway-URL hinterlegt ist, siehst du direkt in der Datenbank:
SELECT name, active, checkout_gateway_url
FROM app
WHERE checkout_gateway_url IS NOT NULL;
Ob der Server die URL überhaupt erreicht, testest du vom Webserver aus (nicht vom eigenen Rechner):
curl -sS -o /dev/null -w '%{http_code} %{time_total}s\n' -X POST '<checkout_gateway_url aus der Tabelle>'
Ein 401 oder 400 ist hier ein gutes Zeichen, denn der Request ist unsigniert und wird zu Recht abgelehnt. Wichtig ist, dass überhaupt eine Antwort kommt, und zwar deutlich unter einer Sekunde. Ein Timeout oder ein Verbindungsfehler bestätigt dagegen das Netzwerkproblem.
Was du je nach Ursache tun kannst
Das hier ist noch kein verifizierter Fix, sondern die Maßnahmen, die zu den jeweiligen Log-Einträgen passen.
Bei Timeouts oder Verbindungsfehlern liegt der Ball beim Hoster oder beim App-Anbieter. Lass ausgehende HTTPS-Verbindungen vom Webserver prüfen, inklusive Proxy-Konfiguration. Tritt der Fehler nur zeitweise und bei vielen Shops gleichzeitig auf, spricht das eher für Probleme auf der Seite des App-Servers. Dann hilft nur ein Ticket beim Shopware-Support mit den Zeitstempeln aus dem Log.
Bei Signaturfehlern oder 401 lohnt ein Blick auf die App-Registrierung. Ein typischer Auslöser ist eine Staging-Kopie der Live-Datenbank oder eine geänderte Domain: Dann stimmen Shop-ID, APP_URL und das registrierte App-Secret nicht mehr zusammen. Im Community-Forum berichten mehrere Shopbetreiber bei Shopware Payments von 401 AUTH__SIGNATURE_INVALID (Thread). Dort wird empfohlen, die Services neu zu installieren:
bin/console services:install -v
Wurde die URL geändert, hängt der passende Befehl von der Version ab. Bis einschließlich 6.7.2 heißt er app:url-change:resolve, ab 6.7.3.0 gibt es stattdessen app:shop-id:check und app:shop-id:change. Was dein Shop kann, zeigt dir:
bin/console list app
Vorsicht bei Strategien wie „neue Shop-ID erzeugen“ auf einem Live-System. Das registriert alle Apps neu, und die App-Anbieter behandeln den Shop danach unter Umständen als neue Installation.
Wenn das nicht hilft
Wenn die Zeile vor der Meldung fehlt, loggt der Shop vermutlich nicht in die Datei, die du gerade liest. Prüf den Monolog-Handler in config/packages/monolog.yaml und ob Fehler zum Beispiel nur an Sentry oder stderr gehen.
Ab Shopware 6.7.13.0 fängt der Payload-Service zusätzlich JSON-Fehler ab. Kaputtes JSON vom App-Server führt dort ebenfalls zu dieser Meldung. Die Zeile davor enthält dann einen JSON-Decode-Fehler statt einer Guzzle-Exception.
Und wenn du Shopware Payments gar nicht aktiv nutzt: Deaktiviere die App. Kein Gateway-Aufruf, kein Log-Eintrag, keine fünf Sekunden Wartezeit im Checkout.
Die Meldung selbst tut niemandem weh. Teuer wird es, wenn der Checkout dabei jedes Mal ein paar Sekunden hängt oder Zahlarten fehlen und das erst in der Monatsauswertung auffällt. ShopSignal liest dein Log nicht mit, beobachtet aber Antwortzeiten und Bestellvolumen deiner Shopware-Shops und meldet sich, wenn beides aus dem Rahmen fällt.