
フローのHTTPコールアウトアクションと変換要素を使ってノーコードでGoogleタスクと連携してみた
はじめに
こんにちは、荒武です。この記事はWinter '24で正式リリースとなったフローのHTTPコールアウトアクションとWinter '24でベータになったデータ変換要素を利用して下記を実行する画面フローをそれぞれ作るチュートリアルとなっています。
GoogleタスクをもとにしたTodoの作成
TodoをもとにしたGoogleタスクの作成
記事に沿って手を動かすとフローでのHTTPコールアウトアクションおよび変換要素の使い方が一通り学べると思います。
フローのHTTPコールアウトアクションとは
フローのHTTPコールアウトアクションはWinter '24で正式リリースとなった機能で、ノーコードでフローからAPI通信を可能にする仕組みです。これまで外部サービスアクションを使うことでフロー上でのAPI呼び出しは可能だったのですが、HTTPコールアウトを用いると外部サービスの作成が自動で行われるので、事前に外部サービスを作成する必要がなくなります。
フローの変換要素とは
フローの変換要素はWinter '24からベータとなった機能で、あるデータから別のデータへ変換するための要素です。変換要素を用いるとこれまで割当要素を使って行われていたであろう、あるデータから別のデータへの変換処理を直感的なUIから簡単に行うことができるようになります。

準備
認証情報の設定
Flow BuilderでHTTP コールアウトアクションを設定する前に、外部システムへの呼び出しを認証するための指定ログイン情報を設定する必要があります。
ユースケースに応じて、以下の項目を設定します。
コールアウトを実行するためのアクセス権限 (必須): ドキュメントに記載は見当たらなかったのですが、外部ログイン情報プリンシパルへのアクセス権限と思われます。
認証プロバイダー : OAuthプロトコルの使用事例でのみ必要
外部ログイン情報(必須): 認証の定義。認証が不要なAPI場合は認証プロトコルで認証なしを選択すればよさそうです。
指定ログイン情報(必須) : HTTPコールアウトアクションで呼び出すAPIのエンドポイントと外部ログイン情報を紐づける
ユーザーログイン情報オブジェクトへのアクセス権限: コールアウト実行時にオブジェクトに アクセスする必要があるので権限セット等を用いてユーザーに権限を付与する。認証が不要なOpen APIの場合は不要。
以下で作成した権限セット、認証プロバイダー、外部ログイン情報、指定ログイン情報のメタデータをのせています。通常は画面から作成すると思うのでこれらのメタデータを参考に作成してください。
今回作成した権限セットのメタデータは以下になります。外部ログイン情報プリンシパルとユーザーログイン情報オブジェクトにアクセスするための権限を付与しています。
<?xml version="1.0" encoding="UTF-8"?>
<PermissionSet xmlns="http://soap.sforce.com/2006/04/metadata">
<externalCredentialPrincipalAccesses>
<enabled>true</enabled>
<externalCredentialPrincipal>google-google_principal</externalCredentialPrincipal>
</externalCredentialPrincipalAccesses>
<hasActivationRequired>false</hasActivationRequired>
<label>google</label>
<objectPermissions>
<allowCreate>true</allowCreate>
<allowDelete>true</allowDelete>
<allowEdit>true</allowEdit>
<allowRead>true</allowRead>
<modifyAllRecords>false</modifyAllRecords>
<object>UserExternalCredential</object>
<viewAllRecords>false</viewAllRecords>
</objectPermissions>
</PermissionSet>
認証プロバイダーのメタデータは以下になります。GoogleTasksにアクセスするためにOAuth認証が必要なので認証プロバイダーが必要となります。
<?xml version="1.0" encoding="UTF-8"?>
<AuthProvider xmlns="http://soap.sforce.com/2006/04/metadata">
<consumerKey>MY_CLIENT_ID</consumerKey>
<consumerSecret>MY_SECRET_KEY</consumerSecret>
<friendlyName>google_provider</friendlyName>
<includeOrgIdInIdentifier>false</includeOrgIdInIdentifier>
<isPkceEnabled>true</isPkceEnabled>
<providerType>Google</providerType>
<requireMfa>false</requireMfa>
<sendAccessTokenInHeader>false</sendAccessTokenInHeader>
<sendClientCredentialsInHeader>false</sendClientCredentialsInHeader>
<sendSecretInApis>true</sendSecretInApis>
</AuthProvider>
外部ログイン情報のメタデータは以下になります。Google Tasks APIにアクセスするためのスコープを指定しています。
<?xml version="1.0" encoding="UTF-8"?>
<ExternalCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<authenticationProtocol>Oauth</authenticationProtocol>
<externalCredentialParameters>
<authProvider>google_provider</authProvider>
<parameterGroup>DefaultGroup</parameterGroup>
<parameterName>AuthProvider</parameterName>
<parameterType>AuthProvider</parameterType>
</externalCredentialParameters>
<externalCredentialParameters>
<parameterGroup>google_principal</parameterGroup>
<parameterName>google_principal</parameterName>
<parameterType>PerUserPrincipal</parameterType>
<sequenceNumber>1</sequenceNumber>
</externalCredentialParameters>
<externalCredentialParameters>
<parameterGroup>DefaultGroup</parameterGroup>
<parameterName>Scope</parameterName>
<parameterType>AuthParameter</parameterType>
<parameterValue>https://www.googleapis.com/auth/tasks openid</parameterValue>
</externalCredentialParameters>
<label>google</label>
</ExternalCredential>
指定ログイン情報のメタデータは以下になります。
<?xml version="1.0" encoding="UTF-8"?>
<NamedCredential xmlns="http://soap.sforce.com/2006/04/metadata">
<allowMergeFieldsInBody>false</allowMergeFieldsInBody>
<allowMergeFieldsInHeader>false</allowMergeFieldsInHeader>
<calloutStatus>Enabled</calloutStatus>
<generateAuthorizationHeader>true</generateAuthorizationHeader>
<label>google_auth</label>
<namedCredentialParameters>
<parameterName>Url</parameterName>
<parameterType>Url</parameterType>
<parameterValue>https://tasks.googleapis.com</parameterValue>
</namedCredentialParameters>
<namedCredentialParameters>
<externalCredential>google</externalCredential>
<parameterName>ExternalCredential</parameterName>
<parameterType>Authentication</parameterType>
</namedCredentialParameters>
<namedCredentialType>SecuredEndpoint</namedCredentialType>
</NamedCredential>
Google API OAuth 2.0 クライアントの作成
Google Tasks APIを利用する必要があるので、GCPのプロジェクトの「APIとサービス」からGoogle Tasks APIを有効にします。

次にOAuth 同意画面とOAuth2.0クライアントIDを作成します。OAuth2.0クライアントIDの承認済みのリダイレクトURIには作成した認証プロバイダーのコールバックURLを設定します。


タスクからTodoを作成
これまでの設定でHTTPコールアウトを作成する準備ができたので実際にフローからGoogle TasksAPIを呼び出し、Google TaskからTodoを作成する画面フローを作成していきます。

タスクリスト取得(GET)のためのHTTPコールアウトアクションの作成
まず、新規に画面フローを作成し、アクション要素を追加します。その際に「HTTPコールアウトを作成」を選択し、タスクリスト取得のためのHTTPコールアウトアクションを追加します。(タスクリストの取得から行うのはAPIを使ってタスクを取得する際、タスクリストのIDが必要だからになります。)

するとHTTPコールアウトアクションの設定画面が表示されるので名前と作成した指定ログイン情報を設定します。

次にラベル、メソッドタスクリストを取得するURLパスを設定します。

次にサンプル応答方法を設定します。「応答の例を使用」を選択します。サンプルとなるレスポンスのJSONを入力し、サンプルレスポンスを設定します。

JSONサンプル
{
"kind": "sample string",
"etag": "sample string",
"items": [
{
"kind": "sample string",
"etag": "sample string",
"id": "sample string",
"title": "sample string",
"updated": "2017-07-21T17:32:28Z",
"selfLink": "sample string"
}
]
}
因みに「スキーマ用に接続」はSpring24から利用可能になった選択肢で、リアルタイムにAPIを呼び出し、設定時点でのレスポンスをサンプルレスポンスとして利用できるというものです。(完璧なレスポンスを生成するためにデータを作成しなければならのが少し面倒な場合もありそうですね)

詳細の「手動で変数を割り当て」にチェックを入れ、レスポンスである2XXから自動生成された同名のApexクラスの変数を割り当てた後、アクションのラベルとAPI参照名を入力して保存(完了)します。(本来であれば手動で割り当てずとも、自動変換されたものをそのまま利用できるはずのですが、自動変換の場合itemsをloop要素のコレクション変数として利用できないなど、うまく動作しなかったので手動で変数に割当てています。)


タスク取得(GET)のためのHTTPコールアウトアクションの作成
取得したそれぞれのタスクリストに紐づいたタスクを取得するのでループ要素を作成します。コレクション変数には作成したタスクリスト取得レスポンスのApexクラス変数のitemsを指定します。

次に繰り返し内の要素にタスク取得のためのHTTPコールアウトアクションをタスクリスト取得のそれと同様に追加します。




JSONサンプル
{
"kind": "sample string",
"etag": "sample string",
"nextPageToken": "sample string",
"items": [
{
"parent": "sample string",
"notes": "sample string",
"hidden": true,
"kind": "sample string",
"completed": "2017-07-21T17:32:28Z",
"title": "sample string",
"selfLink": "sample string",
"deleted": true,
"due": "2017-07-21T17:32:28Z",
"links": [
{
"link": "sample string",
"description": "sample string",
"type": "sample string"
}],
"etag": "sample string",
"id": "sample string",
"position": "sample string",
"updated": "2017-07-21T17:32:28Z",
"status": "sample string"
}
]
}
タスクリストと同様に詳細の「手動で変数を割り当て」にチェックを入れ、レスポンスである2XXから自動生成された同名のApexクラスの変数を割り当て、URLパスの値にループ要素(タスクリスト)のidを指定し、保存(完了)します。

タスクのコレクションを作成
すべてのタスクを参照できるようにタスクをループしてタスク取得レスポンスのitemsのApexクラス型のコレクション変数を作成し追加していきます。



Todoに変換するタスク選択画面の作成
変換対象のタスクを選択できるように選択肢入力は配置された画面要素を追加します。選択肢には作成したコレクション変数をもとにしたコレクション選択肢セットを作成し、指定します。


Todoレコードへの変換
選択されたタスクをタスクのコレクション変数から絞り込み、変換要素を用いてTodoレコードへ変換します。



実行
個人情報の外部ログイン設定から作成した外部ログイン情報の認証を済ませた後、フローを実行するとTodoが作成されていることが確認できます。



Todoからタスクを作成
本項では前項とは逆にTodoをもとにタスクを作成するフローを作っていきます。

タスクリスト取得(GET)のためのHTTPコールアウトアクション要素の追加
まず新たに画面フローを作成します。タスクを作成のリクエストにはタスクの追加先になるタスクリストのIDが必要なのでの前項で作成したタスクリストを取得するHTTPコールアウトアクション要素を追加し、同様に手動で変数を割り当てを行います。

コレクション選択肢セットの作成
変換したApexクラスを用いてタスクリストを選択リストから指定できるようにするため、新たなリソースに、レスポンスのitemsをコレクションとして指定したコレクション選択肢セットを追加します。

タスクに変換するTodo選択画面の作成
変換するTodoとタスクリストを選択できる画面要素を作成します。Todoレコード選択はレコード選択肢リソースを用い、タスクリスト選択にははタスクリストのコレクション選択肢セット変数を用います。


タスク作成(POST)のためのHTTPコールアウトアクションの作成
次にタスクを作成(POST)するためのHTTPコールアウトアクション要素を追加していきます。


タスク作成時にタイトルと期限を入力したいのでtitleとdueをサンプルJSON 要求に入力します。

JSONサンプル
{
"title": "sample string",
"due": "2017-07-21T17:32:28Z"
}
レスポンスのサンプルを入力し、保存します。

JSONサンプル
{
"parent": "sample string",
"notes": "sample string",
"hidden": true,
"kind": "sample string",
"completed": "2017-07-21T17:32:28Z",
"title": "sample string",
"selfLink": "sample string",
"deleted": true,
"due": "2017-07-21T17:32:28Z",
"links": [
{
"link": "sample string",
"description": "sample string",
"type": "sample string"
}],
"etag": "sample string",
"id": "sample string",
"position": "sample string",
"updated": "2017-07-21T17:32:28Z",
"status": "sample string"
}
URLパスにはタスクリスト選択肢の値を設定します。

選択されたTodoのリクエストボディへの変換
選択されたTodoレコードを取得するための要素とTodoレコードをリクエストボディApexクラスへ変換するための変換要素をタスク作成アクションの前に追加し、変換した要素をタスク作成アクションのbodyに指定します。



実行
フローを保存して実行すると、新たにタスクが作成されていることが確認できます。



Tips
この章ではチュートリアルでは触れなかった補足情報を紹介します。
HTTPコールアウトアクションの修正
HTTPコールアウトアクションの修正は紐付いた外部サービスのドロップダウンメニューから行うことができます。


OpenAPIスキーマからのHTTPコールアウトアクションの作成
こちらは不可能です。FlowBuilder上でOpenAPIスキーマからHTTPコールアウトアクションを作成することはできません。OpenAPIスキーマを用いたい場合、基本的に外部サービスを作成し、外部サービスアクションを使うのが良いと思われます。ただ、HTTPコールアウトアクションに紐付いた外部サービスのスキーマに直接な軽微な変更を加えてみたところ問題なく動いていたので、もしかすると1度HTTPコールアウトアクションを作成した後に自動生成された外部サービススキーマを本来のOpenAPIスキーマで上書きする方法でもいけるかもしれないです。
HTTPコールアウトアクションの出力内のコレクションがループで直接利用できないことがある
チュートリアル中でも記載したのですが、HTTPコールアウトアクションの出力内にApexクラスのコレクションの値がある場合、そのままループ要素のコレクションとして指定できないことがありました。いろいろなレスポンスで試してみたのですが、そのままループ要素のコレクションとして指定できるケースのほうが少なく、基本的には手動でApexクラスの変数に割り当てる必要がありそうでした。
おわりに
いかがでしたでしょうか。指定ログイン情報や権限の設定さえ済んでいれば、画面をポチポチするだけで簡単にGoogleタスクと連携できちゃいましたね。
HTTPコールアウトアクションの良いところはAPIのレスポンスとリクエストの内容さえ把握していれば、APIがOpenAPIに対応していないくてもフロービルダーからいい感じに外部サービスとそれを利用するためのアクションを作成してくれるところ、変換要素の良いところは煩わしい割当を直感的なUIで行えるところなのかなと思いました。
HTTPコールアウトの注意点としてはリクエストのbodyやレスポンスのJSONが正しいものになるよう注意しなければならない点が挙げられるかもしれません。例えばレスポンスのJSONに値が足りなかった場合はその値はApex
クラスのプロパティには含まれず、フローでも利用できません。そのため利用するAPIがOpenAPIに対応している場合は外部サービスアクションを用いた方が間違いがなくて良いかもしれません。したがってAPIがOpenAPIに対応していなかったらHTTPコールアウトアクションを利用する、対応していたら外部サービスアクションを利用する、というように使い分けるとよさそうです。