Datenflüsse zwischen Node-Red und Shopware

Der Wasserfall zwischen Shopware und Node-Red

Datenflüsse zwischen Node-Red und Shopware

Immer wieder stellt man sich bei der Entwicklung die Frage, wie man Daten von einem System in ein anderes integriert. Jedes System, ob Web-Shop, ERP, PIM oder andere, bietet Schnittstellen an, um Daten zu lesen oder zu schreiben. Je mehr aber dieser Systeme in der Systemlandschaft existieren, umso komplexer werden auch die Prozesse, die Daten zwischen den System austauschen. Dies betrifft vor allem Applikationen, die in der Cloud liegen und nicht durch Module oder Code-Änderungen angepasst werden können. Das kann die Wartungskosten häufig stark erhöhen, vor allem wenn im laufenden Betrieb neue Systeme hinzukommen.

Hier kommt Node-Red ins Spiel. In diesem Blogartikel wollen wir versuchen, ein existierendes Produkt aus einem Shopware-Shop über die API zu laden und anzuzeigen. Dabei ist es hilfreich, wenn du selbst Entwickler bist und Erfahrung in der Anbindung unterschiedlicher Systeme mitbringst. Nach dem Beispiel solltest du in der Lage sein, auch andere Anbindungen über Node-Red durchzuführen, z.B. Lagerbestände zwischen ERP und Shop täglich zu aktualisieren.

Was ist Node-Red?

Node-RED is a programming tool for wiring together hardware devices, APIs and online services in new and interesting ways. It provides a browser-based editor that makes it easy to wire together flows using the wide range of nodes in the palette that can be deployed to its runtime in a single-click.

Node-Red ist ein Entwicklungstool, um diverse Datenflüsse komfortabel über den Browsers zu designen. Die Umgebung basiert auf Node.js und nutzt dessen event-driven Modell voll aus. Dadurch ist sie ideal auf kostengünstiger Hardware wie dem Raspberry Pi sowie in der Cloud nutzbar. Wer gleich in Node-Red einsteigen möchte und parallel Flows testen will, kann auf https://nodered.org/docs/getting-started/ einen Überblick finden, wie das Tool installiert und genutzt werden kann.

Grundsätzlich bestehen die Datenflüsse aus drei Elementen:

Shopware flow-node-message mit Node Red

1. Node: Ein Node ist der grundlegende Baustein eines Ablaufs. Nodes werden ausgelöst, indem sie entweder eine Nachricht vom vorherigen Knoten in einem Fluss empfangen, oder auf ein externes Ereignis warten, z. B. eine eingehende HTTP-Anforderung oder einen Zeitgeber. Sie verarbeiten diese Nachricht bzw. dieses Ereignis und können dann eine Nachricht an die nächsten Knoten im Fluss senden.

2. Flow: Ein Flow wird als Registerkarte im Arbeitsbereich des Editors dargestellt und ist die Hauptmethode zum Organisieren von Knoten. Der Begriff "Flow" wird auch zur informellen Beschreibung eines einzelnen Satzes von verbundenen Knoten verwendet. Ein Flow (Registerkarte) kann also mehrere Flows enthalten.

3. Message: Die Messages/Nachrichten sind das, was zwischen den Knoten in einem Flow übertragen wird. Sie sind einfache JavaScript-Objekte, die einen beliebigen Satz von Eigenschaften haben können. Im Editor werden sie oft als msg bezeichnet. Per Konvention haben sie eine Payload-Eigenschaft, welche die nützlichsten Informationen enthält.

Über die Palette auf der linken Seite können die verschiedenen Nodes in den Arbeitsbereich gezogen werden und zu einem Flow verknüpft werden.

Der erste Flow - Ein Shopware 6 Connector

Bevor wir direkt mit den diversen Nodes arbeiten, sollte sichergestellt werden, dass wir die Grundlagen kennen. Zur Sicherheit lesen wir https://nodered.org/docs/tutorials/first-flow und erstellen einen Test-Flow. Zusätzlich lesen wir https://nodered.org/docs/tutorials/second-flow#2-add-an-http-request-node, um mehr über den http-request node zu erfahren.

Um einen HTTP-Request an Shopware durchzuführen, sind zwei Dinge notwendig: Die Authentifizierung und die Ausführung des Requests an sich. Die Zugangsdaten können im Shopware Backend unter "Einstellungen / System / Integrationen" generiert werden. Sobald diese erstellt wurden, kann der neue Flow erstellt werden. Grundsätzlich sieht der Datenfluss so aus:

Request Flow zwischen Node Red und Shopware

  1. Prüfe, ob es bereits ein Token für den Request gibt
  2. Wenn noch kein Token existiert, erstelle einen mit einem Auth-Request
  3. Ansonsten führe den Shopware Request aus
  4. Wenn die Zugangsdaten abgelaufen sind (=401), dann wiederhole Punkte 2 und 3

Das können wir in Node-Red fast 1-zu-1 abbilden:

Shopware Request

Gehen wir die einzelnen Nodes Punkt für Punkt durch...

Inject - Set Request

Zum Test eines Requests fügen wir den Inject Node ein, der die Basis-Daten des Requests setzt: HTTP Url, HTTP Methode, Payload und Zugangsdaten.

Beispiel:

  • msg.base = "https://shopware.com"
  • msg.uri = "/api/product"
  • msg.method = "GET"
  • msg.payload = {}
  • msg.client = ""
  • msg.secret = ""

Change - Remember request

Wenn es noch keinen Auth Token gibt, müssen wir einen Request an die auth API durchführen. Da wir msg.method und msg.payload später überschreiben, müssen wir die Daten des Original-Requests zwischenspeichern. Dazu setzen wir:

  • msg.orig_uri = msg.uri
  • msg.orig_method = msg.method
  • msg.orig_payload = msg.payload

Switch - Check token

Ob wir bereits einen Token von einem vorherigen Request haben, können wir durch eine [Kontext-Variable|https://nodered.org/docs/user-guide/context] erkennen. Node-Red bietet dazu den globalen Kontext "global". In dem switch-Node können wir also die Variable "global.shopware_token" prüfen und schauen, ob sie z.B. vom Typ "string" ist. Wenn ja, wird beim eigentlichen Shopware-Request weiter gemacht, ansonsten beim Auth-Request.

Function - Prepare Auth Request

Wie vorher erwähnt, müssen wir für den http-request Node msg.url, msg.payload und msg.method überschreiben. Dazu nutzen wir einen Function Node und fügen diesen Code ein:

msg.payload = {
    "grant_type": "client_credentials",
    "client_id": msg.client,
    "client_secret": msg.secret
};
msg.url = msg.base + "/api/oauth/token";
msg.method = "POST";
 
return msg;

http-request - Get Shopware token

Die Einstellungen des http-request Node können leer bleiben. Die HTTP Methode und url haben wir bereits im vorherigen Node gesetzt. Node-Red lädt diese Werte automatisch innerhalb des Nodes und führt den Request aus.

Wichtig ist nur, dass der Rückgabe Typ "ein parsed JSON-Objekt" ist.

Switch - statusCode!=200

Die HTTP Response vom http-request Node wird in das msg-Objekt gespeichert. Response Body in msg.payload, Header in msg.header, Status Code in msg.statusCode. Dies nutzen wir im Switch-Node, um zu prüfen, ob die Authentifizierung geklappt hat.

Wenn msg.statusCode != 200 ist, dann beenden wir den Flow und geben das Ergebnis im Debug-Node aus. Ansonsten hat der Auth-Request geklappt und wir können den Token aus dem Response Body laden.

Change - Extract Token

Der Response Body ist ein parsed JSON-Objekt. Laut Shopware Dokumentation befindet sich der Token in payload.access_token. Den Token können wir wiederum in den globalen Kontext speichern:

  • global.shopware_token = msg.payload.access_token

Switch - Set orig request

Bevor der eigentliche Request an Shopware gesendet werden kann, müssen wir URL, payload und method zurücksetzen. Dazu setzen wir:

  • msg.uri = msg.orig_uri
  • msg.method = msg.orig_method
  • msg.payload = msg.orig_payload

Function - Prepare header

Für Requests an Shopware sind mindestens drei Header notwendig: Accept, Authorization, Content-Type. Den Token können wir wieder aus der globalen Kontext-Variable "shopware_token" holen und im Header mit übergeben. Als Content-Type kann in den meisten Fällen application/json übergeben werden. Falls hier andere Header gewünscht sind (z.B. bei Produkt-Media-Upload), sollten später Header schon im ersten Schritt mit übergeben werden und hier nur gesetzt werden, wenn der Header noch nicht existiert.

Die Funktion sollte in etwa so aussehen:

msg.headers = {};
msg.headers['Accept'] = '*/*'; // Alternativ kann application/json verwendet werden für simple json response
msg.headers['Authorization'] = 'Bearer ' + global.get('shopware_token');
msg.headers['Content-Type'] = 'application/json';
 
msg.url = msg.base + msg.uri;
 
return msg;

http-request - Send request

Wie beim Auth-Request können die Einstellungen des http-request Node leer bleiben. Die HTTP Methode und url haben wir bereits im vorherigen Node gesetzt. Node-Red lädt diese Werte automatisch innerhalb des Nodes und führt den Request aus.

Auch hier ist wichtig, dass der Rückgabe Typ "ein parsed JSON-Objekt" ist.

Switch - statusCode!=401

Die HTTP Response vom http-request Node wird wieder in das msg-Objekt gespeichert. Response Body in msg.payload, Header in msg.header, Status code in msg.statusCode. Dies nutzen wir im Switch-Node, um zu prüfen, ob eine Authentifizierung notwendig ist, z.B. aufgrund eines abgelaufenen Tokens.

Wenn msg.statusCode != 401 ist, dann beenden wir den Flow und geben das Ergebnis im Debug-Node aus. Wenn jedoch ein 401 zurückgegeben wurde, führen wir den Flow zurück zur Authentifizierung.

Wir beenden den Flow auch in allen anderen Status-Codes und führen keine erneute Authentifizierung aus, denn:

  • bei 400 wurde ein Fehler im Request gemacht, z.B. wenn Shopware Daten fehlen
  • bei 404 gibt es die Entity nicht
  • bei 500ern trat ein interner Shopware Fehler auf, die Fehlerbehandlung sollte je nach URL getrennt behandelt werden.

Der Shopware 6 http-request als dynamischer Subflow

Ein wesentlicher Vorteil von Node-Red ist, dass solch Datenflüsse in sogenannten Sub-Flows geschrieben und oft wiederverwendet werden können, damit die gleichen Abfolgen nicht kopiert werden müssen. Wenn du der groben Anleitung oben gefolgt bist, kannst du alle Nodes markieren (STRG+A) und über das "Menü / Subflow / Auswahl in Subflow umwandeln" in einen Subflow ändern. Die Inject- und Debug-Nodes entfernen wir und ersetzen sie durch Eingabe/Ausgabe Nodes.

Wenn du stattdessen einen fertigen Flow nutzen möchtest, haben wir hierzu den Shopware 6.3 Subflow auf https://flows.nodered.org/flow/b0a2335135754c4386bcbba4a26438dd veröffentlicht. Kopiere dir das Flow-JSON und füge es via Menü / Import in Node-Red ein. In diesem nutzen wir außerdem Umgebungsvariablen. Stelle sicher, dass du Node-Red mit den Umgebungsvariablen "SHOPWARE_URL", "SHOPWARE_CLIENT" und "SHOPWARE_SECRET" startest. Damit musst du die Basis-Daten nicht in jeder Message setzen.

Der Subflow kann nun wie andere Nodes verwendet werden. Erstelle andere Inject-Nodes, um andere Requests auszuführen oder verbinde mehrere Shopware-Requests miteinander. Ob Produkt-CSV Import, oder Bestell-CSV-Exporte, durch die Kombination fertiger Nodes oder Nodes der Community sollte die Datenintegration zu Shopware wenig Probleme bereiten.

CSV-SW-Flow von Nodered und Shopware

Die wichtigsten Vorteile

✓ Verständlich Prozesse können übersichtlich dargestellt werden, sodass auch andere schnell einen Überblick über den Datenfluss haben und ggf. Änderungen vornehmen können.

✓ Günstig Node-Red ist kostenlos und kann sogar auf einem Raspberry Pi betrieben werden. Änderungen können konfortabel über den Browser durchgeführt werden. Dadurch ist es in der Anschaffung und Wartbarkeit sehr kosteneffizient.

✓ Versionierbar Ja, auch die Flows sind versionierbar. Nachdem das Projekt-Feature von Node-Red aktiviert wurde, kann ein Git-Repository eingerichtet werden und mit Node-Red verknüpft werden. Es können über den Browser Änderungen geprüft, committed und gepushed werden.

✓ Testbar Sowohl selbst-entwickelte Nodes als auch komplette Flows können mit automatisierten Tests geprüft werden, sodass Fehler nach Änderungen leicht erkannt werden können. Mehr dazu auf https://github.com/node-red/node-red-node-test-helper und https://github.com/pauldeng/node-red-ci-example

✓ Community Mit Forum, Slack und einem Blog ist Node-Red stark aufgestellt und bietet der Community Möglichkeiten zum Austausch von Nodes, Flows oder ganzen Sammlungen von Funktionalitäten. Tausende Nodes der Community können auf https://flows.nodered.org/ bezogen werden.

Bemerkungen

Natürlich hat Node-Red nicht nur Vorteile. Je nach Situation können Alternativen genutzt werden oder Node-Red erweitert werden, um spezifische Probleme anzugehen:

  • Eine große Schwäche ist die Tatsache dass die Übermittlung einer Nachricht nicht garantiert werden kann. Node-Red verliert bei einem Crash/Reboot jeglichen Zustand, ist daher kein Ersatz für eine unternehmensweite Middleware.
  • Das Programmieren verschiebt sich teilweise in die Verwaltung der Flows. Je nach Komplexität kann es unübersichtlich werden.
  • Prototyping geht schnell, allerdings läuft man Gefahr dass ein Prototyp nicht fertig entwickelt wird. Daher sollten wie in der üblichen Entwicklung Tests geschrieben werden.

Konklusion

Node-Red bietet in der aktuellen Version viele Nodes, um Standard-Prozesse abbilden zu können. Aus der Community kommen viele weitere Nodes oder ganze Flows, die bereits Arbeit abnehmen. Die Einarbeitung geht schnell, Flows können übersichtlich dargestellt werden und am wichtigsten: Node-Red ist kostenlos und günstig in der Wartung. Dadurch wird es zu einem Tool, das die Kommunikation zwischen mehreren Systemen automatisiert übernehmen kann. Mit PM2 und extra Nodes (E-Mail, Twitter, ...) kann Node-Red überwacht werden. Vor allem mit integrierten Tools zur Versionierung und Test-Nodes wird es zu einem unverzichtbaren Tool für Datenintegrationen.

Brauchst du Support bei deiner Datenintegration mit Node-Red? Dann melde dich bei uns!

Weiterführende Links

Du willst bei uns mitmachen?
Zu den Stellen