Ateam Brides Inc. Advent Calendar 2021の6日目は
株式会社エイチームブライズ エンジニア
新卒2年目になった@takaHALが担当します!
これは何?
Lambdaで作ったAPIをSalesforceの外部サービスに登録し
SalesforceのフローからLambdaを実行してみます。
使うもの
-
AWS
- Lambda
- IAM
- APIGateway
- CloudWatch
- 意識して使うのはこの4つ
-
ServerlessFramework
-
Salesforce
- 外部サービス
- 指定ログイン情報
利用するSalesforce環境はtrailheadのplayground環境です。
trailheadに登録すれば誰でも利用できます。
外部サービスとは
OpenAPIのJSONファイルを登録することで、フロー内でOpenAPIに書かれた定義でREST APIを実行できます。
ノーコードでAPIを実行するフローアクションが作成できるので非常に便利なものになってます
レスポンスも受け取ることができるため複雑なロジックもSalesforceの外部に置けるのもいいポイントです。
先にtrailhead
をやっておくとイメージがしやすいと思います。
では早速やっていきましょう
AWS側の準備
ServerlessFrameworkを利用します。
詳しい説明はServerless Framework の使い方を初心者にも分かりやすく説明するで書いてくださっているのでお勧めです。
デプロイに必要なIAMやAWSは準備してある前提で進めます
あくまでもメインはSalesforceなのでAWSとServerlessFramework部分はサクッと済ませます。
1. プロジェクトを作成
開発環境
$ serverless --version
Framework Core: 2.68.0 (local)
Plugin: 5.5.1
SDK: 4.3.0
Components: 3.18.1
$ node -v
v17.1.0
$ mkdir salesforce-lambda-test
$ cd salesforce-lambda-test
$ serverless create --template aws-nodejs-typescript --name salesforce-lambda-test
2. AWSにデプロイ
今回利用したプロジェクトのテンプレートバージョンは以下になります
$ npm install
$ sls deploy
service: salesforce-lambda-test
stage: dev
region: us-east-1
stack: salesforce-lambda-test-dev
resources: 13
api keys:
None
endpoints:
POST - https://{hoge}.us-east-1.amazonaws.com/dev/hello
functions:
hello: salesforce-lambda-test-dev-hello
layers:
None
3. 外部サービスに利用する openapiのjsonファイルを用意する
SalesforceのOpenAPI 2.0 スキーマ定義
は少しクセがあるので、今回はサクッと検証するためにtrailheadのサンプルを少しいじって利用させていただきます。
実際はAPIGatewayの画面からエクスポートしたりdocumentation
として登録するといいと思います。
{
"swagger": "2.0",
"info": {
"version": "1.0",
"title": "Salesforce test"
},
"paths": {
"/hello": {
"post": {
"operationId": "apiHello",
"consumes": ["application/json"],
"produces": ["application/json"],
"parameters": [
{
"name": "accountName",
"in": "formData",
"required": true,
"type": "string",
"description": "Name of the account"
},
{
"name": "accountType",
"in": "formData",
"required": true,
"type": "string",
"description": "The type of account"
}
],
"responses": {
"201": {
"description": "The response when the account does not already exist and we can create one",
"schema": { "$ref": "#/definitions/accountDetails" }
},
"409": {
"description": "The response when the account already exists and we cannot create one",
"schema": { "$ref": "#/definitions/accountDetails" }
},
"400": {
"description": "Error response if the account name parameter is less than minimum characters",
"schema": { "$ref": "#/definitions/errorModel" }
},
"404": {
"description": "Error response if the account is not supported by service or account is not found",
"schema": { "$ref": "#/definitions/errorModel" }
}
}
}
}
},
"definitions": {
"accountDetails": {
"required": ["id", "name", "type", "availableBal"],
"properties": {
"id": { "type": "string", "description": "id" },
"name": { "type": "string", "description": "name" },
"type": { "type": "string", "description": "type" },
"availableBal": { "type": "string", "description": "availableBal" }
}
},
"errorModel": {
"required": ["errorCode", "errorMessage"],
"properties": {
"errorCode": {
"type": "string",
"description": "A service-specific error code."
},
"errorMessage": {
"type": "string",
"description": "A service-specific error code."
}
}
}
}
}
4. IAMを作成する
SalesforceからAPIGatewayを通じでLambdaを実行するために使用するIAMを作成します。
AmazonAPIGatewayInvokeFullAccess
を今回はとりあえず付与しました。
作成したらアクセスキーとシークレットアクセスキーをメモしておきましょうあとで使います。
これでAWS側の設定等の操作は終了です。
Salesforceで外部サービスを登録する
1. 指定ログイン情報の作成
項目 | 内容 |
---|---|
URL | デプロイしたAPIのエンドポイントを記入 |
ID種別 | AWS 署名バージョン4 を選択 |
AWSアクセスキーID | 作成したIAMのアクセスID |
AWSシークレットキー | 作成したIAMのシークレットキー |
AWSリージョン | デプロイしたAPIのリージョン 例) us-east-1 |
AWS サービス | 今回はAPIGatewayにアクセスするので apigateway と記載します |
コールアウトオプション | 全部オフです |
そのまま好きな名前で保存でOKです。
しかし、リージョンとサービスにそのまま 文字列入れるの微妙にいけてないですね。。。。
そもそもここら辺は早くHyperforceでデフォルトでLambdaとかと繋げれるようにしてくれると楽なので今後に期待ですね。
2. 外部サービスの登録
外部サービスを新規作成でAPI仕様からを選択
### 外部サービスを設定
指定ログイン情報
に先程登録したものを選択し、JSON形式の完全なサービススキーマ
を選択
AWS側の準備で準備したものを使います
そのまま登録でOK
フローで外部サービスを使ってみる
1. フローを新規作成
今回はデバッグ実行で動作確認するのみなのでどれでもいいです。今回はスケジュールトリガーフローにしてみます。
2. アクションを追加
外部サービスとして登録したものがフローのアクションとして選択できるので選択します。
入力値で選択できるのはparameters
に記載したものになってます。
"parameters": [
{
"name": "accountName",
"in": "formData",
"required": true,
"type": "string",
"description": "Name of the account"
},
{
"name": "accountType",
"in": "formData",
"required": true,
"type": "string",
"description": "The type of account"
}
],
ちなみに詳細の部分ではresponsesに記載した内容が取得できることがわかります。これでフローを200の時の値を使用したりエラーハンドリングもできますね
"responses": {
"201": {
"description": "The response when the account does not already exist and we can create one",
"schema": { "$ref": "#/definitions/accountDetails" }
},
"409": {
"description": "The response when the account already exists and we cannot create one",
"schema": { "$ref": "#/definitions/accountDetails" }
},
"400": {
"description": "Error response if the account name parameter is less than minimum characters",
"schema": { "$ref": "#/definitions/errorModel" }
},
"404": {
"description": "Error response if the account is not supported by service or account is not found",
"schema": { "$ref": "#/definitions/errorModel" }
}
}
3. デバッグして確認してみる
実行できていますね
CloudWatch側でも確認が取れました。
今回は"in": "formData"
で送信しているので accountName=hoge&accountType=fuga
みたいな形式でデータが送られます。
"parameters": [
{
"name": "accountName",
"in": "formData",
"required": true,
"type": "string",
"description": "Name of the account"
},
{
"name": "accountType",
"in": "formData",
"required": true,
"type": "string",
"description": "The type of account"
}
],
リクエストボディパラメータがメソッド POST、PUT、PATCH について定義されていない場合、フォームデータリクエストパラメータがリクエストボディで application/x-www-form-urlencoded として送信されます
application/json
でデータを送信したい場合は下記のように"in": "body",で記載すると送信できます。
その際はフロー内で変数を作成する際に種別でApex定義を選択しましょう"type": "object",の中身が個別設定できる変数になってくれます。
"consumes": ["application/json"],
"produces": ["application/json"],
"parameters": [
{
"name": "requests",
"in": "body",
"required": true,
"schema": { "$ref": "#/definitions/Requests" },
}
],
"responses": {
"200": {
"description": "OK"
},
"405": {
"description": "Invalid input"
}
}
}
}
},
"definitions": {
"Requests": {
"type": "object",
"required": ["requestId", "name"],
"properties": {
"requestId": {
"type":"integer"
},
"name": {
"type": "string"
},
}
}
}
}
テストで作成したAWSのリソースを削除
削除する場合は以下のコマンドです
$ sls remove
参考にさせてもらった記事
最後に
Salesforce関係の開発を触り始めて日が浅いですが、フローを使って外部APIと連携してみたりデータ連携をコードをほぼ書かなくてもいいようにできないかな?と思っていたところ外部サービス
というものを見つけたので試してみました。
通常のopenapiの記述よりも癖はありますが、使いこなすと非常に便利な機能だと思いますので自分でもマスターしようと思います。
外部サービスをうまく使えば以下のようなことがSalesforce内でApexを書くことなく実現できます。
- 複雑な計算ロジックをSalesforceに持ち込むことなく利用できる
- Salesforce外の自社サービスのデータとコラボレーションしやすい
などいろいろできそうです。
外部サービスとは違いますが、Apexで@InvocableMethod
を使うとフローアクションを作成できるのでそちらもお勧めです。
sObject
型を受け取ることができるので、レコードの更新をトリガーにしてBigQueryにオブジェクトのデータを送るとかさまざまな用途で使えると思います。
もう少し記事を更新していくつもりではいますが、質問やこっちの方がいいよ!みたいな意見があれば是非コメントにていただきたいです。
Ateam Brides Inc. Advent Calendar 2021の7日目は、@rf_pがお送りします!!どんなネタを用意してくるのか楽しみです!!