--- title: LINE の LIFF 開発超入門 : LIFF SDK を使った Web アプリの開発 tags: linebot LIFF author: kenakamu slide: false --- # 本記事の概要 この記事では LINE で提供されている Line Front-end Framework (LIFF) を使ったページの開発方法をチュートリアル形式で記載しています。カバーする内容は LIFF の基本機能をはじめ、Bot との連携例や CLI ツールを使った登録から展開など、LIFF を使うにあたって必要な知識となります。 尚、本記事で利用するコードは [line-liff-starter](https://github.com/line/line-liff-starter) より一部拝借してします。 また最終系は [こちらのレポジトリ](https://github.com/kenakamu/LINE-LIFF-Sample/) にあります。 # LIFF アプリとは LIFF SDK を利用して開発した Web ページの事であり、登録時に取得できる専用のアドレスに LINE からアクセスすることで動作するアプリケーションとなります。つまり、LIFF アプリの開発は LIFF SDK を埋め込んだ Web ページを開発することです。 # 必要なスキルと環境 - LINE Bot の基本的な知識 - [Visual Studio Code](https://code.visualstudio.com/) の基本的な操作方法 - [Azure サブスクリプション](https://azure.microsoft.com/ja-jp/free/) - [Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) - [git](https://git-scm.com/download) - [LIFF CLI](https://qiita.com/kenakamu/items/5a9cbdc32c4575e53c59) ※ この記事では Microsoft Azure を利用しますが、LIFF を利用するサイトのホストは任意です。 # 事前準備 ## チャネルの作成 [こちらのページ](https://developers.line.me/ja/docs/liff/getting-started/) を参考にチャネルを作成します。チャネル作成後、チャネルアクセストークンを発行してコピーしておきます。 また「Your user ID」も後ほど利用するためコピーしておきます。 ## Azure 環境の準備 Azure ポータルを使い慣れている場合はポータルからの操作でもいいですが、今回は Azure CLI を使います。また Heroku など他のサービスを使っている場合はそちらでも結構です。 1\. まだインストールしていない場合は、[Azure CLI](https://docs.microsoft.com/en-us/cli/azure/install-azure-cli?view=azure-cli-latest) をインストール。もしくは [Azure ポータル](https://portal.azure.com) ログイン後、画面右上の Cloud Shell よりコンソールを起動。 2\. Cloud Shall の場合は、手順 4 に進む。コンソールの場合は、まず以下のコマンドでログインを実行。 ``` az login ``` 3\. 画面の指示に順ってログインを完了。 4\. ログイン完了後、複数の Azure サブスクリプションがある場合は、以下のコマンドで使うサブスクリプションをセット。 ``` az account list az account set -s 'subscription id' az account show ``` 5\. まず以下のコマンドでリソースグループを lineliffsample として、地域を東日本で作成。 ``` az group create -n lineliffsample -l japaneast ``` 6\. 次に LIFF アプリケーションのデプロイ先となる WebApps を作成。作成時には、まずサービスプランを作成し、WebApp を作成します。名前はグローバルで一意になるものを指定。 ``` az appservice plan create -n lineliffappplan -g lineliffsample --sku F1 az webapp create -n <ユニークな WebApp の名前> -g lineliffsample -p lineliffappplan ``` 7\. git でデプロイできるように指定。返り値が git のリモートレポジトリとなるため保存しておく。 ``` az webapp deployment user set --user-name <ユーザー名> --password <パスワード> az webapp deployment source config-local-git -n <ユニークな WebApp の名前> -g lineliffsample ``` ## LIFF CLI と既存のサイトを使った LIFF の登録およびテスト LIFF は LIFF SDK を使った Web ページで最大効果を発揮しますが、既存のページを指定してすぐに使うことも可能です。ここではまず LIFF 登録の概念を把握するため、既存のページ (https://linecorp.com/ja/) を登録してみます。 1\. Liff npm パッケージをまだ入れていない場合、npm でインストール。 ``` npm install -g liff ``` 2\. liff init で初期化。上記で取得したチャネルのアクセストークンを渡す。 ``` liff init <チャネルアクセストークン> ``` 3\. LIFF アプリケーションの登録。ここではサイズとして tall を指定。サイズは full, tall, compact がある。 ``` liff add https://linecorp.com/ja/ tall ``` 4\. 戻り値から Liff ID および Accessible URL を確認。 5\. 以下 liff send コマンドでリンクを送付するか、LIFF アドレスを手動で LINE へ送付。LINE アプリよりリンクをクリックしてテスト。 ``` liff send ``` # LIFF アプリの開発 では LIFF SDK を使ったアプリを開発していきます。 ## プロジェクトの作成と LIFF SDK の読み込み 1\. 任意のディレクトに MyFirstLiff フォルダを作成し、Visual Studio Code で開く。 ```shell mkdir MyFirstLiff cd MyFirstLiff code . ``` 2\. Visual Studio Code で新しく index.html ファイルを追加。 ![image.png](https://qiita-image-store.s3.amazonaws.com/0/214116/865c2a24-cbe8-ba88-7dfc-2e37a081984c.png) 3\. index.html の中身に以下のコードをペースト ```html My First LIFF

LIFF Data

language
context.viewType
context.userId
context.utouId
context.roomId
context.groupId
``` 4\. 同じディレクトリに liff.js を追加し、以下コードをペースト。 ```javascript window.onload = function (e) { // init で初期化。基本情報を取得。 // https://developers.line.me/ja/reference/liff/#initialize-liff-app liff.init(function (data) { initializeApp(data); }); }; function initializeApp(data) { document.getElementById('languagefield').textContent = data.language; document.getElementById('viewtypefield').textContent = data.context.viewType; document.getElementById('useridfield').textContent = data.context.userId; document.getElementById('utouidfield').textContent = data.context.utouId; document.getElementById('roomidfield').textContent = data.context.roomId; document.getElementById('groupidfield').textContent = data.context.groupId; } ``` 5\. 全ての保存。 ### LIFF アプリケーションの展開 この段階で一旦 LIFF アプリの公開と登録を行います。 1\. まずレポジトリの初期化。Visual Studio Code より統合コンソールを開き、以下コマンドを実行。 ``` git init ``` 2\. 次に発行先を設定。アドレスは WebApp 作成時に取得したものを使用。 ``` git remote add origin <上記手順で取得したリモート git アドレス> ``` 3\. ファイルの追加とコミット。 ``` git add . git commit -m "初回コミット" ``` 4\. Push でデプロイの実行。 ``` git push -u origin master ``` 5\. LIFF CLI でアプリの登録。 ``` liff add tall ``` 6\. 戻り値を liff send か手動で LINE に送付して SDK の動作を確認。ログインしているユーザーの ID や言語が取得できる。 ## SDK を使ったユーザープロファイルの取得 1\. index.html のコードを以下に変更。 ```html My First LIFF

Profile

userId
displayName
statusMessage

LIFF Data

language
context.viewType
context.userId
context.utouId
context.roomId
context.groupId
``` 2\. liff.js を以下のコードと差し替え。 ```javascript window.onload = function (e) { // init で初期化。基本情報を取得。 // https://developers.line.me/ja/reference/liff/#initialize-liff-app liff.init(function (data) { getProfile(); initializeApp(data); }); }; // プロファイルの取得と表示 function getProfile(){ // https://developers.line.me/ja/reference/liff/#liffgetprofile() liff.getProfile().then(function (profile) { document.getElementById('useridprofilefield').textContent = profile.userId; document.getElementById('displaynamefield').textContent = profile.displayName; var profilePictureDiv = document.getElementById('profilepicturediv'); if (profilePictureDiv.firstElementChild) { profilePictureDiv.removeChild(profilePictureDiv.firstElementChild); } var img = document.createElement('img'); img.src = profile.pictureUrl; img.alt = "Profile Picture"; img.width = 200; profilePictureDiv.appendChild(img); document.getElementById('statusmessagefield').textContent = profile.statusMessage; }).catch(function (error) { window.alert("Error getting profile: " + error); }); } function initializeApp(data) { document.getElementById('languagefield').textContent = data.language; document.getElementById('viewtypefield').textContent = data.context.viewType; document.getElementById('useridfield').textContent = data.context.userId; document.getElementById('utouidfield').textContent = data.context.utouId; document.getElementById('roomidfield').textContent = data.context.roomId; document.getElementById('groupidfield').textContent = data.context.groupId; } ``` 3\. git で変更のコミットしてプッシュ。 ``` git commit -am "add profile" git push origin master ``` 4\. LIFF アプリケーションのアドレスは変わっていないため、先ほどテストで送ったアドレスをクリックして動作を確認。 ## LIFF よりメッセージの送信 LIFF 上のボタンクリックイベントなどから、チャットウィンドウにメッセージを送ることも出来ます。これで Bot と LIFF のシームレスな連携が可能となります。ここではテキストとスタンプを例として実装しますが、他のタイプもサポートされます。 詳細は [liff.sendMessages()](https://developers.line.me/ja/reference/liff/#liffsendmessages()) 参照。 1\. index.html を以下のコードに差し替え。 ```html My First LIFF

Profile

userId
displayName
statusMessage

LIFF Data

language
context.viewType
context.userId
context.utouId
context.roomId
context.groupId
``` 2\. liff.js を以下のコードに差し替え。 ```javascript window.onload = function (e) { // init で初期化。基本情報を取得。 // https://developers.line.me/ja/reference/liff/#initialize-liff-app liff.init(function (data) { getProfile(); initializeApp(data); }); // メッセージの送信 document.getElementById('sendmessagebutton').addEventListener('click', function () { // https://developers.line.me/ja/reference/liff/#liffsendmessages() liff.sendMessages([{ type: 'text', text: "テキストメッセージの送信" }, { type: 'sticker', packageId: '2', stickerId: '144' }]).then(function () { window.alert("送信完了"); }).catch(function (error) { window.alert("Error sending message: " + error); }); }); }; // プロファイルの取得と表示 function getProfile(){ // https://developers.line.me/ja/reference/liff/#liffgetprofile() liff.getProfile().then(function (profile) { document.getElementById('useridprofilefield').textContent = profile.userId; document.getElementById('displaynamefield').textContent = profile.displayName; var profilePictureDiv = document.getElementById('profilepicturediv'); if (profilePictureDiv.firstElementChild) { profilePictureDiv.removeChild(profilePictureDiv.firstElementChild); } var img = document.createElement('img'); img.src = profile.pictureUrl; img.alt = "Profile Picture"; img.width = 200; profilePictureDiv.appendChild(img); document.getElementById('statusmessagefield').textContent = profile.statusMessage; }).catch(function (error) { window.alert("Error getting profile: " + error); }); } function initializeApp(data) { document.getElementById('languagefield').textContent = data.language; document.getElementById('viewtypefield').textContent = data.context.viewType; document.getElementById('useridfield').textContent = data.context.userId; document.getElementById('utouidfield').textContent = data.context.utouId; document.getElementById('roomidfield').textContent = data.context.roomId; document.getElementById('groupidfield').textContent = data.context.groupId; } ``` 3\. git で変更のコミットしてプッシュ。 ``` git commit -am "add send message" git push origin master ``` 4\. LIFF アプリケーションのアドレスは変わっていないため、先ほどテストで送ったアドレスをクリックして動作を確認。 ## LIFF アプリより別ウィンドウを開く LIFF アプリ内で指定した URL を、LINEアプリ 内ブラウザまたは外部ブラウザで開きます。 1\. index.html を以下のコードに差し替え。 ```html My First LIFF

Profile

userId
displayName
statusMessage

LIFF Data

language
context.viewType
context.userId
context.utouId
context.roomId
context.groupId
``` 2\. liff.js を以下のコードに差し替え。 ```javascript window.onload = function (e) { // init で初期化。基本情報を取得。 // https://developers.line.me/ja/reference/liff/#initialize-liff-app liff.init(function (data) { getProfile(); initializeApp(data); }); // ウィンドウを開く // https://developers.line.me/ja/reference/liff/#liffopenwindow() document.getElementById('openwindowbutton').addEventListener('click', function () { liff.openWindow({ url: 'https://line.me' }); }); document.getElementById('openwindowexternalbutton').addEventListener('click', function () { liff.openWindow({ url: 'https://line.me', external: true }); }); // メッセージの送信 document.getElementById('sendmessagebutton').addEventListener('click', function () { // https://developers.line.me/ja/reference/liff/#liffsendmessages() liff.sendMessages([{ type: 'text', text: "テキストメッセージの送信" }, { type: 'sticker', packageId: '2', stickerId: '144' }]).then(function () { window.alert("送信完了"); }).catch(function (error) { window.alert("Error sending message: " + error); }); }); }; // プロファイルの取得と表示 function getProfile(){ // https://developers.line.me/ja/reference/liff/#liffgetprofile() liff.getProfile().then(function (profile) { document.getElementById('useridprofilefield').textContent = profile.userId; document.getElementById('displaynamefield').textContent = profile.displayName; var profilePictureDiv = document.getElementById('profilepicturediv'); if (profilePictureDiv.firstElementChild) { profilePictureDiv.removeChild(profilePictureDiv.firstElementChild); } var img = document.createElement('img'); img.src = profile.pictureUrl; img.alt = "Profile Picture"; img.width = 200; profilePictureDiv.appendChild(img); document.getElementById('statusmessagefield').textContent = profile.statusMessage; }).catch(function (error) { window.alert("Error getting profile: " + error); }); } function initializeApp(data) { document.getElementById('languagefield').textContent = data.language; document.getElementById('viewtypefield').textContent = data.context.viewType; document.getElementById('useridfield').textContent = data.context.userId; document.getElementById('utouidfield').textContent = data.context.utouId; document.getElementById('roomidfield').textContent = data.context.roomId; document.getElementById('groupidfield').textContent = data.context.groupId; } ``` 3\. git で変更のコミットしてプッシュ。 ``` git commit -am "add openwindow" git push origin master ``` 4\. LIFF アプリケーションのアドレスは変わっていないため、先ほどテストで送ったアドレスをクリックして動作を確認。 ## LIFF アプリを閉じる LIFF アプリは右上の「X」をタップするか、tall/compact の場合は領域以外をタップすれば閉じますが、明示的に閉じるイベントもサポートされます。 1\. index.html を以下コードに差し替え。 ```html My First LIFF

Profile

userId
displayName
statusMessage

LIFF Data

language
context.viewType
context.userId
context.utouId
context.roomId
context.groupId
``` 2\. liff.js を以下コードに差し替え。 ```javascript window.onload = function (e) { // init で初期化。基本情報を取得。 // https://developers.line.me/ja/reference/liff/#initialize-liff-app liff.init(function (data) { getProfile(); initializeApp(data); }); // LIFF アプリを閉じる // https://developers.line.me/ja/reference/liff/#liffclosewindow() document.getElementById('closewindowbutton').addEventListener('click', function () { liff.closeWindow(); }); // ウィンドウを開く // https://developers.line.me/ja/reference/liff/#liffopenwindow() document.getElementById('openwindowbutton').addEventListener('click', function () { liff.openWindow({ url: 'https://line.me' }); }); document.getElementById('openwindowexternalbutton').addEventListener('click', function () { liff.openWindow({ url: 'https://line.me', external: true }); }); // メッセージの送信 document.getElementById('sendmessagebutton').addEventListener('click', function () { // https://developers.line.me/ja/reference/liff/#liffsendmessages() liff.sendMessages([{ type: 'text', text: "テキストメッセージの送信" }, { type: 'sticker', packageId: '2', stickerId: '144' }]).then(function () { window.alert("送信完了"); }).catch(function (error) { window.alert("Error sending message: " + error); }); }); }; // プロファイルの取得と表示 function getProfile(){ // https://developers.line.me/ja/reference/liff/#liffgetprofile() liff.getProfile().then(function (profile) { document.getElementById('useridprofilefield').textContent = profile.userId; document.getElementById('displaynamefield').textContent = profile.displayName; var profilePictureDiv = document.getElementById('profilepicturediv'); if (profilePictureDiv.firstElementChild) { profilePictureDiv.removeChild(profilePictureDiv.firstElementChild); } var img = document.createElement('img'); img.src = profile.pictureUrl; img.alt = "Profile Picture"; img.width = 200; profilePictureDiv.appendChild(img); document.getElementById('statusmessagefield').textContent = profile.statusMessage; }).catch(function (error) { window.alert("Error getting profile: " + error); }); } function initializeApp(data) { document.getElementById('languagefield').textContent = data.language; document.getElementById('viewtypefield').textContent = data.context.viewType; document.getElementById('useridfield').textContent = data.context.userId; document.getElementById('utouidfield').textContent = data.context.utouId; document.getElementById('roomidfield').textContent = data.context.roomId; document.getElementById('groupidfield').textContent = data.context.groupId; } ``` 3\. git で変更のコミットしてプッシュ。 ``` git commit -am "add closewindow" git push origin master ``` 4\. LIFF アプリケーションのアドレスは変わっていないため、先ほどテストで送ったアドレスをクリックして動作を確認。 ## LIFF アプリの更新と削除 LIFF CLI を使えば登録済の URL やサイズを変更できるだけでなく、不要となった LIFF アプリを削除することも可能です。現状 10 個までしかアプリを登録できないため、賢く管理する必要があります。 更新 ``` liff update ``` 削除 ``` liff delete liff deleteAll ``` # まとめ LIFF アプリは Web 画面と Bot をシームレスに統合できる便利な機能です。是非色々試してください。