Skip to main content

Documentation Index

Fetch the complete documentation index at: https://dokumentation.websale.de/llms.txt

Use this file to discover all available pages before exploring further.

Aktionen sind das Bindeglied zwischen dem, was ein Benutzer im Shop macht, und dem, was der Shop daraufhin ausführt. Ob ein Kunde ein Produkt in den Warenkorb legt, sich registriert oder einloggt - hinter jedem dieser Vorgänge steckt eine Aktion. Aktionen nehmen die Eingaben des Benutzers entgegen, verarbeiten sie im Hintergrund und geben dem Frontend zurück, ob alles geklappt hat oder ein Fehler aufgetreten ist.

Grundprinzip

Der Shop stellt eine Reihe vordefinierter Aktionen bereit. Diese sind vom System vorgegeben und können nicht frei benannt werden. Jede Aktionen hat einen festen Namen, zum Beispiel BasketItemAdd (Produkt in den Warenkorb legen), Login (Benutzer einloggen) oder AccountRegister (neues Konto anlegen). Aktionen können auf drei Arten ausgeführt werden:
  • Über ein Formular - der häufigste Fall. Der Benutzer füllt ein Formular aus und sendet es ab.
  • Über einen Link - für Aktionen ohne Benutzereingaben, zum Beispiel das Ausloggen.
  • Per AJAX - wenn die Seite nach der Ausführung nicht neu geladen werden soll.
Unabhängig davon, wie eine Aktion ausgeführt wird, läuft im Hintergrund immer derselbe Prozess ab: Der Shop empfängt die Anfrage, verarbeitet sie und gibt zurück, ob die Aktion erfolgreich war oder ein Fehler aufgetreten ist. Einige Aktionen Verhalten sich abweichend und geben statt einer neuen Seite direkt Daten zurück, zum Beispiel als JSON im Rahmen des Checkouts. Dieses abweichende Verhalten ist bei den betreffenden Aktionen jeweils dokumentiert.

Aktionen vorbereiten

Bevor eine Aktion in einem Template genutzt werden kann, muss ein sogenanntes Aktionsobjekt erstellt werden. Man kann es sich wie einen Behälter vorstellen, der alles enthält, was für die Ausführung der Aktion benötigt wird und nach dem Absenden auch die Rückmeldung des Shops enthält. Das Aktionsobjekt wird mit $wsActions.create() erstellt, wobei der Name der gewünschten Aktion übergeben wird:
{{ var $myAction = $wsActions.create("BasketItemAdd") }}
Optional kann hier bereits die Zielseite, auf die nach erfolgreicher Ausführung der Aktion weitergeleitet wird, mitgegeben werden:
{{ var $myAction = $wsActions.create("BasketItemAdd", target=$wsViews.viewUrl('basket.htm')) }}
Das Objekt löst dabei noch nicht aus, es bereitet lediglich die Aktion vor. Die Aktion selbst wird erst ausgeführt, wenn der Benutzer das Formular absendet, auf einen Link klickt oder eine AJAX-Anfrage abgesendet wird. Nach der Ausführung befüllt der Shop das Aktionsobjekt automatisch mit Rückmeldungen. Im Template kann dann über die Variable $myAction darauf zugegriffen werden, zum Beispiel mit $myAction.success oder $myAction.errors. Eine vollständige Beschreibung aller verfügbaren Eigenschaften findet sich in der $wsActions Modulreferenz.
EigenschaftBeschreibung
$action.idDie ID der Aktion, die im Formular benötigt wird, damit der Shop weiß, was ausgeführt werden soll.
$action.csrfEin Sicherheits-Token, das jede Anfrage absichert (mehr dazu hier).
$action.successIst true, wenn die Aktion erfolgreich ausgeführt wurde.
$action.errorIst true, wenn ein Fehler aufgetreten ist.
$action.errorsEine Liste aller aufgetretenen Fehler mit Fehlercode, betroffenem Feld und optionalem Detail.
$action.paramsDie zuletzt eingegebenen Werte. Nützlich, um ein Formular bei einem Fehler vorausgefüllt anzuzeigen, damit der Benutzer nicht alles neu eingeben muss.

Aktionen ausführen

Ausführung über Formulare

Der häufigste Weg, eine Aktion auszuführen, ist ein HTML-Formular. Das vorbereitete Aktionsobjekt wird in das Formular eingebunden und die Aktion wird ausgeführt, sobald der Benutzer das Formular absendet. Das Formular wird immer an die URL der aktuellen Seite gesendet, damit der Shop nach der Ausführung dieselbe Seite neu aufbauen und die Rückmeldung anzeigen kann:
<form method="POST" action="{{= $wsViews.current.url() }}">
Jedes Formular, das eine Aktion ausführt, benötigt drei Pflichtfelder:
FeldWertBeschreibung
wsact{{= $action.id }}Teilt dem Shop mit, welche Aktion ausgeführt werden soll.
wscsrf{{= $action.csrf }}Ein Sicherheits-Token zum Schutz vor unerlaubten Zugriffen (siehe LINK HIER EINFÜGEN).
wstargetz.B. {{= $wsViews.viewUrl('basket.htm') }}Die Seite, auf die der Benutzer nach erfolgreicher Ausführung weitergeleitet wird. Die Weiterleitung verhindert außerdem, dass ein Seiten-Reload das Formular erneut absendet.
Zusätzlich zu den Pflichtfeldern enthält das Formular die aktionsspezifischen Felder. Welche das sind, ist in der jeweiligen Aktionsdokumentation beschrieben. Das folgende Beispiel zeigt ein vollständiges Formular zum Hinzufügen eines Produkts in den Warenkorb:
{{ var $myAction = $wsActions.create("BasketItemAdd") }}
<form method="POST" action="{{= $wsViews.current.url() }}">
  <input type="hidden" name="wsact"     value="{{= $myAction.id }}">
  <input type="hidden" name="wscsrf"    value="{{= $myAction.csrf }}">
  <input type="hidden" name="wstarget"  value="{{= $wsViews.viewUrl('basket.htm') }}">
  <input type="hidden" name="productId" value="12345">
  <input type="number" name="quantity"  value="1">
  <button type="submit">In den Warenkorb</button>
</form>

Tags - mehrere Formulare derselben Aktionsart unterscheiden

Wenn auf einer Seite mehrere Formulare derselben Aktionsart vorkommen, zum Beispiel ein “In den Warenkorb”-Button in jeder Produktbox einer Kategorieseite, teilen sich alle diese Formulare standardmäßig dieselben Rückmeldungen. Das bedeutet: Tritt bei einem Produkt ein Fehler auf, würden alle Formulare auf der Seite diesen Fehler anzeigen. Mit einem Tag lässt sich jede Aktion eindeutig unterscheiden. Als Tag eignet sich zum Beispiel die Produkt-ID:
{{ var $action = $wsActions.create("BasketItemAdd", tag=$product.id) }}
Der Shop erzeugt daraus eine eindeutige ID im Format BasketItemAdd:42 (wobei 42 in diesem Beispiel die Produkt-ID wäre). Dadurch erhält jedes Produkt ein eigenes Aktionsobjekt und Fehler erscheinen nur beim betreffenden Formular. Bei einigen Aktionen, insbesondere im Checkout, wird der Tag genutzt, um den Adresstyp direkt im Aktionsnamen festzulegen:
{{ var $commitBillAction     = $wsActions.create("CheckoutCommitDraftAddress:bill") }}
{{ var $commitShippingAction = $wsActions.create("CheckoutCommitDraftAddress:shipping") }}

Aktionen absichern

Aktionen können auf zwei Arten gegen unerlaubte Zugriffe geschützt werden - durch einen CSRF-Token, der bei jeder Aktion Pflicht ist und optional durch ein Captcha.

CSRF-Schutz

CSRF (Cross-Site Request Forgery) bezeichnet einen Angriff, bei dem eine externe Website im Namen eines eingeloggten Benutzers unbemerkt Anfragen an den Shop sendet, zum Beispiel um eine Bestellung auszulösen oder Kontodaten zu ändern. Der CSRF-Schutz verhindert, dass solche Anfragen vom Shop akzeptiert werden. Dazu wird für jede Benutzersitzung ein einmaliger CSRF-Token erzeugt. Weil der Token an die aktuelle Sitzung gebunden ist, kann eine fremde Website ihn nicht kennen und die Aktion damit nicht unbemerkt auslösen. Der Token steht direkt am Aktionsobjekt zur Verfügung und wird so eingebunden:
<input type="hidden" name="wscsrf" value="{{= $action.csrf }}">

Captcha-Schutz

Für bestimmte Aktionen, zum Beispiel die Registrierung oder ein Kontaktformular, kann zusätzlich ein Captcha aktiviert werden. Ein Captcha ist eine Sicherheitsabfrage, die sicherstellt, dass das Formular von einem echten Menschen ausgefüllt wird und nicht von einem automatisierten Bot. Ist der Captcha-Schutz für eine Aktion aktiv, wird die Aktion nur ausgeführt, wenn der Benutzer das Captcha erfolgreich gelöst hat. Schlägt die Prüfung fehl, wird die Aktion nicht ausgeführt. Damit der Schutz greift, sind zwei Voraussetzungen nötig:
  1. Die Aktion muss in der Shop-Konfiguration unter security.actionGuard für den Captcha-Schutz eingetragen sein.
  2. Das Captcha-Widget muss im Template des zugehörigen Formulars eingebunden sein. Mehr dazu hier.
Wird eine Aktion über einen Bestätigungslink per E-Mail ausgeführt (Opt-In-Link), findet keine Captcha-Prüfung statt. In diesem Fall gilt der Link selbst als Nachweis, dass ein Mensch gehandelt hat.
Aktionen ohne Benutzereingaben, zum Beispiel das Ausloggen oder das Entfernen eines Artikels aus dem Warenkorb, können über einen Link ausgelöst werden, ohne das ein Formular nötig ist. Dazu wird mit $wsActions.url() eine URL erzeugt. Die Methode erwartet drei Angaben: den Aktionsnamen, die Zielseite nach der Ausführung und optionale Parameter als Liste. Sind keine optionalen Parameter nötig, wird eine leere Liste {} übergeben:
<a href="{{= $wsActions.url('Logout', $wsViews.viewUrl('home.htm'), {}) }}">Ausloggen</a>

Ausführung per AJAX

Standardmäßig wird nach dem Absenden eines Formulars die gesamte Seite neu geladen. Manchmal ist das aber nicht gewünscht, zum Beispiel wenn nur ein kleiner Bereich der Seite aktualisiert werden soll, ohne das der Benutzer einen sichtbaren Neuladevorgang erlebt. In solchen Fällen kann die Aktion per AJAX ausgeführt werden. Dabei werden die Daten im Hintergrund an den Shop geschickt und die Antwort (Erfolg oder Fehler) direkt per JavaScript verarbeitet, ohne die Seite neu zu laden. CSRF-Schutz ist dabei genauso erforderlich wie bei Formularen, der Token ist über $wsActions.csrfToken abrufbar. Ein typisches Anwendungsbeispiel:
Der Benutzer legt ein Produkt in den Warenkorb und nur der Warenkorb-Zähler im Header aktualisiert sich, der Rest der Seite bleibt unverändert.
$.post("{{= $wsViews.viewUrl('ajax/actionResponse.json') }}", {
    "wscsrf":    "{{= $wsActions.csrfToken }}",
    "wsact":     "BasketItemAdd",
    "productId": "12345",
    "quantity":  2
}, function(data) {
    if (data.success) {
        // Aktion erfolgreich – z.B. Warenkorb-Zähler im Header aktualisieren
    } else {
        // Fehler anzeigen
        console.log(data.errors);
    }
});

Mehrere Aktionen gleichzeitig ausführen

Manchmal sollen mit einem einzigen Klick auf “Absenden” mehrere Aktionen nacheinander ausgeführt werden. Ein typisches Beispiel ist der letzte Schritt im Checkout, bei dem die Rechnungsadresse und die Lieferadresse bestätigt und die Bestellung abgeschlossen werden. Dafür wird statt des normalen wsact-Feldes das Feld wsmultiact verwendet, und zwar einmal pro Aktion. wsact und wsmultiact können nicht im selben Formular kombiniert werden. Die Aktionen werden in der Reihenfolge ausgeführt in der die wsmultiact-Felder im Formular aufgelistet sind. Felder einer Aktion zuordnen
Weil mehrere Aktionen im selben Formular Felder entgegennehmen, muss jedes Feld klar einer bestimmten Aktion zugeordnet werden. Das geschieht durch ein Präfix vor dem Feldnamen, getrennt durch |. Im Template sieht es so aus:
<input type="hidden" name="{{= $commitBillAction.id }}|addressType" value="bill">
Das bedeutet: Das Feld addressType mit dem Wert bill gehört zur Aktion $commitBillAction. Fehler einer Aktion soll die nächste stoppen
Standardmäßig werden alle Aktionen ausgeführt, auch wenn eine davon fehlschlägt. Soll eine fehlgeschlagene Aktion die nachfolgende abbrechen, kann der Parameter wsmultiactabortonerror auf on gesetzt werden:
<input type="hidden" name="wsmultiactabortonerror" value="on">
Beispiel: Checkout-Abschluss
Das folgende Beispiel zeigt den letzten Schritt eines Checkouts. Mit einem Klick auf “Jetzt bestellen” werden drei Aktionen nacheinander ausgeführt:
{{ var $commitBillAction     = $wsActions.create("CheckoutCommitDraftAddress:bill") }}
{{ var $commitShippingAction = $wsActions.create("CheckoutCommitDraftAddress:shipping") }}
{{ var $checkoutConfirm      = $wsActions.create("CheckoutConfirm") }}

<form method="POST" action="{{= $wsViews.current.url() }}">
  <input type="hidden" name="wscsrf"     value="{{= $commitBillAction.csrf }}">
  <input type="hidden" name="wsmultiact" value="{{= $commitBillAction.id }}">
  <input type="hidden" name="wsmultiact" value="{{= $commitShippingAction.id }}">
  <input type="hidden" name="wsmultiact" value="{{= $checkoutConfirm.id }}">
  <input type="hidden" name="wstarget"   value="{{= $wsViews.viewUrl('order-confirmation.htm') }}">
  <input type="hidden" name="{{= $commitBillAction.id }}|addressType"     value="bill">
  <input type="hidden" name="{{= $commitShippingAction.id }}|addressType" value="shipping">
  <button type="submit">Jetzt bestellen</button>
</form>
Ausführungsreihenfolge des Beispiels:
  1. CheckoutCommitDraftAddress:bill - Rechnungsadresse übernehmen
  2. CheckoutCommitDraftAddress:shipping- Lieferadresse übernehmen
  3. CheckoutConfirm - Bestellung abschließen

Ergebnis der Ausführung

Erfolg

War die Aktion erfolgreich, ist $myAction.success gleich true. In diesem Fall kann eine Erfolgsmeldung angezeigt oder der Benutzer über wstarget auf eine andere Seite weitergeleitet werden.

Fehler

Schlägt die Aktion fehl, zum Beispiel weil ein Pflichtfeld fehlt oder eine E-Mail-Adresse ungültig ist, ist $myAction.error gleich true. Die Fehlermeldungen sollten im Template ausgegeben werden, damit der Benutzer weiß, was korrigiert werden muss:
{{ if $myAction.error }}
  <div class="alert alert-danger">
    Bitte korrigiere folgende Angaben:
    <ul>
      {{ foreach $error in $myAction.errors }}
        {{ if $error.text }}
          <li>{{= $error.text }} ({{= $error.field }}){{ if $error.subCode }} – {{= $error.subCode }}{{ /if }}</li>
        {{ else }}
          <li>{{= $error.code }} ({{= $error.field }}){{ if $error.subCode }} – {{= $error.subCode }}{{ /if }}</li>
        {{ /if }}
      {{ /foreach }}
    </ul>
  </div>
{{ /if }}
Welche Fehlercodes eine bestimmte Aktion zurückgeben kann, ist in der jeweiligen Aktionsdokumentation ausgeführt. Eine Erklärung aller Fehlereigenschaften findet sich in der $wsActions Modulreferenz.

Weiterleitung

Nach einer erfolgreich ausgeführten Aktion kann der Benutzer auf eine Zielseite weitergeleitet werden. Das verhindert außerdem, dass ein Seiten-Reload das Formular erneut absendet. Mehr dazu hier.

Aktionsübersicht

Eine vollständige Übersicht aller verfügbaren Aktionen findet sich in den jeweiligen Themenbereichen: