Der Shopware Shop stellt eine umfassende REST-API zur Verfügung, über die man z.B. Artikel auslesen bzw. bearbeiten kann.
API-User einrichten
Standardmässig ist kein Benutzer mit API-Zugang angelegt, man kann jedoch einfach im Backend in der Userverwaltung für beliebige Nutzer API-Zugriff aktivieren und ein entsprechendes Token vergeben:
Mit der Kombination aus Benutzername und Token kann man sich nun „von aussen“ an der API authentifizieren, entweder mit Digest Auth oder HTTP Basic Auth.
Das kann man z.B. mit Postman sehr schön testen:
Wir nutzen im folgenden HTTP Basic Auth, hier gibt es noch eine kleine Hürde – die Kombination Benutzername und Token muss „Base64“ enkodiert werden für die Anmeldung.
Für PHP findet sich in der Shopware Dokumentation ein CURL-Beispiel, wir wollen jedoch VueJS nutzen, um mit der API zu kommunizieren.
Kommunikation von VueJS aus
Auch für Javascript gibt es natürlich Möglichkeiten, die Login-Daten mit Base64 zu enkodieren, eine davon ist die Verwendung von „CryptoJS“. Dieses können wir uns mit npm bzw. yarn aus dem npm-Repository im Projekt installieren:
npm install crypto-js
oder
yarn add crypto-js
Die Verwendung in Vue sieht dann z.B. so aus:
import CryptoJS from ‚crypto-js‘;
var secStr = CryptoJS.enc.Utf8.parse(apiUsername + „:“ + apiToken);
var base64 = CryptoJS.enc.Base64.stringify(secStr);
var options = {url: myshop.de/api/articles,
method: ‚GET‘,
headers: {
Authorization: „Basic “ + base64
}
}
this.$http(options).then((response) => {
this.productsData = response.body;
…
So weit, so gut… allerdings hat man oft das Problem, dass die Javascript-Anwendung auf einem anderen Server liegt oder zumindest unter einer anderen (Sub-)Domain läuft, dadurch ist die Wahrscheinlichkeit groß, dass man Probleme mit dem sog. CORS (Cross Origin Resource Sharing) bekommt.
CORS Probleme
In diesem Fall kommt man nicht umhin, die Shopware Server Konfiguration anzupassen, um CORS zu ermöglichen. Am einfachsten gelingt dies in der Regel durch Anpassungen an der .htaccess-Datei des Shops, zumindest wenn man einen Apache Webserver nutzt.
Hier fügt man folgende Zeile ein:
<IfModule mod_headers.c>
Header set Access-Control-Allow-Origin „*“
</IfModule>
womit man Zugriff auf die Ressourcen des Shops von anderen (Sub-)Domains aus erlaubt.
Nun sollte die Javascript-Anwendung prinzipiell auf die Shopware REST API Endpoints zugreifen können. Allerdings zeigt sich schnell das nächste Problem.
OPTIONS „Preflight“
Trotz hoffentlich korrekter Zugangsdaten meldet Shopware beim Aufruf, dass der Zugriff nicht authorisiert ist und antwortet mit einem 401 Fehler. Wieso? Das liegt daran, dass bei der Kommunikation über einen AJAX-Request (XmlHttpRequest) vom Browser ein sog. „Preflight“ durchgeführt wird, als HTTP Methode wird hier „OPTIONS“ verwendet.
Normalerweise sollte eine Anwendung hier keine Authentifizierung erwarten bzw. verlangen – leider macht das Shopware aber standardmässig und der Request wird dadurch als nicht erfolgreich betrachtet, da vom Server ein „401 – Authorization failed“ zurückkommt. Jetzt könnten wir also ein Shopware Plugin schreiben, was eine Ausnahme für die OPTIONS-Methode implementiert, oder wir können wiederum über die .htaccess-Datei den „Preflight“ abfangen.
Letzere Option geht deutlich einfacher und sieht so aus – zuerst müssen wir das Setzen des CORS-Headers um „always“ ergänzen, damit dieser in jedem Fall gesetzt wird, danach wird der OPTIONS-Request direkt mit „200 – OK“ beantwortet und zurückgeschickt:
<IfModule mod_headers.c>
Header append X-Frame-Options SAMEORIGIN
# allow cross-site requests
Header always set Access-Control-Allow-Origin „*“
Header always set Access-Control-Allow-Methods „GET, POST, PUT, DELETE, OPTIONS“
Header always set Access-Control-Allow-Headers „*, Authorization, authorization“
</IfModule><IfModule mod_rewrite.c>
RewriteEngine on# always return 200 for preflight OPTIONS requests
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
Et voilá, danach sollte unser API-Request erfolgreich sein und Daten zurückliefern!