iT邦幫忙

2021 iThome 鐵人賽

DAY 19
0
自我挑戰組

從無到有打造驗證碼共享的 Line 機器人系列 第 19

使用 Template Message 替 Line Bot 加上同意條款的功能(2)

昨天我們完成了 user sheet 的 query & upsert 功能,今天就要正式將同意條款的步驟加入現有流程內。

使用 Template Message 構建 Line Message Object

Template Message 總共有四種格式,比較符合同意條款功能的有 Buttons / Confirm 這兩種。因為流程是使用者不同意就不能繼續,所以 no 的回應其實是沒有意義的,這邊就選擇 Buttons template 來實現同意條款的訊息吧!(當然如果你想要漂亮的圖片也可以採用 Imagemap / Image carousel / Flex Message 的形式)

文件

Buttons template

Message Object

根據文件,我們可以初步規劃出以下的 Message Object Json

  • altText: 目前電腦版還沒辦法顯示 Template Message,這時候就會使用這裡的文字內容替代顯示這則訊息。
  • 這邊規劃了兩顆按鈕
    • 同意:使用者點擊後會發送 postback event 到我們的 Reply Message 專案
    • 檢視服務條款:使用者點擊後會開啟服務條款頁面
{
  "type": "template",
  "altText": "請先同意服務條款才能繼續",
  "template": {
      "type": "buttons",
      "text": "請先同意服務條款才能繼續",
      "actions": [
          {
            "type":"postback",
            "label":"同意",
            "data":"agree"
          },
          {  
            "type":"uri",
            "label":"檢視服務條款",
            "uri":"YOUR_TERMS_URL"
          }
      ]
  }
}

使用 GAS 簡單建立服務條款頁面

上述的 Message Object 中,我們需要一個簡單的服務條款頁面網址,但只為了一個簡單的靜態頁面就要去部署一個web server 回應嗎?其實 GAS 也能做到簡單回應 HTML 的功能。

文件

HTML Service: Create and Serve HTML

新建一個 GAS 專案 Pages

點擊右上角的+,選擇 HTML
GAS add HTML

新增一個 terms.html,內容如下
add terms.html

然後在 app.gs 新增 doGet 處理 Get Request

function doGet() {
  return HtmlService.createHtmlOutputFromFile('terms');
}

接著將 Pages 部署為 Web App,如果忘記怎麼部署可以參考 部署 Google App Script 專案(2) & Line Bot 簡單回應訊息 的 部署 Reply Message 為 Web App

查看得到的網頁應用程式網址結果:
term.html result
可以發現,美中不足的是上面有段 Google 防釣魚詐騙的警告,如果在意的人可以改用 GitHub Pages

修改 Reply Message

接著就是要著手修改 Reply Message 專案,加入同意條款的流程

修改 isUserIdVerified.gsgetUserData.gs

  1. isUserIdVerified.gs 的名稱重新命名為 getUserData.gs
  2. 加入 getUserRowData 方便我們取得指定的 userId 的資料做處理
  3. 修改 isUserIdVerified & 新增 isUserIdAgreeTerms 如下
function isUserIdVerified(userId) {
  var userData = getUserRowData(userId);
  return !!userData[3];
}

function isUserIdAgreeTerms(userId) {
  var userData = getUserRowData(userId);
  return !!userData[4];
}

function getUserRowData(userId) {
  var sheet = ReadMailAndInsertToGoogleSheet.connectToSheet('users');
  var searchResult = ReadMailAndInsertToGoogleSheet.searchColumnValue(sheet, 'user_id', userId);
  if (searchResult !== -1) {
    var targetRowIndex =  searchResult+2;
    var range = sheet.getRange(targetRowIndex, 1, 1, 7);
    return range.getValues()[0];
  } 
  return [];
}

修改 replyMessage.gs

首先新增一個 getAgreeTermsMessage 用來產生同意條款訊息物件

function getAgreeTermsMessage() {
  return [
    {
      "type": "template",
      "altText": "請先同意服務條款才能繼續",
      "template": {
        "type": "buttons",
        "text": "請先同意服務條款才能繼續",
        "actions": [
          {
            "type":"postback",
            "label":"同意",
            "data":"agree"
          },
          {  
            "type":"uri",
            "label":"檢視服務條款",
            "uri":"YOUR_TERMS_URL"
          }
        ]
      }
    }
  ];
}

因為同意條款的步驟是在身份認證之後,獲取驗證碼時檢查是否已同意條款,故先修改 userIsVerifiedFlow 的流程如下:

  • 當使用者已認證過且訊息內容為 獲取驗證碼 時,檢查是否已同意條款
    • 已同意條款:回應驗證碼
    • 未同意條款:回應同意條款訊息
  • 當使用者已認證過且訊息內容非 獲取驗證碼 時,回應無效的輸入(含 quick reply)
function userIsVerifiedFlow(userMessage, userId){
  if (userMessage === '獲取驗證碼') {
    return isUserIdAgreeTerms(userId) 
        ? getValidationCodeMessage(userId)
        : getAgreeTermsMessage();
  }
  return getReplyMessage('無效的輸入', generateQuickReply(true));
} 

接著我們要處理同意條款回來的 webhook postback event,首先修改 doPost 增加對 postback event 的處理判斷

function doPost(e) {
  var requestContent = JSON.parse(e.postData.contents);
  var event = requestContent.events[0];
  if(event && event.type) {
    var replyToken = event.replyToken;
    var replyMessage = [];

    switch (event.type) {
      case 'message':
        replyMessage = handleMessageEvent(event);
        break;
      case 'follow':
        replyMessage = handleFollowEvent(event);
        break;
      // 加入以下三行
      case 'postback':
        replyMessage = handlePostbackEvent(event);
        break;
      default:
        // do nothing
    }

    doReplyMessage(replyMessage, replyToken);
  }
      
  return ContentService.createTextOutput('success');
}

然後新增 handlePostbackEvent 進行處理

  • 當收到 postback event 的 data 為 agree 時,將 userId 在 users sheet 的 agree_terms 欄位寫入 true,且回應驗證碼
  • 若收到 postback event 但 data 並非 agree 時,照理來說以現有流程不該出現這種情況,但為了符合一致性,這邊我們依然 return 一個空陣列
function handlePostbackEvent(event) {
  var postbackData = event.postback && event.postback.data;
  if (postbackData === 'agree') {
    var userId = event.source && event.source.userId;
    upsertUserInfo(userId, {'agree_terms': true});
    return getValidationCodeMessage(userId);
  }

  return [];
}

修改 doReplyMessage,若 replyMessage 為空時則不回應訊息

function doReplyMessage(replyMessage, replyToken) {
  // 加入以下這段
  if (replyMessage.length === 0) {
    return;
  }

  var payload = {
    replyToken: replyToken,
    messages: replyMessage
  };

  UrlFetchApp.fetch('https://api.line.me/v2/bot/message/reply', {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + CHANNEL_ACCESS_TOKEN
    },
    'method': 'post',
    'payload': JSON.stringify(payload)
  });
}

修改完了記得儲存,然後要管理部署建立新版本發佈,接著就可以在驗證碼小幫手測試結果囉!

測試結果

加入驗證碼小幫手為好友,提示要身份認證
agree terms result 01

身份認證成功訊息
agree terms result 02

輸入獲取驗證碼,要求要同意條款 & 輸入其他訊息時提示無效輸入
agree terms result 03

檢查點擊檢視服務條款是否有正確開啟先前設定的服務條款頁面

點擊同意後,獲得驗證碼
agree terms result 04

測試再次輸入獲取驗證碼,不再需要同意條款即可取得驗證碼
agree terms result 05

以上~這幾天我們學到了讓 Line Bot 發送不同格式的訊息,進而讓使用者的回應變得更多元。但有注意到 users sheet 有兩個欄位 name & email 還沒有用到嗎?明天就接著進一步運用 Line Messaging API 獲取使用者的 profile 並寫入 users sheet 吧!


上一篇
使用 Template Message 替 Line Bot 加上同意條款的功能(1)
下一篇
使用 Line Messaging Api 取得 User Profile
系列文
從無到有打造驗證碼共享的 Line 機器人30

尚未有邦友留言

立即登入留言