Force.com Canvasのsigned-requestを検証&デコードするNode-REDノード

  • 9
    Like
  • 0
    Comment
More than 1 year has passed since last update.

Node-REDは主にIoT領域でサービス連携に使われてますが、Node-RED を使用してリアルタイムのチャット・アプリケーションを 5 分で作成するのようにWebページ/アプリケーションを作ることも可能です。

ということは、SalesforceのCanvasを使えばNode-REDで作成したWebアプリケーションがSalesforce内で使える!ということで、このたびnode-red-contrib-forceにSigned Requestを検証&デコードするノードを作りました。

以下、チュートリアル的に紹介します。

Node-REDをHerokuで動かす

Node-REDをHerokuで動かすには以下のHerokuボタンをクリックしてください(以下、例として https://node-red-123.herokuapp.com にデプロイしたものとします)

Deploy

何もしないとNode-REDのエディタ画面がフルオープンになってしまうのでHerokuの環境変数としてNODE_RED_USERNAMENODE_RED_PASSWORDを必須としてます。ユーザ名とパスワードを決めて入力したら "Deploy for Free" ボタンをクリックしてください。

スクリーンショット 2015-12-22 14.53.35.png

デプロイしたらホストにアクセスしてみます(今回の例ですと https://node-red-123.herokuapp.com )以下のような画面が表示されますので "Go to your Node-RED flow editor" ボタンをクリックします。

スクリーンショット 2015-12-22 14.56.44.png

するとログイン画面に遷移しますので先ほどHerokuデプロイ画面で設定したユーザ名とパスワードを入力してログインします。

スクリーンショット 2015-12-22 14.58.54.png

これで以下のようにNode-REDエディタ画面が表示されればOKです。今後、直接エディタ画面を開くには/redを付与してアクセスします(今回の例ですと https://node-red-123.herokuapp.com/red

スクリーンショット 2015-12-22 15.01.06.png

あとは今回紹介するnode-red-contrib-forceというモジュール/プラグイン的なもの(Node-REDでは一つ一つのモジュール/プラグイン的なものをノードと呼びます)をインストールします。

node-red-contrib-forceを使うには、npm install -g node-red-adminnode-red-adminをインストールして以下のコマンドを叩きます。

$ node-red-admin target <Node-REDのエディタ画面のURL 例:https://node-red-123.herokuapp.com/red>
$ node-red-admin login
Username: <Herokuにデプロイする時に設定したユーザ名>
Password: <Herokuにデプロイする時に設定したパスワード>
Logged in
$ node-red-admin install node-red-contrib-force
Module:    node-red-contrib-force
Version:   0.0.6                 

Nodes                                               Types                  State  
node-red-contrib-force/chatter                      force-chatter in       enabled
node-red-contrib-force/forcedotcom                  force                  enabled
                                                    force in                      
node-red-contrib-force/forcedotcom-bulk             force-bulk in          enabled
node-red-contrib-force/forcedotcom-signed-request   force signed request   enabled

Node-REDでWebページを作成する

まず、以下のようにHTTP Inputノードをドラッグ&ドロップしてワークスペースの好きな場所へ置きます。

スクリーンショット 2015-12-22 14.42.29.png

次に配置したノードをダブルクリックするとノード定義用の設定ダイアログが開きますので以下のようにHTTP Inputノードに/canvasというURLを設定します。これだけでNode-REDが動くHTTPのGETメソッドのエンドポイントを作成できます。

スクリーンショット 2015-12-22 14.45.58.png

あとは表示するWebページを定義するTemplateノードとHTTP Outputノード(HTTPレスポンス)と念のためDebugノードを以下のように配置してDeployボタンをクリックします。上記でエンドポイントを定義したHTTP Inputノード以外はデフォルトのまま(配置してつなぐだけ)で良いです。

スクリーンショット 2015-12-22 14.38.33.png

ここまでできたところでNode-REDをデプロイしたホストにHTTP Inputノードで定義したエンドポイント(今回の例ですと https://node-red-123.herokuapp.com/canvas )へアクセスしてみます。

スクリーンショット 2015-12-22 14.20.13.png

Templateノードがデフォルト定義のままなので[object Object]となってますがWebページが返ってきました。

続いて先ほどのURLに?aaa=111というパラメータを付与して(今回の例ですと https://node-red-123.herokuapp.com/canvas?aaa=111 )アクセスしてみます。

表示されるWebページは変化ありませんがNode-REDのエディタ画面に戻るとデバッグに送信したパラメータが表示されています。

スクリーンショット 2015-12-22 14.24.57.png

これはHTTP Inputノード([get] /canvas)で受け取ったパラメータをNode-REDがJSONに変換してmsg.payloadというプロパティにセットしてDebugノードへ流した結果です。

スクリーンショット 2015-12-22 14.26.05.png

これでNode-REDのノード同士を接続するラインを流れるメインのデータはmsg.payloadを流れているのが解るのでTemplateノードを以下のように変更してみます(Templateノードをダブルクリックすると設定ダイアログが開きます)

This is the payload: {{payload.aaa}} !

スクリーンショット 2015-12-22 14.32.09.png

これで再度デプロイします。

スクリーンショット 2015-12-22 14.38.33.png

そして再度パラメータ付きでアクセスしてみますと(今回の例ですと https://node-red-123.herokuapp.com/canvas?aaa=111 )以下のようにパラメータの値がWebページ表示されます。あとは "111" を他の値に変えたりして仕組みを理解しましょう。

スクリーンショット 2015-12-22 15.11.42.png

Salesforce Canvasに表示する

さて、前置きが長くなりましたが本題です。

まず接続アプリケーションの作成ですが基本的なSalesforce Canvasの設定についてはSFDC:Force.com CanvasでHerokuアプリと連携してみましたが詳しいです。

あえて補足しますと、以下のように "キャンバスアプリケーションの URL" に作成したエンドポイント(今回の例ですと https://node-red-123.herokuapp.com/canvas )アクセス方法を "署名付き要求(POST)" 、場所に "Visualforce ページ" を選択します。

スクリーンショット 2015-12-22 15.22.35.png

接続アプリケーションのアクセス方法を "署名付き要求(POST)" に設定したので以下のようにNode-REDのエンドポイントもPOSTメソッドを受け付けるように変更します。

スクリーンショット 2015-12-22 15.28.45.png

続いて以下のようにノードを配置してforce signed requestノードをダブルクリックして設定ダイアログを開きます。

スクリーンショット 2015-12-22 15.35.31.png

ここでSalesforceと接続する情報を設定するために以下のようにペンマークのアイコンをクリックします。

スクリーンショット 2015-12-22 15.38.14.png

以下のように "Login Type" は "login By Signed-Request" を選択して "User Name" に組織のユーザ名と "Client Secret" に接続アプリケーションの "コンシューマの秘密" を入力して "Add" ボタンをクリックします。

スクリーンショット 2015-12-22 15.43.33.png

ちなみに、ここで設定した組織のユーザ名は単なる目印なので以下のようにメールアドレス形式でもないものでも構いません。これで "OK" ボタンをクリックしてして設定ダイアログを閉じて "Deploy" ボタンをクリックしてデプロイします。

スクリーンショット 2015-12-22 15.50.24.png

最後にVisualforceページを用意します。詳しく説明しませんが接続アプリケーションが "test" という名前の場合は以下のような感じです。

<apex:page >
  <apex:canvasApp developerName="test"  />
</apex:page>

スクリーンショット 2015-12-22 15.53.05.png

これでプレビューを見てみましょう。以下のようにSalesforceから送られてきたSigned Requestが検証&デコードされてコンテキストがJSONとなって画面とNode-REDのデバッグに表示されればOKです。

スクリーンショット 2015-12-22 15.56.42.png

スクリーンショット 2015-12-22 16.03.12.png

Salesforceのデータを取得して画面にリスト表示する

これでSalesforce CanvasのSigned Requestでの認証はうまくいったので、このままNode-REDでSalesforce側のデータを取得してTemplateノードで表示してみましょう。

まずは以下のようにChangeノードを配置します。

スクリーンショット 2015-12-22 16.09.37.png

配置したChangeノードの設定ダイアログを開き(Changeノードをダブルクリック)以下のようにmsg.payloadSelect Id, Name From AccountというSOQL文字列をセットするように定義します。

スクリーンショット 2015-12-22 16.12.05.png

続いて以下のようにforceノードを配置します。

スクリーンショット 2015-12-22 16.21.59.png

配置したforceノードの設定ダイアログを開き(forceノードをダブルクリック)以下のように "Log in as" は先ほどforce signed requestノードで設定したアカウントと同じアカウントを選択、 "Operation" は "query" を選択してデプロイします。

スクリーンショット 2015-12-22 16.17.26.png

これでSalesforceからデータ取得できるか一旦試してみます。再度、先ほど作成したVisualforceページへアクセスします。以下のようにJSONでAccountの情報が表示されればOKです。

スクリーンショット 2015-12-22 16.24.18.png

これはChangeノードでSOQLをmsg.payloadにセットして流すことで、後続のforceノードが受け取ったSOQLを実行してデータを取得しているという流れです。

Node-REDでは前段のノードから後続ノードのパラメータを流して、後続の動作を動的にするテクニックをよく使います。これによって冗長なデータフローになるのを避けられます。

最後にTemplateノードを以下のように配置して...

スクリーンショット 2015-12-22 16.26.40.png

以下のように定義してデプロイして...

<ul>{{#payload.records}}<li>{{Id}} : {{Name}}</li>{{/payload.records}}</ul>

スクリーンショット 2015-12-22 16.31.09.png

再度、Visualforceページへアクセスして以下のように表示されたらOKです。

スクリーンショット 2015-12-22 16.33.23.png

まとめ

私が思うにNode-REDはSalesforceの外の世界でもビジュアルワークフロー&データフロー的なプロトタイピングでユーザと会話しながら要件の認識を合わせていくのに適したツールだと思います。

そのような使い方を可能にするためには気軽に誰でもどこでもインストールして使えるべきです。オープンソースソフトウェアの時点で、その大半はクリアしているのですが、今後も色々と考慮して発展していかないといけない点も多々あります。

そのためには様々な領域の有志が集い、様々なユースケースにおいてNode-REDを利用するにはどうしたら使いやすいかを考え発展させなければならないと思います。また、Node-REDは発展できるポテンシャルもあります。

貢献してみたい方は是非Node-REDユーザグループに参加しましょう!

おまけ

今回の設定(Node-REDではフローと呼びます)はJSONをインポートすると再現できます。インポートのやり方は以下のようにメニューから "Import > Clipboard" を選択して開いたダイアログに以下のJSONを貼付けます。

スクリーンショット 2015-12-22 16.36.02.png

[{
    "id": "4f9b24d7.b064dc",
    "type": "force",
    "z": "",
    "username": "",
    "loginurl": "https://login.salesforce.com",
    "logintype": "Signed-Request"
}, {
    "id": "68be3f5.f9741c",
    "type": "debug",
    "z": "569fcd48.a96034",
    "name": "",
    "active": true,
    "console": "false",
    "complete": "false",
    "x": 513,
    "y": 222,
    "wires": []
}, {
    "id": "d1e76ece.2e189",
    "type": "http in",
    "z": "569fcd48.a96034",
    "name": "",
    "url": "/canvas",
    "method": "post",
    "swaggerDoc": "",
    "x": 125,
    "y": 63,
    "wires": [
        ["f70ef5e8.08f108"]
    ]
}, {
    "id": "f70ef5e8.08f108",
    "type": "force signed request",
    "z": "569fcd48.a96034",
    "force": "4f9b24d7.b064dc",
    "name": "",
    "x": 320,
    "y": 64,
    "wires": [
        ["870ac031.78f54"]
    ]
}, {
    "id": "870ac031.78f54",
    "type": "change",
    "z": "569fcd48.a96034",
    "name": "",
    "rules": [{
        "t": "set",
        "p": "payload",
        "to": "Select Id, Name From Account"
    }],
    "action": "",
    "property": "",
    "from": "",
    "to": "",
    "reg": false,
    "x": 526,
    "y": 64,
    "wires": [
        ["9238e368.6dc72"]
    ]
}, {
    "id": "9238e368.6dc72",
    "type": "force in",
    "z": "569fcd48.a96034",
    "force": "4f9b24d7.b064dc",
    "operation": "query",
    "sobject": "",
    "extname": "",
    "name": "",
    "x": 128,
    "y": 135,
    "wires": [
        ["68be3f5.f9741c", "7612ac7f.89ed54"]
    ]
}, {
    "id": "5e74439f.a18bbc",
    "type": "http response",
    "z": "569fcd48.a96034",
    "name": "",
    "x": 494,
    "y": 135,
    "wires": []
}, {
    "id": "7612ac7f.89ed54",
    "type": "template",
    "z": "569fcd48.a96034",
    "name": "",
    "field": "payload",
    "format": "handlebars",
    "template": "<ul>{{#payload.records}}<li>{{Id}} : {{Name}}</li>{{/payload.records}}</ul>",
    "x": 310,
    "y": 137,
    "wires": [
        ["5e74439f.a18bbc"]
    ]
}]