這東西應該很久了,但最近有這個需求就做一下筆記囉。

我們在製作 Facebook 粉絲專頁的頁籤應用程式時,會有傳遞參數的需求,但若用一般方式丟參數進去,會發現接不到 :/

https://www.facebook.com/{page_id}?sk=app_{app_id}&key=value

這樣是不行的…

上 stackoverflow 找了一下,原來要透過 app_data 這個參數丟,並透過 signed_request 去解析。

是這樣丟的:

https://www.facebook.com/{page_id}?sk=app_{app_id}&app_data={"key1":"value1","key2":"value2"}

那至於 signed_request 怎麼解呢?
PHP SDK 有很方便的 $facebook->getSignedRequest() 方法,至於 ASP.NET 若要手刻的方式比較麻煩些(微軟那套 C# SDK 應該也是有方法,但它改版速度太快了,怕寫法一下就失效,所以這邊以不透過 SDK 的方式示範囉):

關鍵的 code 在這(C#):(出處 stackoverflow)

string payload = Request.Form["signed_request"].Split('.')[1];
var encoding = new UTF8Encoding();
var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
var json = encoding.GetString(base64JsonArray);
var o = JObject.Parse(json);

解出 app_data 的值之後就可以做事啦,建議可以塞入 json 的字串,例如:

app_data={"key1":"value1","key2":"value2"}

這樣就可以傳遞多個參數了~

其實 signed_request 還有一些資訊可以幫助我們在做頁籤應用程式時使用,
例如:不用透過 Facebook Connect 就判斷使用者是否已經按讚(Like),或是判斷此頁籤應用程式是否被安裝到其他的粉絲專頁中了。
(安裝的方法很簡單:https://www.facebook.com/dialog/pagetab?app\_id={APP\_ID}&next=http://www.facebook.com)

這邊就不多說,直接參考下面的程式碼吧。

完整的 code 在這邊,記得還要將 JSON.NET 加入參考喔!

using System;
using System.Text;
using Newtonsoft.Json.Linq;

public partial class index : System.Web.UI.Page
{
    public string JSONString = "";
    public string output = "";
    public bool liked = false;
    public string pageid = "";
    public JObject app_data;

    protected void Page_Load(object sender, EventArgs e)
    {
        if (string.IsNullOrEmpty(Request.Form["signed_request"]))
        {
            Response.Write("<p>現在不是內嵌在粉絲專頁內喔</p>");
        }

        try
        {
            string payload = Request.Form["signed_request"].Split('.')[1];
            var encoding = new UTF8Encoding();
            var decodedJson = payload.Replace("=", string.Empty).Replace('-', '+').Replace('_', '/');
            var base64JsonArray = Convert.FromBase64String(decodedJson.PadRight(decodedJson.Length + (4 - decodedJson.Length % 4) % 4, '='));
            var json = encoding.GetString(base64JsonArray);
            var o = JObject.Parse(json);

            JSONString = "Decoded: <br />" + json;

            // 是否已經按讚
            liked = (bool)o.SelectToken("page.liked");
            // 粉絲專頁 ID
            pageid = (string)o.SelectToken("page.id");
            // 傳遞變數使用 app_data
            if (o.SelectToken("app_data") != null)
            {
                app_data = JObject.Parse((string)o.SelectToken("app_data"));
            }
        }
        catch (Exception ex)
        {
            output += "解析錯誤: " + ex.Message;
            Response.Write(output);
        }

        Response.Write("<p>" + JSONString + "</p>");

        string liketxt = (liked) ? "哈囉,你已經按讚,謝謝你" : "賞我個讚吧!";
        Response.Write("<p>" + liketxt + "</p>");

        Response.Write("<p>本專頁的 ID 為:" + pageid + "</p>");

        // 接收放在 app_data 中的 test 參數
        Label1.Text = (app_data != null && app_data.SelectToken("test") != null && !string.IsNullOrEmpty((string)app_data.SelectToken("test"))) ? app_data.SelectToken("test").ToString() : String.Empty;
    }
}

參考資料: