LIFF 應用程式
說明
LINE Front-end Framework (LIFF) 是 LINE 提供的前端應用程式框架,可以在 LINE 內運行網頁 APP,藉由 LIFF 應用程式來取得 LINE 相關的用戶資訊以便後續的操作。
專屬網址
LIFF 服務會提供一個 LIFF URL
像是這樣 https://liff.line.me/1657xxxxx-M12dnxxxx
,會在點擊開啟 LINE 在 「LIFF 瀏覽器」 中顯示網站。
流程
- LINE Develop console 創建「LINE Login」頻道且新增「LIFF」服務,取得
LIFF ID
。 - 專案加上 LIFF SDK,
liff
將會被掛載在window.liff
。html<script charset="utf-8" src="https://static.line-scdn.net/liff/edge/2/sdk.js" ></script>
- 使用「LIFF ID」操作 LIFF 相關 API
開發工具
NGROK 將本機 url 變成「外部」可以連結
顯示內容
本地方法
bash
ngrok http 8000
容器方法
docker
docker run -it -e NGROK_AUTHTOKEN=<Token> ngrok/ngrok http 8080
注意
NGROK 登入後可以取得個人
token
NGROK 免費帳號,本地 url 無法使用
ssl
,且vue
開發服務器要充許外部使用。**vue.config.js** ```js {2} devServer: { disableHostCheck: true, // 開發服務器允許外部使用
// https: { // key: // p
rocess.env.NODE_ENV === 'development' // ? fs.readFileSync(path.join(**dirname, '/localhost-key.pem')) // : '', // cert: // p rocess.env.NODE_ENV === 'development' // ? fs.readFileSync(path.join(**dirname, '/localhost.pem')) // : '', // }, }
### **[vConsole]** 手機端 debug 工具
:::details 顯示內容
**安裝**
```bash
npm i vconsole
使用
js
import VConsole from 'vconsole'
const vConsole = new VConsole({ theme: 'dark' }) // 啟動
vConsole.destroy() // 移除
:::
常用 API
LIFF 初始化 liff.init
在初始化之後,才能進行後續的其它 API 操作。
js
// Using a Promise object
liff
.init({
liffId: '123456-abcedfg', // Use own liffId
})
.then(() => {
// Start to use liff's api
})
.catch((err) => {
// Error happens during initialization
console.log(err.code, err.message)
})
// Using a callback
liff.init({ liffId: '123456-abcedfg' }, successCallback, errorCallback)
提醒
初始化也關係到網址「重新導向」的議題,如果有這樣的困擾,就把初始化放在「最入口」端先執行。
是否在 LIFF 瀏覽器 liff.isInClient
用來判斷當前的 LIFF APP 是否在 LIFF 瀏覽器開啟的狀態。
js
liff.isInClient()
是否登入 LINE liff.isLoggedIn
判斷當下是否已經 LINE 登入的狀態。
js
if (liff.isLoggedIn()) {
// The user can use an API that requires an access token, such as liff.getProfile().
}
登入 LINE liff.login
在外部瀏覽器或 LINE 內部瀏覽器執行登入的功能。
js
if (!liff.isLoggedIn()) {
liff.login()
}
注意
不能在 LIFF 瀏覽器內,使用 liff.login
,因為 liff.init
時,它就會自動執行了。
取得使用者 ID Token liff.getIDToken
可以由這個方法,取得當前用戶的 JWT 令牌, 後端
再由這個令牌取得使用者的相關資料。
js
liff
.init({
liffId: '123456-abcedfg', // Use own liffId
})
.then(() => {
const idToken = liff.getIDToken()
console.log(idToken) // print raw idToken object
})
取得當前用戶基本資料 liff.getProfile
js
liff
.getProfile()
.then((profile) => {
const name = profile.displayName
})
.catch((err) => {
console.log('error', err)
})
profile value:
json
{
"userId": "U4af4980629...",
"displayName": "Brown",
"pictureUrl": "https://profile.line-scdn.net/abcdefghijklmn",
"statusMessage": "Hello, LINE!"
}
LIFF URL 重新導向
不會重新導向
一般的情況下 LIFF URL 會是這樣 專屬網址,點擊會直接進入 Endpoint URL
。
多次重新導向
https://liff.line.me/1657672659-G540g2e1?liff_id=1657672659-G540g2e1
LIFF URL 加上查詢參數 ?liff_id=1657672659-G540g2e1
,LINE 開啟時就會經過多次「重新導向」的步驟。LIFF 重新導向說明
- 第一次重新導向 URL 編碼後,把查詢參數放在
liff.state
內https://liff.line.me/1657672659-G540g2e1?liff.state=%2#liff_id1@#1657672659!@#G540g2e1
- 第二次重新導向
liff.state
解碼後再加到Endpoint URL
上https://liff.line.me/1657672659-G540g2e1?liff_id=1657672659-G540g2e1
重新導向取查詢參數
如果會重新導向,你無法預測會導向的次數 (LINE 可能也會增加再次導向),可以使用下面的方法,解析網址後取得「查詢參數」。
注意
LIFF URL 如果要帶參數 (search),不要在參數前加 /
,會影響到 android url 解析。
❌ https://liff.line.me/1657672659-G540g2e1/?liff_Id=1657672659-G540g2e1
✅ https://liff.line.me/1657672659-G540g2e1?liff_Id=1657672659-G540g2e1
js
export const parseUrlQuery = (locationSearch) => {
let liffId = null
let agentCode = null
const liffState = new URLSearchParams(locationSearch).get('liff.state')
// 若參數在 liff.state 內
if (liffState) {
liffId = new URLSearchParams(liffState).get('liff_Id')
agentCode = new URLSearchParams(liffState).get('agent_code')
// 已解碼到 Endpoint URL 上
} else {
liffId = new URLSearchParams(locationSearch).get('liff_Id')
agentCode = new URLSearchParams(locationSearch).get('agent_code')
}
return { liff_Id: liffId, agent_code: agentCode }
}
🔥🔥 android 特殊情況 🔥🔥
假設 LIFF URL (search 前加上 /
),在 android
需要另外處理 url 的 search
參數!
https://liff.line.me/1657672659-G540g2e1/?liff_Id=1657672659-G540g2e1
第一次重新導向的網址會是
www.example.com?liff.state=%2F%3Fliff_Id%3D1657711508-k2K91AR3%26log%3Dtrue
在 liff.state
的值會被「多加」符號 /?
const liffState = new URLSearchParams('?liff.state=%2F%3Fliff_Id%3D1657711508-k2K91AR3%26log%3Dtrue').get('liff.state')
console.log(liffState) // /?liff_Id=1657711508-k2K91AR3&log=true
這會導致你的 liff_Id
為 null
,因為變成了 /?liff_Id
。
所以剛的函式可以這樣改,把 /?
移除。
js
export const parseUrlQuery = (locationSearch) => {
let liffId = null
let agentCode = null
const liffState = new URLSearchParams(locationSearch).get('liff.state')
// 若參數在 liff.state 內
if (liffState) {
// 如果有 /?
if (liffState.indexOf('/?') > -1) {
liffState = liffState.replace('/?', '')
}
liffId = new URLSearchParams(liffState).get('liff_Id')
agentCode = new URLSearchParams(liffState).get('agent_code')
// 已解碼到 Endpoint URL 上
} else {
liffId = new URLSearchParams(locationSearch).get('liff_Id')
agentCode = new URLSearchParams(locationSearch).get('agent_code')
}
return { liff_Id: liffId, agent_code: agentCode }
}
這是可以正常進入的 LIFF URL
https://liff.line.me/1657672659-G540g2e1?liff_Id=1657672659-G540g2e1