Исходный вопрос
Я хочу загрузить фотографии на Flickr с помощью PHP, и сначала мне нужно выполнить аутентификацию пользователя с помощью OAuth.
Вот ссылка на api do c:
Сначала вы должны создать базовую строку из вашего запроса. Базовая строка создается путем объединения HTTP-глагола, URL-адреса запроса и всех параметров запроса, отсортированных по имени, с использованием лексикографического упорядочения байтовых значений, разделенных символом «&».
Использование базовой строки в качестве текста и ключ - это объединенные значения Consumer Secret и Token Secret, разделенные знаком '&'.
И согласно эта , tokenSecret
является пустой строкой при вызове request_token
Вот мой фрагмент кода:
/**
* generateSignature
* @param $httpVerb
* @param $requestUrl
* @param $parameters
* @param string $tokenSecret
*
* @return string
*/
function generateSignature($httpVerb, $requestUrl, $parameters, $tokenSecret=''){
global $consumerSecret;
ksort($parameters);
$queryStr = http_build_query($parameters);
//not urlencode, same error
//$baseStr = $httpVerb . '&' . $requestUrl . '&' . $queryStr;
//urlencode
$baseStr = urlencode($httpVerb . '&' . $requestUrl . '&' . $queryStr);
$key = $consumerSecret . '&' . $tokenSecret;
$signature = hash_hmac('sha1', $baseStr, $key, false);
return $signature;
}
/**
* getRequestToken
* @return string
*/
function getRequestToken(){
global $consumerKey;
global $callbackUrl;
$requestTokenURL = 'https://www.flickr.com/services/oauth/request_token';
$queryParameters = [
//nonce: temporarily use hard code
'oauth_nonce' => '83273423',
'oauth_timestamp' => time(),
'oauth_consumer_key' => $consumerKey,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_version' => '1.0',
'oauth_callback' => urlencode($callbackUrl),
];
$queryParameters['oauth_signature'] = generateSignature('GET', $requestTokenURL, $queryParameters);
$queryStr = http_build_query($queryParameters);
return $requestTokenURL . '?' . $queryStr;
}
$consumerKey = '<YOUR_CONSUMER_KEY>';
$consumerSecret = '<YOUR_CONSUMER_SECRET>';
$callbackUrl = '<YOUR_REDIRECT_URL>';
$requestTokenURLWithQueryStr = getRequestToken();
// echo $requestTokenURLWithQueryStr;exit;
header('Location: '. $requestTokenURLWithQueryStr);
Но я получил "oauth_problem = signature_invalid" от Flickr, я не знаю, где я не прав, любой, кто знаком с этим можете мне помочь?
Обновление
Ну, во-первых, я должен поблагодарить @CBroe за указание моей неправильной точки, и вот мой код после изменения:
/**
* generateSignature
* @param $httpVerb
* @param $requestUrl
* @param $parameters
* @param string $tokenSecret
*
* @return string
*/
function generateSignature($httpVerb, $requestUrl, $parameters, $tokenSecret=''){
global $consumerSecret;
ksort($parameters);
$queryStr = http_build_query($parameters);
$queryStr = urlencode(urldecode($queryStr));
// echo $queryStr;exit;
$baseStr = $httpVerb . '&' . urlencode($requestUrl) . '&' . $queryStr;
echo $baseStr;exit;
$key = $consumerSecret;
$signature = hash_hmac('sha1', $baseStr, $key, false);
return $signature;
}
/**
* getRequestToken
* @return string
*/
function getRequestToken(){
global $oauth_nonce;
global $oauth_timestamp;
global $oauth_consumer_key;
global $oauth_callback;
$requestTokenURL = 'https://www.flickr.com/services/oauth/request_token';
$queryParameters = [
'oauth_nonce' => $oauth_nonce,
'oauth_timestamp' => $oauth_timestamp,
'oauth_consumer_key' => $oauth_consumer_key,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_version' => '1.0',
'oauth_callback' => urlencode($oauth_callback),
];
// var_dump($queryParameters);exit;
$queryParameters['oauth_signature'] = generateSignature('GET', $requestTokenURL, $queryParameters);
$queryStr = http_build_query($queryParameters);
return $requestTokenURL . '?' . $queryStr;
}
$oauth_nonce = '95613465';
$oauth_timestamp = '1305586162';
$oauth_consumer_key = '653e7a6ecc1d528c516cc8f92cf98611';
$oauth_consumer_secret = '*******';
$oauth_callback = 'http://www.example.com';
$requestTokenURLWithQueryStr = getRequestToken();
header('Location: '. $requestTokenURLWithQueryStr);
Сейчас я использую точно такой же параметр, как в примере , и я должен указать на одну вещь, в примере параметр oauth_nonce
и oauth_timestamp
в «URL» не так же, как их в «базовой строке» ( см. скриншот ниже):
Я использую параметр oauth_nonce
и oauth_timestamp
в "базовой строке", чтобы я мог генерировать точно такую же "базу" string "в качестве примера.
Запустите мой код, и этот оператор echo $baseStr;exit;
выведет« базовую строку », она точно такая же, как в примере, верно?
Но даже Я воспроизвожу пример, если я заменю значение параметра ($oauth_nonce
, $oauth_timestamp
, $oauth_consumer_key
, $oauth_consumer_secret
, $oauth_callback
) своим собственным, то же сообщение об ошибке "signature_invalid". Что мне теперь делать?
Обновление 2
Вот мой обновленный код (конечно, мне пришлось заменить параметры на свои, особенно oauth_consumer_key
и oauth_consumer_secret
и oauth_callback
), но подпись по-прежнему недействительна:
function generateSignature($httpVerb, $requestUrl, $parameters, $tokenSecret=''){
global $consumerSecret;
ksort($parameters);
$queryStr = http_build_query($parameters);
$queryStr = urlencode($queryStr);
$baseStr = $httpVerb . '&' . urlencode($requestUrl) . '&' . $queryStr;
$key = $consumerSecret . '&' . $tokenSecret;
$signature = hash_hmac('sha1', $baseStr, $key, false);
return $signature;
}
function getRequestToken(){
global $oauth_nonce;
global $oauth_timestamp;
global $oauth_consumer_key;
global $oauth_callback;
$requestTokenURL = 'https://www.flickr.com/services/oauth/request_token';
$queryParameters = [
'oauth_nonce' => $oauth_nonce,
'oauth_timestamp' => $oauth_timestamp,
'oauth_consumer_key' => $oauth_consumer_key,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_version' => '1.0',
'oauth_callback' => $oauth_callback,
];
// var_dump($queryParameters);exit;
$queryParameters['oauth_signature'] = generateSignature('GET', $requestTokenURL, $queryParameters);
$queryStr = http_build_query($queryParameters);
return $requestTokenURL . '?' . $queryStr;
}
//official document example paramters
$oauth_nonce = '95613465';
$oauth_timestamp = '1305586162';
$oauth_consumer_key = '653e7a6ecc1d528c516cc8f92cf98611';
$oauth_consumer_secret = '*******';
$oauth_callback = 'http://www.example.com';
$requestTokenURLWithQueryStr = getRequestToken();
// echo $requestTokenURLWithQueryStr;exit;
header('Location: '. $requestTokenURLWithQueryStr);
Сохраните следующий код в файл php (скажем, test.php
), затем замените параметр oauth_consumer_key
, oauth_consumer_secert
и oauth_callback
на свой, и запустите код, у вас все получится (и, пожалуйста, не верьте официальным API , это полная чушь):
<?php
/**
* generateSignature
* @param $httpVerb
* @param $requestUrl
* @param $parameters
* @param string $tokenSecret
*
* @return string
*/
function generateSignature($httpVerb, $requestUrl, $parameters, $tokenSecret=''){
global $oauth_consumer_secret;
ksort($parameters);
$queryStr = http_build_query($parameters);
$baseStr = $httpVerb . '&' . urlencode($requestUrl) . '&' . urlencode($queryStr);
$key = $oauth_consumer_secret . '&' . $tokenSecret;
$signature = hash_hmac('sha1', $baseStr, $key, true);
$signature = urlencode(base64_encode($signature));
return $signature;
}
/**
* Get authorization header
* @return array
*/
function getRequestHeaders(){
global $oauth_consumer_key;
global $oauth_callback;
global $requestTokenURL;
$queryParameters = [
'oauth_nonce' => crc32(time()),
'oauth_timestamp' => time(),
'oauth_consumer_key' => $oauth_consumer_key,
'oauth_signature_method' => 'HMAC-SHA1',
'oauth_version' => '1.0',
'oauth_callback' => $oauth_callback,
];
// var_dump($queryParameters);exit;
$queryParameters['oauth_signature'] = generateSignature('GET', $requestTokenURL, $queryParameters);
//urldecode the oauth_callback url(cause http_build_query() will urlencode it)
$queryStr = urldecode(http_build_query($queryParameters));
//replace "&" with ",",and add double quote at the right side of the "=" and the left side of the ",",
//doing this is because we need to add double quote to the value of the query string, because this string
//will use as authorization header, not as query string.
$authorization = str_replace('&', '", ', str_replace('=', '="', $queryStr)) . '"';
$authorization = 'Authorization: OAuth realm="", ' . $authorization;
return [$authorization];
}
/**
* getRequestToken
* @return array
*/
function getRequestToken(){
$headers = getRequestHeaders();
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, 'https://www.flickr.com/services/oauth/request_token');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt ($ch, CURLOPT_CONNECTTIMEOUT, 30);
curl_setopt ($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt ($ch, CURLOPT_SSL_VERIFYHOST, 0);
//in case you need a proxy
//curl_setopt ($ch, CURLOPT_PROXY, 'http://127.0.0.1:1087');
$returnStr = curl_exec($ch);
if(curl_errno($ch)){
echo 'Error: ' . curl_error($ch);
}
curl_close($ch);
$returnArr = [];
parse_str($returnStr, $returnArr);
return $returnArr;
}
$requestTokenURL = 'https://www.flickr.com/services/oauth/request_token';
$oauth_consumer_key = '<YOUR_CONSUMER_KEY>';
$oauth_consumer_secret = '<YOUR_CONSUMER_SECERT>';
$oauth_callback = '<YOUR_CALLBACK_URL>';
$tokens = getRequestToken();
var_dump($tokens);
Оказывается, нам нужно передать параметр в заголовок http и официальный API никогда не говори об этом, это сводит меня с ума.