◾️ はじめに
LIFF(LINE Front-end Framework)を使用してアプリケーションを開発した際、LIFF URLにパラメータ(例:shopId)を付与して店舗ごとのページを表示する仕組みを実装しました。
しかし、外部ブラウザで開いた場合、2次リダイレクト時にURLに付与したパラメータが消える という問題が発生しました。
例えば、以下のようなURLを使用した場合:
- 与えたURL:
https://liff.line.me/hogehoge/?shopId=1
- 期待動作:
https://liff.line.me/hogehoge/?shopId=1
に遷移して店舗情報を表示 - 実際の動作(問題発生時):
https://liff.line.me/hogehoge/
に遷移し、パラメータが消失
この記事では、この問題の原因と、liff.stateを削除し、もともとURLに渡していたパラメータ(shopId)を活かす方法について説明します。
◾️ LIFFの2次リダイレクトプロセスについて
LIFF URLにアクセスしてからLIFFアプリが開くまでの動作は以下の通りです。
リダイレクト先 | 説明 |
---|---|
1次リダイレクト | ユーザーがLIFF URLにアクセスすると、LINEブラウザが state パラメータを自動付与します。これにより、LIFFアプリの準備が行われます。 |
2次リダイレクト | 1次リダイレクト後、LIFFアプリが内部的に設定されたURLにリダイレクトします。 |
◾️ liff.stateとは
liff.state は、LINE Front-end Framework (LIFF) アプリケーションで使用される仕組みの一つで、LIFFアプリが開かれた際に、URLに含まれるstateパラメータを取得するために使われます。
パラメータを設定した場合
LIFFアプリを開くとき、LINEの内部でURLに自動的にstateパラメータが付与されます。
例えば、次のようなURLでLIFFアプリを開こうとした場合:
https://liff.line.me/{liffId}?redirectUri=https://example.com
LINEはこのURLに対して、次のような stateパラメータを自動的に追加します:
https://liff.line.me/{liffId}?redirectUri=https://example.com&state=someState
このstateパラメータは、LINEがLIFFアプリのセッションや状態を管理するために付与するものです。
liff.stateの役割
liff.stateは、URLに含まれるstateパラメータの値を取得するために使用されます。
例えば、上記の例では liff.stateを実行すると、someState
という値が返されます。
今回の事例に戻りますが、liff.stateの役割はパラメータの値を取得するために使用されるのにも関わらず、2次リダイレクトの際にパラメータがなぜ消えてしまうのでしょうか?
この問題の原因と解決方法について以下で解説していきます。
◾️問題の原因と解決方法
原因
1. LINEが自動的に追加するliff.stateパラメータの影響
liff.stateは、LINEがLIFF初期化時にURLに自動で付与するパラメータです。
このパラメータが、元々のクエリパラメータ(例:shopId)を上書きしたり、リダイレクト時に一部のパラメータが削除される原因になることが動作検証で判明しました。
2. 2次リダイレクト時のパラメータ消失
LIFFの2次リダイレクトのプロセスでは、LINE内部の処理によってURLがリセットまたは再構築されることがあります。
この際、開発者が設定したクエリパラメータ(shopIdなど)がURLから削除される場合があることがわかりました。
この挙動に関してLINE公式ドキュメントでは明確な説明がないため、仕様か不具合かは定かではありませんが、動作検証の結果としてこの問題を確認しています。
解決方法
1. URLからクエリ文字列を取得
window.location.search を使って、現在のURLからクエリ文字列部分を取得します。
例: ?liff.state=some_state_value&shopId=1
2. liff.stateを削除
.replace('?liff.state=', '') によって、URLに含まれる不要なliff.state部分を削除します。
結果:shopId=1
のみが残ります。
3. shopIdを抽出して保持
URLSearchParamsを使用、クエリ文字列を解析し、shopId の値を抽出します。
取得したshopIdをリアクティブ変数 shopId.valueに格納します。
◾️ LIFFのURLにパラメータ追加する実装
店舗ごとのページを表示するため、LIFF URLに shopId パラメータを付与して使用していました。
例:https://liff.line.me/hogehoge/?shopId=1
以下のコードは、以下のコードでは、クエリパラメータを取得してshopIdを利用し、店舗ごとに異なるページを表示する仕組みを実装しています。
実装コード例:
<script setup lang="ts">
import { useRoute } from 'vue-router'
import { ref, watch } from 'vue'
import { RouterView } from 'vue-router'
const shopId = ref<number | null>(null)
const route = useRoute()
const fetchShopName = async () => {
if (!shopId.value) return
try {
const response = await getShopName()
shopName.value = response
console.log(shopName.value)
} catch (e) {
error.value = e
console.log(e)
}
}
// initializeLiff関数を削除し、removeLiffState関数を追加
const removeLiffState = () => {
// 現在のURLのクエリ文字列を取得、かつ、shopIdを取り出し、?liff.state= を取り除く
const queryString = decodeURIComponent(window.location.search).replace(
'?liff.state=',
''
)
// クエリ文字列を解析
const queries = new URLSearchParams(queryString)
// shopId パラメータを取得
const _shopId = queries.get('shopId')
// shopId.value に設定する
shopId.value =_shopId
}
/*
route.query.shopIdを監視
shopIdの値が変化した場合に、shopId.valueを更新
*/
watch(
() => route.query.shopId,
(selectedShopId) => {
if (selectedShopId) {
shopId.value = Number(selectedShopId)
fetchShopName()
} else if (shopId.value) {
fetchShopName()
}
}
)
// コンポーネントがマウントされたタイミングで、removeLiffState関数を実行
onMounted(() => {
removeLiffState()
})
</script>
<template>
<Loading v-if="isProcessing" />
<v-app>
<RouterView />
</v-app>
</template>
◾️ おわりに
この記事では、LIFFアプリケーションで2次リダイレクト時にパラメータが消えてしまう問題の原因と解決方法について説明しました。
最後まで記事を読んでいただきありがとうございました。