使用 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 吧!


<<:  Day_07 : 让 Vite 来开启你的Vue 之 Vite 核心 esbuild

>>:  [Day16] Andoroid - Kotlin笔记: CustomDialog

【第十八天 - 命令执行】

Q1. 什麽是命令执行 指令是与电脑互动的一种方式,一般来说作业系统会包含至少一个 Shell 程序...

Day 22 来写一个简单e2e测试

今天我们来写一个简单的form来当作测试吧,首先我们刻出一个简单的画面 const App: FC ...

Day2-为小学生撰写的网站小游戏_template精简程序码

昨天写的小网站後续看文章时觉得有一部分JS有硬干的嫌疑(?) 所以把一些部分做了改动 首先使用了HT...

数字认证(Digital Authentication)

以下是《数字身份准则》(NIST SP 800-63-3)的摘录: . 在数字认证申请人拥有并控制一...

30天程序语言研究

今天是30天程序语言研究的第十九天,由於深度学习老师多让我们上了python的进阶课程里面包括之前没...