サイトにSlackで共有ボタンを設置する


概要

LINEで送るの様なSNS共有ボタンのSlack版をサービスサイトへ設置する手順。
LINEで送ると同じ様に「ユーザー名」で「指定ユーザー」に共有できることを目的とします。

LINEで送るはこちらを参照してください。

利用するSlack API Method

メッセージを送るだけならばIncoming webhooksを利用する方法もありますが、今回は上記の条件でメッセージをユーザー TO ユーザーで送りたいので、下記のAPI METHODを利用します。

oauth.access
chat.postMessage

※注意するポイントはOAuthv2ではなくOAuthの方で実現することです。

SlackにAppを作成する

https://api.slack.com/ にアクセスしてAppを作成します。

こちらのStart Buildingボタンを押すと以下のページに遷移します。

しかし、ここのCreate Slack Appを指定して作成してしまうとOAuth v2で作成されてしまうため、閉じるボタンを押してスキップします。

左メニューの
Installation & permissions > Installing with OAuth を選択しページを遷移
ページ最下部まで移動してCreate classic Slack appボタンを押してください。

これでOauthのAppが作成できます。

まずOauth認証に必要なClient IDClient Secret
Settings > Basic Information のApp Credentialsから保存してください。
適当にテキストファイル等にコピーしておいてください。(もちろん取り扱い注意)

SlackAppを動く状態にする

OAuth認証の設定をしてSlackAppが動く様に登録していきます。

Features > OAuth & Permissions よりRedirect URLsScopeの登録をします。

リダイレクトURLはコールバックを受けるURLでSlackの認証ページから戻ってくる、またはSlack側のエラー画面で利用する戻るボタンに設置されます。

Scopeは今回作成するAppが利用できる権限の設定を行う場所です。
※今回はClassicAppで作成しているので設定は1箇所ですが、OAuth2の場合はBotのScopeとUserのScopeの2種類指定する必要があります。

今回は「chat:write:user」と「incoming-webhook」の2つを指定してください。
こちらが「ユーザー」「指定ユーザー」に共有するための権限です。

ここまで設定すると
Settings > Manage DistributionSharable URLが表示され、これが認証に利用するURLとなるので保存しておいてください。

また、App Suggestions HTMLのMETAタグを上記Appを動かすページへ貼り付けてください。

これでAppが動く様になりました。

ただし、この状態では自分の(Appが作成された)ワークスペースでしかメッセージを送ることができません。

先ほどのSharable URL以下の様な黒い画面になるはずです。

別のワークスペースを選択できる様にする

今の状態だとこのAppが作成されたワークスペースしかメッセージを送ることができないので、OAuth認証ページで別のワークスペースを表示する設定をします。

Settings > Manage Distribution > Share Your App with Other WorkspacesRemove Hard Coded Informationの項目を有効にする必要があります。

その他の項目は今までの手順で有効(チェック済み)の状態になっているはずなので
こちらのI’ve reviewed and removed any hard-coded information.のチェックボックスにチェックを入れてActivate Public Distribustionボタンを押してください。

すると以下の様にSlackのAppディレクトリへの申請画面となります。とりあえず公式Appとせずシェア機能だけのテストなので申請は行いませんが、Scopeに関する説明を付与する必要があります。

適当に英語で理由を申請してください。

このReview your permission scopesの項目にすべてチェックが入れば晴れて公開Appとなり他のワークスペースへインストールすることができます。

Sharable URLへもう一度アクセスすると下記の様に右上にワークスペースを選択するコンボボックスが表示されます。

これでLINEで送ると同じ様に
ユーザー指定ユーザー に共有する準備ができました。

※ちなみにscopeにincoming-webhookを指定した理由はOAuth認証画面に宛先追加のプルダウンを表示したかったからです。

自分で宛先追加プルダウンを作る場合は他のMethodを使って自作してください。

コールバックを受けるプログラムを作る(Redirect_URL)

先ほどの認証画面で許可をする、またはキャンセルするとコールバックURLへcodeというパラメータがGETで帰ってきます。

このcodeをoauth.accessメソッドに渡してaccess_tokenを取得することでAppが権限を得ることができます。

以下簡単なコード(PHP)を記載しておきますので参考にしてください。

<?php
if($_GET['code'] != '')
{
    $share = $_GET['share_url']; /* /oauth/authorizeにあらかじめ共有URLを渡しておくと、コールバック時に返してくれます */
    $url = 'https://slack.com/api/oauth.access';
    $params['client_id'] = 'ここにクライアントID';
    $params['client_secret'] = 'ここにclient_secret';
    $params['redirect_uri'] = '自分自身のURL(redirect_uriで指定)'
    $params['code'] = $_GET['code'];
    $queryString = http_build_query($params, null, '&');
    $header = array(
        "Content-Type: application/x-www-form-urlencoded",
        "Content-Length: ".strlen($queryString)
    );
    /* oauth.access は x-www-form-urlencodedしか受け付けない */
    $options = array(
        "http" => array(
        "method"  => "POST",
        "header"  => implode("\r\n", $header),
        "content" => $queryString
        )
    );
    /* アクセストークンの取得 */
    $result = file_get_contents($url,false, stream_context_create($options));

    $json = json_decode($result,true);

    if($json['ok'] != true)
    {
        print('問題が発生しました');
        return;
    }
    $payload['text'] = "共有です。<" . $share . "|ここ>";
    $payload['channel'] = $json['incoming_webhook']['channel'];
    $payload['as_user'] = 'true'; /* これを指定するとユーザーとしてメッセージを送ります */
    /* こちらはJsonで送れますがcharsetを送らないと叱られます. */
    /* access_tokenはここで指定してください。 */
    $header = array(
        "Content-Type:  application/json charset=utf-8;",
        'Authorization: Bearer ' . $json['access_token']
    );
    $options = array(
        'http' => array(
            'method' => 'POST',
            'header' => implode("\r\n", $header),
            'content' => json_encode($payload),
        )
    );
    /* message発射!! */
    $response = file_get_contents('https://slack.com/api/chat.postMessage',false, stream_context_create($options));
}
?>
<html>
    <head>
        <script>location.replace(<?=$share?>);</script>
    </head>
    <body>
        移動しますね。
    </body>
</html>

これでアクセストークンをDBに保存するなり、PHPのSESSION等を利用してシームレスに動く様にするなど工夫すれば完成すると思います。