2010-09-28 91 views
1

我想我最好使用PHP和OAuth(PECL擴展)上傳圖片到Twitpic和我不斷收到以下錯誤:認證和頭拒絕與Twitpic和OAuth

Could not authenticate you (header rejected by twitter)

這是我的代碼遠:

$arguments[] = "oauth_consumer_key=" . $this->consumer_key; 
$arguments[] = "oauth_nonce="  . md5(time()); 
$arguments[] = "oauth_signature_method=HMAC-SHA1"; 
$arguments[] = "oauth_timestamp=" . time(); 
$arguments[] = "oauth_token="  . $this->oauth_token; 
$arguments[] = "oauth_version=1.0"; 

$sbs  = oauth_get_sbs("POST", "http://api.twitpic.com/2/upload.xml", $arguments); 
$signature = urlencode(base64_encode(hash_hmac("sha1", $sbs, $this->consumer_secret . "&", true))); 

$arguments[] = "oauth_signature=" . $signature; 

sort($arguments); 

$headers[] = "X-Auth-Service-Provider: http://api.twitter.com/1/account/verify_credentials.json"; 
$headers[] = "X-Verify-Credentials-Authorization: OAuth\n" . implode(",\n", $arguments); 

$postfields["key"]  = $this->api_key; 
$postfields["media"] = "@$image"; 
$postfields["message"] = $message; 

$curl = curl_init(); 
curl_setopt($curl, CURLOPT_URL, "http://api.twitpic.com/2/upload.xml"); 
curl_setopt($curl, CURLOPT_POST, true); 
curl_setopt($curl, CURLOPT_POSTFIELDS, $postfields); 
curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); 
curl_setopt($curl, CURLOPT_VERBOSE, true); 
curl_setopt($curl, CURLOPT_HEADER, true); 
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); 
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
echo curl_exec($curl); 

有人可以告訴我我做錯了什麼嗎?

回答

3

我遇到了一個大量使用OAuth回聲的麻煩,但經過這裏有些日子是我工作的代碼:)希望它會幫助你:

<?php 
    $timestamp = time(); 
    $nonce = md5(uniqid(rand(), true)); 
    $consumer_key = 'o6HXSybcBTrF9sylWzr04wzLjudbdZBQDpxGRdnBM'; 
    $access_token = '147679787-tPB5UjfzQ1OPmn8JHzHmDWRYmI2yzN1Q9eMocGA'; 
    $access_secret = 'hiding'; 
    $consumer_secret = 'hiding'; 

    $twitpic_url = 'http://api.twitpic.com/2/upload.json'; 
    $args['key'] = 'hiding'; //This is your twitpic api key 
    $args['message'] = "testing twitpic from api"; 
    $args['media'] = "@/tmp/linux.png" ; //Don't forget the @ 

    //Here we build the oauth headers args which will be used for the signature base string 
    $oauth_args['oauth_consumer_key'] = $consumer_key; 
    $oauth_args['oauth_nonce'] = $nonce; 
    $oauth_args['oauth_signature_method'] = "HMAC-SHA1"; 
    $oauth_args['oauth_timestamp'] = $timestamp; 
    $oauth_args['oauth_token'] = $access_token; 
    $oauth_args['oauth_version'] = "1.0"; 
    $sbs_args = $oauth_args; 
    //We sort it... 
    ksort($sbs_args); 
    $url = 'https://api.twitter.com/1/account/verify_credentials.json'; 
    $sbs = oauth_get_sbs(OAUTH_HTTP_METHOD_GET, $url, $sbs_args); 
    //This above function is from pecl oauth package 
    //It can be easily replaced by a homemade function for no dependancy code 
    //Here is the signature_base_string which is generated : 
    /* 
    GET&http%3A%2F%2Fapi.twitter.com%2F1%2Faccount%2Fverify_credentials.json&oauth_consumer_key%3DtL0auuqfuu8vyHt5Md9bg%26oauth_nonce%3Dacb327b80ae4bf35e895774f89a6afe2%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1285880687%26oauth_token%3D147679787-tPB5UjfzQ1OPmn8JHzHmDWRYmI2yzN1Q9eMocGA%26oauth_version%3D1.0 
    /* 
     * You should use a function to concatenate your keys ($access_secret is not mandatory. The function would encode the keys before concatenating (as far as i've seen in others sources... 
    */ 
    $key = $consumer_secret.'&'.$access_secret; 
    $signature = urlencode(base64_encode(hash_hmac('sha1', $sbs, $key, true))); 
    $headers = 
      <<<EOF 
OAuth realm="http://api.twitter.com/", oauth_consumer_key="$consumer_key", oauth_signature_method="HMAC-SHA1", oauth_token="$access_token", oauth_timestamp="$timestamp", oauth_nonce="$nonce", oauth_version="1.0", oauth_signature="$signature" 
EOF; 
     //Everything must be on a single line... 

/* 
* In fact, as you can see, the signature is generated against twitter verify_credentials.json 
* and not against twitpic upload url...The base signature string does NOT take the twitpic 
* parameters !! This is where i had lots of troubles... 
* To be clear, we have to generate a header with oauth parameters only, we have to build 
* a base signature string with those parameters sorted and the verifiy_credentials.json url 
* in the same way as if we would authenticate directly against twitter (no twitpic magic here) 
*/ 

     $curl = curl_init(); 
     //We are going to call twitpic api, not twitter : 
     curl_setopt($curl, CURLOPT_URL, $twitpic_url); 

     curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); 
     curl_setopt($curl, CURLOPT_FAILONERROR, false); 

     // Set our OAuth Echo headers 
     /* 
     * This is the oauth magic. We pass to twitpic the url where he has to authorize user 
     * We pass the header to pass to this url. 
     * We constructed a beautifull header ready for verify_credentials.json 
     * Twitpic will send this header to twitter by calling verify_credentials.json 
     * And then continue process if twitter answer correctly ! 
     */ 
     curl_setopt($curl, CURLOPT_HTTPHEADER, array(
      'X-Verify-Credentials-Authorization: ' . $headers, 
      'X-Auth-Service-Provider: ' . $url 

     )); 

     //We post your $args array with you api key, message, and media... 
     curl_setopt($curl, CURLOPT_POST, 1); 
     curl_setopt($curl, CURLOPT_POSTFIELDS, $args); 

     $response = curl_exec($curl); 
     if (!$response) { 
      $response = curl_error($curl); 
     } 

     curl_close($curl); 
     //Twitpic json respone 
     var_dump($response); 

?> 

的事情之一是,twitpic API文檔是遠離明確。 當您知道您必須僞造https://api.twitter.com/1/account/verify_credentials.json而不是http://api.twitpic.com/2/upload.json的電話時,纔會開始更容易...當你知道在你的簽名基礎字符串,你只需要oauth_parameters它更容易...

希望它會幫助你!