[c#] winphone plurk app 開發紀錄 (一)

  • 3108
  • 0
  • C#
  • 2012-08-14

摘要:[c#] winphone plurk app 開發紀錄 (一)

前陣子 被Chrono Plurk 搞到很煩,所以興起了自己也來寫一個的念頭。

在此紀錄一下自己開發的過程。

=====================================================

參考資料:

小朱的OAuth 系列文 

小朱的 EasyOAuth  Libray 2.0 sp1

OAuth  Core 1.0a spec

Plurk 2.0 API Reference

忠成老師的 Windows Phone 7 Web Browser 控制項應用 Part 1

====================================================

Step 1: 到Plurk 註冊應用程式。 

註冊完成後會取得 App key 及 App secret  這兩個值就是OAuth的oauth_consumer_key 及 oauth_consumer_secrect兩個參數

 

Step 2: 取得 request token

0. 要向 plurk 取得 request token

必須向 http://www.plurk.com/OAuth/request_token 送出 request

並且在標頭加入Authorizaion的資訊 

Hearder 是以KeyValuePairt的方式存取 

Key : "Authorization"

Value: "OAuth " + <parameter pairs>

每組參數是以 paramter_name = "paramter_value" 的樣式組成

每組參數之間以,連接

參數說明如下:

1.oauth_callback

手機應用程式因為沒有回呼網址  因此為 oob

2. oauth_consumer_key

就是向Plurk 註冊 所取得App key

3. oauth_signature_method

Plurk 目前只使用HMAC-SHA1 

4. oauth_timestamp

由1970/1/1 0:0:0 到目前為止所經過的秒數


        public long TimeStamp
        {
            get
            {
                return Convert.ToInt64(((TimeSpan)(DateTime.UtcNow - (new DateTime(1970, 1, 1, 0, 0, 0)))).TotalSeconds);
            }
        }

 

5. oauth_nonce 

這是一個隨機字串。由oauth_timestamp參數當作參數計算出的雜湊值。


        public string Nonce
        {
            get
            {
                StringBuilder nonceData = new StringBuilder();
                byte[] data = new SHA1Managed().ComputeHash(Encoding.UTF8.GetBytes(TimeStamp.ToString()));
                foreach (var d in data)
                {
                    nonceData.Append(d.ToString("x2").ToLower());
                }
                return nonceData.ToString();
            }
        }

6. oauth_version

目前Plurk是使用OAuth 1.0a規範 所以這個值為 1.0

7.  oauth_signature

這個參數算是最麻煩也是最容易出錯的地方。(事實上我在這裡卡關卡很久)

 (1)  基礎字串(base string) :

       由三個部分組成 :

              1. Http Method: 此時為 GET

              2. 目標網址: 此時為 http://www.plur,com/OAuth/request_token

              3. 正規化參數: 每組參數以 Name=Value 組成且以&連接, 參數必須按順序排列

      三組部分經過UrlEncode後以&連結, 即為 base string

(2) 簽章金鑰             

     由consumer_secrect及token_secrect(在取得request_token時, 這個值是空字串)組成, consumer_secrect及token_secrec經過UrlEncode 後以&連結, 即為簽章金鑰  

基礎字串 由HAMC-SHA1演算法及簽章金鑰 產生的資料 即為簽章值
需注意的是如果特殊符號使用HttpUtility的UrlEncode 產出的值會是小寫,而非OAuth要求的大寫
 


        public void AskForRequestToken()
        {
            this.RequestTokenSecret = string.Empty;
            parameters.Clear();
            parameters.Add("oauth_callback", "oob");
            parameters.Add("oauth_consumer_key", ConsumerKey);
            parameters.Add("oauth_nonce", Nonce);
            parameters.Add("oauth_signature_method", "HMAC-SHA1");
            parameters.Add("oauth_timestamp", TimeStamp.ToString());
            parameters.Add("oauth_version", Version);
            parameters.Add("oauth_signature", GenerateSign(RequestPhraseEnum.RequestToken));

            WebClient requestToken = new WebClient();
            string oauth = parameters.ToString(EncodePhraseEnum.OAuth);
            requestToken.Headers["Authorization"] = string.Format("OAuth {0}", oauth);
            requestToken.DownloadStringCompleted += new DownloadStringCompletedEventHandler(requestToken_DownloadStringCompleted);
            requestToken.DownloadStringAsync(new Uri(requestUrl));
        }

之後 plurk  會以QueryString的格式回傳 三個參數 oaut_token , oauth_token_secret , oauth_callback_confirm 

 


        void requestToken_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                throw new Exception(e.Error.Message);
            }
            else
            {
                string result = e.Result;
                Dictionary<string, string> requestToken = PlurkUtility.ParseQueryString(result);
                this.Token = requestToken["oauth_token"];
                this.TokenSecret = requestToken["oauth_token_secret"];
                this.CallBackConfirmed = requestToken["oauth_callback_confirm"];
            }
        } 

取得request_token 及 request_token_secret 下一步就是要取得使用者許可 

這部分留待下一篇再談