用 Line LIFF APP 实现信箱验证绑定功能(1) - 取得 user email

先前提过,手动发身份认证码给使用者,再让使用手动输入验证码的流程太不友善,今天就开始着手优化这个步骤吧!过程中会用到前几篇提到的 Nodejs + Heroku 进行开发。

流程构思

使用者点击身份认证後:

  1. 透过 Line LIFF APP 取得 user email,会有以下两种情况:
    • 取得 email 成功:页面上要有 1. 已发送验证码到该 email 的提示 2. 重新发送验证码(倒数) 3. 可输入认证码的 Form
    • 取得 email 失败:若使用者没有绑定信箱,或者不许可取用 email时,就会无法透过 Line 取得使用者信箱,这时需要多一个手动输入 email 的介面(要检验 email),输入有效email後跳到上面的成功页
  2. 输入认证码送出後,Line LIFF APP 串接 GAS 专案进行身份认证,并根据回传结果显示:
    • 绑定成功结果页面 + Line Bot 发送绑定成功讯息
    • 绑定失败结果页面

取得 user email

今天的目标是用 Line LIFF APP 成功取得 user email

文件

要进行开发最简单的方式,就是直接 fork 之前的 line-liff-v2-starter 直接修改,也可参考下面文件的步骤进行
Building a sample bot with Heroku

若你有已经有自己的 Node js 专案或其他专案,也可以考虑安装 Line Bot SDK
LINE Messaging API SDK for nodejs
使用 npm 安装:

$ npm install @line/bot-sdk --save

要取得使用者的 email 则是要使用到 liff.getDecodedIDToken()

更改 Line Login 设定取得 user email

如果要取得使用者的 email,那我们必须先修改 Line Login 设定要求使用者授权使用。

  1. 进入 Line Developers Console
  2. 点击进入验证码小帮手的 Line Login Channel
  3. 在 Basic settings 页签往下滑,找到 OpenID Connect 的选项如下图:
    OpenID Connect 01
  4. 点击 Apply 并完成相关设定填写後储存,可以看到 OpenID Connect 的状态改变如下:
    OpenID Connect 02
  5. 点击 LIFF 页签,找到 Scopes 的选项,按下编辑
    Scopes 01
  6. 这时候就会出现 email 的选项如下:
    Scopes 02
  7. 勾选 email 并按下 update 更新设定

如此一来,使用者在开启 LIFF APP 时,就会跳出系统页面请使用者授权 email 使用。只要使用者许可,我们就可以在 LIFF 直接取得 User Email。

修改 Line Liff V2 Starter

将 Line Liff V2 Starter fork 到你的 github repo,或者直接在你的 github repo 新建一个 public repo,并放入以下档案:

  • public
    • index.html
    • liff-app.js
  • index.js
  • package.json
  • app.json
  • LICENSE

修改 app.json & package.json

将这两个档案内容修改成符合你的 github repo 专案的资讯
其中 app.json 是在部署到 Heroku 时会用到的档案

修改 index.html

因为我们不会用到所有的 Line Liff V2 Starter 展示的功能,所以这边就先建立一个简单的 landing page 吧

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>验证码小帮手 - 身份认证</title>
    </head>
    <body>
		<div>user email is <span id="userEmail"></span></div>
        <div id="error" style="color: red;"></div>
        <script charset="utf-8" src="https://static.line-scdn.net/liff/edge/2/sdk.js"></script>
        <script src="liff-app.js"></script>
    </body>
</html>

liff-app.js

在 Line Liff V2 Starter 架构的基础上,删除不需要的函式与判断式後,将 initializeApp 的内容改为使用 liff.getDecodedIDToken() 取得使用者资料,并判断是否有取得 email 来呈现页面

window.onload = function () {
    // DO NOT CHANGE THIS
    let myLiffId = "";

    fetch('/send-id')
        .then(function (reqResponse) {
            return reqResponse.json();
        })
        .then(function (jsonResponse) {
            myLiffId = jsonResponse.id;
            initializeLiffOrDie(myLiffId);
        })
        .catch(function (error) {
            console.log(error);
            showErrorMsg("get Liff Id fail");
        });
};

function showErrorMsg(message) {
    document.getElementById("error").textcontent = message;
}

/**
 * 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) {
        showErrorMsg("get Liff Id fail");
    } 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) => {
            console.log(err);
            showErrorMsg("initializeLiff fail");
        });
}

/**
 * Initialize the app by calling functions handling individual app components
 */
function initializeApp() {
    if (liff.isLoggedIn() && liff.isInClient()) {
        const user = liff.getDecodedIDToken();
        if (user && user.email) {
            displayUserEmail(user.email)
        } else {
            showErrorMsg("user does not have email");
        }
    } else {
        showErrorMsg("please use line liff open");
    }
}

function displayUserEmail(email) {
    document.getElementById("userEmail").textcontent = email;
}

部署到 Heroku

将修改都 push 到 github repo 後,只要仿照 Line Liff V2 Starter 的教学,在浏览器网址列键入以下网址,就会看到跟先前一样的部署页面,填写必要资讯且确认无误後就按下 Depoly app 吧!

https://heroku.com/deploy?template={YOUR_GITHUB_REPO_URL}

范例:https://heroku.com/deploy?template=https://github.com/line/line-liff-v2-starter

部署好了记得要将 LIFF ID 设定为环境变数,如果忘记的话请参考 应用 LINE Front-end Framework 轻松建立互动 (1)在 Heroku 设定 LIFF ID

或者你也可以安装 Heroku CLI 进行手动部署

测试是否能取得 user email

将上述 Heroku App 网址设定为 LIFF 的 Endpoint URL 就可以进行测试了~(如果忘记的话,请参考 应用 LINE Front-end Framework 轻松建立互动 (1)设定 LIFF APP)

首先按下点此进行身份认证,第一次会跳出授权范围提示如下:
result 01

选择不授权 email 的情况,看到以下画面:
result 02

再按一次点此进行身份认证,这次授权 email,看到以下画面:
result 03

以上,我们成功在 LIFF APP 取得 user email,明天继续完成接下来的步骤~


<<:  元件基本使用

>>:  [Day 21] Node 注册事件 2

递回函式与回溯法优化

题组回顾与观念统整 前三天的练习我们深入「递回(Recursion)」的方法做了一连串的实作练习,...

Day 5 Docker 基础网路设定

容器技术具备了隔离性,若要与其他容器或是外部网路存取的话,那便需要一个虚拟的网路环境。docker ...

Week39 - 各种安全性演算法的应用 - 窃听、电子欺骗实作 [高智能方程序系列]

本文章同时发布於: Medium iT 邦帮忙 大家好,继上次Week38 - 各种安全性演算法的应...

[Day-24] - Spring Reactor Mono 一日初探就上手

Abstract 昨日已先行提过Flux,可方便处理一连串指定类型事件,所以说Flux就像瑞凡,被众...

[DAY 03] EC2

EC2 (Elastic Compute Cloud) 这是 AWS 服务中最为经典以及最受欢迎的项...