記得當時歷經了 Line 機器人沒多久,隔一天手癢想試試看 Facebook 的 Messenger 機器人,搞了一天總算看懂這是怎麼玩的!(奇怪!😂我怎麼不記得以前 FB 文件有寫得這麼清楚……)

本篇文章共有三頁,分為:1. 步驟紀錄 2. 成果紀錄 3. 送審後續

在開始做 Facebook Messenger Bot 之前,要先搞定兩個東西:粉絲專頁、應用程式

因為 Facebook 只提供粉絲專頁開發機器人功能,跟 Line 只提供官方帳號是一樣的意思,所以一定要先建立一個粉專!另一個是需要使用 Webhook 串接 API,也要建立一個應用程式,並且這整件事情如果要開放給大眾玩還需要送審!

簡單來說整個流程就是:建立粉絲專頁 → 建立應用程式 → 撰寫程式並架在雲端上 → 送審

以下步驟主要是參考 Facebook 官網的文件:Messenger 平台快速入門教學課程
而我還是用 nodeJS 來開發,基本上照著它的步驟寫就可以用設定好機器人了!而且他還有翻成繁中!麻瓜的我都看得懂!你也一定看得懂!😂

因為涉及粉專和應用程式的設定,我還是有參考網路上大大的筆記,補充官方文件說明上的不足,先貼一下以表尊敬:

步驟跟 LineBot 很類似,所以相同的地方我會省略說明~
詳細解說可以參考上篇文章的紀錄:聊天機器人 try try 抗之 LineBot 特輯
接下來開始進入步驟說明嘍!


STEP 1. 先把環境和該裝的東西先裝好

依據官方文件上提供能快速建置的 github 連結,可以直接把整個檔案拉下來,放到自己的專案裡!

打開 app.js 會看到需要的外掛,請自行 npm install 下面這些檔案:

const 
    request = require('request'),
    express = require('express'),
    body_parser = require('body-parser'),


這個檔案除了載入套件和建立本機端伺服器之外,下面有兩個主要的程式,先簡單介紹一下:

  1. POST 用來接收和傳遞訊息
  2. GET 用來驗證網頁憑證
// Accepts POST requests at /webhook endpoint
app.post('/webhook', (req, res) => {  
  let body = req.body;

  if (body.object === 'page') {
    body.entry.forEach(function(entry) {
      let webhook_event = entry.messaging[0];
      console.log(webhook_event);
    });
    res.status(200).send('EVENT_RECEIVED');
  } else {
    res.sendStatus(404);
  }

});

// Accepts GET requests at the /webhook endpoint
app.get('/webhook', (req, res) => {
  const VERIFY_TOKEN = "<YOUR_VERIFY_TOKEN>";
  
  let mode = req.query['hub.mode'];
  let token = req.query['hub.verify_token'];
  let challenge = req.query['hub.challenge'];

  if (mode && token) {
    if (mode === 'subscribe' && token === VERIFY_TOKEN) {
      console.log('WEBHOOK_VERIFIED');
      res.status(200).send(challenge);
    } else {
      res.sendStatus(403);      
    }
  }
});


STEP 2. 申請粉絲專頁

Facebook 首頁左下角找到「粉絲專頁」> 「建立粉專」或直接點進此連結建立


STEP 3. 申請應用程式,設定和連接粉專

Facebook 首頁左下角「管理應用程式」>「建立應用程式」或直接點進此連結建立



建立好了,請自行到「設定」>「基本資料」填寫資料,例如網域、隱私權網址、應用程式圖示等等,主要我們要到「產品」那邊新增兩個權限功能,分別是 Messenger 和 Webhook,如下圖


好了之後要來設定連結對應的粉專,請在「Messenger」>「設定」中找到「存取權杖」和「Webhooks」,設定好要對應的粉專~

存取權杖的 token 碼等下會使用,可以先複製好!


如果設定完成,在對應的「粉絲專頁」>「設定」>「Messenger 開放平台」中找到「連結的應用程式」,就會看到兩者有串起來嘍!(好煩喔!一直在 Facebook 大海裡跑來跑去😆)


STEP 4. 取得權杖

接下來先把應用程式中「存取權杖」取得的權杖憑證(就是傳說中的 token,以下都簡稱 token)貼到 app.js 程式中,為了方便後面程式碼使用,可以宣告一個常數:

const PAGE_ACCESS_TOKEN = "<YOUR_VERIFY_TOKEN>";


這樣就可以把原本 GET 那段改成這樣:

app.get('/webhook', (req, res) => {
    const VERIFY_TOKEN = PAGE_ACCESS_TOKEN;
    // 以下省略...
});

這樣就表示設定好 Webhook 的憑證了!


STEP 5. 接受和回應資料

設定好 GET 憑證,現在來說明 POST 那一坨(?!)東西吧!

主要需要用到的地方就是 body.entry.forEach 裡面的 function:

app.post('/webhook', (req, res) => {  
    let body = req.body;
    if (body.object === 'page') {
        body.entry.forEach(function(entry) {
            // 取得 Webhook 的事件
            let webhook_event = entry.messaging[0];
            // 取得發送者的 PSID
            let sender_psid = webhook_event.sender.id;
            // 判斷訊息是屬於 message 還是 postback
            if (webhook_event.message) {
                handleMessage(sender_psid, webhook_event.message);        
            } else if (webhook_event.postback) {
                handlePostback(sender_psid, webhook_event.postback);
            }
        });
      res.status(200).send('EVENT_RECEIVED');
    } else {
      res.sendStatus(404);
    }
});


上方程式碼中,「PSID」就是機器人需要回應的「對象」,也就是我們 FB 的辨識 ID,而另一個「判斷訊息是屬於 message 還是 postback」意思是發送者是否是透過機器人提供的選擇做回覆,如果「是」就是 postback;「不是」就屬於 message,官方教學分別用下面這兩個函數包起來:

// 處理發送者直接傳送的訊息
function handleMessage(sender_psid, received_message) {
    // ...
}
// 處理發送者回覆機器人的訊息
function handlePostback(sender_psid, received_postback) {
    // ...
}


然後兩種訊息的處理一樣需要讓機器人做出回應,所以官方教學是用 callSendAPI 函數包起來重複使用:

// 發送機器人的回應
function callSendAPI(sender_psid, response) {
    let request_body = {
      "recipient": {
        "id": sender_psid
      },
      "message": response
    }
    request({
        "uri": "https://graph.facebook.com/v2.6/me/messages",
        "qs": { "access_token": PAGE_ACCESS_TOKEN },
        "method": "POST",
        "json": request_body
    }, (err, res, body) => {
        if (!err) {
            // console.log('---> message sent!')
        } else {
            console.error("Unable to send message:" + err);
        }
    }); 
}


處理訊息的部分就需要透過開發者編寫!
首先,handleMessage 是處理發送者直接傳送的訊息,官方提供如下:

function handleMessage(sender_psid, received_message) {
  let response;
  // 判斷訊息是否包含文字
  if (received_message.text) {    
    // 回傳的文字訊息
    response = {
      "text": `You sent the message: "${received_message.text}". Now send me an image!`
    }
  }  
  // 機器人發送回應
  callSendAPI(sender_psid, response);    
}


handlePostback 是處理發送者回覆機器人的訊息,官方提供如下:

function handlePostback(sender_psid, received_postback) {
  let response;
  // 取得發送者回覆內容
  let payload = received_postback.payload;
  // 判斷回覆的內容,對應機器人回應的訊息
  if (payload === 'yes') {
    response = { "text": "Thanks!" }
  } else if (payload === 'no') {
    response = { "text": "Oops, try sending another image." }
  }
  // 機器人發送回應
  callSendAPI(sender_psid, response);
}

因此要做很多機器人的腳本回應,都可以在 handleMessage 和 handlePostback 裡面加以撰寫!

若要判斷發送者的訊息是什麼類型可以在Sending Messages找到對應的名稱。
當然,跟 Line 機器人一樣,Facebook 也有提供很多訊息範本和回傳訊息的格式可以使用,都可以自行到官網查詢。

好可惜竟然不能傳貼圖!!!!! 😭😭😭
只好寫信請 Facebook 改進惹(喂


STEP 6. 連上 Webhook,用 ngrok 在本地端測試

同上一篇的聊天機器人 try try 抗之 LineBot 特輯,這邊也是用 ngrok 做本地測試!

ngrok 設定完成後,就可以回到 Facebook 應用程式裡,點擊左方我們申請的產品「Webhook」,勾選所需的功能,這些功能就是送審的主要 API,我這邊只勾了「pages_messaging」,官方說法是「讓你的應用程式可以使用 Facebook 粉絲專頁發送和接收訊息」的功能。

然後在「回呼網址」貼上 ngrok 產生的 https 網址;「驗證權杖」貼上 token,點擊「驗證並儲存」之後,就可以在本機測試看看有沒有連成功喔!

小提醒,如果回頭要修改網址和權杖,就會跟第一次進來畫面不同,要記得點擊「Edit Subscription」就能再做修改!


STEP 7. 連上正式的 Webhook,用 Heroku 發佈到雲端

同上一篇的聊天機器人 try try 抗之 LineBot 特輯,這邊也是發佈到 Heroku!一樣修改好 package.json 和 app.js 裡 port 的設定並 git 上傳上去後,回到上一步的「應用程式」>「Webhook」>「Edit Subscription」裡修改「回呼網址」,這樣就完成了喔!


其他補充

在寫回應的部分,我剛好需要傳送一些圖片和語音,但我發現在 Facebook 裡傳遞這些非 Facebook 網址、跨網域的檔案需要先做設定,否則會有錯誤,在「粉絲專頁」>「設定」>「Messenger 開放平台」中找到「允許清單中的網域」,加入你存放檔案的網域就可以使用了!


最後,就會看到它真的會亂傳垃圾話給我呢~~😂