# LIFFアプリを開発する

LIFFアプリを開発する手順を説明します。 LIFFアプリを開発したら、任意のサーバーにデプロイしてください。

# LIFFアプリを開発する

LIFFアプリは、HTMLやJavaScriptで構成されるウェブアプリです。ここでは、LIFFアプリ特有の処理について説明します。

# LIFFアプリのタイトルを設定する

LIFFアプリのタイトルは、LIFFアプリのタイトルバーに表示されます。 LIFFアプリのHTMLソースの<title>要素に、LIFFアプリのタイトルを指定します。

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>LIFF Starter</title>
        <link rel="stylesheet" href="style.css">

# LIFFアプリにLIFF SDKを組み込む

LIFFアプリには、以下の2種類の方法でLIFF SDKを組み込めます。

# CDNパスを指定する

LIFF SDKで提供する機能を利用するには、LIFFアプリのHTMLソースの<script>要素のsrc属性に、LIFF SDKのCDNパスを指定します。 LINEでは、以下の2種類のCDNパスを用意しています。目的に合ったCDNパスを指定してください。

CDNパス 説明
CDNエッジパス メジャーバージョンのみを含むCDNパスです。常に最新の機能を使用する場合は、このCDNパスを使用します。メジャーバージョンがアップデートされたときのみURLを更新する必要があります。
例:https://static.line-scdn.net/liff/edge/2/sdk.js
CDN固定パス パッチバージョンまで含むCDNパスです。特定のバージョンの機能を使用する場合は、このCDNパスを使用します。LIFFアプリを更新しない限り、指定したパッチバージョンを使い続けることができます。LIFFの新機能や、セキュリティ改善、バグ修正を反映したいときのみURLを更新してください。自動的に更新されないため、LIFF SDKのアップデートの影響を受けません。
例:https://static.line-scdn.net/liff/edge/versions/2.1.13/sdk.js
どのバージョンを使うべきか

CDN固定パスを使用している開発者は、LIFFアプリを更新するタイミングを決める必要があります。アップデートの内容を正しく理解し、自分のLIFFアプリに適しているか判断するために、『LIFFドキュメント』の「リリースノート」をこまめに確認してください。

CDNエッジパスを指定する例:

<script charset="utf-8" src="https://static.line-scdn.net/liff/edge/2/sdk.js"></script>
LIFF SDKはUTF-8で書かれています

LIFF SDKはUTF-8で書かれているため、HTMLソースをUTF-8以外の文字コードで作成する場合は、charset="utf-8"をあわせて指定してください。

# npmパッケージを利用する

LINEでは、npmパッケージも公開しています。npmを利用して、LIFF SDKをインストールすることもできます。

SDKバージョンを管理してください

適切なSDKバージョンを使用することは開発者の責任です。SDKバージョンを最新の状態に保つために、LIFFリリースノートを定期的に確認し、ローカルのSDKを頻繁に更新してください。LIFFのバージョニングポリシーの詳細は『LIFF SDK(sdk.js)のアップデートポリシー』を参照してください。

npmパッケージの試験公開

npmパッケージは、試験的に公開しています。今後、予告なく変更、または削除される可能性があります。

LIFF SDKをnpmでインストールし、アプリに組み込むための手順は、以下のとおりです。

  1. 以下のコマンドをターミナルで実行し、npmでLIFF SDKをインストールしてください。

    $ npm install --save @line/liff
    

    あるいは、以下のコマンドをターミナルで実行し、YarnでLIFF SDKをインストールすることもできます。

    $ yarn add @line/liff
    
  2. SDKをアプリに組み込む

    JavaScriptまたはTypeScriptファイルに以下のコードを組み込んでください。

    import liff from '@line/liff';
    
    liff.init({ liffId: 'myLiffId' });
    

    TypeScriptの型の定義は@line/liffパッケージに含まれています。

    window.liff を宣言および編集しないでください

    下位互換性を維持するため、グローバルLIFFインスタンスのwindow.liffを宣言および編集しないでください。LINEが正常に動作しなくなる可能性があります。

関連ページ:https://www.npmjs.com/package/@line/liff

# LIFF APIを呼び出す

LIFF SDKを組み込むと、以下の操作を実行できます。

# LIFFアプリを初期化する

liff.init()メソッドを実行するタイミングに注意してください

ユーザーがエンドポイントURLに初めてリダイレクトされたタイミング(1次リダイレクト先URL)で、liff.init()メソッドを実行してください。 これ以外のタイミングでliff.init()メソッドを実行すると、INIT_FAILEDが返され、LIFFアプリを開けません。 詳しくは、「LIFF URLにアクセスしてからLIFFアプリが開くまでの動作について」を参照してください。

liff.init()メソッドを実行すると、LIFFアプリが初期化され、LIFFアプリからLIFF SDKのほかのメソッドを実行できるようになります。

liffIdに指定するLIFFアプリIDは、LIFFアプリをチャネルに追加すると取得できます。詳しくは、「LIFFアプリをチャネルに追加する」を参照してください。

/**
* Initialize LIFF
* @param {string} myLiffId The LIFF app ID of the selected element
*/
function initializeLiff(myLiffId) {
    liff
        .init({
            liffId: myLiffId
        })
        .then(() => {
            // start to use LIFF's api
            initializeApp();
        })
        .catch((err) => {
            document.getElementById("liffAppContent").classList.add('hidden');
            document.getElementById("liffInitErrorMessage").classList.remove('hidden');
        });
}

なお、liff.readyで、LIFFアプリ起動後、liff.init()の実行が初めて終了したときにresolveするPromiseオブジェクトを取得できます。

詳しくは、『LIFF v2 APIリファレンス』の「liff.init()」および「liff.ready」を参照してください。

# 外部ブラウザでLINEログインを利用する場合

外部ブラウザでLINEログインを利用する場合は、以下のとおりliff.init()メソッドを2回実行します。

  1. LIFF SDKロード後に、liff.init()メソッドを実行します。

  2. liff.login()メソッドを実行し、認証ページおよび認可画面の処理が終了すると、LIFFアプリ(redirectUri)にリダイレクトされます。そこで、改めてliff.init()メソッドを実行します。

    liff.init()メソッドの処理中にエラーが発生した場合、またはログイン時にユーザーが認可をキャンセルした場合は、errorCallbackが実行されます。

フロー図

# LIFFアプリが動作している環境を取得する

liff.isInClient()メソッドやliff.getOS()メソッドなどを実行して、LIFFアプリが動作している環境を取得します。

/**
* Display data generated by invoking LIFF methods
*/
function displayLiffData() {
    document.getElementById('browserLanguage').textContent = liff.getLanguage();
    document.getElementById('sdkVersion').textContent = liff.getVersion();
    document.getElementById('isInClient').textContent = liff.isInClient();
    document.getElementById('isLoggedIn').textContent = liff.isLoggedIn();
    document.getElementById('deviceOS').textContent = liff.getOS();
    document.getElementById('lineVersion').textContent = liff.getLineVersion();
}

詳しくは、『LIFF v2 APIリファレンス』の「liff.getOS()」および「liff.isInClient()」を参照してください。

# LINEログインを行う

liff.login()メソッドを実行して、ウェブアプリ向けのLINEログインの処理(ウェブログイン)を行います。

注意

liff.login()は、LINE内ブラウザでは利用できません。

// login call, only when external browser is used
document.getElementById('liffLoginButton').addEventListener('click', function() {
    if (!liff.isLoggedIn()) {
        // set `redirectUri` to redirect the user to a URL other than the endpoint URL of your LIFF app.
        liff.login();
    }
});

また、liff.logout()メソッドを実行して、ログアウトすることもできます。

// logout call only when external browse
document.getElementById('liffLogoutButton').addEventListener('click', function() {
    if (liff.isLoggedIn()) {
        liff.logout();
        window.location.reload();
    }
});

詳しくは、『LIFF v2 APIリファレンス』の「liff.login()」および「liff.logout()」を参照してください。

# URLを開く

liff.openWindow()メソッドを実行して、指定したURLをLINE内ブラウザまたは外部ブラウザで開きます。

以下のコードはhttps://line.meを外部ブラウザで開きます。

// openWindow call
document.getElementById('openWindowButton').addEventListener('click', function() {
    liff.openWindow({
        url: 'https://line.me',
        external: true
    });
});

詳しくは、『LIFF v2 APIリファレンス』の「liff.openWindow()」を参照してください。

PDFを開く

LIFFアプリからPDFを開くには、<a href="">で対象のPDFのパスを指定します。

<a href="/path/to/your.pdf">Open a PDF</a>

リンクをクリックすると、LINE内ブラウザまたは外部ブラウザで対象のPDFが開きます。

別タブで表示する場合は、target="_blank"を追加します。

<a href="/path/to/your.pdf" target="_blank">Open a PDF in another tab</a>

# QRコードリーダーを表示する

liff.scanCode()メソッドを実行して、LINEのQRコードリーダーを起動し、ユーザーが読み取った文字列を取得します。

// scanCode call
document.getElementById('scanQrCodeButton').addEventListener('click', function() {
    if (!liff.isInClient()) {
        sendAlertIfNotInClient();
    } else {
    	if (liff.scanCode) {
	        liff.scanCode().then(result => {
	            // e.g. result = { value: "Hello LIFF app!" }
	            const stringifiedResult = JSON.stringify(result);
	            document.getElementById('scanQrField').textContent = stringifiedResult;
	            toggleQrCodeReader();
	        }).catch(err => {
	            document.getElementById('scanQrField').textContent = "scanCode failed!";
	        });
    	}
    }
});

詳しくは、『LIFF v2 APIリファレンス』の「liff.scanCode()」を参照してください。

iOS版LINEバージョン9.19.0以降では使用できません

技術的な問題があり、iOS版LINEバージョン9.19.0以降では、liff.scanCode()undefinedになります。サンプルコードのように、関数の存在を確認してから、使用してください。

注意

liff.scanCode()は、外部ブラウザでは利用できません。

# LIFFアプリが起動された画面を取得する

liff.getContext()メソッドを実行して、LIFFアプリが起動された画面(1対1のトーク、グループ、トークルーム、または外部ブラウザ)に関する情報を取得します。 なお、1対1のトーク、グループ、およびトークルームの場合は、一意に識別できる値も取得できます。

const context = liff.getContext();
console.log(context);
// {"type": "utou", "utouId": "UU29e6eb36812f484fd275d41b5af4e760926c516d8c9faa35…b1e8de8fbb6ecb263ee8724e48118565e3368d39778fe648d", "userId": "U70e153189a29f1188b045366285346bc", "viewType": "full", "accessTokenHash": "ArIXhlwQMAZyW7SDHm7L2g", "availability": {"shareTargetPicker": {"permission": true, "minVer": "10.3.0"}}}

詳しくは、『LIFF v2 APIリファレンス』の「liff.getContext()」を参照してください。

# ユーザーのプロフィールを取得する

LIFFアプリでユーザーのプロフィールを取得する方法は2つあります。 目的に合わせて正しく使い分けてください。

# サーバーに送信するために取得する

LIFFアプリからサーバーにユーザー情報を送信する場合は、以下の方法で取得したアクセストークンまたはIDトークンを送信します。 サーバーでユーザー情報を使用する方法について詳しくは、「LIFFアプリおよびサーバーでユーザー情報を使用する」を参照してください。

  • liff.getAccessToken()メソッドを実行して、現在のユーザーのアクセストークンを取得します。

    // get access token
    document.getElementById('getAccessToken').addEventListener('click', function() {
        if (!liff.isLoggedIn() && !liff.isInClient()) {
            alert('To get an access token, you need to be logged in. Please tap the "login" button below and try again.');
        } else {
            const accessToken = liff.getAccessToken();
            document.getElementById('accessTokenField').textContent = accessToken;
            toggleAccessToken();
        }
    });
    

    詳しくは、『LIFF v2 APIリファレンス』の「liff.getAccessToken()」を参照してください。

  • liff.getIDToken()メソッドを実行して、「現在のユーザーの生のIDトークン」を取得します。

    liff.init(() => {
        const idToken = liff.getIDToken();
        console.log(idToken) // print raw idToken object
    });
    

    詳しくは、『LIFF v2 APIリファレンス』の「liff.getIDToken()」を参照してください。

# LIFFアプリで使用するために取得する

liff.getDecodedIDToken()メソッドを実行して、現在のユーザーのプロフィール情報およびメールアドレスを取得します。

LIFFアプリでユーザーの表示名などを利用する場合に、このAPIを利用してください。

ユーザー情報をサーバーに送信しないでください

liff.getDecodedIDToken()で取得したユーザー情報をサーバーに送信しないでください。 代わりに、liff.getIDToken()で取得したIDトークンを送信します。

liff.init(() => {
    const idToken = liff.getDecodedIDToken();
    console.log(idToken) // print decoded idToken object
});

詳しくは、『LIFF v2 APIリファレンス』の「liff.getDecodedIDToken()」を参照してください。

# ユーザーとLINE公式アカウントの友だち関係を取得する

ユーザーと、LIFFアプリが追加されているLINEログインのチャネルにリンクされているLINE公式アカウントの友だち関係を取得します。

LINEログインのチャネルにLINE公式アカウントをリンクする方法については、『LINEログインドキュメント』の「LINE公式アカウントをLINEログインのチャネルにリンクする」を参照してください。

liff.getFriendship().then(data => {
  if (data.friendFlag) {
    // something you want to do
  }
)

詳しくは、『LIFF v2 APIリファレンス』の「liff.getFriendship()」を参照してください。

LIFF SDKは現在のページのパーマネントリンクを保持しています。

liff.permanentLink.createUrl()メソッドを実行して、パーマネントリンクを取得できます。

// For example, if current location is
// /shopping?item_id=99#details
// (LIFF ID = 1234567890-AbcdEfgh)
const myLink = liff.permanentLink.createUrl()
 
// myLink equals "https://liff.line.me/1234567890-AbcdEfgh/shopping?item_id=99#details"

詳しくは、『LIFF v2 APIリファレンス』の「liff.permanentLink.createUrl()」を参照してください。

また、現在のページのパーマネントリンクにクエリパラメータを追加することもできます。

// For example, if current location is
// /food?menu=pizza
// (LIFF ID = 1234567890-AbcdEfgh)
liff.permanentLink.setExtraQueryParam('user_tracking_id=8888')
const myLink = liff.permanentLink.createUrl()
 
 
// myLink equals "https://liff.line.me/1234567890-AbcdEfgh/food?menu=pizza&user_tracking_id=8888"

詳しくは、『LIFF v2 APIリファレンス』の「liff.permanentLink.setExtraQueryParam()」を参照してください。

# 現在のトーク画面にメッセージを送信する

liff.sendMessages()メソッドを実行して、ユーザーの代わりに、LIFFアプリが開かれているトーク画面にメッセージを送信します。1回のリクエストでメッセージオブジェクトを最大5つまで送信できます。トーク画面以外でLIFFアプリが開かれた場合は、メッセージは送信できません。

以下のコードは、LIFFアプリが表示されているトーク画面に、ユーザーのメッセージとして「Hello, World!」を送信します。

// sendMessages call
document.getElementById('sendMessageButton').addEventListener('click', function() {
    if (!liff.isInClient()) {
        sendAlertIfNotInClient();
    } else {
        liff.sendMessages([{
            'type': 'text',
            'text': "You've successfully sent a message! Hooray!"
        }]).then(function() {
            window.alert('Message sent');
        }).catch(function(error) {
            window.alert('Error sending message: ' + error);
        });
    }
});

詳しくは、『LIFF v2 APIリファレンス』の「liff.sendMessages()」を参照してください。

注意

liff.sendMessages()は、外部ブラウザでは利用できません。

# ユーザーの友だちにメッセージを送信する(シェアターゲットピッカー)

liff.shareTargetPicker()メソッドを実行して、ターゲットピッカー(グループまたは友だちを選択する画面)を表示し、ターゲットピッカーで選択した相手に、開発者が作成したメッセージを送信します。このメッセージは、ユーザーが送信したかのように、グループまたは友だちに表示されます。

target picker

以下のコードは、ターゲットピッカーを表示し、選択したグループまたは友だちに、ユーザーのメッセージとして「Hello, World!」を送信します。 あらかじめ、liff.isApiAvailable()メソッドを実行すると、LIFFアプリを起動した環境でターゲットピッカーが使用可能であることを確認できます。

if (liff.isApiAvailable('shareTargetPicker')) {
  liff.shareTargetPicker([
    {
      type: "text",
      text: "Hello, World!"
    }
  ])
}

詳しくは、『LIFF v2 APIリファレンス』の「liff.isApiAvailable()」および「liff.shareTargetPicker()」を参照してください。

注意
  • ターゲットピッカーを表示するには、コンソールでシェアターゲットピッカーをオンにしてください。詳しくは、「シェアターゲットピッカーを利用するには」を参照してください。
  • 外部ブラウザで利用する場合は、liff.login()を呼び出して、LINEログインの処理(ウェブログイン)を行ってから、liff.shareTargetPicker()を呼び出します。
ターゲットピッカーの動作環境について

ターゲットピッカーは、iOS版とAndroid版のLINE 10.3.0以降でサポートされます。

それ以前のバージョンでターゲットピッカーを起動すると、エラーメッセージが表示されます。ユーザーの混乱を避けるために、liff.shareTargetPicker()を実行する前に、liff.isApiAvailable()を実行して、LIFFアプリを起動した環境でターゲットピッカーが使用できることを確認してください。

# LIFFアプリを閉じる

liff.closeWindow()メソッドを実行して、開いているLIFFアプリを閉じます。

// closeWindow call
document.getElementById('closeWindowButton').addEventListener('click', function() {
    if (!liff.isInClient()) {
        sendAlertIfNotInClient();
    } else {
        liff.closeWindow();
    }
});

詳しくは、『LIFF v2 APIリファレンス』の「liff.closeWindow()」を参照してください。

注意

liff.closeWindow()は、外部ブラウザでは利用できません。

# OGPタグを設定する

LIFFアプリの各ページにOGPタグを設定すると、たとえばLINEのトークルームでLIFFアプリのURL(https://liff.line.me/{liffId})をシェアしたときに、任意のタイトルや説明文、サムネイル画像を表示できます。

LIFFで対応しているOGPタグは以下のとおりです。 OGPタグについて詳しくは、「The Open Graph protocol」を参照してください。

<html lang="ja" prefix="og: http://ogp.me/ns#">
<meta property="og:title" content="タイトル">
<meta property="og:type" content="`website`、`blog`、または`article`">
<meta property="og:description" content="ページの簡単な説明">
<meta property="og:url" content="ページのURL">
<meta property="og:site_name" content="サイト全体を表す名前">
<meta property="og:image" content="サムネイル画像のURL">
注意

LIFFアプリのURLを、line://app/{liffId}(非推奨)の形式でシェアしたときは、OGPタグは無視されます。

# 次のステップ

LIFFアプリを任意のサーバーにデプロイしたら、以下の操作を行います。

  1. LIFFアプリをチャネルに追加する
  2. LIFFアプリを開く