Facebook Graph API v2.2 リリース: 各種更新のサーバ間通知機能が熱い件


前回の Graph API v2.1 リリースからわずか 83 日、日本時間の今日 (10/31) 未明に Graph API v2.2 が発表された。細かい点は色々あるにしても、前回までと異なり、今回は規約上または利用上の制限を加える方向のアップデートはほぼないといってよい。

主な変更点は以下の通り。

  • API 経由で Facebook ページ投稿のコメントの非表示化および非表示化のやり直しが可能となった。これにともない、コメント関連の APIcan_hideis_hidden などのフィールドが追加されている。
  • 複数アプリ間で名寄せを可能にするための新フィールド、token_for_business がユーザオブジェクトに追加された。
    • Facebook app をビジネスマネージャに登録していれば、token_for_business が取得できるようになる。
    • ただし、紐付けるビジネスマネージャを変更すると token_for_business の戻り値も変わるので、ユーザ識別用には使いづらい。
  • ユーザ情報、Facebook ページ、アプリのパーミッション、支払い情報などが変更された場合、変更があったことをリアルタイムでサーバ間通知する API エッジ subscribed_apps の追加。
  • API 経由で変更できる Facebook ページの設定項目をさらに追加。

また、今月頭に Ads API もバージョニングが導入されていたが、今回に合わせて Ads API のバージョンも Graph API と同じ v2.2 にアップデートされた。

そのほか、詳細な変更点は こちら

今回のアップデートで一番熱いのは、なんと言っても 各種更新情報をリアルタイムでサーバ間通知される機能だろう。

これまでもアプリを削除した場合には signed_request でサーバ間通知される機能はあったが、例えばアプリ設定でメールアドレスの提供のみ停止したり、Facebook に登録しているメールアドレスや名前、プロフィール画像を変更してもそれをリアルタイムに知る手段がなかった。今回のこの機能により、例えばメールアドレスが変更されたかどうかをチェックするために毎日 Graph API にアクセスして確認しなくても、更新のタイミングでほぼ数秒の遅延のみでエンドポイントに更新情報が POST されるようになる

せっかくなので、少し試してみた。サーバ間通知するエンドポイントを登録するには、User Access Token ではなく App Access Token を取得する必要がある。

curl -G https://graph.facebook.com/oauth/access_token \
 -d "client_id=[APP_ID]" \
 -d "client_secret=[APP_SECRET]" \
 -d "grant_type=client_credentials"

これで App Access Token が返ってくる。Graph API ではないので、戻り値は JSON ではなく「キー=値」形式になっている。

access_token=APP_ID|xxxxxxx

次に通知先となるエンドポイントを実装する。エンドポイントには 2 つの機能を実装する必要がある。

  1. エンドポイント登録時にチェックのための GET アクセスがあるので、クエリストリング hub.modesubscribe なら hub.challenge の値をレスポンスボディに書き戻す機能。
  2. リクエストが POST かつ Content-Type が application/json なら、リクエストボディの JSON を解釈して通知された変更に対する処理を行う機能。

ドキュメントにも書いてあるが、PHP だと hub.challenge は PHP 側で hub_challenge に書き換えられるので気をつける必要がある。

エンドポイントができたら、/[APP_ID]/subscriptions エンドポイントに POST リクエストを飛ばすことで実際に Facebook アプリに紐付ける。例えば、メールアドレスが変更された場合に http://example.com/path/to/notify に通知させる場合は以下となる。

curl -X POST https://graph.facebook.com/[APP_ID]/subscriptions \
 -F "object=user" \
 -F "callback_url=https://example.com/path/to/notify" \
 -F "fields=email" \
 -F "verify_token=hoge" \
 -F "access_token=[APP_ACCESS_TOKEN]"

初回アクセス時には http://example.com/path/to/notify が存在するか、正しく動作するかの検証で Facebook からのリクエストが来るが、このリクエストの hub.verify_token には上記 verify_token に設定した任意の文字列が付与される。通知の際に付与される hub.verify_tokenverify_token と一致するかを検証することで、通知の設定が正しく行われているかを確認できる。

正しく登録できれば、JSON null が返ってくる。/[APP_ID]/subscriptions に GET リクエストを投げて、実際に登録できているかを確認できる。

curl -G https://graph.facebook.com/113985868730280/subscriptions \
 -d "access_token=113985868730280|GyO-gN-av_TU3qP_cqyAIJXRkh0"

結果は JSON で返ってくる。

{
  "data":[
    {
      "object":"user",
      "callback_url":"http:\/\/example.com\/path\/to\/notify",
      "fields":[
        "email"
      ],
      "active":true
    }
  ]
}

この状態で実際にメールアドレスを変更してみると、数秒遅れて Facebook より https://example.com/path/to/notify に以下のようなリクエストボディを持つ POST リクエストが飛んでくる。

{
  "object":"user",
  "entry":[
    {
      "uid":"[APP_BASED_USER_ID]",
      "id":"[APP_BASED_USER_ID]",
      "time":1414721892,
      "changed_fields":[
        "email"
      ]
    }
  ]
}

削除は DELETE メソッドでリクエストする。Ads API などと異なりオブジェクト ID が渡されるわけではないので、一括削除となる。

curl -X DELETE https://graph.facebook.com/[APP_ID]/subscriptions \
 -F "object=user" \
 -F "access_token=[APP_ACCESS_TOKEN]"

この機能は相当熱い。今までは変更があるかを定期的にポーリングする必要があった。特に各種パーミッションやメールアドレスなどは変更の有無が(実装上またはビジネス上)致命的な場合が多いので定期的にポーリングして変更がないか確認する実装をしているところも多いが、今回のアップデートにより、そういった「無駄な」リクエストを削減できることになる。