這東西應該很久了,但最近有這個需求就做一下筆記囉。
我們在製作 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;
}
}
參考資料:
- http://stackoverflow.com/questions/9571971/referral-urls-on-facebook-page-tab
- http://stackoverflow.com/questions/10801807/facebook-fan-page-app-pass-string-to-app-data-and-retrieve
- http://blog.fbdoctor.com/2011/04/%E5%A6%82%E4%BD%95%E5%88%A9%E7%94%A8signed-request%E5%88%A4%E5%AE%9A%E4%BD%BF%E7%94%A8%E8%80%85%E6%98%AF%E5%90%A6%E5%9C%A8%E7%B2%89%E7%B5%B2%E5%B0%88%E9%A0%81%E4%B8%8A%E9%9D%A2%E7%80%8F%E8%A6%BD/
不好意思,請問一下,
有辦法不要經過內嵌的app就得知使用者是否有加入粉絲團嗎?
我有一個web使用Facebook登入,但Facebook一直不讓我通過取得使用者的user_likes,
找到 signed_request的方法後,研究了好幾天,
看了大大您的作法後才發現,這個方式似乎是Facebook呼叫內嵌網頁時才發出的Request…
不知道大大有沒有其他妙招Orz
印象中目前 Facebook app 「是否為粉絲」的權限應該要送審才能取得,
不過我也有陣子沒實作 Facebook app 的專案了,目前還沒有辦法經驗分享囉 😛
https://developers.facebook.com/docs/apps/changelog