第二章:在 React 中完美整合 LIFF 與 Line Login

上一章我們拿到了神聖的 LIFF ID,現在我們要回到 React + Vite 的專案中,把 Line 的 SDK 裝起來。 只要學會這一步,你的網頁就能擁有「點開即登入」的黑科技。

1. 安裝 @line/liff 套件

在終端機中執行:

npm install @line/liff

2. 建立 LIFF 初始化 Hook (useLiff.ts)

不要把 LIFF 邏輯散落在各個元件裡!我們寫一個自訂的 Hook 來統一管理 Line 的登入狀態。

// src/hooks/useLiff.ts
import { useEffect, useState } from 'react';
import liff from '@line/liff';

export function useLiff() {
  const [profile, setProfile] = useState<any>(null);
  const [error, setError] = useState<string | null>(null);
  const [isReady, setIsReady] = useState(false);

  useEffect(() => {
    // 這裡填入你上一章拿到的 LIFF ID
    liff.init({ liffId: import.meta.env.VITE_LIFF_ID })
      .then(() => {
        setIsReady(true);
        // 檢查是否是在 Line 內部打開,或是否已登入
        if (liff.isLoggedIn()) {
          liff.getProfile().then((p) => {
            setProfile(p);
          }).catch((err) => {
            console.error('取得 Profile 失敗', err);
            setError(err.toString());
          });
        } else {
          // 如果沒有登入,主動要求 Line Login
          liff.login();
        }
      })
      .catch((err) => {
        console.error('LIFF 初始化失敗', err);
        setError(err.toString());
      });
  }, []);

  return { profile, error, isReady, liff };
}

3. 在打卡頁面使用使用者的資訊

現在,只要在你的打卡元件中呼叫這個 Hook,你就能立刻拿到員工的名字與頭像,完全不需要他們輸入帳號密碼!

// src/components/PunchCard.tsx
import { useLiff } from '../hooks/useLiff';

export function PunchCard() {
  const { profile, isReady, liff } = useLiff();

  if (!isReady) return <div>載入 Line 系統中...</div>;
  if (!profile) return <div>請先登入 Line...</div>;

  const handlePunch = async () => {
    // 取得安全的 Access Token 送給我們自己寫的 FastAPI 後端
    const accessToken = liff.getAccessToken();
    
    await fetch('https://api.yourdomain.com/punch', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${accessToken}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ action: 'check-in' })
    });
    
    alert('打卡成功!');
    // 打卡完畢後,直接關閉 Line 視窗!超有尊榮感!
    liff.closeWindow();
  };

  return (
    <div className="p-4 bg-white rounded-xl shadow-md flex flex-col items-center">
      <img src={profile.pictureUrl} alt="avatar" className="w-20 h-20 rounded-full mb-4" />
      <h2 className="text-xl font-bold mb-6">你好,{profile.displayName}</h2>
      
      <button 
        onClick={handlePunch}
        className="w-full bg-green-500 text-white font-bold py-4 rounded-lg text-lg"
      >
        上班打卡
      </button>
    </div>
  );
}

4. 為什麼這個架構這麼強?

仔細看 liff.getAccessToken() 這行程式碼。 這是 LIFF 最強大的地方:它幫你生出了一把「只有這支手機的 Line」才能產生的鑰匙。我們把它傳給後端 (FastAPI),後端只要向 Line 的伺服器驗證這把鑰匙,就能確認「這個人絕對沒有作弊代打卡」!

這就是 SaaS 接案的底氣。下一章,我們將去 FastAPI 後端實作這把鑰匙的驗證機制!

解鎖完整教學內容

本章為付費內容。加入專案即可解鎖超過 5000 字的深度解析,包含 10 個以上神級 Prompt 與真實 Source Code 範例!