Как сделать запрос 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 шт):

Автор решения: Artem S. Zhelonkin

Предлагаю попробовать следующее:

  1. Не приводить к str timestamp, а подавать его в int в body, а затем приводить словарь в json строку (при этом использовать round для округления):
timestamp = round(datetime.timestamp(datetime.now()))
body = {"timestamp": timestamp}
body = json.dumps(body)
  1. Перевести в байтовые строки значения тела запроса и ключа и конкатенировать их при передаче в 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()
  1. Добавить заголовок Content-Type:
headers = {
    "Authorization": h,
    "Content-Type": "application/json"
}
  1. В качестве аргумента для тела запроса использовать json=body, а также отдельно проверить с 'data=body'.
  2. Добавить 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)

Возможно более точный ответ я смогу дать, если будет информация о получаемой ошибке. Но всё же надеюсь, что мой текущий ответ будет полезен.

→ Ссылка