今天繼續搭配 LIFF 的文件研究 Line LIFF App line-liff-v2-starter 的範例
<title>LIFF Starter</title> 設置 LIFF App 的標題window.onload = function() {
    const useNodeJS = true;   // if you are not using a node server, set this value to false
    const defaultLiffId = "";   // change the default LIFF value if you are not using a node server
    // DO NOT CHANGE THIS
    let myLiffId = "";
    // if node is used, fetch the environment variable and pass it to the LIFF method
    // otherwise, pass defaultLiffId
    if (useNodeJS) {
        fetch('/send-id')
            .then(function(reqResponse) {
                return reqResponse.json();
            })
            .then(function(jsonResponse) {
                myLiffId = jsonResponse.id;
                initializeLiffOrDie(myLiffId);
            })
            .catch(function(error) {
                document.getElementById("liffAppContent").classList.add('hidden');
                document.getElementById("nodeLiffIdErrorMessage").classList.remove('hidden');
            });
    } else {
        myLiffId = defaultLiffId;
        initializeLiffOrDie(myLiffId);
    }
};
Developing a LIFF app 講述了如何開發一個 LIFF app,裡面有幾個章節跟今天的範例有關:
Setting the title of the LIFF app
可以看到 public/index.html 裡用 HTML TAG <title>LIFF Starter</title> 設置 LIFF Starter 為 LIFF App 的標題
Integrating the LIFF SDK with the LIFF app
<!DOCTYPE html>
...(略)
        <script charset="utf-8" src="https://static.line-scdn.net/liff/edge/2/sdk.js"></script>
        <script src="liff-starter.js"></script>
    </body>
</html>
Calling the LIFF API
initializeLiff(myLiffId);
liff.init() initializing-liff-app ,若初始化成功則繼續執行 initializeApp();
initializeApp();
displayLiffData(); 使用 LIFF SDK 取得並顯示 LIFF APP 環境基本資訊 
displayIsInClientInfo(); 判斷是不是用 Line 開啟 LIFF APP,並控制相關顯示registerButtonHandlers(); 註冊按鈕 click event handlers/**
* Check if myLiffId is null. If null do not initiate liff.
* @param {string} myLiffId The LIFF ID of the selected element
*/
function initializeLiffOrDie(myLiffId) {
    if (!myLiffId) {
        document.getElementById("liffAppContent").classList.add('hidden');
        document.getElementById("liffIdErrorMessage").classList.remove('hidden');
    } else {
        initializeLiff(myLiffId);
    }
}
/**
* Initialize LIFF
* @param {string} myLiffId The LIFF ID of the selected element
*/
function initializeLiff(myLiffId) {
    liff
        .init({
            liffId: myLiffId
        })
        .then(() => {
            // start to use LIFF's api
            initializeApp();
        })
        .catch((err) => {
            document.getElementById("liffAppContent").classList.add('hidden');
            document.getElementById("liffInitErrorMessage").classList.remove('hidden');
        });
}
/**
 * Initialize the app by calling functions handling individual app components
 */
function initializeApp() {
    displayLiffData();
    displayIsInClientInfo();
    registerButtonHandlers();
    // check if the user is logged in/out, and disable inappropriate button
    if (liff.isLoggedIn()) {
        document.getElementById('liffLoginButton').disabled = true;
    } else {
        document.getElementById('liffLogoutButton').disabled = true;
    }
}
displayLiffData(); 使用 LIFF SDK 取得並顯示 LIFF APP 環境基本資訊/**
* Display data generated by invoking LIFF methods
*/
function displayLiffData() {
    document.getElementById('browserLanguage').textContent = liff.getLanguage();
    document.getElementById('sdkVersion').textContent = liff.getVersion();
    document.getElementById('lineVersion').textContent = liff.getLineVersion();
    document.getElementById('isInClient').textContent = liff.isInClient();
    document.getElementById('isLoggedIn').textContent = liff.isLoggedIn();
    document.getElementById('deviceOS').textContent = liff.getOS();
}
接著就讓我們來看看範例程式的每一個按鈕 click 做了什麼事情:
/**
* Register event handlers for the buttons displayed in the app
*/
function registerButtonHandlers() {
    // button handlers...
}
Opening a URL 開啟一個網頁,可以在 Line 內建瀏覽器呼叫,也可以在外部瀏覽器呼叫
// openWindow call
document.getElementById('openWindowButton').addEventListener('click', function() {
    liff.openWindow({
        url: 'https://line.me',
        external: true
    });
});
Closing the LIFF app 關閉現在開啟中的 LIFF APP,在外部瀏覽器時無效
// closeWindow call
document.getElementById('closeWindowButton').addEventListener('click', function() {
    if (!liff.isInClient()) {
        sendAlertIfNotInClient();
    } else {
        liff.closeWindow();
    }
});
Sending messages to the current chat screen 發送訊息到聊天室 (必須要 InClient & 使用者要許可權限才能成功發送)
// sendMessages call
document.getElementById('sendMessageButton').addEventListener('click', function() {
    if (!liff.isInClient()) {
        sendAlertIfNotInClient();
    } else {
        liff.sendMessages([{
            'type': 'text',
            'text': "You've successfully sent a message! Hooray!"
        }]).then(function() {
            window.alert('Message sent');
        }).catch(function(error) {
            window.alert('Error sending message: ' + error);
        });
    }
});
Get user profile LIFF SDK 可以取得 access token 用舊有 Line Login 方式取得 User Profile,也可以直接 Call LIFF SDK 取得 User Profile
// get access token
document.getElementById('getAccessToken').addEventListener('click', function() {
    if (!liff.isLoggedIn() && !liff.isInClient()) {
        alert('To get an access token, you need to be logged in. Please tap the "login" button below and try again.');
    } else {
        const accessToken = liff.getAccessToken();
        document.getElementById('accessTokenField').textContent = accessToken;
        toggleAccessToken();
    }
});
// get profile call
document.getElementById('getProfileButton').addEventListener('click', function() {
    liff.getProfile().then(function(profile) {
        document.getElementById('userIdProfileField').textContent = profile.userId;
        document.getElementById('displayNameField').textContent = profile.displayName;
        const profilePictureDiv = document.getElementById('profilePictureDiv');
        if (profilePictureDiv.firstElementChild) {
            profilePictureDiv.removeChild(profilePictureDiv.firstElementChild);
        }
        const img = document.createElement('img');
        img.src = profile.pictureUrl;
        img.alt = 'Profile Picture';
        profilePictureDiv.appendChild(img);
        document.getElementById('statusMessageField').textContent = profile.statusMessage;
        toggleProfileData();
    }).catch(function(error) {
        window.alert('Error getting profile: ' + error);
    });
});
Sending messages to a user's friend (share target picker) 如果可以使用 shareTargetPicker 功能的話就出現按鈕,可以利用這個功能分享訊息給朋友 (Line Developers Console 也要允許使用 shareTargetPicker)
document.getElementById('shareTargetPicker').addEventListener('click', function () {
    if (liff.isApiAvailable('shareTargetPicker')) {
        liff.shareTargetPicker([{
            'type': 'text',
            'text': 'Hello, World!'
        }]).then(
            document.getElementById('shareTargetPickerMessage').textContent = "Share target picker was launched."
        ).catch(function (res) {
            document.getElementById('shareTargetPickerMessage').textContent = "Failed to launch share target picker.";
        });
    } else {
        document.getElementById('shareTargetPickerMessage').innerHTML = "<div>Share target picker unavailable.<div><div>This is possibly because you haven't enabled the share target picker on <a href='https://developers.line.biz/console/'>LINE Developers Console</a>.</div>";
    }
});
效果如示意圖:
Performing a login process 在外部瀏覽器時實現 Line 登入/登出的功能
// login call, only when external browser is used
document.getElementById('liffLoginButton').addEventListener('click', function() {
    if (!liff.isLoggedIn()) {
        // set `redirectUri` to redirect the user to a URL other than the front page of your LIFF app.
        liff.login();
    }
});
// logout call only when external browse
document.getElementById('liffLogoutButton').addEventListener('click', function() {
    if (liff.isLoggedIn()) {
        liff.logout();
        window.location.reload();
    }
}); 
實現的流程如下圖:
以上~這樣就把 LIFF SDK 的功能看完了 80% 左右,有很多實用的功能 (例如判斷是不是 OA 好友,判斷登入環境等,尤其是直接取得 User Profile 是最方便實用的功能)
花時間了解 LIFF SDK 的功能後,接下來就是要修改範例程式碼,讓驗證碼小幫手能使用 LIFF 完成一些互動功能囉~