駆け出しLIFFプレイヤーに残す道標

この記事は[PARONYMAdventCalendar2020](https://qiita.com/advent-calendar/2020/paronym)の3日目です
最近LIFFを扱う機会があったのですが、詰まったときにググってもなかなか情報が出てこないで困ることが多かったです。
まだ自分も導入段階ですが、試行錯誤して理解することが多かったのでここにまとめておこうと思います。
自分と同じようにネットを彷徨う駆け出しLIFFプレイヤーの道標になるような記事になりますように…

# この記事が向いている人
LIFF導入段階で詰まっている人
LIFFに関するエラーが出てそのままググってる人

# 前提
自分はJavaScriptを使用しています。
- LIFFとは何なのかの理解
- LINE Developersの登録
- 自分のLIFFアプリのエンドポイントURLの設定
- LIFFアプリIDの取得
以上のことが完了していることを前提にしています。
その辺はたくさんまとめられているのでググってください🙇‍♂️

# LIFF導入〜ログインLINEユーザーデータまでの手順
1.LIFF SDK読み込み
2.LIFFアプリ初期化
3.LINEログイン
4.ログインLINEユーザーデータ取得

この記事ではログイン中のLINEユーザーデータを取得するまでがゴールとなっています。取得までの過程を掘り下げて行こうと思います！（なぜなら自分もまだここまでしかやってないから）

## 1.LIFF SDK読み込み
LIFFメソッド(liff.で始まるメソッド)を扱うためにどこかでSDKを読み込んでおきます。この辺は公式読んだ方が詳しく書いてます。

```html
<script charset=utf-8 src=https://static.line-scdn.net/liff/edge/2/sdk.js></script>
```

もしくはパッケージをインストールし、読み込む

```
$ npm install --save @line/liff
```

```js
import liff from '@line/liff';
```

## 2.LIFFアプリ初期化
LINEログイン処理をするにしてもとにかくまずは初期化処理が必要です。初期化を行わないとLIFF SDKのメソッドを使うことが出来ないからです。(初期化前に使用できる例外もあります。)

初期化にはliff.init()メソッドを使います。タイミングは画面表示時で良いので、window.onloadと合わせて使用するといいと思います。

```js
window.onload = function (e) {
    liff
    .init({liffId: 'LIFFアプリID'})
    .then(() => {
        // 初期化完了
        initializeApp();
    })
};
```
LIFFアプリIDが正しく入力されていればひとまずは初期化完了です。これでliff.init()以外のメソッドが使えるようになりました。
## 3.LINEログイン
続いて初期化成功後に実行されるように設定したinitializeApp関数の中身です。

```js
function initializeApp() {
    // ログインチェック
    if (liff.isLoggedIn()) {
        //ログイン済
        getLineData();
    } else {
        // 未ログイン
        let result = window.confirm("LINE Loginしますか？");
        if(result) {
            liff.login();
        }
    }
}
```
中身について説明します。
liff.isLoggedIn()メソッドはラインログインが完了していた場合はtrue、していない場合はfalseを返すLIFFメソッドです。ラインログインが済んでいる場合はユーザーデータを取得できる状態なので、[4.ログインユーザーデータ取得](## 4.ログインユーザーデータ取得に進みます)に進みます

未ログインの場合について見てみましょう。ログインしていない場合はliff.isLoggedIn()メソッドがfalseを返すので、条件分岐を使ってliff.login()メソッドを呼び出しましょう。

liff.login()メソッドを実行することでラインのログイン処理が行われます。ラインアプリ内のブラウザで操作していてアクセスを許可していた場合は自動ログイン、別ブラウザを使用していて初回アクセスの場合は画像のようにログイン画面が表示されます。
![スクリーンショット 2020-12-03 18.36.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/926874/e3e31989-0200-b713-527e-abd1c2f5d325.png)

##4.ログインLINEユーザーデータ取得
ログインが完了したらあとはログインLINEユーザーデータを取得するだけです。ログイン完了後実行されるように設定したgetLineData関数の中身です。

```js
function getLineData() {
    liff.getProfile()
    .then(profile => {
      console.log("ログインしてるユーザーのid:" + profile.userId);
      console.log("ログインしてるユーザーの名前:" + profile.displayName);
      console.log("ログインしてるユーザーの画像URL:" + profile.pictureUrl);
    })
}
```
liff.getProfile()メソッドはログインが成功している場合のみに実行出来るメソッドです。
userId…ユーザーID
displayName…表示名
pictureUrl…画像のURL
以上三つの情報を取得出来ます。

これでログイン中のLINEユーザーのデータを取得するところまで完了です！

#発生した問題と解決法
ここまではぶっちゃけ調べればたくさん出てきますので、前座のようなものです 笑
ここからの問題解決法はググっても簡単には見つけられなかったので、LIFF導入時に役立つと思います！
## 問題1.liff.init()のタイミング失敗

```
Error: liffId is necessary for liff.init()
```
簡単に言うとLIFFの初期化が出来てないよ！ってエラーです。
このエラーはliffの初期化が終わる前にliff.login()だったりliff.getProfile()を実行するなどのLIFFメソッドを実行することで発生するエラーです。
### 解決法
最初の頃は処理の順番を気を付けることでエラーを防いでいましたが、流石LIFFさん、便利なプロパティを用意してくれてました…！
それがliff.readyプロパティです。

```js
liff.ready.then(() => {
  // liff.init()完了後に実行される処理
  liff.getProfile()
  then(profile => {
      console.log('初期化が終わってから実行されるよ！');
    })
})
```
liff.readyプロパティはJavaScriptで言うPromiseのような使い方が出来ます。liff.ready内に書いた処理はliff.init()が完了された後に実行されるので、今回のエラーの回避に非常に役立ちました。

## 問題2.URLにパラメータを渡している状態でliff.login()を行いLINEログイン認証をすると、パラメータが消し飛ぶ
LIFFアクセスURLに設定したURLの後ろにパラメータをつけることが出来ます。

```
https://{LIFFアクセスURL}?id=xxxx&name=xxxxxxx
```
この機能を利用し、自分が開発するアプリ内でURLに渡したパラメータを使用し意図した挙動をさせることも可能です。
###ここから問題
ですが初回ログイン時のliff.login()を実行したタイミングで、LIFFアプリに設定されているLIFFアクセスURLに書き換わってしまいます

```
// ログイン後は後ろにつけたパラメータが消えてしまう
https://{LIFFアクセスURL}
```
### 解決法
少し調べると、liff.login()ではredirectUriという引数を渡せることがわかりました。

```js
liff.login({ redirectUri: 'リダイレクトさせたいURL' });
```
なのでログイン後も現在のURLパラメータのまま遷移させたい場合は

```js
liff.login({ redirectUri: location.href });
```
このような書き方をすることで、URLのパラメータを維持したままLINEログインを行うことが出来ました。

### 注意点
リダイレクト先のURLはあくまでLIFFアクセスURLから始まるURLでないといけません。

```js
iff.login({ redirectUri: 'LIFFアクセスURLとは関係ないURL' });
```
仮にこのような書き方をした場合、画像のように400 Bad Requestと表示されてしまいます。
![スクリーンショット 2020-12-03 20.51.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/926874/3969c0cc-5ada-da56-1c9b-7d18ae854457.png)
パラメータを維持したままLINEログインをする方法は、自分がググった限り解決法が出て来なかったので、もし困っている人はこの記事が助けになることを願っています。