【Salesforce Apex】フローからSlackへBlock Kitで作成したチャットを送信！

皆さんこんにちは。

今回は「SalesforceのフローからSlackへチャット通知を送る」というのが趣旨の記事になります。
ただ、普通にチャットメッセージを送るだけだとあまりにも普通なので、折角なのでBlock Kitで作ったSlackメッセージをフローから送ってみたいと思います。

## Block Kitとは？
[Block Kit](https://api.slack.com/block-kit)は、かなりざっくり簡単に言うとSlackのメッセージの中でUIを作成するための仕組みのことです。
ここの本題ではないので細かい説明は割愛させていただきます。

## 作成する際の流れ
今回の作成の流れとしては大きく分けて、5つのステップがあります。
1. Slack: アプリを作成
2. Salesforce: Apex作成
3. Slack: Block Kitでメッセージを作成
4. Salesforce: フロー作成

## Slack: アプリを作成
まずは、Slack Appsを作成していきます。
[Slack api](https://api.slack.com/)のページへ行き、Your appsを開きます。サインインをしていない場合、サインインを実施しましょう。
Create an Appをクリックし、From scratchをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/9542c6b8-aa47-16b1-40bf-aafb12e60910.png)
「App Name」には今回作成するアプリ名を適当な形で入力します。
「Pick a workspace to develop your app in:」では、作成したアプリをインストールしたいワークスペースを選んでおきます。
設定を終えたら、Create Appをクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/94755f92-9370-1ed7-5562-1d2702dd51f0.png)


### アプリの設定
アプリが作成出来たら、設定を行っていきます。
まずは、「OAuth & Permissions」をクリックして開いておきます。

ScopesにBot Token Scopesという個所があるので、こちらに必要な権限を付与しましょう。
今回はチャットを送るだけなので、下記があれば十分だと思います。必要に応じて適宜追加をしてください。
・chat:write
・chat:write.public
・chat:write.customize
・channels:read
・channels:history
・groups:read
・groups:history

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/dacc4f8c-7c2f-5be3-f77f-10fd7e69efab.png)

設定が終わったら、少し上にスクロールした場所にあるOAuth Tokensの「Install to ｛ワークスペース名｝」をクリックしてアプリをインストールしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/2e6dae9c-60bb-955c-d08d-98d59739a6f0.png)

下記のような画像が表示されると思いますので、「許可する」をクリックしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/2ec8d9d6-fd47-1cb5-a8bd-6e515bc560f5.png)

インストール後、後で使用するため、Bot User OAuth Tokenをコピーしておいてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/8038d080-b808-da45-2740-d00107f075e0.png)



## Salesforce Apex作成
ここからは、Salesforceのコードに移ります。
今回、ソースの細かいところは重要な点でないので、詳細は省いて記載します。

今回は説明のため、トークンやチャンネルをハードコーディングしてますが本来であればカスタムメタデータなどを使用して実装するのが良いかと思います。

``` JS
public class SampleSalesforce2Slack {
    private static String TOKEN = '{Bot User OAuth Token}';  // OAuth & Permissions
    private static String CHANNEL = '{送信したいSlackチャンネルID}'; // メッセージを送信するSlackチャンネル

    /**
    * フローからアクションとして呼び出される場所
    */
    @InvocableMethod(label='Slack通知' description='SlackBlockKitを使用した送信' category='Qiita Sample')
    public static List<Result> execute(List<Request> requests) {
        List<Result> results = new List<Result>();

        for( Request req : requests ) {
            results.add(postSlack(req.userName, req.message, req.blockKitJson));
        }

        return results;
    }

    public static Result postSlack(String userName,  String message, String blockKitJson) {
        Result result = new Result();

        // パラメータ設定
        Map<String, String> options = new Map<String, String>{
            'token' => TOKEN,
            'channel' => CHANNEL,
            'username' => userName,
            'text' => message,
            'attachments' => blockKitJson
        };
        PageReference pr = new System.PageReference('https://slack.com/api/chat.postMessage');
        pr.getParameters().putAll(options);

        // HTTP要求
        HttpRequest req = new HttpRequest();
        req.setEndpoint(pr.getUrl().substringBefore('?'));
        req.setHeader('Content-Type', 'application/x-www-form-urlencoded');
        req.setMethod('POST');
        req.setBody(pr.getUrl().substringAfter('?'));

        Http http = new Http();
        HttpResponse res;
        try {
            res = http.send(req);
            result.status = res.getStatus();
            result.code = res.getStatusCode();

            System.debug(LoggingLevel.INFO, 'Response :' + res.toString());
        } catch (System.CalloutException ex) {
            System.debug(LoggingLevel.ERROR, 'Error :' + ex.getMessage());
        }

        return result;
    }

    public class Result {
        @InvocableVariable(label='Response Status')
        public String status; 

        @InvocableVariable(label='Response Code')
        public Integer code; 
    }

    public class Request {
        @InvocableVariable(label='表示ユーザー名')
        public String userName; 

        @InvocableVariable(label='メッセージ')
        public String message; 
        
        @InvocableVariable(label='Block Kitで作成したJSON文字列')
        public String blockKitJson; 
    }
}
```

## Block kit builderで送信メッセージを作成
[Slack Block Kit Builder](https://app.slack.com/block-kit-builder/)を開いて送信したいメッセージを作成します。
最初は簡単なものを作成してから送信するのが良いかと思いますので、下図のようなものを作成してみました。

```json
{
	"blocks": [
		{
			"type": "header",
			"text": {
				"type": "plain_text",
				"text": "新しい取引先が作成されました",
				"emoji": true
			}
		},
		{
			"type": "divider"
		},
		{
			"type": "section",
			"fields": [
				{
					"type": "plain_text",
					"text": "作成者：",
					"emoji": true
				},
				{
					"type": "plain_text",
					"text": "取引先名：",
					"emoji": true
				}
			]
		}
	]
}
```

上記のJSONを元にフローを作成していきます。

## フローを作成
まずは非同期のパスを設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/fe149a21-0d94-7b6b-47b1-6631fbcfeb3f.png)


アクションを配置するとApexで作成した際に設定しているcategoryで検索ができます。
該当の個所は下記の個所です。
```JS
@InvocableMethod(label='Slack通知' description='SlackBlockKitを使用した送信' category='Qiita Sample')
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/039d37a2-cbc4-52d5-30e6-204d5352491f.png)

categoryを開くと、作成したApexのアクションがあるので選択します（labelがアクション名になっています）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/50259a9a-37ef-ee78-5558-d37225726140.png)


設定項目の中で、今回設定するのは「Block Kitで作成したJSON文字列」と「表示ユーザー名」の2つです。
表示ユーザー名はSlackへ送信したときに表示したい名前です。
Block Kitで作成したJSON文字列はフローでテキストテンプレートを作成していきます。
※ プレーンテキストとして作成してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/cd4c152f-c7cf-ea21-f3be-e78091ef608a.png)


Block Kitで作成したJSON文字列：作成したものを下記のように書き換えてテキストテンプレートの本文に入力します。
```diff_json
+ [
    {
+       "color": "#FF00FF",
    	"blocks": [
    		{
    			"type": "header",
    			"text": {
    				"type": "plain_text",
    				"text": "新しい取引先が作成されました",
    				"emoji": true
    			}
    		},
    		{
    			"type": "divider"
    		},
    		{
    			"type": "section",
    			"fields": [
    				{
    					"type": "plain_text",
+    					"text": "作成者：{!$Record.CreatedBy.LastName} {!$Record.CreatedBy.FirstName}",
    					"emoji": true
    				},
    				{
    					"type": "plain_text",
+    					"text": "取引先名：{!$Record.Name}",
    					"emoji": true
    				}
    			]
    		}
    	]
    }
+]
```

アクションの設定に反映します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/ba83bf78-033c-cfcc-7635-290442a43a91.png)

ここまで出来たら、デバッグしてみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2520055/137a1513-540d-e91a-22ed-c467d82aaa2a.png)


上で新しく設定したColorが左のラインカラーになるので、ここを変更すれば別の色に変更できます。


## 
いかがだったでしょうか？
実施にはカスタム通知を使った方が楽ではありますが、Block Kitを使用したい欲が出ることもあるかもしれません。
その際にはSalesforceからでも使えるということを簡単にですが、まとめてみました。

お役に立つかは分かりませんが、閲覧いただいた方の何かを充たすことができたらうれしいです。