Аутентификация и отклонение заголовка с помощью Twitpic и OAuth

Я изо всех сил стараюсь загружать изображения в Twitpic с помощью PHP и OAuth (расширение PECL), но постоянно получаю следующую ошибку:

Не удалось аутентифицировать вас (заголовок отклонен твиттером)

Это мой код до сих пор:

$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);

Может кто-нибудь сказать мне, что я делаю неправильно?


person user461054    schedule 28.09.2010    source источник


Ответы (1)


я столкнулся с множеством проблем, используя oauth echo, но через несколько дней вот мой рабочий код :) Надеюсь, он вам поможет:

<?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);

?>

Дело в том, что документация API twitpic далека от четкой. Когда вы знаете, что вам нужно подделать вызов для https://api.twitter.com/1/account/verify_credentials.json, а не для http://api.twitpic.com/2/upload.json, это начинает проще... Когда вы знаете, что в вашей базовой строке подписи вам нужны только параметры oauth_parameters, это еще проще...

Надеюсь, это поможет вам!

person Guillaume Chanaud    schedule 30.09.2010