POST запрос CURL, возвращает 404

296
22 октября 2017, 23:12

Нужно отправить POST-запрос банку для авторизации. Запрос отправляю CURL, но возвращается 404 код. Что делаю не так?

Запрос нужно отправить в таком формате:

POST /secure/token HTTP/1.1
Authorization: Basic строкаАвторизации
Content-Type: application/x-www-form-urlencoded
Request Body:
grant_type=authorization_code&code=<код авторизации>&redirect_uri=<URL возврата>

Отправляю запрос через CURL:

$params=[
   'grant_type'=>'authorization_code',
   'code'=>$code,
   'redirect_uri'=>$uri
];
$headers = [
   'POST /secure/token HTTP/1.1',
   'Content-Type: application/x-www-form-urlencoded'
];
$curlURL='https://sso.tinkoff.ru';       
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL,$curlURL);
curl_setopt($ch, CURLOPT_HTTPAUTH, CURLAUTH_BASIC);
curl_setopt($ch, CURLOPT_USERPWD, $user . ":" . $pass);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS,http_build_query($params));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_VERBOSE, true);
if(curl_exec($ch)) {
   $server_output = json_decode(curl_exec($ch));
}

Что делаю неправильно?

UPD: Разобрался, в чем дело. Дело было в https. Как только получил SSL сертификат — заработало. Спасибо за помощь!

Answer 1

По документации видно, что url должен быть https://sso.tinkoff.ru/secure/token, а у вас идет https://sso.tinkoff.ru/ поменяйте урл и все заработает

upd: и оставьте только так

$headers = [
   'Content-Type: application/x-www-form-urlencoded'
];

и этот кусок поправьте

if(curl_exec($ch)) {
   $server_output = json_decode(curl_exec($ch));
}

на

$curl_res = curl_exec($ch);
if($curl_res) {
    $server_output = json_decode($curl_res);
}

а то вы два запроса делаете

Answer 2

libcurl штука хорошая, но при работе с ней понимать структуру HTTP запросов и ответов всё равно требуется.

Заголовки запроса вам даже из-за включенного CURLOPT_VERBOSE должны быть видны и там отчётливо виден запрос

POST / HTTP/1.1

Вместо /secure/token. Почему? Потому что CURLOPT_URL имеет приоритет над CURLOPT_HTTPHEADER. Content-Type же необходимый выставит CURLOPT_POSTFIELDS самостоятельно.

Как итог - вам не нужен CURLOPT_HTTPHEADER вообще. Библиотека проставит все заголовки самостоятельно.

Как уже написал в комментариях - каждый вызов curl_exec осуществляет HTTP запрос. Т.е. ваш код делает два запроса, при том отбрасывает результат первого. Да и результат второго запроса тоже отбрасывает. Потому что json_decode дальше по коду требует чтобы ему был передан JSON документ. На заголовки HTTP-ответа он отреагирует единственно возможным способом - решит что это не JSON-документ и ответит NULL. А вы никуда ответ не сохранили и вообще не проверили, был ли корректно выполнен запрос через curl_errno/curl_error

Сторонняя система вполне может считать коды авторизации одноразовыми.

Я очень надеюсь, что вы не системой платежей занимаетесь. Для работы с деньгами у вас очень сильно не хватает ни понимания своего собственного кода ни опыта отладки - это отчётливо видно по комментариям.

// TODO: write to log outcoming request
$ch = curl_init();
/// curl_setopt*
$response = curl_exec($ch);
if (curl_errno($ch)) {
    throw new \RuntimeException('Curl error #'. curl_errno($ch) . ': ' .curl_error($ch));
}
$requestInfo = curl_getinfo($ch);
$responseBody = substr($response, $requestInfo['header_size']);
$responseHeaders = substr($response, 0, $requestInfo['header_size']);
// TODO: записать в лог выполненный запрос с полным $requestInfo, $responseBody и $responseHeaders
// TODO: проверить $requestInfo['http_code'] согласно документации API. >=500 явно ошибка, остальные смотреть документацию что должны отвечать
$decodedResponse = json_decode($responseBody);
if (is_null($decodedResponse)) {
    throw new \RuntimeException('response is not JSON');
}
// TODO: проверить декодированную структуру на наличие необходимых элементов
READ ALSO
Регулярка php preg_match table + class

Регулярка php preg_match table + class

Здравствуйте, требуется помощь в написание регулярки для PHP preg_match, нужно вытащить весь текст вместе с тегами (<table>), которые имеют определенный...

235
Передача параметров по кнопке в php

Передача параметров по кнопке в php

На сайте имеется компонент тестирования AriQuizВо время тестирования на вопросы можно отвечать, или пропускать(чтобы ответить позже)

270
Проверить активность соединения

Проверить активность соединения

Есть два Инет-провайдеракоторые "отваливаются" с непредсказуемой периодичностью

209
Как к элементу массива, присвоить данные с поля?

Как к элементу массива, присвоить данные с поля?

Как к элементу массива UserName, присвоить данные с input type="text"?

195