Hallo,
ich schreibe ein Dropshipping-Plugin. Nach dem der Kunde den Kauf bestätigt hat (checkout/confirm), muss eine Anfrage an einen Lieferanten-Server ausgeführt werden, die versucht die Bestellung an den Lieferanten zu übermitteln. Die Anfrage kann als Ergebnis eine Antwort vom Lieferanten bekommen, dass die Bestellung nicht möglich ist. In diesem Fall muss der Kunde wieder zum checkout/confirm mit einer Fehlermeldung umgeleitet werden. Wenn aber alles mit der Anfrage gut gelaufen ist, muss eine gesonderte AnfrageID in einem Freitextfeld von Order gespeichert werden. Diese AnfrageID brauchen wir, um mit dem Lieferanten später über die Bestellung reden zu können. Nach diesen Vorgängen darf es mit der Zahlung angefangen werden.
Ich habe gestern mehrere Stunden die Controller-Quellcodes von Shopware gelesen sowie die Tutorials, insb. https://developers.shopware.com/developers-guide/payment-plugin. Ich bin dazu gekommen, dass ich auf PreDispatch von checkout/payment die Anfrage erledige und danach Checkout->saveOrder() aufrufe. Als Ergebnis von Checkout->saveOrder() bekomme ich die Ordernummer, mithilfe dessen ich dann die AnfrageID speichern könnte. Das funktioniert aber nicht, weil Datenbank-Schema-Regeln irgendwie beim Aufruf von Checkout->saveOrder() an diesem Zeitpunkt verletzt werden:
Shopware Order Fatal-Error myshop.de :SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'paymentID' cannot be null in engine/Shopware/Core/sOrder.php on line 621
Ich könnte das vllt. irgendwie umgehen, weil PaymentID ist an diesem Zeitpunkt schon in sOrderVariables anscheinend enthalten. Aber ohne Sicherheit, dass das klappt und dass das nicht etwas weiter zerstört, weil ich damit in Checkout-Prozess wesentlich eingreife und dann kann, laut der genannten Anleitung, unbeabsichtigte schwerwiegende folgen haben.
Obwohl, anscheinend, die Bestellung wird kurz nachdem gespeichert, dass der Kunde sein Kaufille bestätigt, wird die Bestellung, laut derselben Anleitung mit Status „cancel“ oder sowas an dieser Stelle gespeichert, sodass sie noch nicht im Backend sichtbar ist und noch keine wirkliche Ordernummer hat. Eine Ordernummer wird nur später dadurch erstellt, dass nach der Bezahlung das Payment-Plugin sOrder->sSaveOrder() betätigt. An dieser Stelle ist es etwa zu spät für mein Plugin, weil aus Rechtlichen Gründen möchten wir keinen Kaufwille annehmen, wenn der Lieferant die Bestellung nicht annimt. Ich könnte meinen Vorgang Aufteilen, indem ich die Anfrage auf Lieferantenserver auf PreDispatch checkout/payment erledige und die AnfrageID in Session-Data speichere, damit ich später, während z.B. PreDispatch checkout/finish, was schon nach payment passiert, die Bestellung so aktualisiere:
$sessionNamespace = $this->container->get('session');
$orderVariables = $sessionNamespace->get('sOrderVariables')->getArrayCopy();
$orderNumber = $orderVariables['sOrderNumber'];
$AnfrageID = $orderVariables['lieferantenAnfrage']['AnfrageID']; // das speichere ich früher
$orderResource = Manager::getResource('order');
$order = $orderResource->getOneByNumber($orderNumber);
$order['attribute']['AnfrageID'] = $AnfrageID;
$orderResource->update($order['id'], $order);
Und das kann wohl funktionieren. Aber ich soll irgendwie das Problem mit saveOrder bevor Zahlungsvorgang lösen.
Also:
- kann ich irgendwie die Bestellung bevor Bezahlung „abschließen“, sodass sie sowohl in Backend sichtbar ist, als auch eine Ordernummer hat als auch die Kaufbestätigung an den Kunden verschickt wird? Wie?
- oder: gibt es einen richtigen weg das von mir gedachte zu implementieren?
P.S. Wäre toll, wenn Shopware so eine Einstellung hätte, dass die Bestellung gerade nach „Kostenpflichtig bestellen“ als wirkliche Bestellung gespeichert wird, sogar wenn noch nicht bezahlt. Das entspricht dem deutschen Recht gut, soweit ich verstehe.
P.P.S. Ich habe auf PreDispatch Checkout/Payment mit var_export() und Pluginlogger geprüfft, dass es in sOrderVariables in Session-Data PaymentID tatsächlich vorhanden ist und zwar an mehreren Stellen, insbesondere an $sOrderVariables[‚sUserData‘][‚additional‘][‚payment‘][‚id‘]. sOrder->getPaymentId() benutzt $this->sUserData[‚additional‘][‚payment‘][‚id‘], um PaymentId zurückzugeben. Ich vermute, dass sOrder->sUserData eine kopie von sUserData aus sOrderVariables ist. sOrder->getPaymentId() wird von sOrder-sSaveOrder() verwendet, um PaymentId zu bekommen. So lässt es sich vermuten, dass ich die genannte Integrity Violation nicht verursachen könnte. Aber in Checkout->saveOrder() wird
$order->sUserData = $this->View()->sUserData;
aufgerufen, anstatt die Daten aus sOrderVariables zu kopieren. Ich versuchte das zu verfolgen. Diese View() gibt Enlight_View_Default zurück, was von Enlight_View erbt. In beiden Enlight_View habe ich keine „sUserData“ gefunden. Wie kann das sein?
In Shopware_Controllers_Frontend_Payment->saveOrder() wird $this->getUser() aufgerufen, die Shopware()->Session()->sOrderVariables[‚sUserData‘] zurückgibt. Ich soll vllt. eine eigene SaveOrder Methode schreiben, die diebesten Sachen aus den von Frontend_Checkout und Frontend_Payment nimmt Wäre das eine gute option?
P.P.P.S ich verwende Shopware 5.3.7.