Как отформатировать полезную нагрузку для Kartra API в Python

#python #php #api #curl #python-requests

#python #php #API #curl #python-запросы

Вопрос:

Итак, я пытаюсь вызвать API post для этого входящего API Kartra, используя Python requests.post. Вот мой код на Python:

  payload = { 
    'api_key': settings.KARTRA_API_KEY,
    'api_password': settings.KARTRA_API_PASSWORD,
    'app_id': settings.KARTRA_APP_ID,
    'lead': {
        'email': 'joe@joe.com',
        'first_name': 'Joseph',
        'last_name': 'Smith'
    },
    'actions': {
        '0': {'cmd': 'search_lead'}
    }
}
url = settings.KARTRA_API_URL
response = requests.post(url, data=payload)
  

Единственный пример, которому я должен следовать, — это PHP (с которым я не работал). Это выглядит так:

 curl_setopt($ch, CURLOPT_POSTFIELDS,
http_build_query(
    array(
        'app_id' => 'AIm863DwsOW',
        'api_key' => 'QG9GPLW8G',
        'api_password' => 'kdwFAfwrfVS',
        'lead' => array(
            'id' => '3232323223', //you may pass either ID or EMAIL. If both, the system will pick ID
            'email' => 'JoeSmith@domain.com',     
        ),
        'actions' => array(
            '0' => array(
                   'cmd' => 'search_lead',
             ),
        )
  )
  

)
);

Все, что я могу получить, это ошибка, подобная этой:

 {"status":"Error","message":"'actions' not an array","type":"224"}
  

Я проверил, что мои ключи и токены, похоже, работают правильно.

Я перепробовал все, что мог придумать, чтобы заставить конечную точку интерпретировать «действия» как массив. Может кто-нибудь, пожалуйста, просветите меня?? ОЧЕНЬ признателен, поскольку я потратил буквально часы, возясь с этим.

Комментарии:

1. Итак, для всех, кто может это увидеть… Я много общался с командой «поддержки» из Kartra, и все, что я получаю, это ссылки на неадекватные документы, которые я уже прочитал, и снисходительные лекции о том, что я несу ответственность за то, чтобы заставить мой собственный код работать! Без шуток? Спасибо, вы были полезны. Они указали, что мое электронное письмо для приведенного выше руководства должно заканчиваться на @kartra.com в тестовом режиме. Попробовал это, и ошибка была той же.

Ответ №1:

Как я уже говорил в комментариях, поддержка Kartra не помогла. Soo… Я взял пример PHP и отправил его в https://httpbin.org/post чтобы выяснить, что на самом деле было отправлено. Это само по себе было откровением (никогда не знал о подобных инструментах).

Вот ссылка на пример в PHP: https://documentation.kartra.com/section-28-php-sample-creating-a-lead /

Вот что на самом деле отправляется в api:

 {
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "actions[0][cmd]": "create_lead", 
    "actions[1][cmd]": "assign_tag", 
    "actions[1][tag_name]": "My customer", 
    "api_key": "QG9GPLW8G", 
    "api_password": "kdwFAfwrfVS", 
    "app_id": "AIm863DwsOW", 
    "lead[custom_fields][0][field_identifier]": "text1", 
    "lead[custom_fields][0][field_value]": "text message", 
    "lead[custom_fields][1][field_identifier]": "dropdown1", 
    "lead[custom_fields][1][field_value]": "612", 
    "lead[custom_fields][2][field_identifier]": "checkbox1", 
    "lead[custom_fields][2][field_value][0]": "620", 
    "lead[custom_fields][2][field_value][1]": "621", 
    "lead[email]": "JoeSmith@domain.com", 
    "lead[first_name]": "Joe", 
    "lead[last_name]": "Smith"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Content-Length": "678", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "X-Amzn-Trace-Id": "Root=1-5f77604a-7b5fee841e85d78f6b352133"
  }, 
  "json": null, 
  "origin": "104.14.117.45", 
  "url": "https://httpbin.org/post"
}
  

Вот фактический рабочий код Python для теста:

 payload = { 
    'api_key': settings.KARTRA_API_KEY,
    'api_password': settings.KARTRA_API_PASSWORD,
    'app_id': settings.KARTRA_APP_ID,
    'lead[email]': 'joe@kartra.com',
    'lead[first_name]': 'Joe',
    'lead[last_name]': 'Smith',
    'actions[0][cmd]': 'create_lead',
}

url = settings.KARTRA_API_URL
response = requests.post(url, data=payload)
  

Еще один момент, который я узнал из этого, заключается в том, что библиотека requests.post() не выполняет глубокую копию ниже второго уровня Python dict of dicts of dicts. Подробнее см. Мой первоначальный вопрос…

Я искренне надеюсь, что это поможет кому-то избежать боли, через которую мне пришлось пройти, чтобы разобраться в этом. По общему признанию, было бы проще, если бы я знал больше о Python, HTTP и PHP и не пытался избежать использования PHP для тестирования кода примера. Живи и учись!

Комментарии:

1. Это было чрезвычайно полезно, я пару дней бился головой о стол, спасибо!

2. С удовольствием. Мне потребовалось буквально пару дней, чтобы разобраться. Я был готов кричать. Рад, что смог помочь.

Ответ №2:

Этот PHP-код:

        'actions' => array(
            '0' => array(
                   'cmd' => 'search_lead',
             ),
  

Может интерпретироваться как list или dict , вы можете попытаться «перевести» бит PHP в это:

 'actions': [
    {
        'cmd': 'search_lead'
    }
]
  

редактировать:.
Что, если вы попробуете:

 'actions': [
    {
        0: {'cmd': 'search_lead'}
    }
]
  

Комментарии:

1. Спасибо за попытку помочь. Попробовал и точно такой же результат. Если я посмотрю на ‘0’, похоже, что они требуют его в качестве ключа к массиву. Я ожидал другого ответа от API, основанного на вашем предложении. Точно так же.

2. добавлена еще одна попытка в этом посте @BillHuang

3. Никакой радости. Я пробовал все это. Даже не могу заставить его работать в Postman с помощью []. Понятия не имею, чего они здесь хотят. Никаких документов, которые помогли бы. Еще раз спасибо за попытку. Мои исследования показывают, что CURL хочет urlencode все. Тоже пробовал. Они обрабатывают поступающий JSON или urlencoded как атаку и блокируют ее.

4. хорошо, извините, я не очень помогаю, возможно, стоит попробовать urlencode полезной нагрузки. но что, если вы попытаетесь использовать json параметр в requests.post методе? response = requests.post(url, json=payload)

5. Пробовал оба из них. Никакой радости. Ждем ответа от их службы поддержки. Обновит поток, когда я взломаю это! Еще раз спасибо.

Ответ №3:

Если ошибка проста, как 'actions' not an array тогда, это может означать только одно — actions aren't given as an array . В Python массивы заключаются [] в квадратные скобки, а {} для структуры данных используются фигурные скобки dictionary .

Простое изменение части actions в виде массива должно решить проблему

 'actions': [
    {
        0: {'cmd': 'search_lead'}
    }
]
  

Подробный API также объясняет причину ошибки здесь.

Комментарии:

1. Спасибо за ответ. Во-первых, недопустимый синтаксис Python, поэтому он не будет запускаться. Во-вторых, я посмотрел на страницу, на которую ссылается ссылка, и все, что там сказано, это то, что элемент не является массивом. Это точное повторение фактического сообщения об ошибке.