Facebook Graph API 與 Demo Example

常用 Graph API 說明與 Example Demo。

Facebook Graph API & Social Demo Example

什麼是 Graph API?

Graph API 是 Facebook 所推出的技術標準,它的核心概念是「物件與連結」。由於整個 Facebook 是透過這些物件與連結建立而成的 Social Graph,因此這樣提供存取的介面就稱為「Graph API」。

例如,我可以經由我的 ID(物件「ME」)-> Graph API(連結)-> 取得朋友(Friend)、喜愛的電影(Movie)、Po 文(Feed)(物件)。

Facebook Graph API

如何使用 Graph API?

主要有兩種方式-使用 HTTP Request 或 JavaScript SDK。

使用 HTTP Request

公式為

https://graph.facebook.com/ID/TARGET_OBJECT?oauth_token=[oauth_token]

https://graph.facebook.com/ID/TARGET_OBJECT?access_token=[access_toke]

ID 為物件的 ID,TARGET_OBJECT為想要取得的物件。另外,若是需要取得使用者同意才能獲得的資料,必須加上 oauth_token。

例如,想要取得自己喜愛的電影,可以這樣用

https://graph.facebook.com/me/movies?oauth_token=CAAAA...

使用 JavaScript SDK

FB.api('/me/movies', function(response) {
  console.log(response);
});

OAuth 2 / Access Token

如果第三方網站(App)想要跟 Facebook 取得特定使用者的資料,必須使用 Access Token 來取得。Access Token 就像是一個有時效性的令牌,Facebook 依照這個令牌來決定是否要跟 App 分享資料。

公式為

https://graph.facebook.com/me?access_token=[access_toke]

範例如下

https://graph.facebook.com/me?access_token=CAAAA......

得到資料

{
  "id": "10200976708138630",
  "first_name": "Hsin-Hao",
  "gender": "female",
  "last_name": "Tang",
  "link": "https://www.facebook.com/cythilya",
  "locale": "en_US",
  "name": "Hsin-Hao Tang",
  "timezone": 8,
  "updated_time": "2014-05-23T10:04:39+0000",
  "username": "cythilya",
  "verified": true
}

Demo

此 Demo 範例共有以下幾個頁面:首頁、關於我、Feed、Friends、Post、Invite、Check、Comment、Permission Revoke。

首頁

來到首頁,就會有登入與授權的狀況。來補談 OAuth 2 Token Flow 吧。

OAuth 2 Token Flow

OAuth 2 Token Flow

在使用 App 前,App 會先將使用者送到 Facebook 做請求授權的動作,Facebook 授權此 App 可暫時存取特定資料,App 會取得一組特定的 Access Token 字串,App 就可以利用這 Access Token 做登入、存取資料的動作。

取得 Access Token

FB.getLoginStatus(function(response) {
  if (response.status === 'connected') {
    // the user is logged in and has authenticated your app,
    // and response.authResponse supplies
    // the user's ID, a valid access token, a signed request,
    // and the time the access token and signed request each expire

    //get access token, and save it in local storage
    localStorage.setItem('accessToken', response.authResponse.accessToken);

    //check user, in order to get user info
    checkUser();
  } else if (response.status === 'not_authorized') {
    // the user is logged in to Facebook, but has not authenticated the app
  } else {
    //response.status === 'unknown'
    // the user isn't logged in to Facebook.
  }
});

若使用者狀態若為「connected」,則表示使用者已授權並登入此 App,因此會回傳一個物件。回傳的物件為

Object {
  authResponse: Object,
  status: "connected"
}

此物件包含 User ID、Access Token、Access Token 可使用的時間、使用者狀態。

若使用者狀態若為「not_authorized」,則表示使用者並未授權 App,此時會導到 Facebook 授權的畫面。回傳的物件為

Object {
  authResponse: undefined,
  status: "not_authorized"
}

登入與導回首頁

按下 Login Button 後,經由 redirect 字串做登入的動作。

https://www.facebook.com/dialog/oauth?client_id=[APP_ID]&redirect_uri=[REDIRECT_URL]

APP_ID 為 App 的 ID,REDIRECT_URL 為轉跳回來的 URL。導到 Facebook 登入頁面,完成登入後轉跳回指定畫面(即首頁)。

程式碼如下

var dLogin = $('.login');

dLogin.click(function(e) {
  //click login button
  //redirect to fb login page
  //after logging in, back to index

  var redirect =
    'https://www.facebook.com/dialog/oauth?client_id=132069051838&redirect_uri=http://localhost/social_demo/fb_greeting';

  location.href = redirect;
});

畫面展示

若尚未登入 Facebook,按下右上角 Login Button 後,會導到 Facebook 登入畫面。

Facebook Login

Facebook 登入畫面。

Facebook Login

登入成功。

Facebook Login

若未授權,按下右上角 Login Button 後,會出現請求授權的 Popup。授權完畢後,再導回首頁。

Facebook APP 授權

關於我

取得自己的公開資訊。

使用 HTTP Request

https://graph.facebook.com/me?access_token=CAAAAH...

使用 Javascript SDK

FB.api('/me', function(response) {
  console.log(response);

  //id
  if (id != undefined) {
    var picture = 'http://graph.facebook.com/' + response.id + '/picture?width=140&height=140';
    dUserProfileBlock.find('.id').html(id);
    dUserProfileBlock.find('.img-thumbnail').attr('src', picture);
  } else {
    //no op
  }
});

取得資訊

{
   "id": "10200976708138630",
   "first_name": "Hsin-Hao",
   "gender": "female",
   "last_name": "Tang",
   "link": "https://www.facebook.com/cythilya",
   "locale": "en_US",
   "name": "Hsin-Hao Tang",
   "timezone": 8,
   "updated_time": "2014-05-23T10:04:39+0000",
   "username": "cythilya",
   "verified": true
}

備註

(2017/05/17 更新)

目前取使用者資訊必須指定欄位,無法如上例一次取得所有使用者的資料。如下,指定取得使用者 id、名稱、性別、年齡範圍、生日、封面圖、綁定裝置、信箱、姓、名。

function getUserInfo(accessToken) {
  FB.api(
    '/me',
    'get',
    {
      access_token: accessToken,
      fields: 'id, name, gender, age_range, birthday, cover, devices, email, first_name, last_name',
    },
    function(response) {
      console.log(response);
    },
  );
}

關於我

Feed

取得自己的分享內容。

Facebook Feed

使用 Graph API

公式為

FB.api('/me/feed');

範例

FB.api('/me/feed', function(response) {
  console.log(response);

  if (response && !response.error) {
    var feedData = response.data;
    console.log(response.data);
  }
});

回傳一個物件 response,response.data 包含 Feed 的資料(含標題、連結、預覽圖等),response.paging 為一個網址,可找到上(多)筆或下(多)筆的資料。

Facebook Feed

Friends

取得好友名單。

Facebook , friends, 取得好友名單

使用 Graph API

公式為

FB.api('/me/taggable_friends');

範例

FB.api('/me/taggable_friends', function(response) {
  //taggable_friends: A list of friends that can be tagged or mentioned in stories published to Facebook.

  if (response && !response.error) {
    console.log(response);
  }
});

taggable_friends 是可被 tag 或在 FB 貼文中標註的朋友。 之前的 friends 已經無法使用。回傳一個物件 response (Object {data: Array[785], paging: Object}),response.data 包含朋友的資料,含 id、name、picture。但 id 並非真實的 User ID,而是不同的 App 對於不同的使用者,分別取得不同的 ID,因此無法跟之前一樣,直接利用這個假 ID 去取得使用者的公開資料。

詳細說明可參考-Facebook Graph API - Taggable Friends:由於 IKEA 做了一個好玩的活動網站「來 IKEA 睡一晚」,其中含有邀請朋友並標記、分享到 Facebook 上,因此也做了一個範例來玩玩。

Post by Graph API / UI

貼文有兩種方式,可使用 Graph API 或 Facebook 提供的 UI 來 PO 文。

Post by Graph API

公式為

FB.api('/me/feed', 'post', data);

Demo 頁面的資料填寫欄位。

Post by Graph API

範例

var params = {};
params['name'] = 'Social Demo';
params['caption'] = 'BBC One - Sherlock, Series 1';
params['message'] = 'Worth a share.';
params['description'] =
  "Sherlock Holmes and Dr John Watson's adventures in 21st Century London. A thrilling, funny, fast-paced contemporary reimagining of the Arthur Conan Doyle classic. Made by Hartswood Films.";
params['link'] = 'http://www.bbc.co.uk/programmes/b00t4pgh';
params['picture'] = 'http://goo.gl/RNpxEN';

FB.api('/me/feed', 'post', params, function(response) {
  if (!response || response.error) {
    alert('Error occured');
  } else {
    //回傳貼文的ID,之後可經由此ID刪除貼文
    alert('Post ID: ' + response.id);
  }
});

PO 文成功會回傳 Post ID。

Post by Graph API

取得公開貼文的權限

記得要取得公開貼文的權限。

FB.login(
  function(response) {
    //login...
  },
  { scope: 'publish_actions' },
);

scope 的權限以逗號分隔,若要額外取得使用者的公開發表和 Email 的權限,則在 login 的 function 後加上{scope: "publish_actions, email"}。當使用者登入時,就會看到 Facebook 要求這些額外的權限。

Facebook 介面呈現與欄位對照

Facebook Post by Graph API

Post by UI

使用 Facebook 提供的 UI 來 PO 文,可在此調整 PO 文的對象。

var dPostUI = $('.postui'); //click Post UI button

dPostUI.click(function(e) {
  e.preventDefault();

  FB.ui(
    {
      method: 'feed',
      name: 'Social Demo',
      caption: 'BBC One - Sherlock, Series 1',
      description:
        "Sherlock Holmes and Dr John Watson's adventures in 21st Century London. A thrilling, funny, fast-paced contemporary reimagining of the Arthur Conan Doyle classic. Made by Hartswood Films.",
      link: 'http://www.bbc.co.uk/programmes/b00t4pgh',
      picture: 'http://goo.gl/9ngEIK',
    },
    function(response) {
      console.log('publishStory response: ', response);
    },
  );
});
Facebook 介面呈現與欄位對照

Facebook Post by UI

備註:目前經由 UI 分享的權重高於使用 Graph API 分享。權重牽涉到使用者是否可在自己的動態牆上看到該則訊息。私心的認為這是為了之後的廣告收費鋪路…

Invite

經由 App 邀請好友。

範例

經由 App 邀請好友的 UI 程式碼。

var dBtnInviteFriends = $('.inviteFriends');

dBtnInviteFriends.click(function() {
  FB.ui({
    method: 'apprequests',
    message: 'Greeting',
  });
});

按下按鈕「Invite Friends」跳出 Popup,可選擇好友後送出邀請。回傳的 res 為一個物件。

Object {
  request: "1430775300521224",
  to: Array[1],
  e2e: "{ "submit_0": 1402112773854 }"
}

物件中包含(邀請使用的)使用者 ID。而我們可以經由這個 ID 與 Access Token 查到發送的來源與目的地、訊息與時間。

例如我們可以這樣查詢

https://graph.facebook.com/1430775300521224?access_token=CAAAAH...

即可得到

{
  "id": "1430775300521224",
  "application": {
    "name": "Greeting",
    "namespace": "cythilya",
    "id": "132069051838"
  },
  "from": {
    "id": "10200976708138630",
    "name": "Hsin-Hao Tang"
  },
  "message": "Greeting",
  "created_time": "2014-06-07T03:46:14+0000"
}

經由 App 邀請好友的 UI 畫面

Facebook 經由 App 邀請好友

取得使用此 App 的朋友

var fql =
  'SELECT uid, name, pic_square, is_app_user FROM user ' +
  'WHERE uid IN (SELECT uid2 FROM friend WHERE uid1 = me()) ' +
  'OR uid IN(SELECT uid1 FROM friend WHERE uid2=me()) ORDER BY name';

FB.api('/fql', 'get', { q: fql }, function(response) {
  if (response.data) {
    console.log(response.data);
  } else {
    alert('Try again later.');
  }
});

response.data 為安裝此 App 的好友,即 Demo 頁面的三位好友。

Facebook 經由 App 邀請好友

確認是否對特定粉絲頁按讚

使用 Graph API

FB.api('me?fields=likes');

先取得按讚過的粉絲頁,並對這些粉絲頁的 ID 做比對。

//get my like list
FB.api('me?fields=likes', function(response) {
  if (response && !response.error && response.likes != null) {
    var likeData = response.likes.data;
    var nextUrl = getParameterByName('after', response.likes.paging.next);
    var stop = false;

    $.each(likeData, function(index, value) {
      //對這一頁的列表做比對
      if (id == value.id) {
        dCheckLikeFanGroupMessage.html('Match');
        stop = true;
      }
    });

    if (!stop && nextUrl != null) {
      //假設這一頁沒有查到,且有下一頁的列表存在,則接著比對下一頁
      checkID(id, nextUrl);
    }
  } else {
    //Try again later
  }
});

取得 URL 中特定參數的 function。

//get parameter
var getParameterByName = function(name, href) {
  name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
  var regexS = '[\\?&]' + name + '=([^&#]*)';
  var regex = new RegExp(regexS);
  var results = regex.exec(href);

  if (results == null) {
    return '';
  } else {
    return decodeURIComponent(results[1].replace(/\+/g, ' '));
  }
};

若在列表中比對到,表示有按讚過,則會出現「Match」,否則出現「None Match」。由於列表並非一次傳回所有按讚過的粉絲團,要一頁一頁取。因此若現在這一頁的列表沒有,就要取下一頁做比對。

var checkID = function(id, nextUrl) {
  var targetId = id;
  var nextPageUrl = nextUrl;

  FB.api(myID + '/likes?limit=25&after=' + nextUrl, function(response) {
    var nextData = response.data;
    var nextUrl = getParameterByName('after', response.paging.next);
    var stop = false;

    $.each(nextData, function(index, value) {
      if (targetId == value.id) {
        stop = true;
        console.log('Match');
      }
    });

    //resursive
    if (!stop && nextUrl != '') {
      checkID(targetId, nextUrl);
    }

    if (stop == false && nextUrl == '') {
      console.log('None Match');
    }
  });
};

留言

在 view 上放置 HTML 程式碼並用 js 做 FB.init()。

<div
  class="fb-comments"
  data-href="http://www.bbc.co.uk/programmes/b018ttws"
  data-numposts="5"
  data-colorscheme="light"
></div>

刪除授權

使用 Graph API:FB.api(“/me/permissions”, “delete”) 按下 “Revoke Permission” 按鈕,以刪除權限。

Facebook Graph API 刪除授權

FB.api('/me/permissions', 'delete', function(res) {
  if (res && !res.error) {
    if (res) {
      alert('Permission revoked.');
    } else {
      alert('Permissions delete error.');
    }
  } else {
    alert('Try again later.');
  }
});

刪除成功 res 會回傳 ture。

Demo 範例網站

下載程式碼

Graph API Explorer

如果想知道使用該 App 送出的 Graph API 的欄位、Access Token 或權限是否正確,可使用 Graph API Explorer 測試是否能正確取得資料。

Graph API Explorer

Graph API Explorer

參考資料


這篇文章的原始位置在這裡-Facebook Graph API & Demo Example

由於部落格搬遷至此,因此在這裡放了一份,以便閱讀;部份文章片段也做了些許修改,以期提供更好的內容。

Facebook Graph API