# Aktualisierung/Speicherung von Order gerade vor Bezahlung

**URL:** <https://forum.shopware.com/t/aktualisierung-speicherung-von-order-gerade-vor-bezahlung/53529>\
**Category:** Programmierung\
**Created:** [17. Juni 2018 um 15:54 UTC](https://forum.shopware.com/t/aktualisierung-speicherung-von-order-gerade-vor-bezahlung/53529 "2018-06-17T15:54:44Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![rreimche](https://avatars.discourse-cdn.com/v4/letter/r/71c47a/32.png) [@rreimche](https://forum.shopware.com/u/rreimche)\
**Post date:** [17. Juni 2018 um 15:54 UTC](https://forum.shopware.com/t/aktualisierung-speicherung-von-order-gerade-vor-bezahlung/53529/1 "2018-06-17T15:54:44Z")

</div>

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.&nbsp;[https://developers.shopware.com/developers-guide/payment-plugin](https://developers.shopware.com/developers-guide/payment-plugin). Ich bin dazu gekommen,&nbsp;dass ich auf PreDispatch von checkout/payment die Anfrage erledige und danach Checkout-\>saveOrder() aufrufe.&nbsp;Als Ergebnis von Checkout-\>saveOrder()&nbsp;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.&nbsp;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,&nbsp;die Bestellung wird kurz nachdem gespeichert, dass der Kunde sein Kaufille bestätigt,&nbsp; 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&nbsp;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&nbsp;

```
$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?&nbsp;

In Shopware\_Controllers\_Frontend\_Payment-\>saveOrder() wird&nbsp;$this-\>getUser() aufgerufen, die&nbsp;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.

---

<div class="post-metadata">

**Author:** ![rreimche](https://avatars.discourse-cdn.com/v4/letter/r/71c47a/32.png) [@rreimche](https://forum.shopware.com/u/rreimche)\
**Post date:** [21. Juni 2018 um 14:25 UTC](https://forum.shopware.com/t/aktualisierung-speicherung-von-order-gerade-vor-bezahlung/53529/2 "2018-06-21T14:25:50Z")

</div>

Hereby I summon the almighty answering powers of the Shopware staff! ,)

---

<div class="post-metadata">

**Author:** ![rreimche](https://avatars.discourse-cdn.com/v4/letter/r/71c47a/32.png) [@rreimche](https://forum.shopware.com/u/rreimche)\
**Post date:** [28. Juni 2018 um 08:04 UTC](https://forum.shopware.com/t/aktualisierung-speicherung-von-order-gerade-vor-bezahlung/53529/3 "2018-06-28T08:04:38Z")

</div>

Ok, ich habe meine eigene saveOrder geschrieben:

```
/**
     * @param \Enlight_Controller_Action $controller
     */
// ich übergebe aus einem Action-Hook den Controller
    private function saveOrder(\Enlight_Controller_Action $controller){

        if (!empty(Shopware()->Session()->sOrderVariables['sUserData'])) {
            $userData = Shopware()->Session()->sOrderVariables['sUserData'];
        } else { throw new Exception("No user data found during saving order when placing order at EET.");}

        if (!empty(Shopware()->Session()->sOrderVariables['sBasket'])) {
            $basketData = Shopware()->Session()->sOrderVariables['sBasket'];
        } else { throw new Exception("No basket data found during saving order when placing order at EET.");}

        $order = Shopware()->Modules()->Order();

        $order->sUserData = $userData;

        $order->sComment = isset($this->session['sComment']) ? $this->session['sComment'] : '';

        $order->sBasketData = $basketData;

        $order->sAmount = $basketData['sAmount'];

        $order->sAmountWithTax = !empty($basketData['AmountWithTaxNumeric']) ? $basketData['AmountWithTaxNumeric'] : $basketData['AmountNumeric'];

        $order->sAmountNet = $basketData['AmountNetNumeric'];

        $order->sShippingcosts = $basketData['sShippingcosts'];

        $order->sShippingcostsNumeric = $basketData['sShippingcostsWithTax'];

        $order->sShippingcostsNumericNet = $basketData['sShippingcostsNet'];

        $order->dispatchId = Shopware()->Session()->sDispatch;

        $order->sNet = empty($userData['additional']['charge_vat']);

        $order->deviceType = $controller->Request()->getDeviceType();

        return $order->sSaveOrder(); // return order number
    }

```

Jetzt wird die Bestellung gespeichert und zwar genau dort wo ich das möchte. Das Problem ist aber, dass noch eine Kopie der Bestellung wird später vom Zahlungsplugin gespeichert. Ich muss nun einen Weg finden, Zahlungsplugins zu zwingen, die gespeicherte Bestellung zu aktualisieren.

---

<div class="post-metadata">

**Author:** ![optimondo](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.shopware.com/optimondo/32/12853_2.png) [@optimondo](https://forum.shopware.com/u/optimondo)\
**Post date:** [28. Juni 2018 um 08:58 UTC](https://forum.shopware.com/t/aktualisierung-speicherung-von-order-gerade-vor-bezahlung/53529/4 "2018-06-28T08:58:36Z")

</div>

Hey

Du kannst das notify vom Checkout nutzen, genau dort wo die fertige Bestellung abgespeichert wird.

Subscriber rein, Order.php dazu. Dann kannste das in etwa so ansteuern:  
&nbsp;

```
.
..

public static function getSubscribedEvents()
{
	return [
		'Shopware_Modules_Order_SaveOrder_ProcessDetails' => 'onSaveOrder'
	];
}

public function onSaveOrder(\Enlight_Event_EventArgs $args)
{
	$orderNumber = $args->getSubject()->sOrderNumber; // was auch immer ;-)
	
..
.

```

Evt. hilft dir das.

Grüße

---

<div class="post-metadata">

**Author:** ![rreimche](https://avatars.discourse-cdn.com/v4/letter/r/71c47a/32.png) [@rreimche](https://forum.shopware.com/u/rreimche)\
**Post date:** [28. Juni 2018 um 10:39 UTC](https://forum.shopware.com/t/aktualisierung-speicherung-von-order-gerade-vor-bezahlung/53529/5 "2018-06-28T10:39:21Z")

</div>

@optimondo‍: Guter Punkt, versuche ich. Aber wäre es nicht besser in sOrder::sGetBasket::replace zu hooken? Weil&nbsp;Shopware\_Modules\_Order\_SaveOrder\_ProcessDetails schon nach Speicherung der neuen Bestellung passiert. Ich könnte dann in Replace-Hook entweder die normale sOrder::sGetBasket ausführen oder stattdessen eine eigene Sache, die die schon vorhandene Bestellung aktualisiert, statt die neue zu speicher.

---

<div class="post-metadata">

**Author:** ![optimondo](https://dub1.discourse-cdn.com/flex013/user_avatar/forum.shopware.com/optimondo/32/12853_2.png) [@optimondo](https://forum.shopware.com/u/optimondo)\
**Post date:** [28. Juni 2018 um 11:38 UTC](https://forum.shopware.com/t/aktualisierung-speicherung-von-order-gerade-vor-bezahlung/53529/6 "2018-06-28T11:38:44Z")

</div>

Der Ansatz war lediglich nach erfolgter Bezahlung, also wenn wirklich alles fertig ist, die Daten zu holen. Das war ja deine Frage&nbsp; ![Wink](https://europe1.discourse-cdn.com/flex013/uploads/shopware/original/1X/b3785da0cbf2c8566cb535dcf55b2730b5224899.png "Wink")

Aber teste das ruhig mal. Die replaces immer schön mit Vorsicht behandeln, denke dran. Wärst nicht der erste der dann ein System zerlegt&nbsp; ![Grin](https://europe1.discourse-cdn.com/flex013/uploads/shopware/original/1X/70033cde8e8ff79cfa538293ae71318d6f788423.png "Grin")

Grüße

---

<div class="post-metadata">

**Author:** ![rreimche](https://avatars.discourse-cdn.com/v4/letter/r/71c47a/32.png) [@rreimche](https://forum.shopware.com/u/rreimche)\
**Post date:** [30. Juni 2018 um 14:36 UTC](https://forum.shopware.com/t/aktualisierung-speicherung-von-order-gerade-vor-bezahlung/53529/7 "2018-06-30T14:36:06Z")

</div>

OK, es sieht soweit machbar. Ich speichere die Bestellung wie früher beschrieben und danach hooke ich in&nbsp;Shopware\_Modules\_Order\_SaveOrder\_ProcessDetails, lade beide Betellungen (sowohl die, die ich früher gespeichert habe, als auch die, die Shopware im Normalfall später speichert) und copiere von der&nbsp;zweiten in die erste Werte, die ich denke, relevante sind (das sind dieeinzige Werte, die in 2 Bestellungen unterscheiden, außer Datum, OrderId, orderDetailId usw):

```
        $controller = $args->get('subject');
        $sessionNamespace = $this->container->get('session');
        $duplicateOrderNumber = $controller->sOrderNumber;
        $originalOrderNumber = $sessionNamespace->get('originalOrderNumber');

        $orderResource = Manager::getResource('order');
        $duplicateOrder = $orderResource->getOneByNumber($duplicateOrderNumber);
        $originalOrder = $orderResource->getOneByNumber($originalOrderNumber); 
       
        $originalOrder['transactionId'] = $duplicateOrder['transactionId'];
        $originalOrder['temporaryId'] = $duplicateOrder['temporaryId'];
        $originalOrder['billing'] = NULL;
        $originalOrder['shipping'] = NULL;

        $orderResource->update($originalOrder['id'], $originalOrder);

```

Danach möchte ich duplicateOrder löschen (das habe ich noch nicht geschrieben).

Das Problem ist nun, dass ich in Backend für die 2 Bestellungen unterschiedliche Werte von Transaktion in “Kunden/Bestellungen” habe. Das sieht sowas aus:&nbsp;[Dropbox - File Deleted](https://www.dropbox.com/s/s8o7suupiptifpa/Screenshot%202018-06-30%2016.35.06.png?dl=0)

Wenn das Bild nicht sichtbar ist, habe ich bei der ersten Bestellung “sWP6T0Fz4pyRWjP9ndVAbnxT…” als Transaktion in Backend und bei der 2. sowas wie “147519-337392-5B379216-17…”.

Der Wert vom originalOrder sieht sehr wie ein Hash aus, aber wo kann ich den Wert von duplicateOrder bekommen?

Und noch eine Frage. Wie kann ich an dieser Stelle, also bei Shopware\_Modules\_Order\_SaveOrder\_ProcessDetails, eine Bestellung löschen? Ich kann das nicht durch Resource-Manager&nbsp;von API machen, weil bei API gibt es kein Löschen von Bestellungen und Shopware/Core/sOrder stellt auch keine Methode zum Löschen zur Verfügung.
