人事労務freeeとSlackを連携させるためにやったこと

この記事は裏freee developers Advent Calendar 2018の8日目&freee 19新卒 Advent Calendar 2018の24日目です。今年の10月から新卒で入社した@liaoziyangと申します。現在freee株式会社の大阪開発拠点で人事労務freeeの勤怠周り改善の開発を担当しています。

freeeではいろんなサービスとの連携を積極的に推進していて、その一環として私が人事労務freeeとSlackの連携機能の開発を担当することになりました。今回は人事労務freeeとSlackを連携させるためにやったことをお話します。

今回作ったもの

freee hr slack app

ざっくり機能を説明するとこんな感じです。

  • 勤怠打刻
  • 指定月の勤怠サマリを確認
  • 通知の受け取り(給与明細、年末調整)

開発環境の構築

ざっくり流れとしては、Slackアプリケーションを作る→外部公開用の設定をする→Oauthの認証を行うためのコードを書くになっています。
まずSlackからメッセージを受信するためには、ローカル環境に構築したアプリケーションに対して外部(Slack)からhttpsリクエストを受け付けられるようにする必要がありますが、ngrokを使えば簡単にできます。詳細な手順はこちらです。
https://api.slack.com/tutorials/tunneling-with-ngrok

外部に公開するためのSlack Appを作る手順

社内や自分のSlack WorkSpaceにHubotなどを使ってBotを追加することはよくあると思いますが、この場合はBot OAuth Access Tokenを取得し、設定に入れれば動かせることができます。

一般公開するためのSlack APPはこちらの公式ドキュメントに従って作る必要があります。

Slack App設定画面の設定

Create New Appをクリックして、名前と開発用のSlack WorkSpaceを設定した後に、Slack Appの設定画面に入ります。いろんな項目がありますが、最低限必要なものは

  • 使う機能の設定
  • OAuthのリダイレクトURL
  • 必要とする権限の設定

になります。

OAuth認証

本家のドキュメントに書いてあるように、まずはユーザに対して、Slackと自分が作ったアプリケーションが連携することを承認(許可)してもらう必要があります。

https://slack.com/oauth/authorizeに対して、GET

  • client_id - アプリの作成時に発行されます(必須)
  • scope - 要求する権限(下記参照)(必須)
  • redirect_uri - リダイレクト先のURL(下記参照)(オプション)
  • state - 完了時に戻される一意の文字列(オプション)
  • team - 連携できるWorkspaceを指定する(オプション)

を渡します。

Railsで動的にURLを生成するならこのようになります。

1
2
3
4
5
6
7
8
9
10
11
def activate
oauth_state = Slack::GenerateOauthStateService.new(company: current_company).execute
uri = URI('https://slack.com/oauth/authorize')
uri.query = {
client_id: SLACK_CLIENT_ID,
scope: 'bot,users:read.email,commands,users:read',
state: oauth_state,
}.to_query

redirect_to uri.to_s
end

生成したリンクにアクセスするとSlackの認証画面が表示され、scopeに応じた権限の承認を求められます。ユーザーが承認すると、設定したredirect_uriに対してアクセストークンの認証コードと共にリダイレクトされます。

slack auth window

アクセストークンの認証コードを手に入れたら、認証コードを使ってアクセストークンと交換することができます。
slack-ruby-clientを使えば簡単にSlack APIを叩くことができます。

1
2
3
4
5
6
client = Slack::Web::Client.new
response = client.oauth_access({
client_id: SLACK_CLIENT_ID,
client_secret: SLACK_CLIENT_SECRET,
code: oauth_params[:code]
})

帰ってきたresponseにはこのようにaccess_tokenが含まれているので、access_tokenを使ってSlack APIを叩いていろんな情報を取ることができるようになりました。

勤怠打刻コマンドを作る

機能はいくつかありますが、ここでは打刻コマンドの実装のみを説明します。

初期設定

Slackメッセージ入力欄に/を打つことでSlash Commandを使うことができます。この機能を使って打刻コマンドを作ります。
https://api.slack.com/slash-commands

slack slash command

Slash Commandは以下のようにSlack設定画面で設定することができます。設定したCommandが使われたら、自分で設定したRequest URLに情報が送信されます。

slack edit command

打刻メッセージを返す

Slackユーザーが打刻コマンドを打ったら、そのユーザーの現時点の打刻状況に応じて、打刻メッセージを返す必要があります。例えばまだ出勤していなかったら「出勤ボタン」を表示し、既に出勤していたら「休憩開始ボタン」と「退勤ボタン」を表示します。

Slackのメッセージの組み立て方がここに書いてありますので、これに従って打刻メッセージを作ってユーザーに返せば、打刻ボタンが含まれたメッセージが表示されます。
https://api.slack.com/docs/message-attachments

実際の打刻の流れは、このように/freee_dakokuを送信することで、出勤ボタンが表示されて、そのボタンを押せば出勤できましたっという感じになっています。
slack dakoku command

打刻ボタンを押されたら打刻する

出勤などの処理は上記のメッセージにあるボタンを通してやっていて、Slackではinteractive messageと呼んでいます。ボタンを押すと事前に設定したURLにリクエストがPOSTされ、リクエスト内容は以下のjsonのようになっており、パラメータにあるresponse_urlに対して、ボタンを押した後に表示したい内容を返すことによって、打刻処理の結果をユーザーに通知することができます。
https://api.slack.com/interactive-messages

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
{
"type": "interactive_message",
"actions": [
{
"name": "channel_list",
"type": "select",
"selected_options":[
{
"value": "C24BTKDQW"
}
]
}
],
"callback_id": "pick_channel_for_fun",
"team": {
"id": "T1ABCD2E12",
"domain": "hooli-hq"
},
"channel": {
"id": "C9C2VHR7D",
"name": "triage-random"
},
"user": {
"id": "U900MV5U7",
"name": "gbelson"
},
"action_ts": "1520966872.245369",
"message_ts": "1520965348.000538",
"attachment_id": "1",
"token": "lbAZE0ckwoSNJcsGWE7sqX5j",
"is_app_unfurl": false,
"original_message": {
"text": "",
"username": "Belson Bot",
"bot_id": "B9DKHFZ1E",
"attachments":[
{
"callback_id": "pick_channel_for_fun",
"text": "Choose a channel",
"id": 1,
"color": "2b72cb",
"actions": [
{
"id": "1",
"name": "channel_list",
"text": "Public channels",
"type": "select",
"data_source": "channels"
}
],
"fallback":"Choose a channel"
}
],
"type": "message",
"subtype": "bot_message",
"ts": "1520965348.000538"
},
"response_url": "https://hooks.slack.com/actions/T1ABCD2E12/330361579271/0dAEyLY19ofpLwxqozy3firz",
"trigger_id": "328654886736.72393107734.9a0f78bccc3c64093f4b12fe82ccd51e"
}

Slack Appを公開する

公開する準備ができたら、Slackに審査を出します。
審査のチェックリストに従って準備を行う必要があります。https://api.slack.com/docs/slack-apps-checklist
とくに、以下の二点は注意が必要です。

  • プライバシーポリシーの英語版
  • Permissionsのscopeの必要な理由をきちんと書く

Slack側が審査が終え、作ったアプリがApprovedされました!この状態ではまだ審査通っただけなので、また一般公開されません。

slack app approved

Publishボタンを押したら、Slack App Directoryに一般公開されます。

slack app live

終わりに

エンジニアで自分でも使えるようなものを作るのは結構楽しいですね。機能面も今後たくさん追加する予定です。お楽しみに。

freee大阪開発拠点も絶賛メンバー募集中ですので、興味ある方はぜひ!

明日は

  • プロダクト開発基盤チームに所属するcindyさん(裏freee developers Advent Calendar 2018)
  • 19新卒の仲間宇都宮まゆさん(freee 19新卒 Advent Calendar 2018)

です!ご期待ください〜