Ошибка 204 Tinkoff: неверный токен - причины и исправление
Разработчики, интегрирующие платёжный сервис Тинькофф, нередко сталкиваются с ошибкой ErrorCode: '204' и сообщением «Неверный токен. Проверьте пару TerminalKey/SecretKey». Это означает, что запрос к API сформирован некорректно - скорее всего, неправильно вычислен токен (подпись). В этой статье мы разберём, как правильно генерировать токен для запроса проверки статуса платежа, и исправим типичную ошибку в коде на Python с библиотекой aiohttp.
Почему возникает ошибка 204
Код 204 в ответе Tinkoff API указывает на то, что переданный параметр Token не совпадает с тем, который ожидает сервер. Токен - это SHA-256 хеш от конкатенации значений всех параметров запроса, отсортированных в алфавитном порядке, с добавлением секретного ключа (SecretKey). Ошибка чаще всего возникает, если:
- Неправильно собран набор полей для хеширования;
- Не учитываются все обязательные параметры запроса;
- Используется неверный SecretKey или TerminalKey;
- Порядок конкатенации не соответствует алфавитному.
Как правильно генерировать токен по документации
Согласно официальной документации Тинькофф, для формирования токена необходимо:
- Выбрать все параметры JSON-запроса, исключая сам
Token; - Отсортировать их ключи в алфавитном порядке;
- Склеить значения этих параметров (без ключей) в строку;
- Добавить в конец строки SecretKey;
- Вычислить SHA-256 хеш от полученной строки (в нижнем регистре).
Важно: все значения должны быть строками. Если значение имеет тип int или float, его нужно привести к строке.
Исправляем код проверки статуса платежа
В исходном примере токен формировался как passwordd + str(order_id) + Ter_key. Это неверно по нескольким причинам:
- Параметр
TerminalKeyне включён в хеш, хотя он обязателен; - Отсутствует сортировка ключей;
- Вместо
SecretKeyиспользуетсяpasswordd(возможно, опечатка).
Исправленный вариант функции на Python с использованием библиотеки hashlib:
import hashlib
import json
def generate_token(params: dict, secret_key: str) -> str:
# Убираем Token из словаря
params.pop('Token', None)
# Сортируем ключи по алфавиту
sorted_keys = sorted(params.keys())
# Склеиваем значения
concatenated = ''.join(str(params[k]) for k in sorted_keys)
# Добавляем SecretKey
data = concatenated + secret_key
# SHA-256 хеш
return hashlib.sha256(data.encode('utf-8')).hexdigest()
async def check_payment_status(order_id: int):
params = {
"TerminalKey": Ter_key,
"PaymentId": order_id
}
params['Token'] = generate_token(params, secret_key)
async with aiohttp.ClientSession() as session:
async with session.post(TINKOFF_API_URL_get, json=params) as response:
data = await response.json()
if data.get("Success"):
return data.get("Status")
else:
return NoneОбратите внимание: secret_key - это строка из личного кабинета Тинькофф, не путайте с TerminalKey. В приведённом примере мы корректно сортируем ключи (PaymentId, TerminalKey) и добавляем секретный ключ в конец.
Дополнительные рекомендации
Если ошибка 204 продолжает появляться:
- Проверьте, что
TerminalKeyиSecretKeyсоответствуют друг другу (например, не перепутаны кавычки или лишние пробелы); - Убедитесь, что
PaymentIdпередан как строка, а не число - в некоторых версиях API это имеет значение; - Протестируйте запрос через Postman или curl, чтобы изолировать проблему от кода.