Как сделать запрос requests?
Я работаю с API, но не понимаю, как правильно составить запрос.
В документации нет определенных данных, поэтому мне дали копипасту кода (ниже)
Документация: https://taxicrm.ru/doc/taxicrm_public_api
Главные моменты:
При обращении к любым интерфейсам данного API в теле запроса всегда должен присутствовать обязательный параметр timestamp, содержащий в себе метку времени, когда запрос к публичному API taxiCRM был создан.
Все запросы к публичному API должны быть подписаны с помощью API ключа
Формирование подписи запросов
Подпись запроса необходимо передавать в заголовках запроса в параметре Authorization
Пример:
Authorization: 0ed9166cbb3595ec9bdaf4cbb79b94196d8d8be5
Сама подпись является sha1 хешем полученной из конкатенированной строки,
содержащей в себе: «json представление тела запроса» + «API ключ»
Вот мой код:
import requests, json, hashlib
from datetime import datetime
url ='Нужный url'
key = "Мой ключ"
timestamp = str(int(datetime.timestamp(datetime.now())))
body = {'timestamp': timestamp}
json_key = json.dumps(body)+key
h = hashlib.sha1(json_key.encode('utf-8')).hexdigest()
headers = {'Authorization': h}
req = requests.post(url, headers=headers, data=body)
try:
resp = req.json()
except Exception as e:
print(e)
resp = None
print(resp)
Так же мне дали копипасту кода для лучшего понимания и написали это:
Берем апи, сервак, диапазон дат (откуда до куда нужна информация).
Функция получения самих дат.
$url_car_transaction - эту ссылку меняете на нужную (смотря что вам надо получить).
Далее перебираем дни и на каждый день делаем запрос на получение данных.
далее 'курл'
и потом обработка фактических данных.
<?php
include('config.php');
$key = $_POST['api'];
$server = $_POST['server'];
$date_start = $_POST['date_start'];
$date_stop = $_POST['date_stop'];
function getDates($startTime, $endTime)
{
$day = 86400;
$format = 'Y-m-d';
$startTime = strtotime($startTime);
$endTime = strtotime($endTime);
# $numDays = round(($endTime - $startTime) / $day); // без +1
$numDays = round(($endTime - $startTime) / $day) + 1;
$days = array();
for ($i = '0'; $i < $numDays; $i++) {
$days[] = date($format, ($startTime + ($i * $day)));
}
return $days;
}
# Берем все даты на загрузку (в днях)
$days = getDates($date_start, $date_stop);
$url_car_transaction = "https://".$server.".taxicrm.ru/api/public/v1/car/transaction/list";
# Перебор массива всех дней
foreach ($days AS $day)
{
$method = "POST";
$post_data = [
"timestamp" => time(),
"filters" => [
"date_start" => $day,
"time_start" => "00:00:00",
"date_end" => $day,
"time_end" => "23:59:59",
]
];
$data_json = json_encode($post_data);
$curl = curl_init();
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 2);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($curl, CURLOPT_POST, true);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data_json);
curl_setopt($curl, CURLOPT_HTTPHEADER, array(
'Authorization: '. sha1($data_json . $key),
'Content-Type:application/json'
));
curl_setopt($curl, CURLOPT_URL, $url_car_transaction);
$html = html_entity_decode(curl_exec($curl), ENT_HTML401, 'UTF-8');
$array = json_decode($html);
curl_close($curl);
foreach ($array->{"transactions_list"} as $line)
{
// добавляем транзакции в базу
$sql = "INSERT INTO `***`
(`***`, `***`, `***`, ... `***`) VALUES
('".$line->{"transaction_id"}."', ... '".$line->{"car_id"}."')";
mysqli_query($conn, $sql);
}
}
?>
Ответы (1 шт):
Предлагаю попробовать следующее:
- Не приводить к str timestamp, а подавать его в int в body, а затем приводить словарь в json строку (при этом использовать round для округления):
timestamp = round(datetime.timestamp(datetime.now()))
body = {"timestamp": timestamp}
body = json.dumps(body)
- Перевести в байтовые строки значения тела запроса и ключа и конкатенировать их при передаче в sha1:
raw_body_data = bytes(body, encoding='utf-8')
raw_key = bytes(key, encoding='utf-8')
h = hashlib.sha1(raw_body_data+raw_key).hexdigest()
- Добавить заголовок Content-Type:
headers = {
"Authorization": h,
"Content-Type": "application/json"
}
- В качестве аргумента для тела запроса использовать
json=body, а также отдельно проверить с 'data=body'. - Добавить timeout (возможно будет полезно в будущем) и сформировать запрос в следующем виде:
response = requests.request("POST",
url,
headers=headers,
json=body,
timeout=120)
Если будет ошибка, то посмотреть тело ответа, например, через обычный print(response.text) или print(response.json), либо логгер, если он используется. В итоге получится следующий запрос:
import requests, json, hashlib
from datetime import datetime
url ='your_url'
key = "key_value"
timestamp = round(datetime.timestamp(datetime.now()))
body = {"timestamp": timestamp}
body = json.dumps(body)
raw_body_data = bytes(body, encoding='utf-8')
raw_key = bytes(key, encoding='utf-8')
h = hashlib.sha1(raw_body_data+raw_key).hexdigest()
headers = {
"Authorization": h,
"Content-Type": "application/json"
}
response = requests.request("POST",
url,
headers=headers,
json=body,
timeout=120)
print(response.text)
Возможно более точный ответ я смогу дать, если будет информация о получаемой ошибке. Но всё же надеюсь, что мой текущий ответ будет полезен.