about 1 year ago

最近臉書粉絲專頁的貼文留言操作越來越常見,後來花了一點時間採坑後,認真覺得工程師的青春不該浪費在無謂的流程設定上,所以決定公開做法供大家參考,先貼兩種不同做法的範例:

  1. Nike Taiwan - 留言後官方直接在留言下回覆
  2. 華康字型 - 留言後官方用Messenger私訊方式回覆

這兩種作法我都會介紹,以下是整個流程圖,基本上都是在弄FB應用程式與Graph API Explore居多,程式碼參考Github分享,我會在後續解釋

註冊並開通FB應用程式與設定Webhook

到Facebook Developer後台申請新的應用程式,接著進去後點選新增產品,並選擇Webhook


選擇後你會發現有出現一個需要認證的按鈕,點下去會出現這個畫面,此時跳去設定你的Web Service,即得要用HTTPS(可以用certbot免費聲請憑證喔)

現在Web Service的程式碼

// facebook 驗證webhook用,不用改,只需要注意verify_token

router.get("/webhook", function (ctx, next) {
    let hub_verify_token = ctx.query["hub.verify_token"]
    let challenge = ctx.query["hub.challenge"]

    if (hub_verify_token === verify_token) {
        return ctx.body = challenge
    }
    return
})

// facebook webhook發送通知的路徑

router.post("/webhook", async function (ctx, next) {
  .... 驗證階段先不用管
  console.log(ctx.body)
}

最重要的就是GET /webhook這段,FB會呼叫這個URL並需要你回傳設定的驗證Token,這個驗證Token是你自己設定的,所以要輸入 "123"這種也行

成功驗證後就會跳出很多選項,左上方的下拉選單選擇Page,接著勾選feed,記得要先測試,成功的話FB會POST /webhook,我習慣先整個打印出來看內容

取得粉絲專頁權限Token並延長使用期限,並啟用關係連線

確定應用程式串好Webhook到Web service後,接著就要實踐粉絲專頁串應用程式Webhook這段;
先建立個粉絲專頁以後,記得你自己要是編輯者或管理員身份,接著找出page id,因為太難找了所以我用 findmyfbid網站
接著就是用Graph API Explore來取得授權與後續的綁定動作

近來後第一步要記得先選擇好應用程式,接著點取得權杖->使用者授權權杖,我建議是把紅色筐的權限都先拿到


接著取得使用者授權後,因為有page-list-show這個權限理論上取得權杖 -> 取得粉絲專頁權杖下方就會出現你所有管理的粉絲專頁,點選你要的粉絲專頁(OS. 可能要等一段時間才有反應),然後執行

/v2.10/{123....}?fields=access_token中間那串數字就是你的page_id,下面的操作也都是喔
另外access_token等等會在Web service用上喔

接著要先將粉專的Token替換上去喔,接著執行 POST /v2.11/{page-id}/subscribed_apps


記得GET/POST都來一下,如果有出現什麼Unauthorized錯誤可能是權限不對或是FB還沒有設定好,我之前試有時要等一段時間才有反應。
GET是取得目前這個粉絲專頁有跟哪個app建立訂閱關係
POST則是粉絲專頁要跟哪個app建立關係
所以如果是第一次做的話, 只要跑POST subscribed_apps
要看沒有有成功,就跑GET subscribed_apps (感謝 Neil Wang的留言補充)
也可以用CURL直接發送HTTP Request,如curl -X POST "https://graph.facebook.com/v2.6/{粉專Id}/subscribed_apps?access_token={粉絲專頁Token}" 也可以,成功會回傳"success: true"

這樣就設定完成了!
其他參考資料:官方文件 - 粉絲專頁設定官方文件 - 應用程式如何綁定粉絲專頁

Web Service處理

接著我們來看POST /webhook之後要怎麼處理與回覆,首先看FB收到粉專留言後傳送的訊息

{"entry":[
    {"changes":
    [{
    "field":"feed",
    "value":
        {"parent_id":"271641136643394_303574286783412","sender_name":"...","comment_id":"303574286783412_303889220085252","sender_id":"1764716423541857","post_id":"271641136643394_303574286783412","verb":"remove","item":"comment","created_time":1503677342}}],
      "id":"271641136643394","time":1503677345}],
 "object":"page"}

格式有點亂,大概就是entry array包著 changes array在包著實際的訊息,那你可以看到實際的value中有幾個不同的_id,我想應該都蠻好認的

// verb的話add表示新增,移除會是remove

// 重新排除page_id是因為自動回話後FB會再通知粉專自己的回覆,自己的留言就沒必要處理所以排除

// 注意這裡的page_id跟上面的page_id不一樣!建議打印出來ctx.body自己分析JSON格式

if (c.value && c.value.comment_id && c.value.verb === 'add' && c.value.sender_id !== page_id) {
    ......
  // 這是使用者輸入

  c.value.message
  
}

return ctx.status = 200

可以看到我最後都會回200成功給FB,這樣FB收到成功訊息後就不會再重複傳送,反之如果沒有回傳FB可能會重複傳喔!

最後來看一開始說的兩種回應方式,其實就是套用不同的Graph API

  1. 直接在留言回覆
    await axios.post("https://graph.facebook.com/v2.10/" + c.value.comment_id + "/comments?access_token=" + access_token, {message: "看你想要回什麼"})
    
  2. 用Messenger私訊回覆
    await axios.post("https://graph.facebook.com/v2.10/" + c.value.comment_id + "/private_replies?access_token=" + access_token, {message: "以私"})
    

第一個方法我目前發現的侷限是只能回傳第一層的留言,第二層回覆的無法在自動回覆留言!
第二個方法的侷限是 官方文件寫只能回傳Text,其他Messenger支援的結構化資訊和圖片通通不支援

延展Token

用Graph API Explore僅能取得一小時到期的短期權杖,可以透過以下API換成兩個月到期的長期權杖

$ curl -X POST "https://graph.facebook.com/v2.6/oauth/access_token?grant_type=fb_exchange_token&client_id={應用程式 id}&client_secret={應用程式 secret}&fb_exchange_token={短期權杖}"

其他的在看我的程式碼即可,應該不會太難懂,有什麼問題歡迎留言囉~

*補充,於2018/07/09重新測試流程應該是沒有問題

OS. 程式碼有一段是處理messenger的發文,如果要取得粉專的messenger留言一樣先找到webhook並開通訂閱即可。
OS2. 最近有實作 網站供使用者FB登入,並在前端取得使用者粉絲專頁並授權,然後就可以用Token幫用戶接收訊息等,整體思路大概是

  1. 創建FB應用程式
  2. 前端登入套用FB JS SDK,應用程式編號記得填入,並同樣取得應有的權限
  3. 用戶在前端登入,先拉出他的粉絲專頁列表,接著呼叫/v2.10/{123....}?fields=access_token(前端處理即可)
  4. 前端取得用戶的粉專Token後,送至後端並延展Token期限至3個月,然後放入資料庫,之後操作粉專都是用粉專Token而非應用程式Token喔;
← Coscup - MySQL 5.7與8.0部分功能Review與測試 使用influxdb/grafana/collectd做系統性能監控 →
 
comments powered by Disqus