LIFFをSpring Bootで動かす


はじめに

LIFFをJavaのWebアプリ上で動かす手段が投稿されていない様だったので、やってみました。

line/line-bot-sdk-java を使う場合、Bot側はWebhookできるように、Spring Boot等でサーバにホストされた状態で利用しているはずなので、その中でLIFF用の画面を作ればいいじゃんね?

ということで、Spring Boot上のThymeleafでLIFFアプリ用の画面を作れることを試しました。

手順

すでに line/line-bot-sdk-java がSpring Boot等で動作している状態を前提とする。URLは ngrok で発行している。

(宣伝:前提までの進め方もふくめて、Javaユーザグループ北海道のハンズオン資料で公開しています)

  1. ライブラリにThymeleafを追加する
  2. Spring BootでThymeleafのWebページを表示する
  3. LIFFのサンプルを表示する

の手順で進める。

1. ライブラリにThymeleafを追加する

プロジェクトファイル(ルートフォルダ)の pom.xml の <properties>〜</properties> の中に、Thymeleafの記述を追加する。

<properties>
  (中略)
  <thymeleaf.version>3.0.9.RELEASE</thymeleaf.version>
  <thymeleaf-layout-dialect.version>2.3.0</thymeleaf-layout-dialect.version>
</properties>

プロジェクトファイル(ルートフォルダ)の pom.xml の <dependencies>〜</dependencies> の中に、Thymeleafの記述を追加する。(spring-boot-starter-webの下あたり)

<dependencies>
  (中略)
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
  </dependency>
  (中略)
</dependencies>

その他のソース(src/main/resources)の application.properties の末尾に、Thymeleafの設定を追加する

## thymeleaf
spring.thymeleaf.mode=HTML

2. Spring BootでThymeleafのWebページを表示する

ファイルの作成

その他のソース(src/main/resources)の templates フォルダの中に liff.html を作成する
(フォルダがない場合は作成する)

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
  <meta charset="UTF-8" />
  <title>Hello Thymeleaf</title>
</head>
<body>
<h1>[[${test}]]</h1>
</body>
</html>

ソース・パッケージ(src/main/java)に com.example.linebot.web パッケージを作成し、その中に LIFFController クラスを作成する

package com.example.linebot.web;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class LIFFController {

  @GetMapping("/liff")
  public String hello(Model model) {
    // [[${test}]] の部分を Hello... で書き換えて、liff.htmlを表示する
    model.addAttribute("test", "Hello Tymeleaf!");
    return "liff";
  }

}

Thymeleafの動作確認

  1. LineBotApplication を一度停止して、再起動する
  2. http://localhost:m8080/liff にアクセスする
  3. ブラウザに下のように表示されることを確認する

    ( liff.html の[[${test}]]の部分を、 LIFFController でセットしたModelの情報で書き換えている)

3. LIFFのサンプルを表示する

ファイルの作成

line/line-liff-starter のサンプルコードを(少し変更して)動作させる。

上記のサイトの liff-starter.js と style.css をコピーして、その他のソース(src/main/resources)の static フォルダの中に複製する
(フォルダがない場合は作成する)

上記のサイトの index.html の内容をもとに、その他のソース(src/main/resources)の templates/liff.html を書き換える。

<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<!-- The html based on https://github.com/line/line-liff-starter/blob/master/index.html -->
<head>
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>LIFF Starter</title>
  <link rel="stylesheet" href="style.css">
</head>

<body>

<h1>[[${test}]]</h1>

<div class="buttongroup">
  <div class="buttonrow">
    <button id="openwindowbutton">Open Window</button>
    <button id="closewindowbutton">Close Window</button>
  </div>
  <div class="buttonrow">
    <button id="getprofilebutton">Get Profile</button>
    <button id="sendmessagebutton">Send Message</button>
  </div>
</div>

<div id="profileinfo">
  <h2>Profile</h2>
  <a href="#" onclick="toggleProfileData()">Close Profile</a>
  <div id="profilepicturediv">
  </div>
  <table border="1">
    <tr>
      <th>userId</th>
      <td id="useridprofilefield"></td>
    </tr>
    <tr>
      <th>displayName</th>
      <td id="displaynamefield"></td>
    </tr>
    <tr>
      <th>statusMessage</th>
      <td id="statusmessagefield"></td>
    </tr>
  </table>
</div>

<div id="liffdata">
  <h2>LIFF Data</h2>
  <table border="1">
    <tr>
      <th>language</th>
      <td id="languagefield"></td>
    </tr>
    <tr>
      <th>context.viewType</th>
      <td id="viewtypefield"></td>
    </tr>
    <tr>
      <th>context.userId</th>
      <td id="useridfield"></td>
    </tr>
    <tr>
      <th>context.utouId</th>
      <td id="utouidfield"></td>
    </tr>
    <tr>
      <th>context.roomId</th>
      <td id="roomidfield"></td>
    </tr>
    <tr>
      <th>context.groupId</th>
      <td id="groupidfield"></td>
    </tr>
  </table>
</div>

<script src="https://d.line-scdn.net/liff/1.0/sdk.js"></script>
<script src="liff-starter.js"></script>
</body>
</html>

LIFFアプリとして追加する

LIFFアプリを追加するために、下のコマンドを端末(ターミナル)から実行する。

Windowsの場合はcurlをインストールするか、同等のパラメータでHTTPリクエストが行えるツール(ARCなど)を利用する。
また、line/line-bot-sdk-java には、Javaで動作するLIFF/リッチメニュー登録用のコマンドラインツール(line-bot-cli)も用意されている。

コマンドを実行する場合、以下の部分は個別に編集が必要。

  • "Authorization: Bearer xxxxxx..."xxxxxx... には、Botのアクセストークン(ロングターム)の値を改行なしで貼り付ける(ので、コマンドがとても長くなる)
  • "https://xxx.ngrok.io/liff"xxx.ngrok.io は、ngrokで取得したURLにする
  • Type には compact, tall , full の三種類があり、LIFFアプリのウィンドウの高さを決める
  • url は https のURLを指定する
curl -XPOST \
-H "Authorization: Bearer xxxxxx..." \
-H "Content-Type: application/json" \
-d '{
    "view": {
        "type": "tall",
        "url": "https://xxx.ngrok.io/liff"
    }
}' \
https://api.line.me/liff/v1/apps

成功すれば、liffIdが返信される。

{"liffId":"0000000000-nnnnnnnn"}%

LIFFアプリの動作確認

上記の手順で取得した liffId をもとに、アプリにアクセスするURLを作成する。

URLは、 line://app/ と liffId を結合した line://app/0000000000-nnnnnnnn となる。

本来はトリガとなる行動にあわせてBotがユーザにURLを発話すれば良いが、ここでは簡易的な動作確認のため、自分でURLを投稿する。

自分が投稿したURL(もしくはBotが発話したURL)をクリックすると、下のようにLIFFアプリが表示される。
特に、Thymeleafにより Hello Thymeleaf! を表示していること、LIFF APIにより表の中のlanguage, context.viewType, context.userId, context.utouId などの項目に値が表示されていることを確認する。

Open window ボタンを押すと、アプリ内ブラウザでlineのホームページが表示される。

Get profile ボタンを押すと、自分のLINEに設定しているアイコンとプロフィールが表示される。

Send Message ボタンを押すと、メッセージを送信した旨のダイアログが表示され、自分に You've successfully sent a message! Hooray! というメッセージと、スタンプが表示される。

このように、LIFFアプリを用いると、LINEのWebサイトにLINEの情報を連携させたり、Webサイト側からLINEのクライアントにイベントを発生させることができる。

LIFFアプリの削除

追加したLIFFアプリを削除するには、下のコマンドを端末(ターミナル)から実行する。

  • 0000000000-nnnnnnnn の部分は、 liffId と置き換える
  • "Authorization: Bearer xxxxxx..."xxxxxx... の部分には、Botのアクセストークン(ロングターム)の値を改行なしで貼り付ける
curl -X DELETE https://api.line.me/liff/v1/apps/0000000000-nnnnnnnn \
-H "Authorization: Bearer xxxxxx..."

成功すれば何も表示されない。(失敗時にはエラーメッセージが表示される)

おわりに

Spring Boot上のThymeleafでLINE Appを作れることが確認できた。

Thymeleaf側でFormとかを用意して、フォームで投稿した情報を使うようなLIFFアプリや、ThymeleafとLIFF APIをうまく連携させたLIFFアプリも作れそうですね(作りたい)。

参考文献