この記事は「make Advent Calendar 2024」23日目の記事です。
このアドベントカレンダーについて
このアドベントカレンダーは25日間でIPaaS製品の「make」について使い方や、実践を学べる連続ブログ企画です。
「おかしん」「ばるす」「たにあん」の3名がリレー形式でお届けします。
25日間のスケジュールは以下の通りです。
| 日付 | 内容 | 担当 |
| 12/1 | 話題のIPaaS製品「make」とは | おかしん |
| 12/2 | makeで作ってみたScenario紹介 | ばるす |
| 12/3 | make 基本操作編 機能紹介:Organization | たにあん |
| 12/4 | make 基本操作編 機能紹介:Scenario、Template | おかしん |
| 12/5 | make 基本操作編 機能紹介:Connections | ばるす |
| 12/6 | make 基本操作編 機能紹介:Webhooks | たにあん |
| 12/7 | make 基本操作編 機能紹介:DataStores、DataStructures | おかしん |
| 12/8 | make 基本操作編 機能紹介:Devices | ばるす |
| 12/9 | make 基本操作編 機能紹介:Functions | たにあん |
| 12/10 | make 基本操作編 機能紹介:CustomApps | おかしん |
| 12/11 | make 基本操作編 機能紹介:Flow Control,Tools,Text parser | ばるす |
| 12/12 | make ドキュメント動線の話:ResourceHub | たにあん |
| 12/13 | make 検証:Make Bridge | おかしん |
| 12/14 | make 検証:Make REST API | ばるす |
| 12/15 | make 検証:AI Search | たにあん |
| 12/16 | make Community Hub:Overview | おかしん |
| 12/17 | make Community Hub:Academy Courses,Blog Articles | ばるす |
| 12/18 | make Community Hub:Showcase,CustomApps | たにあん |
| 12/19 | makeの管理運用の話:Github連携 | おかしん |
| 12/20 | makeの管理運用の話:実行ログと再実行と停止中リクエスト滞留 | ばるす |
| 12/21 | makeの管理運用の話:Connection権限管理 | たにあん |
| 12/22 | makeで作ってみた事例:(未定) | おかしん |
| 12/23 | makeで作ってみた事例:(未定) | ばるす |
| 12/24 | makeで作ってみた事例:(未定) | たにあん |
| 12/25 | makeの総論を語る | ばるす |
はじめに
どーもばるすです。
いよいよこのアドベントカレンダーも大詰めですね。
ブログの掲載順が前後しているのは時空のゆがみです。ご容赦ください。
色々とmakeの機能をご紹介してきましたが、今日は実際に弊社で動かしているScenarioの事例について書きます。
処理フロー概要
Scenario全体像

これが動くとどうなるか
Asanaのタスクのステータスを変更すると、Salesforceのレコード情報も同様に変更されます。

フロー詳細:作り方
1.トリガー部分の設定
1-a.makeでWebhookトリガーのScenarioを作成
1-a-1.Webhook作成時、Get request headers にYesを入れる

1-a-2.DataStructureを作成し、Generate をクリック

1-a-3.以下のJsonを貼り付け

{
"value": "{}",
"__IMTHEADERS__": [
{
"name": "connection",
"value": "upgrade"
},
{
"name": "x-real-ip",
"value": "xxx.xxx.xxx.xxx"
},
{
"name": "x-request-id",
"value": "24fxxxxxxxxxx"
},
{
"name": "content-length",
"value": "2"
},
{
"name": "cdn-loop",
"value": "cloudflare; loops=1"
},
{
"name": "cf-ipcountry",
"value": "US"
},
{
"name": "accept-encoding",
"value": "gzip, br"
},
{
"name": "cf-ray",
"value": "8f6cfcf65b5d0a17-IAD"
},
{
"name": "cf-visitor",
"value": "{\\"scheme\\":\\"https\\"}"
},
{
"name": "content-type",
"value": "application/json"
},
{
"name": "user-agent",
"value": "Asana"
},
{
"name": "x-hook-secret",
"value": "567xxxxxxxxxxxxxxxxxx"
},
{
"name": "cf-connecting-ip",
"value": "xxx.xxx.xxx.xxx"
}
],
"__IMTMETHOD__": "POST"
}
1-a-4.作成するとWebhookURLが生成されるのでこれを控えておく

1-b.Heartbeatを返す処理を追加
1-b-1.WebhookトリガーからWebhook Responseを延ばす

1-b-2.WebhookResponseを設定

Webhookの初回登録時と、登録以降定期的に飛んでくるHeartbeatリクエストへの処理方法は同じです。
3.AsanaにWebhook登録
初回だけなので好みのやり方でOKです。
※Webhook登録にはAsanaのAPI Tokenが必要です。
リクエストURL:https://app.asana.com/api/1.0/webhooks
リクエストBody
{
"data": {
"filters": [
],
"resource": "[task_gid]",
"target":"[Webhook_URL]"
}
}
※Filtersの例
{
"action": "changed",
"resource_type": "task"
}
Pattern1:APIリクエストツールでやる場合

Pattern2:makeでリクエストする場合

どちらでもやることは変わりません。お好みで。もちろんGASとかでも可能です。
{
"value": "{}",
"__IMTHEADERS__": [
{
"name": "connection",
"value": "upgrade"
},
{
"name": "x-real-ip",
"value": "xxx.xxx.xxx.xxx"
},
{
"name": "x-request-id",
"value": "24fxxxxxxxxxx"
},
{
"name": "content-length",
"value": "2"
},
{
"name": "cdn-loop",
"value": "cloudflare; loops=1"
},
{
"name": "cf-ipcountry",
"value": "US"
},
{
"name": "accept-encoding",
"value": "gzip, br"
},
{
"name": "cf-ray",
"value": "8f6cfcf65b5d0a17-IAD"
},
{
"name": "cf-visitor",
"value": "{\"scheme\":\"https\"}"
},
{
"name": "content-type",
"value": "application/json"
},
{
"name": "user-agent",
"value": "Asana"
},
{
"name": "x-hook-secret",
"value": "567xxxxxxxxxxxxxxxxxx"
},
{
"name": "cf-connecting-ip",
"value": "xxx.xxx.xxx.xxx"
}
],
"__IMTMETHOD__": "POST"
}
2回目以降のリクエスト
[
{
"value": {
"events": [
{
"user": {
"gid": "119xxxxxxxxxxxxxx",
"resource_type": "user"
},
"created_at": "2024-12-24T20:56:02.103Z",
"action": "removed",
"resource": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "story",
"resource_subtype": "section_changed"
},
"parent": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "task",
"resource_subtype": "default_task"
}
},
{
"user": {
"gid": "1199xxxxxxxxxxxxx",
"resource_type": "user"
},
"created_at": "2024-12-24T20:56:02.167Z",
"action": "added",
"resource": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "story",
"resource_subtype": "section_changed"
},
"parent": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "task",
"resource_subtype": "default_task"
}
},
{
"user": {
"gid": "1199xxxxxxxxxxxxx",
"resource_type": "user"
},
"created_at": "2024-12-24T20:56:01.983Z",
"action": "added",
"resource": {
"gid": "12090xxxxxxxxxxxxx",
"resource_type": "task",
"resource_subtype": "default_task"
},
"parent": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "section"
}
}
]
},
"__IMTHEADERS__": [
{
"name": "connection",
"value": "upgrade"
},
{
"name": "x-real-ip",
"value": "172.68.245.55"
},
{
"name": "x-request-id",
"value": "2eda1xxxxxxxxxxxxx"
},
{
"name": "content-length",
"value": "903"
},
{
"name": "cdn-loop",
"value": "cloudflare; loops=1"
},
{
"name": "cf-ipcountry",
"value": "US"
},
{
"name": "accept-encoding",
"value": "gzip, br"
},
{
"name": "cf-ray",
"value": "xxxxxxxxxxxxx-IAD"
},
{
"name": "cf-visitor",
"value": "{\"scheme\":\"https\"}"
},
{
"name": "content-type",
"value": "application/json"
},
{
"name": "user-agent",
"value": "Asana"
},
{
"name": "x-hook-signature",
"value": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"name": "x-asana-request-signature",
"value": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"name": "cf-connecting-ip",
"value": "xxx.xxx.xxx.xxx"
}
],
"__IMTMETHOD__": "POST"
}
]
2.分岐、Request Body整形処理の追加
2−a.Routerを追加する
2−a−1.JsonParser を追加

!)どこともつながってないっすよってエラーが出るけど気にしない

2−a−2.JsonからWebhookトリガーへ線を延ばす

2−a−3.Routerが追加されるので、赤枠部分の通過条件を入力する

1st の条件:リクエストのHeaderの12個目の要素が’x-hook-secret’である

2ndの条件:リクエストのHeaderの12個目の要素が’x-hook-secret’ではない

2-b.リクエスト内容の判別に使うデータを成形する
2-b-1.Json ParserのData StructureをAdd

2-b-2.Generateをクリックし以下のJsonを追加

[
{
"value": {
"events": [
{
"user": {
"gid": "119xxxxxxxxxxxxxx",
"resource_type": "user"
},
"created_at": "2024-12-24T20:56:02.103Z",
"action": "removed",
"resource": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "story",
"resource_subtype": "section_changed"
},
"parent": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "task",
"resource_subtype": "default_task"
}
},
{
"user": {
"gid": "1199xxxxxxxxxxxxx",
"resource_type": "user"
},
"created_at": "2024-12-24T20:56:02.167Z",
"action": "added",
"resource": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "story",
"resource_subtype": "section_changed"
},
"parent": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "task",
"resource_subtype": "default_task"
}
},
{
"user": {
"gid": "1199xxxxxxxxxxxxx",
"resource_type": "user"
},
"created_at": "2024-12-24T20:56:01.983Z",
"action": "added",
"resource": {
"gid": "12090xxxxxxxxxxxxx",
"resource_type": "task",
"resource_subtype": "default_task"
},
"parent": {
"gid": "1209xxxxxxxxxxxxx",
"resource_type": "section"
}
}
]
},
"__IMTHEADERS__": [
{
"name": "connection",
"value": "upgrade"
},
{
"name": "x-real-ip",
"value": "172.68.245.55"
},
{
"name": "x-request-id",
"value": "2eda1xxxxxxxxxxxxx"
},
{
"name": "content-length",
"value": "903"
},
{
"name": "cdn-loop",
"value": "cloudflare; loops=1"
},
{
"name": "cf-ipcountry",
"value": "US"
},
{
"name": "accept-encoding",
"value": "gzip, br"
},
{
"name": "cf-ray",
"value": "xxxxxxxxxxxxx-IAD"
},
{
"name": "cf-visitor",
"value": "{\\"scheme\\":\\"https\\"}"
},
{
"name": "content-type",
"value": "application/json"
},
{
"name": "user-agent",
"value": "Asana"
},
{
"name": "x-hook-signature",
"value": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"name": "x-asana-request-signature",
"value": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
},
{
"name": "cf-connecting-ip",
"value": "xxx.xxx.xxx.xxx"
}
],
"__IMTMETHOD__": "POST"
}
]
2-b-3.Json String にValueを入れる

2-c.WebhookResponse処理を入れる
200を返すだけでOKです。

ここまでで基本的なAsana Webhookの処理は完了です。
テンプレにしとくと楽です。
3.データ更新処理(SAMPLE)
3-a.AsanaのタスクIDを元にSalesforceのレコードを取得

3−b.Asanaのタスク詳細を取得

3-c.取得した内容でSalesforceのレコードを更新

以上で、主なデータ更新系の処理も追加完了です。
トリガー、Webhookの処理が複雑な一方で、データ更新系の処理はシンプルです。
応用例
- Asanaのタスクが完了されたら、コメント欄を取得してKintoneに記載
- Asanaのタスクが新規追加されたら、概要欄をAIに記載させる
- Asanaのタスクが完了されたら、後続のタスクを新規作成して担当者をアサインしSlackに通知
おわりに
以上、AsanaのWebhook APIを用いたデータ更新処理系のScenarioをご紹介しました。長かった…
実はこれ、Workatoでは実現不可なんですよね。
WorkatoってWebhookリクエストへのレスポンスをカスタマイズできないので、AsanaのWebhook APIの初回登録ができないのです。
WorkatoはWorkatoで使いやすいし、やはり使っていて細部まで設計されてて良いなと思うんですけど、Asana Webhook APIについてはWorkatoと相性悪いものでした。
まあiPaaSでWebhookレスポンスをカスタマイズできるものの方が珍しいです。これはmakeがすごい。
iPaaSに限った話ではないのですが、こういう自動化を組むときに一番時間がかかるのはデータの変換処理とかトリガーの設定とかエラーハンドリングなんですよね。
今回の内容からエラーハンドリングは割愛しましたが、以後運用していく場合にはいくつか想定できるエラーのパターンに合わせて、エラー時の処理を追加していく必要があります。
エラーハンドリングについてはまた後日かなー。これだけですごい長くなるから…
ではでは。

