Day 24:LIFF 刮刮樂實戰體驗
4.2k 字,約 4 分鐘
2025 iThome 鐵人賽:Line Bot × NestJS:30 天開發日記。 原文發表於 iThome,也可以在下方留言。
前言
在了解 LIFF 的基礎設計流程後,本文將透過「刮刮樂」案例示範 LIFF API 的實際應用。從啟動時檢查權限與執行環境、確認用戶分享功能權限,到刮刮樂結束後發送訊息並關閉 LIFF,完整呈現 LIFF 在互動應用中的整合流程,幫助大家更清楚理解其實際運作方式。
本日程式碼的範例連結。本文著重於 LIFF API 的整合應用,以刮刮樂為例說明完整的互動流程,刮刮樂的視覺實作細節請參考範例程式碼。
實作目標
本次將打造一個互動式刮刮樂應用,具備以下功能
- 建立行動裝置刮刮樂體驗:開發一個在行動裝置上運作流暢的刮刮樂網站,支援觸控操作
- 社群分享機制:刮出獎項後,使用者可將中獎結果分享給 LINE 好友
- 結果通知功能:自動將刮獎結果透過訊息發送至使用者的聊天室
- 自動關閉流程:無論使用者是否進行分享操作,完成互動後皆會自動關閉 LIFF 視窗,返回聊天室介面
資料夾結構說明
本次在 components 目錄中建立了三個核心組件
- ScratchCard.vue:使用 p5.js 實作刮刮樂互動效果,處理觸控刮除邏輯與視覺呈現
- PrizeModal.vue:自訂模態框組件,當刮刮樂完全刮開時顯示中獎結果
- Toast.vue:提示訊息組件,用於顯示分享成功訊息及錯誤提示
用戶裝置及權限驗證
使用到的 LIFF API
- liff.isLoggedIn():檢查使用者目前是否已登入 LINE 帳號
- liff.login():當使用者尚未登入時,引導至 LINE 登入畫面進行授權
- liff.isInClient():檢查使用者是否在 LINE 內建瀏覽器中開啟
- liff.getOS():取得使用者的作業系統類型,回傳值包含
ios、android及web三種 - liff.isApiAvailable('shareTargetPicker'):檢查使用者的 LINE 版本是否支援分享功能。
/** 檢查並處理用戶登入狀態 */
const checkLoginStatus = (): void => {
if (!liff.isLoggedIn()) {
liff.login();
}
};
/** 驗證用戶裝置及執行環境 */
const validateEnvironment = async (): Promise<boolean> => {
const userOS = liff.getOS();
if (!liff.isInClient() || userOS === 'web') {
await showErrorDialog('請在 LINE 應用程式中開啟此活動');
closeLiffWindow(3000);
return false;
}
return true;
};
/** 檢查是否支援分享功能 */
const checkShareAvailability = (): boolean => {
const isAvailable = liff.isApiAvailable('shareTargetPicker');
if (!isAvailable) {
showToast('提醒用戶!分享功能不可用', '需要更新 LINE 版本', 'error');
}
canShare.value = isAvailable;
return isAvailable;
};
/** 初始化 LIFF */
const initializeLiff = async (): Promise<void> => {
try {
// 初始化 LIFF SDK
await liff.init({ liffId: import.meta.env.VITE_LIFF_ID });
// 檢查用戶登入狀態
checkLoginStatus();
// 驗證執行環境
const isValidEnvironment = await validateEnvironment();
if (!isValidEnvironment) {
return;
}
// 檢查分享功能可用性
checkShareAvailability();
} catch (error) {
console.error("LIFF 初始化失敗:", error);
showResultMessage('初始化失敗', '請重新整理頁面', 'error');
}
};
結果通知功能
當使用者刮開刮刮卡並抽中獎項時,系統會在顯示中獎訊息的同時,自動透過 LINE 聊天室發送通知訊息,讓使用者可以保存中獎記錄。
使用到的 LIFF API
- liff.sendMessages():將中獎結果自動發送至當前 LINE 聊天室,訊息會顯示在與官方帳號的對話視窗中
App.vue script:
/** 發送 LINE 訊息 */
const sendLineMessage = async (message: string): Promise<void> => {
await liff.sendMessages([
{
type: "text",
text: `🎉 ${message}\n感謝您參與我們的活動!`
}
]);
};
/** 處理刮刮卡完成事件 */
const handleScratchComplete = async (data: { progress: number; message: string }): Promise<void> => {
try {
await sendLineMessage(data.message);
showPrizeMessage(data.message);
} catch (error) {
console.error('處理完成訊息時發生錯誤:', error);
showToast('操作失敗', '請稍後再試', 'error');
}
};
社群分享機制
透過 LIFF SDK 將中獎訊息即時分享到 LINE 聊天室,提升活動的社群擴散效果。
使用到的 LIFF API
- liff.shareTargetPicker():開啟 LINE 的分享選擇器,讓使用者可以主動選擇要分享的聊天室或好友。可以在分享訊息中包含 LIFF URL,當其他使用者點擊連結後,被引導加入對應的官方帳號並參與活動
在 shareTargetPicker 的 callback 函數中,應避免使用 alert()、confirm() 等會阻塞執行緒的方法,這可能導致 LIFF 在部分裝置上無法正常運作。因此本次實作皆採用自訂組件來顯示提示訊息。
使用 shareTargetPicker 功能前,要確認以下兩項條件
- 使用者必須已登入 LINE 帳號
- 已在 LINE Developers 控制台的 LIFF 應用設定中啟用相關設定
shareTargetPicker 支援發送的訊息類型(這部分與 sendMessages 相同)
- 六種基礎訊息:text、image、video、audio、location、sticker
- Template Message:buttons、confirm、carousel、image carousel等樣板訊息
- Flex Message:高度客製化訊息
只有
image、audio及video訊息可以透過external參數標記來源為 LIFF
App.vue template:
<div id="app">
<!-- 刮刮樂組件 -->
<ScratchCard @onCompleted="handleScratchComplete" />
<!-- 中獎彈窗 -->
<PrizeModal :show="showModal" :message="prizeMessage" :canShare="canShare" @share="handleShare"
@close="handleClose" />
<!-- 結果提示 -->
<Toast :show="showToastVisible" :title="toastTitle" :text="toastText" :type="toastType" />
</div>
App.vue script:
/** 分享訊息到 LINE */
const shareToLine = async (message: string): Promise<void> => {
const liffUrl = `https://liff.line.me/${import.meta.env.VITE_LIFF_ID}`;
await liff.shareTargetPicker([
{
type: "text",
text: message
},
{
type: "template",
altText: "刮刮卡活動邀請",
template: {
type: "buttons",
text: "你也來挑戰刮刮卡吧!",
actions: [
{
type: "uri",
label: "立即參加抽獎",
uri: liffUrl
}
]
}
}
]);
};
/** 處理分享按鈕點擊事件 */
const handleShare = async () => {
showModal.value = false;
try {
await shareToLine(prizeMessage.value);
showToast('分享成功!', '訊息已分享到 LINE');
} catch (error) {
console.error('分享失敗:', error);
showToast('分享失敗', '請稍後再試', 'error');
} finally {
closeLiffWindow(1500); // 延遲關閉視窗
}
};
自動關閉流程
不論使用者是否完成分享,或是直接點擊關閉按鈕,系統都能順利關閉 LIFF 視窗並返回 LINE 聊天室,提供流暢的使用體驗。
使用到的 LIFF API
- liff.closeWindow():關閉當前 LIFF 瀏覽器視窗,讓使用者返回 LINE 聊天室介面
/** 關閉 LIFF 視窗 */
const closeLiffWindow = (delay: number = 2000): void => {
setTimeout(() => {
liff.closeWindow();
}, delay);
};
LIFF 與官方帳號的連結配置
當需要重新觸發 LIFF 授權畫面時,可以透過以下步驟取消既有的應用程式連結
- 開啟 LINE 應用程式
- 前往「主頁」→「設定」→「我的帳號」
- 點選「連結中的應用程式」
- 找到已綁定 LINE Login 的頻道並取消連結
完成上述步驟後,下次點選 LIFF 連結時就會重新顯示授權畫面。
LINE Login 頻道綁定官方帳號
在 LINE Developers Console 中,將 Login 頻道與 LINE 官方帳號進行綁定,建立兩者之間的關聯性。
LIFF 應用程式加好友選項
在 LIFF 應用程式設定中,可以配置「加好友選項」(Add friend option),讓使用者在授權時可以同步加入官方帳號為好友。
LIFF 授權畫面呈現
啟用 LIFF 選項後,使用者在首次開啟 LIFF 應用時,授權畫面會顯示「加入好友」的選項,讓使用者可以一併將官方帳號加為好友。
透過這些設定,可以在使用者首次開啟 LIFF 應用時,引導他們加入官方帳號,有助於提升官方帳號的好友數量與後續互動機會。
分享 LIFF 網頁前的狀態檢查
在 LINE Developers 控制台選擇對應的 LIFF 進行設定
Developing 狀態
- 無法分享給其他用戶
- 僅供開發者測試使用
Published 狀態
- 可分享給其他用戶
- 發布後無法切回 Developing 狀態
本日結語
相對於昨天的基礎應用,今天的實作聚焦在單一完整的互動功能上。這個刮刮卡應用可以直接整合到 LINE 圖文選單中,讓使用者點擊後立即參與抽獎,刮開後的中獎結果會自動發送到聊天室,創造即時且有趣的互動體驗。
留言
留言使用 GitHub 帳號登入(Giscus),留言會存在 GitHub Discussions。