alibek Posted March 21 Posted March 21 Переделываю ботов на Макс. Почти все сделал, но столкнулся со странной проблемой. Не работает редактирование сообщений (PUT messages) и их закрепление (PUT chats/{$chat}/pin). На своей стороне делаю следующее: 1. Задаю заголовок Content-Type: application/json; charset=utf-8 2. Для POST-запросов (которые работают) задаю опции CURLOPT_POST и затем CURLOPT_POSTFIELDS, в которую передаю параметры (закодированные json_encode). Для PUT-запросов вначале задаю CURLOPT_CUSTOMREQUEST (с указанием PUT), затем CURLOPT_POSTFIELDS (с параметрами, закодированными json_encode), затем добавляю заголовок Content-Length. 3. Затем выполняю запрос. Но вместо выполнения сервер Макса сообщает, что "No access token", хотя токен я передаю. Если для curl включить отладку, то получается странное: * Host platform-api.max.ru:443 was resolved. ... * using HTTP/2 * [HTTP/2] [1] OPENED stream for https://platform-api.max.ru/messages?message_id=mid.*** * [HTTP/2] [1] [:method: PUT] * [HTTP/2] [1] [:scheme: https] * [HTTP/2] [1] [:authority: platform-api.max.ru] * [HTTP/2] [1] [:path: /messages?message_id=mid.***] * [HTTP/2] [1] [accept: */*] * [HTTP/2] [1] [content-length: 14] * [HTTP/2] [1] [content-type: application/x-www-form-urlencoded] > PUT /messages?message_id=mid.*** HTTP/2 Host: platform-api.max.ru Accept: */* Content-Length: 14 Content-Type: application/x-www-form-urlencoded * old SSL session ID is stale, removing < HTTP/2 401 < server: kittenx < date: Sat, 21 Mar 2026 11:12:49 GMT < content-type: application/json; charset=utf-8 < content-length: 51 < cache-control: no-cache < strict-transport-security: max-age=2592000;includeSubdomains < * Connection #0 to host platform-api.max.ru left intact Смущают две вещи. Во-первых, тип почему-то "application/x-www-form-urlencoded", хотя я задаю правильный тип: if (isset($data)) { curl_setopt($this->curl, CURLOPT_POSTFIELDS, $data); curl_setopt($this->curl, CURLOPT_HTTPHEADER, ["Content-Length: " . strlen($data)]); } curl_setopt($this->curl, CURLOPT_CUSTOMREQUEST, $method); И судя по наличию и значение заголовка Content-Length — этот код выполняется. Во-вторых, в отладочном выводе почему-то нет тела запроса. Или в отладке он просто не выводится, или при указании CURLOPT_CUSTOMREQUEST запрос изменяется. Никто с таким не сталкивался? Вот отладочный вывод POST-запроса: * Host platform-api.max.ru:443 was resolved. ... * using HTTP/2 * [HTTP/2] [1] OPENED stream for https://platform-api.max.ru/messages?chat_id=-*** * [HTTP/2] [1] [:method: POST] * [HTTP/2] [1] [:scheme: https] * [HTTP/2] [1] [:authority: platform-api.max.ru] * [HTTP/2] [1] [:path: /messages?chat_id=-***] * [HTTP/2] [1] [accept: */*] * [HTTP/2] [1] [authorization: ***] * [HTTP/2] [1] [content-type: application/json; charset=utf-8] * [HTTP/2] [1] [content-length: 438] > POST /messages?chat_id=-*** HTTP/2 Host: platform-api.max.ru Accept: */* Authorization: *** Content-Type: application/json; charset=utf-8 Content-Length: 438 * old SSL session ID is stale, removing < HTTP/2 200 < server: kittenx < date: Sat, 21 Mar 2026 11:26:27 GMT < content-type: application/json; charset=utf-8 < content-length: 1088 < vary: Accept-Encoding < cache-control: no-cache < strict-transport-security: max-age=2592000;includeSubdomains < * Connection #0 to host platform-api.max.ru left intact Судя по нему — тело запроса в отладку не выводится. Но в нем, в отличии от предыдущих запросов — все заголовки передаются нормально. Пробовал вначале задать тип запроса, а затем все остальное — ничего не поменялось. Вставить ник Quote
alibek Posted March 21 Author Posted March 21 В общем, похоже какой-то баг в cURL. После установки CURLOPT_CUSTOMREQUEST часть данных в запросе сбрасывается. Продублировал установку заголовков непосредственно перед вызовом curl_exec — и запрос выполнился нормально. Вставить ник Quote
TimberLike Posted August 25 Posted August 25 Это не похоже на баг cURL. Скорее всего, где-то раньше при настройке этого же handle задаётся CURLOPT_HTTPHEADER, и при повторной настройке он заменяется. Важный момент: CURLOPT_HTTPHEADER не дополняет существующий список заголовков, а устанавливает его заново. Поэтому вот это: curl_setopt($this->curl, CURLOPT_HTTPHEADER, ["Content-Length: " . strlen($data)]); фактически выбрасывает ранее заданный Content-Type и Authorization. В результате cURL, видя CURLOPT_POSTFIELDS, сам подставляет Content-Type: application/x-www-form-urlencoded. То, что после повторной установки всех заголовков непосредственно перед curl_exec() всё заработало, как раз хорошо это подтверждает. Я бы сделал установку всех заголовков в одном месте, например: curl_setopt($curl, CURLOPT_HTTPHEADER, [ 'Authorization: ' . $token, 'Content-Type: application/json; charset=utf-8', 'Content-Length: ' . strlen($data), ]); А Content-Length вообще можно не задавать вручную — при передаче строки через CURLOPT_POSTFIELDS cURL сам корректно сформирует его. Отсутствие тела в CURLOPT_VERBOSE тоже само по себе ничего не доказывает: verbose-вывод cURL не обязан показывать содержимое тела запроса. Вставить ник Quote
murano Posted August 27 Posted August 27 function apiRequest($method, $url, $data = null) { $curl = curl_init(); // Базовые настройки curl_setopt($curl, CURLOPT_URL, $url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); curl_setopt($curl, CURLOPT_HEADER, false); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); $headers = [ 'Authorization: Bearer YOUR_TOKEN_HERE', 'Content-Type: application/json; charset=utf-8' ]; if ($method === 'POST') { curl_setopt($curl, CURLOPT_POST, true); if ($data) { $jsonData = json_encode($data); curl_setopt($curl, CURLOPT_POSTFIELDS, $jsonData); $headers[] = 'Content-Length: ' . strlen($jsonData); } } elseif ($method === 'PUT') { curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'PUT'); if ($data) { $jsonData = json_encode($data); curl_setopt($curl, CURLOPT_POSTFIELDS, $jsonData); $headers[] = 'Content-Length: ' . strlen($jsonData); } } curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); // curl_setopt($curl, CURLOPT_VERBOSE, true); $response = curl_exec($curl); $info = curl_getinfo($curl); curl_close($curl); return [ 'response' => $response, 'info' => $info ]; } Пример использования: $result = apiRequest('PUT', 'https://platform-api.max.ru/messages?message_id=mid.***', [ 'text' => 'Новый текст сообщения' ]); Вставить ник Quote
zander Posted August 29 Posted August 29 Btw: max api требует хедер Authorization без Bearer, сразу Authorization: 'tokenXXXXyyyy' Вставить ник Quote
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.