前面幾天的教學都是用送訊息的方式來觸發 Event,但有些時候可以善用平台提供的按鈕跟快速回覆功能,讓使用者省去打一行字的時間,而且可以預先提供推薦的選項給使用者。這些功能不是每個平台都會有,語音助理更不可能有按鈕可以按,不過很多的平台都有支援這樣的功能。
下面這個就是上一篇所提到的一般型範本 (Generic Template) 所附帶的按鈕:
按鈕可以出現在許多地方,而最常見的就是上一篇所講的 Generic Template(一般型範本)跟 Button Template(按鈕範本),如果不記得趕快去複習一下。
這邊我想要特別介紹的是「postback」的按鈕,title
用來顯示在按鈕上,而 payload
則是按了按鈕後會送到 Webhook 的資料:
{
type: 'postback',
title: 'Start Chatting',
payload: 'USER_DEFINED_PAYLOAD',
}
收到的這樣的 Event,就可以針對 payload
去處理:
if (context.event.isPayload) {
console.log(context.event.payload); // 'USER_DEFINED_PAYLOAD'
}
因為按鈕是不會消失的,不但可以按超過一次以上,而且不管對話如何進行,先前對話的按鈕都會繼續留著。依照這個特性,我們可以簡單把按鈕分成 Stateful Button (有狀態按鈕)、以及 Stateless Button (無狀態按鈕)。
按下按鈕的當下才根據狀態去做應對、查資料庫、查 API 的,我稱它為 Stateful Button (有狀態按鈕)。它的 Payload 是一個指令。
以前面幾天有講過的計數器範例來舉例,當我準備了一個按鈕,按鈕送出 Payload - COUNT + 1
,代表想要把計數往上加 1
,格式會是這樣:
{
type: 'postback',
title: 'Count + 1',
payload: 'COUNT + 1',
}
然後我的程式可以這樣寫,當 payload 命中 COUNT + 1
的時候就用 context.setState
來遞增數值:
if (context.event.payload === 'COUNT + 1') {
context.setState({
count: context.state.count + 1,
});
}
在這個情況下,只要狂按那個按鈕,計數就可以一直上去。
把所有要顯示的資訊或是操作完的結果都放在 Payload 裡,這種我稱它為 Stateless Button (無狀態按鈕)。當你希望不管未來何時按下、按下多少次都得到恆定的結果,那你應該是想要這個。
一樣以計數器範例來舉例,當我準備了一個按鈕,按鈕送出 Payload - GET COUNT 98
,代表想要得到計數為 98
的結果:
{
type: 'postback',
title: 'Get Count 98',
payload: 'GET COUNT 98',
}
然後我的程式這樣寫,當 payload 中 GET COUNT 98
的時候就用 98
當作 count
來處理:
if (context.event.payload === 'GET COUNT 98') {
// count is 98, so how should I do?
}
看出其中的差別了嗎?根據情況,你應該分別使用適合的做法。
https://developers.facebook.com/docs/messenger-platform/reference/buttons/postback
快速回覆是個現在對話系統常見的模式,包括你不想回信時的罐頭訊息等等,就是直接給你捷徑去選一個你想回的訊息,在 Messenger 上類似這樣:
在寫程式時,就在你傳送任何種類訊息時,多附加一個參數:
await sendText('Pick a color:', {
quick_replies: [
{
content_type: 'text',
title: 'Red',
payload: 'DEVELOPER_DEFINED_PAYLOAD_FOR_PICKING_RED',
},
{
content_type: 'text',
title: 'Green',
payload: 'DEVELOPER_DEFINED_PAYLOAD_FOR_PICKING_GREEN',
},
],
});
快速回覆可以用訊息的方式來處理,也可以用 Payload 的方式來處理,端看怎樣的方式適合。在按下 Red
快速回覆後,你會收到這樣的 Event:
context.event.text // 'Red'
context.event.payload // 'DEVELOPER_DEFINED_PAYLOAD_FOR_PICKING_RED'
另外,你甚至還可以讓使用者快速的回覆他的 Email 與電話:
await sendText('Send us your email to get more deals and offers!', {
quick_replies: [
{
content_type: 'user_email',
},
],
});
也算是省下兩個不好打、容易打錯的項目。
快速回覆在選擇完之後就會自動消失,所以要注意設計理念跟使用者體驗都跟按鈕不太類似。
按鈕跟快速回覆就類似網頁的超連結,網頁可以用 /path?query
的方式來帶資料,而按鈕跟快速回覆也是如此,後面會另外開主題來介紹關於 Payload 格式設計的部分。