Node.js
Heroku
Line
bot
LINEWORKS

LINE WORKSで初めてのBot開発!(後編)

この記事は、LINE WORKSでBotを開発してみたい!けど、今までBotを開発したことがない方向けに、手順を紹介しています。

前編は、こちらからご覧ください!


LINE WORKSで初めてのBot開発!(前編)



Botを開発する


Bot用プログラミング

先ほど作成したindex.jsを書き換えて、ユーザーが送ったメッセージを返信するBotのプログラムを書いていきます。

ここでは、5つの要素に分けて説明したいと思います。

i.追加モジュールのインストール

下記モジュールを追加でインストールします。

$ npm install body-parser --save

$ npm install jsonwebtoken --save
$ npm install https --save
$ npm install request --save
$ npm install querystring --save

index.jsにて、モジュールをインポートしておきます。


index.js

//モジュールインポート

const bodyParser = require("body-parser");
const jwt = require('jsonwebtoken');
const https = require("https");
const request = require("request");
const qs = require("querystring");

ii.環境変数設定

Server TokenやConsumer Keyは、Herokuの環境変数へ設定します。

Herokuの環境変数への設定はHerokuのダッシュボードから設定することができます。手順はこちらを参照してください。

今回は、下記5つの値をHerokuの環境変数として設定しましょう。

環境変数名
Developer Consoleの表示箇所

APIID
[API]メニューのAPI IDに表示されている英数字

CONSUMERKEY
[API]メニューのServer API Consumer KeyのKey欄に表示されている英数字

SERVERID
[API]メニューのServer List(ID登録タイプ)のID欄に表示されている英数字

PRIVATEKEY
[API]メニューのServer List(ID登録タイプ)の[認証キー再発行]ボタンからダウンロードします。

ダウンロードしたファイルに表示されている英数字

BOTNO
[Bot]メニューに表示されているBotをクリックし、
[Bot No.]に表示されている4桁の数字

全て設定するとこんな感じになります。

設定したら、プログラムから利用できるよう変数として定義しておきましょう。


index.js

const APIID = process.env.APIID;

const SERVERID = process.env.SERVERID;
const CONSUMERKEY = process.env.CONSUMERKEY;
const PRIVATEKEY = process.env.PRIVATEKEY;
const BOTNO = process.env.BOTNO;

iii.ユーザーのメッセージを受け取る

メッセージはPOSTリクエストのbody 部分に含まれて通知されます。サンプルは下記となります。(メッセージのプロパティについて、詳細はこちらを参照してください。)

{

"type": "message",
"source": {
"accountId": "admin@example.com",
"roomId": "12345"
},
"createdTime": 1470902041851,
"content": {
"type": "text",
"text": "hello"
}
}

このオブジェクトから、メッセージを送信する時に利用する値を、変数として格納しておきます。


index.js

//POSTのパラメータをJSONで取得

server.use(bodyParser.json());

// Botからメッセージに応答
server.post('/callback', (req, res) => {
res.sendStatus(200);
const message = req.body.content.text;
const roomId = req.body.source.roomId;
const accountId = req.body.source.accountId;

});



[注意]

受信したメッセージが、本当にLINE WORKSのサーバーから送信されたメッセージであり、そのメッセージが改ざんされていないかどうか、を確認するようにしてください。

確認のプロセスは、こちらを参考にしてください。


iv.メッセージをユーザーへ送信するためのトークンを取得する

トークンは、下記の流れで取得します。

1.JWTを取得

2.JWTを使ってServer Tokenを取得

それぞれ実装のサンプルコードは下記となります。詳細な仕様についてはこちらを参照してください。


index.js

    getJWT((jwttoken) => {

getServerToken(jwttoken, (newtoken) => {
//取得したnewtokenを使ってメッセージ送信
});
});

//1. JWTを取得
function getJWT(callback){
const iss = SERVER_ID;
const iat = Math.floor(Date.now() / 1000);
const exp = iat + (60 * 60); //JWTの有効期間は1時間
const cert = PRIVATEKEY;
const token = [];
const jwttoken = jwt.sign({"iss":iss, "iat":iat, "exp":exp}, cert, {algorithm:"RS256"}, (err, jwttoken) => {
if (!err) {
callback(jwttoken);
} else {
console.log(err);
}
});
}
//2.JWTを使ってServer Tokenを取得
function getServerToken(jwttoken, callback) {
const postdata = {
url: 'https://authapi.worksmobile.com/b/' + API_ID + '/server/token',
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8',
},
form: {
"grant_type" : encodeURIComponent("urn:ietf:params:oauth:grant-type:jwt-bearer"),
"assertion" : jwttoken
}
};
request.post(postdata, (error, response, body) => {
if (error) {
console.log(error);
callback(error);
} else {
const jsonobj = JSON.parse(body);
const AccessToken = jsonobj.access_token;
callback(AccessToken);
}
});
}



[注意]

Server Token(access_token)は24時間以内に利用されない場合には自動的に失効します。access_token発行時に、発行時間とaccess_tokenを保存し、Server APIを実行する際には有効期限を確認するようにしてください。有効期限内であれば保存したaccess_tokenを利用することができます。


v.メッセージを送信する

取得したServerTokenを使って、ユーザーへメッセージを送信します。

メッセージ送信APIの詳細な仕様はこちらを参照してください。

実装サンプルコードは下記となります。


index.js

    getJWT((jwttoken) => {

getServerToken(jwttoken, (newtoken) => {
sendMessage(newtoken, accountId, message);
});
});
function sendMessage(token, accountId, message) {
const postdata = {
url: 'https://apis.worksmobile.com/' + API_ID + '/message/sendMessage/v2',
headers : {
'Content-Type' : 'application/json;charset=UTF-8',
'consumerKey' : CONSUMERKEY,
'Authorization' : "Bearer " + token
},
json: {
"botNo" : Number(BOTNO),
"accountId" : accountId,
"content" : {
"type" : "text",
"text" : message
}
}
};
request.post(postdata, (error, response, body) => {
if (error) {
console.log(error);
}
console.log(body);
});
}


 [注意]

Botから1人のユーザーに対しメッセージを送信する場合は、上記のようになります。

トークルームに対しメッセージを送信する場合は、下記のようにaccountIdをnullにして、その代わりにroomIdを送信してください。


サンプルのJSONデータ

{

"botNo" : Number(BOTNO),
"accountId" : null,
"roomId" : roomId,
"content" : {
"type" : "text",
"text" : message
}


最終的なサンプルコード

完成したindex.jsのサンプルコードは下記のようになります。


[注意]

今回は、わかりやすいようにindex.jsに全てのコードを記述しています。必要に応じて、モジュール化を検討してください。



index.js

"use strict";

// モジュールインポート
const express = require("express");
const server = express();
const bodyParser = require("body-parser");
const jwt = require('jsonwebtoken');
const https = require("https");
const request = require("request");
const qs = require("querystring");

//変数
const APIID = process.env.APIID;
const SERVERID = process.env.SERVERID;
const CONSUMERKEY = process.env.CONSUMERKEY;
const PRIVATEKEY = process.env.PRIVATEKEY;
const BOTNO = process.env.BOTNO;

server.use(bodyParser.json());

// Webアプリケーション起動
server.listen(process.env.PORT || 3000);

// サーバー起動確認
server.get('/', (req, res) => {
res.send('Hello World!');
});

// Botからメッセージに応答
server.post('/callback', (req, res) => {
res.sendStatus(200);

const message = req.body.content.text;
const roomId = req.body.source.roomId;
const accountId = req.body.source.accountId;

getJWT((jwttoken) => {
getServerToken(jwttoken, (newtoken) => {
sendMessage(newtoken, accountId, message);
});
});
});

//サーバーAPI用JWT取得
function getJWT(callback){
const iss = SERVERID;
const iat = Math.floor(Date.now() / 1000);
const exp = iat + (60 * 60); //JWTの有効期間は1時間
const cert = PRIVATEKEY;
const token = [];
const jwttoken = jwt.sign({"iss":iss, "iat":iat, "exp":exp}, cert, {algorithm:"RS256"}, (err, jwttoken) => {
if (!err) {
callback(jwttoken);
} else {
console.log(err);
}
});
}

function getServerToken(jwttoken, callback) {
const postdata = {
url: 'https://authapi.worksmobile.com/b/' + APIID + '/server/token',
headers : {
'Content-Type' : 'application/x-www-form-urlencoded; charset=UTF-8',
},
form: {
"grant_type" : encodeURIComponent("urn:ietf:params:oauth:grant-type:jwt-bearer"),
"assertion" : jwttoken
}
};
request.post(postdata, (error, response, body) => {
if (error) {
console.log(error);
callback(error);
} else {
const jsonobj = JSON.parse(body);
const AccessToken = jsonobj.access_token;
callback(AccessToken);
}
});
}

function sendMessage(token, accountId, message) {
const postdata = {
url: 'https://apis.worksmobile.com/' + APIID + '/message/sendMessage/v2',
headers : {
'Content-Type' : 'application/json;charset=UTF-8',
'consumerKey' : CONSUMERKEY,
'Authorization' : "Bearer " + token
},
json: {
"botNo" : Number(BOTNO),
"accountId" : accountId,
"content" : {
"type" : "text",
"text" : message
}
}
};
request.post(postdata, (error, response, body) => {
if (error) {
console.log(error);
}
console.log(body);
});
}



Herokuへデプロイ

プログラムがすべて用意できたら、Herokuへデプロイしましょう。

コマンドは、下記となります。

$ git add .

$ git commit –m ‘commit message’
$ git push heroku master


Botを公開し利用する


Bot利用設定

Admin Consoleにて、Developer Consoleで登録したBotの利用設定を行います。

①[サービス]の[Bot]メニューにて、[+追加]ボタンをクリックします。

②追加できるBotが表示されますので、選択して[追加]をクリックします。

image.png

③Botが追加されました!

image.png

④追加されたBotを選択し詳細ページにて、[使用権限]と[公開設定]の設定をします。
今回Botは誰でも利用できるように設定するので、[使用権限] は[すべて]に設定し、 [使用権限]の[公開]にチェックを入れます。

⑤設定が終わったら、[保存]をクリックします。


Botに話しかけてみましょう!

トークにて、Botを追加し話しかけると、同じメッセージの返信がきたら、成功です!


最後に

最後まで読んでくださってありがとうございます。この記事は現時点での最新情報をもとに作っていますが、LINE WORKSのAPIが更新された場合は動かなくなる可能性もありますので、そういった場合はコメントでお知らせください。

またそれ以外にも、おかしなところがあればご指摘頂けると嬉しいです!(プログラム初心者なものでおかしなところあると思います。。。)