Facebookページのタブにアプリを統合してみる&signed_requestの状態を確認するPHP

めずらしくFacebook

Facebookアプリと,FacebookページのLike or UnLikeの分岐とか,概念がよくわかっていませんでしたが調べたのでメモ.

どうやら「Facebookページで自由度の高いコンテンツを見せるために,Facebookアプリのiframeみたいな仕組みを統合する必要がある」というノリみたいです.Facebookアプリとしてゴリゴリ作るのはまた別の話.

※最近調べた話なので,iframe版オンリーの話です.

Facebookアプリのセットアップ概略

Facebook Developersの上にある,MyApps(マイアプリ)をクリックすると,Developer(開発者)というアプリへの認証が求められます.これまでに何かの拍子で認証済みであれば,すぐにDevelopersが表示されるはずです.



このFacebookアプリが,自分のFacebookアプリのIDや秘密鍵などの各種設定を管理してくれます.右上のSet Up New Appから,アプリの名前の入力とCAPTCHA認証を通ると,すぐにアプリが作成されてそのほかの詳細な設定を行えます.

※携帯番号やクレジットカードを使ったアカウント認証が済んでいない場合,警告がでるので注意

Facebookアプリの2つの利用シーン

Facebookアプリには,2つの形態があります.以下,日本語化が中途半端なので,2011-06-10時点のEnglish(US)ラベルを元に,単語を選んでいます.



Facebook Integrationで,Canvas&Tabsの設定と,singed_requestの確認に使用するApplication Secretなどの項目を確認できます.

Canvas

Canvasは,Canvas Pageの項目に示されるhttp://apps.facebook.com/***/のURLで表示するページです.ここのCanvas URLが,Canvas Pageで設定したURLでiframe内に読み込まれます.SSL接続時はSecure Canvas URLが読み込まれます.

※Facebookページに統合するだけで,Facebookアプリとして運用しないなら,無くても良いと思います.

Page Tabs

Page Tabsは,そのFacebookアプリがAdd to Pageされて,Facebookぺージの1タブとして統合された状態で表示するページです.ここで設定されたTab URLとSecure Tab URLが,iframe内に読み込まれます.

※Edit URLってのもありますが,これはAdmin用のページなので利用しなくても問題ありません.)

このエントリーで説明しているのは,このFacebookページに統合するタブのほうです.

Facebookぺージのタブとして統合する

早速,登録したアプリを,Facebookぺージのタブとして統合してみましょう.



Facebook自体になれていないと,ナビゲーションをうまくたどれない感じなので,注意深くメニュー項目を追っかけます,自分は慣れてないので最初は迷子でした.


  1. Edit Settings → Facebook Integration → Page Tabsの"Tab Name", "Tab Url", "Secure Tab Url"を入れてSave.
  2. 統合したいFacebookページのAdminユーザーでログインしているのを確認して,設定したアプリのApplication Profile Pageへ.
  3. 左のカラムの下の方に Add to My Pageという項目があるので,これをクリック.
  4. 自分の管理しているFacebookページが一覧に出るので,追加したいページにAdd to Page.

これで追加したFacebookページにいくと,左側のメニューにアプリによって追加された新しいタブが出現しているはずです.

右の写真はテストアプリです.


signed_requestの確認をするPHP

Facebook側で指定したURLをiframe内に読み込んでもらう指定は終わったので,指定したURLに何らかの処理を挟んだPHPを配置します.ここでは,singed_requestの確認サンプルを紹介します.

signed_requestは,iframeで読み込んでいるページに,このリクエストが署名済みの正規リクエストであることを証明するための情報です.なぜかPOSTリクエストで飛んでくるので,$_POSTを参照することになります.

※ちゃんと署名をチェックしないと,変なPOSTリクエストにも反応してしまう可能性があるので気をつけましょう.

function base64_url_decode($str) {
  return base64_decode(strtr($str, '-_', '+/'));
}

function get_signed_data($secret) {
  if ( isset($_POST['signed_request']) ) {
    list($enced, $payload) = explode('.', $_POST['signed_request'], 2);
    // JSON
    $data = json_decode(base64_url_decode($payload), true);
    // 署名
    $sig  = base64_url_decode($enced);

    switch ($data['algorithm']) {
      case 'HMAC-SHA256'  :
        // ペイロードとシークレットをハッシュ化して確認用の署名を作成
        $expected_sig = hash_hmac('sha256', $payload, $secret, true);
        break;
      default :
        $expected_sig = null;
        break;
    }
   
    if ( $sig === $expected_sig ) {
      // リクエストの正当性が確認できたのでOK
      return $data;
    } else {
      // 署名が不正だったのでNG
      return false;
    }
  }
  // そもそもsigned_requestじゃないっぽい
  return null;
}

$app_secret = '(Facebook Application secret)';

var_dump(get_signed_data($app_secret));

OAuthでユーザー情報を存分に利用する場合は,Facebook PHP SDKを使えばすごくラクですが,ここではsigned_requestだけ参照できればいいので,SDKなしのサンプルコードとしました.


$dataなるJSONの中身

大体このような形の配列として取得できるはずです.このデータのメジャーな使い道は,$data['page']['liked']の値による,Likeしてくれたら〜〜〜を見せるよ的な分岐処理でしょう.

管理者にだけ特定のコンテンツなり集計情報などを出したい場合は,$data['page']['admin']も分岐処理に使えそうです.

array(4) {
    ["algorithm"]=> string(11) "HMAC-SHA256"
    ["issued_at"]=> int(**********)
    ["page"]=> array(3) {
        ["id"]=> string(15) "********************"
        ["liked"]=> bool(true)
        ["admin"]=> bool(false)
    }
    ["user"]=> array(3) {
        ["country"]=> string(2) "jp"
        ["locale"]=> string(5) "ja_JP"
        ["age"]=> array(2) {
            ["min"]=> int(18)
            ["max"]=> int(20)
        }
    }
}

参考になれば幸いですが,きっとすぐに古い情報に…

とりあえずここを中心に,公式ドキュメント見ればいいと思います.へたにGoogle先生にお伺いを立てると,古い情報がわんさか出てきて混乱することも...