Facebookログインと同時投稿方法が変わりました(Javascript SDKの使い方も解説)

まめわざでは、TwitterとFacebookのアカウントでのログインと、両SNSにまめわざで作ったページの紹介を同時投稿する機能を提供しています。
Facebookの仕様変更により、Facebookのログイン方法と同時投稿の方法が変わりましたので、ここでご説明いたします。
末尾にはFacebook Javascript SDKの使い方も解説します。

Facebookのログイン・投稿手順

まめわざにFacebookアカウントでログインする

まめわざのログイン画面で、「Facebookでログイン」を押すだけです。
ただし、Facebookアカウントを予め関連付けする必要があります。
関連付け(ログイン設定)の方法を、ホームページが作成済みの場合、これから新規作成する場合の両方について以下で説明します。

まめわざで作成済みのホームページにFacebookアカウントを関連付ける

  • まわわざにログイン後、右上の三本線(ハンバーガー)アイコンを押し、「ログイン設定」を押してログインページに移動します
  • ログイン設定ページで、「Facebookアカウントでログイン」欄の「設定」を押します
  • Facebookにログインしていない場合は、小窓が表示されるのでログインします
  • 最後にログイン設定ページの最下部の「保存」を押します

まめわざで新規作成するホームページにFacebookアカウントを関連付ける

  • まめわざ登録ページのステップ4「保存」で、「Facebookアカウントでログイン」の「設定」を押します
  • Facebookにログインしていない場合は、小窓が表示されますのでログインします
  • その他の内容を入力後に「無料ホームページを作成」ボタンを押します

Facebookに同時投稿する

まめわざでページを新設・更新する際に、その内容の要約をFacebookの個人のウォールや管理しているFacebookページのウォールに投稿できます。
ブログ機能との相性が良く、ブログ記事の投稿とFacebookでの紹介が同時にできるので便利です。

  • (事前準備)Facebookのウォールに投稿する場合は、上記のいずれかの方法でFacebookアカウントでのログイン設定(関連付け)をします
  • ページを新設・更新する際に、編集ページの右下にある「ページ名などの設定」を押します。
  • 「Facebook」の「同時投稿する」をチェックします。
    ウォールへの投稿を一度も許可していない場合は、Facebookの小窓が表示され許可を求められますのでOKします。
    管理しているFacebookページがある場合は、選択欄が表示されるので、対象対象のウォールを選びます。
  • 最後に最下部のボタンで「保存」「保存&トップへ」「保存&編集継続」ボタンを押してページを保存し、同時投稿します

以前との違い)以前はFacebookに投稿するために「その他の設定」で関連付けをする必要がありましたが、現在はその作業は不要になりました。
Facebookでログインをしていると、各ページの保存時に下部に「同時投稿する」のチェックが表示されます。

(技術的な説明)FacebookのJavascript SDKを使ってログイン・ウォールに投稿する

これまで使っていたFacebook PHP SDKからJavascript SDKに変更をしました。
Javascript SDKを使って、Facebookログインや個人のウォール・Facebookページのウォールに投稿するまでの技術的な手順を説明します。
尚、ここではjQueryの利用を前提としていますのでご了承願います。

事前準備)アプリケーションIDの登録・権限承認(最難関)

事前にFacebookのアプリケーションIDを取得する必要があります。大まかには

  • Facebookアプリの新規作成
  • テストユーザーの登録
  • テストユーザーでのアプリの実装(作成)
  • Facebookへの権限利用の申請(ただしログインのみの場合は審査なし)

という流れです。時間も面倒も掛かる最難関のステップですが、その説明は過去のこちらの記事に譲ります。
尚、publish_actionsなど投稿関連の審査は、2015年の上記記事の投稿時に比べ、更に厳しくなっています。Facebookへ投稿する際の、投稿内容(本文・リンク・画像など)を投稿者が自ら設定できなければいけないようなのでご注意下さい。

Javascript SDKを使ってログインする

コードは非常にシンプルです。
Javascript SDKによるログインの肝は「Facebookの非ログインユーザーにログインを促す時のポップアップブロックの回避」にあると言っても過言ではありません。
以下のコードでは、下記で解説するようにポップアップブロックが動作しないようにSDKの本体ファイルを$(document).readyで非同期に前読みしており、またFacebookの公式説明にあるFB.getLoginStatusは利用していません。

<button onclick="fb_login()">Facebookログイン</button>
<script type="text/javascript">
function fb_login() {
    FB.login(function(res) {
        if(typeof(res) == "object" && typeof(res.authResponse) == "object") {
            //ログインしている場合の処理
            alert("ログイン中。IDは" + res.authResponse.userID + "です。");

        } else {
            //ログインしていない場合の処理
            alert("ログインしていません。再度ログインしてください。");
        }
    } );
};
$(document).ready(function() {
    $.ajax( {
        "dataType": "script",
        "cache": true,
        "url": "//connect.facebook.net/ja_JP/sdk.js",
        "success": function() {
            FB.init( {
                appId: "アプリケーションID",
                version: "v2.3",
            } );
        },
    } );
} );
</script>
 

ポップアップブロックの動作判定

下記の4つのケースについて、Facebookの非ログインユーザーがボタンを押した際のポップアップの動作状況を確認しました。
ポップアップの動作は、iOSのSafari、AndroidのChrome、IE11、Edge、Chromeなど主要ブラウザで同様の結果となります(ただし、ポップアップブロックが動作した際に、それを知らせるブラウザと、無視するブラウザがあります)。

a) ボタン押下前にFacebookのscriptを取得しておきログイン

成功例です。
sdk.jsを前読みしておき、ボタン押下→FB.loginと間を挟まずにすぐ実行するとポップアップブロックが動作しません。

コードは上記と同一。

b) ボタン押下後にFacebookのscriptを取得しログイン

失敗例です。
FBがundefinedの場合にsdk.jsを読み込みます。Facebookの公式説明にもある「アクション時にsdk.jsを読み込む」方法ですが、多くのブラウザでポップアップブロックが動作します。

<button onclick="fb_login()">Facebookログイン</button>
<script type="text/javascript">
function fb_login() {
    if(typeof(FB) == "undefined") {
        $.ajax( {
            "dataType": "script",
            "cache": true,
            "url": "//connect.facebook.net/ja_JP/sdk.js",
            "success": function() {
                FB.init( {
                    appId: "アプリケーションID",
                    version: "v2.3"
                } );
                fb_login();
            },
        } );
        return "";
    }

    FB.login(function(res) {
        if(typeof(res) == "object" && typeof(res.authResponse) == "object") {
            alert("ログイン中。IDは" + res.authResponse.userID + "です。");
        } else {
            alert("ログインしていません。再度ログインしてください。");
        }
    } );
};
</script>
 

c) ボタン押下前にFacebookのscriptを取得しておき、ログイン確認後にログイン

失敗例です。
こちらは(a)のFB.loginを、公式説明にあるFB.getLoginStatusに変え、ログインしていない場合に新たにFB.loginを実行するケースです。すぐにFB.loginを実行した(a)と異なり、ポップアップブロックが動作します。

<button onclick="fb_login()">Facebookログイン</button>
<script type="text/javascript">
function fb_login() {
    FB.getLoginStatus(function(res) {
        if(typeof(res) == "object" && typeof(res.authResponse) == "object") {
            alert("ログイン中。IDは" + res.authResponse.userID + "です。");
        } else {
            FB.login();
        }
    } );
};
$(document).ready(function() {
    $.ajax( {
        "dataType": "script",
        "cache": true,
        "url": "//connect.facebook.net/ja_JP/sdk.js",
        "success": function() {
            FB.init( {
                appId: "アプリケーションID",
                version: "v2.3"
            } );
        },
    } );
} );
</script>
 

d) Facebookページにリダイレクトしログイン

もう1つの成功例です。
window.location.hrefによりFacebookページにリダイレクトすることで、当然ながらポップアップブロックは回避できますが、FB.getLoginStatusの使い所の例として挙げました。
リダイレクト処理が挟まるためページは再読込されます。Facebookログイン設定以外に入力欄がある場合など、ページが再読込されては困る場合は、この方法は利用できません。

<button onclick="fb_login()">Facebookログイン</button>
<script type="text/javascript">
function fb_login() {
    if(typeof(FB) == "undefined") {
        $.ajax( {
            "dataType": "script",
            "cache": true,
            "url": "//connect.facebook.net/ja_JP/sdk.js",
            "success": function() {
                FB.init( {
                    appId: "アプリケーションID",
                    version: "v2.3"
                } );
                fb_login();
            },
        } );
        return "";
    }

    FB.getLoginStatus(function(res) {
        if(typeof(res) == "object" && typeof(res.authResponse) == "object") {
            alert("ログイン中。IDは" + res.authResponse.userID + "です。");
        } else {
            window.location.href = "https://www.facebook.com/dialog/oauth?client_id=アプリケーションID&redirect_uri=" + encodeURIComponent(document.URL);
        }
    } );
};
</script>
 

Javascript SDKを使って個人のウォールやFacebookページに投稿する

1.ログイン&許可を得る

FB.loginの第2引数で、scopeを指定し、return_scopes: trueとします。scopeは

  • 自分のウォールへの投稿を許可するpublish_acitons
  • 自分で管理するFacebookページのリストを表示するmanage_pages
  • 自分で管理するFacebookページへの投稿を許可するpublish_pages

の3つです。自分のウォールへの投稿に限った場合はpublish_actionsだけでOKです。

FB.login(mycallback, {
    "scope": "publish_pages,publish_actions,manage_pages",
    "return_scopes": true
} );
 

2.個人のウォールとFacebookページのウォールのID・access_tokenを取得する

FB.loginのコールバック(第1引数)として以下を実行します(関数名は任意で変更して下さい)。
まず、コールバック関数の引数に含まれるres.authResponse.grantedScopesで、権限が与えられたことを確認する必要があります。こちらも、自分のウォールへの投稿に限った場合はpublish_actionsだけでOKです。
権限が得られた場合は、FB.api("/me/accounts")で管理するFacebookページのリストを取得します。ここでは、selectタグでウォールの選択欄を設けるためにoptionタグを生成しています。

var mycallback = function(res) {
    if(typeof(res) != "object" || typeof(res.authResponse) != "object") {
        //ログインしていない場合の処理
        alert("ログインしていません。");
        return "";
    }

    var scopes = res.authResponse.grantedScopes;
    if(!scopes || scopes.indexOf("publish_pages") == -1 || scopes.indexOf("publish_actions") == -1 || scopes.indexOf("manage_pages") == -1) {
        //許可が得られなかった場合の処理
        alert("一部が許可されていません。もう1度ログインしてください。");
        return "";
    }

    //許可が得られた場合の処理(ここではselectにoptionタグを設置)
    var options = "<option value=\"\">個人のウォール</option>";
    FB.api("/me/accounts", {}, function(res) {
        if(typeof(res) != "object" || typeof(res.data) != "object" || !res.data[0]) {
            return "";
        }

        for(var i = 0; i < res.data.length; i++) {
            options += "<option value=\"" + res.data[i].id + "\" data-token=\"" + res.data[i].access_token + "\">『" + res.data[i].name + "』のウォール</option>";
        }
    } );

    //selectタグにoptionを設置
    $("select[name=\"fb_wall\"]").html(options);
};
 

3.投稿する

「投稿する」ボタン押下時に、選んだウォールのIDとaccess_tokenを取得し、textareaに入力したメッセージを投稿するサンプルです。
投稿は
FB.api("/me/feed", "post", {"message": "メッセージ"});
で行います。
Facebookウォールに投稿する際は、下記のようにFacebookページのIDとaccess_tokenをセットする必要があります。

  • 第1引数に"/123456789/feed"のようにmeの代わりにFacebookページのIDをセット
  • 第3引数に{"message": "メッセージ", "access_token": "abcdedg"}のようにFacebookページのaccess_tokenをセット

<select name="fb_wall">
<option value="" data-token="">自分のウォール</option>
<option value="(FacebookページaのID)" data-token="(Facebookページaのaccess_token)">『〇〇』のウォール</option>
<option value="(FacebookページbのID)" data-token="(Facebookページbのaccess_token)">『〇〇』のウォール</option>
</select>
<textarea name="fb_msg" colspan="20" rowspan="5"></textarea>
<button onclick="fb_post()">投稿する</button>

var fb_post = function() {
    var id = $("select[name=\"fb_wall\"]").val();
    var token = $("select[name=\"fb_wall\"]" option:selected").data("token");
    var msg = $("textarea[name=\"fb_msg\"]").val();

    var dat = {
        "message": msg,
    };

    if(token) {
        dat.access_token = token;
    }

    FB.api("/" + (id ? id : "me") + "/feed", "post", dat, function(res) {
        if(typeof(res) == "object" && res.id) {
            alert("投稿に成功しました。投稿した文章のIDは" + res.id + "です。");
        } else {
            alert("投稿に失敗しました。");
        }
    } );
};
 

(蛇足)Facebook PHP SDK→Javascript SDKへ

2017年3月末にあったFacebookの仕様変更により、一時的にFacebookログインが出来ない状況が続き、ご不便をおかけしまして申し訳ございませんでした。
この仕様変更によってFacebook側でOAuthの取扱方法が変更になり、その結果Facebook PHP SDK v3が利用できなくなって、最新版であるv5へのバージョンアップを余儀なくされました。
しかしv5はPHPのバージョーンが5.4以上の環境でなければ利用できないという更なる制約があります。
まめわざのサーバー事情を鑑みて検討した結果、代替案として挙がったのがFacebook Javascript SDKの導入でした。
処理をサーバーサイドからクライアントサイドに変更するという根本的な変更を伴いますが、Facebook APIのドキュメントを見る限りでは可能なようなのでトライしました。
今後も仕様変更を繰り返す可能性があるPHP SDKに比べると、Javascript SDKは仕様変更に振り回されるずに長く使える可能性が期待できます。

2017/4/18