Создание категории через api

Здравствуйте!

Пытаюсь создать новую категорию через API:


data = {}
data["name"] = u"Мини камеры видеонаблюдения"
data["url"] = "shpionskie-mini-kamery-videonablyudeniya"
data["description"] = u"Контроль за поведением сотрудников или ребенка, а также защиту от злоумышленников отлично обеспечивают миникамеры. Сфера применения этих компактных устройств достаточно широка, а их небольшие размеры позволяют легко скрыть их в деталях интерьера. Есть модели с креплением – они размещаются в любых местах, даже на одежде или вертикальной поверхности."
data["include_sub_categories"] = "1"
data["status"] = "1"

headers = {  'Content-Type': 'application/json',
            'Accept': 'application/json',
'Authorization': self.access_token}
url = "http://*.*.*.*/webasyst/api.php/shop.category.add"
result = requests.post(url, json = data, headers=headers)

Получаю ответ:

{"error":"invalid_param","error_description":"Required parameter is missing: name"}

Как выяснилось, приложение не получает параметры, передаваемые в POST-запросах (хотя на этом же сервере API другой платформы работает прекрасно).. Подскажите, пожалуйста, в чем может быть проблема? 

1 ответ

  • 1
    EnsoStudio 8 июля 2021 01:40 #
    • access_token GET

      Токен авторизации, полученный при подкючении к API.


    • +1
      pitekantrop pitekantrop 8 июля 2021 10:22 #

      Не понял ваш комментарий.. Проблема не с авторизацией, а с тем, что сервер не получает параметры, передаваемые в post-запросах..

      • +1
        Алексей Алексей Webasyst 8 июля 2021 10:50 #

        Посмотрите описание метода https://developers.webasyst.ru...
        токен требуется отправить как GET запрос, POST игнорируется.

        • +1
          pitekantrop pitekantrop 8 июля 2021 11:45 #

          Уже проверено: токен принимается как в заголовке, так и через get-запрос. Сначала отправлял токен через post-запрос - была ошибка 

          {"error":"invalid_request","error_description":"Required parameter is missing: access_token"}

          После добавления в заголовок/get-запрос стала возвращаться ошибка 

          {"error":"invalid_param","error_description":"Required parameter is missing: name"}

          Т.е. налицо неполучение приложением параметров из post-запросов.

          • +1
            Николай Иванов Николай Иванов 8 июля 2021 16:43 #

            Есть мнение что у вас  ни один POST-параметр не долетает до API.
            Может у вас какой-нибудь редирект срабатывает?

        • +1
          EnsoStudio EnsoStudio 11 июля 2021 14:46 #

          добавьте в ошибки описание к "invalid_request"

      • +1
        EnsoStudio EnsoStudio 8 июля 2021 18:19 #

        передача токена в заголовке не документирована, видимо Вы передаете данные не json'ом. сбросьте curl/http запрос которые передается методом requests.post()

        • +1
          pitekantrop pitekantrop 8 июля 2021 21:03 #

          Судя по следующему коду, заголовки все-таки проверяются:

          $token = waRequest::request('access_token', null, 'string');
                  if (!$token) {
                      if (function_exists('getallheaders')) {
                          $headers = getallheaders();
                          $token = ifset($headers, 'Authorization', null);
                      }
                      if (!$token) {
                          $token = waRequest::server('HTTP_AUTHORIZATION', null, 'string');
                      }
                      if ($token) {
                          $token = preg_replace('~^(Bearer\s)~ui', '', $token);
                      }
                  }
                  if (!$token) {
                      throw new waAPIException('invalid_request', 'Required parameter is missing: access_token', 400);
                  }

          Параметры отправляются верные:

          print result.request.body
          {"status": "0", "name": "test", "url": "test", "include_sub_categories": "1", "parent_id": 0, "description": "test"}
          
          print result.request.headers
          {'Content-Length': '116', 'Accept-Encoding': 'gzip, deflate', 'Accept': '*/*', 'User-Agent': 'python-requests/2.22.0', 'Connection': 'keep-alive', 'Content-Type': 'application/json'}

          Много раз приходилось иметь дело с разным api, но с такой ситуацией сталкиваюсь впервые, поэтому даже не знаю, куда копать..

          • +1
            EnsoStudio EnsoStudio 8 июля 2021 22:51 #
            Судя по следующему коду, заголовки все-таки проверяются

            я не говорю что это не работает, просто рекомендуемый вариант:

            $token = waRequest::request('access_token', null, 'string');

            в каком формате передаются post данные? тело запроса должно содержать строку с данными в формате

            Content-Type: application/x-www-form-urlencoded

            сложно посоветовать что-то конкретное - я не то что кода requests не видел, но даже в языке не уверен, поэтому и написал

            сбросьте curl/http запрос который передает метод requests.post()

        • +1
          pitekantrop pitekantrop 8 июля 2021 21:20 #

          Выяснилось, что дело не в настройках моего сервера: при отправке того же запроса на облачный сервер возвращается та же ошибка..

          • +1
            Николай Иванов Николай Иванов 9 июля 2021 12:46 #

            Слехка поэксперементировал с api/json/post.
            У меня получается, что при

            $data = array( 'access_token' => 'asdasd245jjfcsdga0r10945u', 'aaa' => 'ooo' ); $payload = json_encode($data); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); 

            Данные POST до сервера не долетают. Почему, я не стал выяснять.
            Если передавать обычный массив

            curl_setopt($ch, CURLOPT_POSTFIELDS, $data); 

            и убрать заголовок

            curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type:application/json')); 

            то POST-данные в api прилетают. Но там дальше есть одна "затычка" в виде

            $method = new $class_name(); $this->response($method->getResponse()); 

            И дальше, в wa-system/api/waAPIMethod.class.php смотрим getResponse()

                protected $method = 'GET';    .....    public function getResponse($internal = false)    {        if (!$internal) {            // check request method            $request_method = strtoupper(waRequest::method());            if ((is_array($this->method) && !in_array($request_method, $this->method)) ||                (!is_array($this->method) && $request_method != $this->method)            ) {                throw new waAPIException('invalid_request', 'Method '.$request_method.' not allowed', 405);            }        }         $this->execute();        return $this->response;    }

            Из-за чего получаем уже другую ошибку.

            '{    "error": "invalid_request",    "error_description": "Method POST not allowed" }'  


            Таким образом, фраза в документации

            Безопасный способ передачи токена авторизации Для того чтобы исключить отслеживание токена по URL запросов, передавайте его в составе POST-запроса в поле access_token. В этом случае формируйте URL запроса без использования этого значения:

            является не верной?
            И речь идёт о передаче access_token в заголовке? Или возможность передачи через POST сделали, но забыли убрать запрет на сам POST в api?

            Это уже к webasyst вопросы. Дальше у ковырять не буду.

            • +1
              EnsoStudio EnsoStudio 9 июля 2021 13:08 #

              свойство method переопределяется в классах api методов, у меня в комменте ошибка - данные должны передавать не как application/json, а application/x-www-form-urlencoded

            • +1
              pitekantrop pitekantrop 10 июля 2021 09:56 #

              При передаче обычным массивом работает, спасибо!

Добавить ответ

Чтобы добавить комментарий, зарегистрируйтесь или войдите