昨天我們完成了 user sheet 的 query & upsert 功能,今天就要正式將同意條款的步驟加入現有流程內。
Template Message 總共有四種格式,比較符合同意條款功能的有 Buttons / Confirm 這兩種。因為流程是使用者不同意就不能繼續,所以 no 的回應其實是沒有意義的,這邊就選擇 Buttons template 來實現同意條款的訊息吧!(當然如果你想要漂亮的圖片也可以採用 Imagemap / Image carousel / Flex Message 的形式)
根據文件,我們可以初步規劃出以下的 Message Object Json
{
  "type": "template",
  "altText": "請先同意服務條款才能繼續",
  "template": {
      "type": "buttons",
      "text": "請先同意服務條款才能繼續",
      "actions": [
          {
            "type":"postback",
            "label":"同意",
            "data":"agree"
          },
          {  
            "type":"uri",
            "label":"檢視服務條款",
            "uri":"YOUR_TERMS_URL"
          }
      ]
  }
}
上述的 Message Object 中,我們需要一個簡單的服務條款頁面網址,但只為了一個簡單的靜態頁面就要去部署一個web server 回應嗎?其實 GAS 也能做到簡單回應 HTML 的功能。
HTML Service: Create and Serve HTML
Pages點擊右上角的+,選擇 HTML
新增一個 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
查看得到的網頁應用程式網址結果:
可以發現,美中不足的是上面有段 Google 防釣魚詐騙的警告,如果在意的人可以改用 GitHub Pages
Reply Message接著就是要著手修改 Reply Message 專案,加入同意條款的流程
isUserIdVerified.gs 為 getUserData.gsisUserIdVerified.gs 的名稱重新命名為 getUserData.gs
getUserRowData 方便我們取得指定的 userId 的資料做處理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 進行處理
agree 時,將 userId 在 users sheet 的 agree_terms 欄位寫入 true,且回應驗證碼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)
  });
}
修改完了記得儲存,然後要管理部署建立新版本發佈,接著就可以在驗證碼小幫手測試結果囉!
加入驗證碼小幫手為好友,提示要身份認證
身份認證成功訊息
輸入獲取驗證碼,要求要同意條款 & 輸入其他訊息時提示無效輸入
檢查點擊檢視服務條款是否有正確開啟先前設定的服務條款頁面
點擊同意後,獲得驗證碼
測試再次輸入獲取驗證碼,不再需要同意條款即可取得驗證碼
以上~這幾天我們學到了讓 Line Bot 發送不同格式的訊息,進而讓使用者的回應變得更多元。但有注意到 users sheet 有兩個欄位 name & email 還沒有用到嗎?明天就接著進一步運用 Line Messaging API 獲取使用者的 profile 並寫入 users sheet 吧!