ID TECH
Kontakt
Alle technischen Beiträge

Technischer Beitrag

USB-Kartenleser mit Websockets verbinden

Mit Websockets und NodeJS können Sie über jeden Webbrowser eine Verbindung zu beliebigen USB-Kartenlesegeräten herstellen. Das bedeutet, dass Sie EMV-Transaktionen über ein virtuelles Terminal durchführen können. Wie das funktioniert, erfahren Sie im Folgenden.

Im letzten Beitrag habe ich gezeigt, wie man USB-Konnektivität über JavaScript einrichtet , mithilfe von NodeJS und einem Modul namens node-hid. Das Ergebnis war, dass wir mit nur etwa 75 Zeilen Code programmatischen Zugriff auf USB-Geräte über JavaScript erhalten konnten. Unser Skript implementierte eine automatische Geräteerkennung und -verbindung und lieferte uns ein Geräte-Handle, mit dem wir USB-Daten lesen und schreiben konnten.

Das ist durchaus praktisch, wenn man lediglich programmatischen Zugriff auf USB-Daten innerhalb eines Node-Skripts benötigt.

Aber was, wenn Sie diese Daten an einen anderen Prozess übermitteln möchten? Was, wenn Sie beispielsweise USB-Daten an einen Webbrowser senden oder an einen Server weiterleiten möchten?

Kein Problem. Das ist problemlos möglich – und ganz einfach!

Websockets als Rettungsanker

Das Websocket-Protokoll (IETF-Spezifikation hier) ist einer der nützlichsten Web-Standards, der seit sehr langer Zeit entwickelt wurde. Erfreulicherweise wird er von allen modernen Browsern unterstützt. Darüber hinaus steht er auch für Node-Skripte zur Verfügung. Das bedeutet, dass Ihr Node-Code problemlos mit Ihren Browser-Skripten kommunizieren kann – Sie müssen lediglich eine Socket-Verbindung aufbauen, die beide Welten miteinander verbindet.

Auf der Node-Seite müssen Sie eine OS-Konsole öffnen und npm install socket.io -g ausführen (einmalig), um das weit verbreitete und zu Recht beliebte socket.io -Modul zu installieren. Anschließend können Ihre Skripte require("socket.io") aufrufen, um die leistungsstarken Funktionen dieses Moduls zu nutzen. (Dazu gleich mehr.)

Auf der Browser-Seite müssen Sie auf die socket.io.slim.js Skript, damit Ihre Webseite Websocket-Daten empfangen kann. (Verwenden Sie hierfür nicht die Standard-Websocket-API des Browsers, da das oben genannte socket.io-Modul ein eigenes Keep-Alive-Verfahren nutzt, das Ihrem Browser nicht bekannt ist. Um Konflikte zu vermeiden, setzen Sie das clientseitige Skript socket.io.slim.js ein. Ein weiterer Vorteil: Das Skript enthält Polyfills, die älteren Browsern Websocket-Kompatibilität ermöglichen.) Am einfachsten erhalten Sie das clientseitige Skript, indem Sie es von einem Edge-Server (CDN) laden – fügen Sie dazu folgenden Codeausschnitt in Ihre Webseite ein:

Sobald dieses Skript eingebunden ist, kann Ihre Webseite eine Verbindung zu Sockets herstellen, die von Ihrem eigenen Socket-Server bereitgestellt werden.

Websockets bereitstellen

Sprechen wir darüber, wie Sie einen Socket-Server im Loopback-Modus einrichten – also unter ws://localhost. Das ist denkbar einfach und äußerst praktisch für die Kommunikation zwischen Prozessen.

Sie benötigen natürlich Node sowie das socket.io-Modul (wie oben beschrieben). Anschließend starten Sie Node und lassen es ein Skript wie das folgende ausführen:

Abgesehen von den Kommentaren umfasst der Code hier nur etwa 30 Zeilen. Konzeptuell läuft das Ganze so ab: Wir require('http')um eine einfache HTTP-Server-Instanz einzurichten. Dann require('socket.io').listen(server) damit das socket.io-Modul eingehende HTTP-Anfragen auf Websocket-Verbindungen umstellen kann.

Standardmäßig ermöglichen Websocket-Verbindungen eine vollduplexfähige, nachrichtenbasierte Punkt-zu-Punkt-Kommunikation zwischen den verbundenen Parteien. Punkt-zu-Punkt bedeutet jedoch nicht, dass Nachrichten automatisch an andere Verbindungen übertragen werden. Um Broadcasting zu aktivieren, registrieren wir einen benutzerdefinierten Event-Listener, das on.('echo') Listener in Zeile 58, der eingehende „echo"-Nachrichten als neue Nachricht vom Typ „message" an alle Socket-Verbindungen weiterleitet. Die Regel lautet also: Für die Punkt-zu-Punkt-Kommunikation wird der Ereignistyp „message" verwendet; damit der Socket-Server Ihre Nachricht an alle Listener weitergibt, nutzen Sie hingegen den Nachrichtentyp „echo". (Dies ist übrigens unsere eigene Konvention und keine Vorgabe von socket.io.)

Abschließend ist zu beachten, dass der obige Code für sich allein nichts bewirkt, da es sich um eine Klassendefinition handelt. Um sie nutzen zu können, muss die Klasse zur Laufzeit instanziiert werden. Das ist jedoch ganz einfach. Die Kommentare am Anfang des Codes erläutern die Verwendung der Klasse. Außerdem werden wir in den kommenden Blog-Beiträgen sehen, wie sie eingesetzt wird.

Verpassen Sie nicht die nächsten Beiträge dieser Serie – denn schon bald werden wir kontaktlose Transaktionen über ein Live-Gateway abwickeln, und zwar direkt aus dem Browser heraus mit JavaScript! Schauen Sie bald wieder vorbei!