Real-time Updatesの和訳です。これを用いることで、Facebook上で更新されたアプリユーザの情報について通知を受けることができます。Facebook Night vol.7 発表内容まとめ 3:Batch RequestとReal-time Update APIで実装例を紹介していますので、そちらもご覧ください。


以下、2012年6月21日 9:39更新分までの本文です。

Introduction

Facebook上での変更を購読できるよう、Graph APIはReal-time Updates APIを提供しています。これにより、都度Facebookサーバへ問い合わせるのではなく、データをキャッシュしておいて必要に応じて更新できるようになります。データのキャッシュとこのAPIを併用することで、アプリの信頼性やロード時間の向上が期待できます。

購読対象に変更があった場合、Facebookはアプリ側が指定したコールバックURLに対してHTTP POSTリクエストを送信して、変更一覧を渡します。大体の場合、この通知は変更が起きてから数分の間に渡されます。

以下は購読登録のステップです。

  1. FacebookからのHTTP GETリクエスト(確認用)とHTT POST(変更データの受け取り用)を受け付けるエンドポイントURLを設定します。
  2. https://graph.facebook.com/<app-id>/subscriptionsへHTTP POSTリクエストを送信し、確認用リクエストを受け取ります。

Objects

以下のオブジェクトを購読可能です。

  • userGraph APIユーザオブジェクトの特定のフィールドやコネクションに変更があったときに通知を受けることができます。
  • permissions – Get notifications when your users change the permissions they afford your applications. The available permissions are listed in the scope table in the permissions API reference. ユーザがアプリに対して許可しているパーミッションに変化があった時に通知されます。対象となるパーミッションはPermissionsドキュメントをご覧ください。
  • page - Facebookページのタブにアプリをインストールしている場合、そのFacebookページのname, category, pictureなどの一般公開プロパティに変化があった時に通知を受けられます。対象となるプロパティはhttps://graph.facebook.com/<PAGE_ID>で得られるものと同じです。

注意:ユーザオブジェクトの全プロパティやコネクションが購読対象となるわけではありません。verifiedプロパティは購読対象外であることに気をつけてください。ユーザオブジェクトのコネクションの中で購読できるのは、feed, friends, activities, interests, music, books, movies, television, likes, checkins, location, eventsです。home, tagged, posts, photos, albums, videos, groups, notes, inbox, outbox, updates, accountsの購読はまだできません。

将来的には対応するプロパティを増やす予定です。興味のある方はこのページを時々チェックしてください。


Subscription APIs

https://graph.facebook.com/<app-id>/subscriptions?access_token=... に対してリクエストを送信することでできることは3つあります。違いは、送信するリクエストがPOST, GET, DELETEメソッドのどれになるかという点です。

  • POST: 購読の追加もしくは変更
  • GET: 購読対象オブジェクトとフィールドの一覧取得
  • DELETE: 購読削除

いずれの場合も、アプリのアクセストークンが必要となります。取得にはアプリのアプリIDとアプリのシークレットキーを使います。

https://graph.facebook.com/oauth/access_token?client_id=<APP_ID>&client_secret=<APP_SECRET>&grant_type=client_credentials

Add or Modify a Subscription

購読を追加するには、以下のパラメータと共にPOSTリクエストを送信します。

  • object - アップデートの通知を受けたいオブジェクトを指定します。user, page, permissionsを指定できます。ここで指定するタイプのオブジェクト全部に対する変更通知を受けることになります。例えばここでuserを指定すれば、アプリ利用ユーザ全員が対象となりますし、pageを指定すれば、アプリをタブに追加しているFacebookページ全部が対象となります。
  • fields - objectで指定したオブジェクトのプロパティもしくはコネクションをカンマ区切りで指定します。ユーザのname, picture, friends, ニュースフィードの変更通知を受けるには、name,picture,friends,feedを指定します。
  • callback_url - 更新通知を受けるコールバックURLです。
  • verify_token - アプリ側が指定するトークンで、購読確認用のリクエスト受信時に送られてきます。PubSubHubbubの仕様に基づいたパラメータです。

FacebookがPOST送信を受け付けると、アプリのコールバックURLに対してGETリクエストを送信し、URLが有効で更新通知を受け付けるよう実装されていることを確かめます。この確認手順については後述します。購読追加を完了するには、コールバックURLは確認用のリクエストに対し、正しくレスポンスを返す必要があります。

それぞれのオブジェクトに対して一個の購読紙か追加できないことに気をつけてください。既に該当オブジェクトを購読中の場合は、既存の登録内容が上書きされます。

List Subscriptions

GETリクエストを送ることで、JSONエンコードされた購読内容一覧が返されます。

[
  {
    "object": "user",
    "callback_url": "http://www.xyz.com/sub_endpoint?xyz_token=123",
    "fields": ["email", "friends", "name", "picture"],
    "active": true
  },
  {
    "object": "permissions",
    "callback_url": "http://www.xyz.com/sub_endpoint?xyz_token=123",
    "fields": ["email", "read_stream"],
    "active": true
  },
  {
    "object": "errors",
    "callback_url": "http://www.otherdomain.com/sub_endpoint?xyz_token=456",
    "fields": ["canvas"],
    "active": true
  }
]

Delete Subscriptions

DELETEリクエストを送ることで全購読を解除できます。objectパラメータを指定すれば、そのオブジェクトに対する購読のみ解除できます。


Your Callback Server

コールバックURLに指定したエンドポイントは、GETとPOST双方のリクエストを捌けなくてはなりません。

購読追加時の確認手順ではGETリクエストが送信され、購読追加完了の後、変更通知はPOSTリクエストで送信されます。

Subscription Verification

購読の追加 / 変更の過程で、コールバックURLに対して以下のパラメータがGETリクエストで渡されます。

  • hub.mode - 文字列subscribeが常に渡されます。
  • hub.challenge - ランダム文字列
  • hub.verify_token - アプリからverify_tokenで渡された文字列

まずアプリ側はverify_tokenをチェックし、hub.challengeの値を返すべきです。これにより、悪意あるアプリのDDoS攻撃を防ぎます。

PHP開発者への注意:PHPでは、クエリパラメータ名のドットとスペースがアンダースコアに置き換えられます。そのため、上記のパラメータへのアクセスには、$_GET["hub_mode"], $_GET["hub_challenge"], $_GET["hub_verify_token"]を用いる必要があります。詳しくはPHPのマニュアルをご覧ください。

Change Notifications

購読対象のオブジェクトに変更があった際には、FacebookサーバからコールバックURLに対してHTTP POSTリクエストが送られます。content-typeはapplication/jsonで、更新内容のJSONエンコードされた物がbodyで渡されます。
{
"object": "user",
"entry": 
[
    {
        "uid": 1335845740,
        "changed_fields": 
        [
            "name",
            "picture"
        ],
       "time": 232323
    },
    {
        "uid": 1234,
        "changed_fields": 
        [
            "friends"
        ],
       "time": 232325
    }
]
}

ここでは実際のデータが渡されないことに注意してください。更新後の値を取得するには、通常の手順でAPIを用いてアクセスします。常時アクセスできるデータである場合、更新通知された直後に最新データを取得し、次回ユーザがログインした際の読み込み時間を短縮したいと思うでしょう。

Facebookは変更内容を要約し、5秒に一回、もしくは未通知の更新が1000個を越えた段階で、まとめてコールバックURLに対して送信します。それだけの量に対応できるように実装してください。通知に失敗した場合、Facebookはすぐに再通知を試み、徐々に頻度を落としながら24時間リトライを続けます。

全部のレスポンスで、通知内容のSHA1シグネチャを含むX-Hub-SignatureをHTTPヘッダで送信しますが、これにはアプリのシークレット鍵がキーに用いられます。

Other Examples

購読追加 / 変更に失敗した場合のエラーは以下のようになります。

{
"i":1234,
"o":"errors",
"u":4,
"f":["canvas"],
"d":{
    "url":"http:\/\/www.example.com",
    "suf":"onethefarm\/",
    "e":"HTTPErrorException",
    "c":"500"
    }
 }

Sample Implementations

githubでサンプルを公開していますので、そちらもご覧ください。