技術記事
WebSocketでUSBカードリーダーに接続する
WebSocketとNodeJSを使えば、任意のWebブラウザから任意のUSBカードリーダーに接続できます。つまり、仮想端末からEMV決済が可能になるということです。その方法を以下でご紹介します!
前回は、 JavaScript経由でUSB接続を設定する方法 を、NodeJSと node-hidというモジュールを使ってご紹介しました。その結果、わずか75行ほどのコードで、JavaScriptからUSBデバイスにプログラム的にアクセスできるようになりました。スクリプトはデバイスの自動検出と接続を実装し、USBデータの読み書きに使用できるデバイスハンドルを取得できました。
Nodeスクリプト内からUSBデータにプログラム的にアクセスするだけで十分なら、これで問題ありません。
しかし、そのデータを別のプロセスに伝えたい場合はどうでしょうか?たとえば、USBデータをWebブラウザに送信したい場合は?あるいはサーバーにプッシュしたい場合は?
問題ありません。実現可能です。しかも簡単です!
WEBSOCKETの出番です
WebSocketプロトコル(IETF仕様 こちら)は、近年登場したWeb標準の中でも特に驚くほど便利なものの一つです。そして嬉しいことに、すべての最新ブラウザに実装されています。さらに、Nodeスクリプトからも利用可能です。つまり、両者を橋渡しするソケット接続を作成するだけで、Nodeコードとブラウザスクリプトが簡単に通信できるということです。
Node側では、OSコンソールを開いて npm install socket.io -g (一度だけ)を実行し、広く使われていて当然ながら人気の socket.io モジュールをインストールする必要があります。これを行った後、スクリプトから require("socket.io") を呼び出すことで、このモジュールの驚異的なパワーを活用できるようになります。(詳しくはこの後すぐにご紹介します。)
ブラウザ側では、 socket.io.slim.js スクリプトを指定する必要があります。これにより、Webページ側でWebSocketデータを受け取れるようになります。(標準のブラウザWebSocket APIをそのまま使おうとしないでください。先述のsocket.ioモジュールは、ブラウザが認識しない独自のキープアライブ方式を使用しているからです。競合を避けるため、クライアント側ではsocket.io.slim.jsスクリプトを使用してください。副次的なメリットとして、このスクリプトには古いブラウザにWebSocket互換性を提供するポリフィルが含まれています。)クライアント側スクリプトを取得する最も簡単な方法は、以下のスニペットをWebページに記述してエッジサーバー(CDN)から取得することです:
このスクリプトを配置すれば、Webページはあなた自身のソケットサーバーが提供するソケットに接続する準備が整います。
WEBSOCKETを提供する
ループバックモード(つまりws://localhost上)でソケットサーバーをセットアップする方法について説明しましょう。信じられないほど簡単で、プロセス間通信に非常に便利です。
もちろんNodeが必要で、socket.ioモジュールも必要です(前述の通り)。次に、Nodeを起動して以下のようなスクリプトを実行する必要があります:
コメントを除けば、ここで見ているのはわずか30行程度のコードです。概念的には、次のようなことが行われています: require('http')を実行してダミーのHTTPサーバーインスタンスをセットアップできるようにします。次に、 require('socket.io').listen(server) を実行することで、socket.ioモジュールが受信HTTPリクエストをWebSocket接続にアップグレードできるようになります。
デフォルトでは、WebSocket接続は接続された当事者間で全二重・メッセージベース・ポイントツーポイントの通信を可能にします。しかし、ポイントツーポイントとは、メッセージが他の接続にも自動的にブロードキャストされるという意味ではありません。ブロードキャストを有効にするには、カスタムイベントリスナー、つまり58行目の on.('echo') リスナーを登録します。これは受信した「echo」メッセージを、すべてのソケット接続に対して 'message' タイプの新しいメッセージとして再送信します。つまりここでのルールは:ポイントツーポイントのメッセージングを行うには 'message' イベントタイプを使い、ソケットサーバーがそのメッセージを全リスナーに転送することを確実にするには 'echo' メッセージタイプを使う、ということです。(ちなみに、これは私たち独自の取り決めであり、socket.ioによって課されているものではありません。)
最後に注意すべき点は、上記のコードはそれ自体では何もしないということです。なぜならこれはクラス定義だからです。使用するには、実行時にクラスをインスタンス化する必要があります。とはいえ、これは非常に簡単です。コード冒頭のコメントに、クラスの使用方法が説明されています。さらに、今後のブログ記事でもその使い方をご紹介していきます。
このシリーズの次回以降の記事もお見逃しなく。すぐに、ブラウザからJavaScriptを使って、実稼働ゲートウェイに対する非接触決済を行えるようになります!近日中に再度ご覧ください!
