Интеграция платёжной системы Тинькофф Кассы на сайт
Тинькофф Касса — один из наиболее распространённых платёжных шлюзов на российском рынке. Поддерживает карты Visa, Mastercard, МИР, СБП, Apple Pay, Google Pay и рассрочку через «Тинькофф Рассрочку». Официальный SDK есть для PHP, Java, .NET, Python и Node.js, но большинство интеграций делается напрямую через REST API.
Подключение и получение доступов
Для работы нужны два ключа: TerminalKey и Password. Получить их можно в личном кабинете Тинькофф Бизнес — раздел «Приём платежей» → «Терминалы». Там же настраивается уведомление об оплате (webhook URL) и список разрешённых IP для нотификаций.
Тестовая среда: https://rest-api-test.tinkoff.ru/v2/
Боевая среда: https://securepay.tinkoff.ru/v2/
Переключение между ними — только через TerminalKey: тестовые ключи начинаются с TinkoffBankTest.
Создание заказа и инициализация платежа
Платёж инициируется через метод Init. Базовый запрос:
$params = [
'TerminalKey' => env('TINKOFF_TERMINAL_KEY'),
'Amount' => 150000, // в копейках
'OrderId' => 'order-12345',
'Description' => 'Заказ #12345',
'NotificationURL' => 'https://example.com/webhook/tinkoff',
'SuccessURL' => 'https://example.com/payment/success',
'FailURL' => 'https://example.com/payment/fail',
];
// Добавляем токен
ksort($params);
$tokenStr = implode('', array_values($params)) . env('TINKOFF_PASSWORD');
$params['Token'] = hash('sha256', $tokenStr);
$response = Http::post('https://securepay.tinkoff.ru/v2/Init', $params);
$paymentUrl = $response->json('PaymentURL');
Важный момент с токеном: он считается по конкатенации отсортированных по алфавиту значений (не ключей) плюс пароль. Ошибки в генерации токена — самая частая проблема при интеграции.
После получения PaymentURL покупатель перенаправляется на страницу Тинькофф. Весь UI оплаты — на их стороне.
Webhook и проверка статуса
После оплаты Тинькофф отправляет POST на NotificationURL с данными в формате application/x-www-form-urlencoded:
public function handleWebhook(Request $request): JsonResponse
{
$data = $request->all();
// Проверяем токен
$received = $data['Token'];
$checkData = $data;
unset($checkData['Token']);
ksort($checkData);
$expected = hash('sha256', implode('', array_values($checkData)) . env('TINKOFF_PASSWORD'));
if (!hash_equals($expected, $received)) {
return response()->json(['error' => 'Invalid token'], 403);
}
if ($data['Status'] === 'CONFIRMED') {
Order::where('id', $data['OrderId'])->update(['status' => 'paid']);
// отправить чек, запустить логику доставки
}
return response()->json(['OK' => true]);
}
Статусы, которые нужно обрабатывать: AUTHORIZED (заморожены средства), CONFIRMED (деньги списаны), REJECTED, REFUNDED, PARTIAL_REFUNDED, CANCELED.
Дополнительная защита — проверка IP отправителя. Тинькофф публикует список своих IP в документации, можно фильтровать на уровне nginx или middleware.
Фискализация через ФФД 1.2
Если бизнес обязан пробивать чеки (54-ФЗ), в запрос Init передаётся объект Receipt:
'Receipt' => [
'Email' => '[email protected]',
'Taxation' => 'usn_income',
'Items' => [
[
'Name' => 'Товар 1',
'Price' => 100000, // в копейках
'Quantity' => 1.0,
'Amount' => 100000,
'Tax' => 'none',
'PaymentMethod' => 'full_payment',
'PaymentObject' => 'commodity',
],
],
],
Фискализация выполняется Тинькофф автоматически — подключать собственную онлайн-кассу не нужно. Чек уходит на email или телефон покупателя.
Возвраты
Возврат через метод Cancel:
$params = [
'TerminalKey' => env('TINKOFF_TERMINAL_KEY'),
'PaymentId' => '12345678',
'Amount' => 75000, // частичный возврат
];
// добавить Token по той же схеме
Http::post('https://securepay.tinkoff.ru/v2/Cancel', $params);
Полный возврат — передать Amount равным сумме заказа или не передавать вовсе.
Сроки и особенности
Тестирование и сдача интеграции у Тинькофф занимает около 2–3 рабочих дней: нужно провести несколько тестовых транзакций, после чего менеджер активирует боевой терминал. Для фискализации срок увеличивается: нужно согласовать настройки кассы. На практике полный цикл от получения доступов до первого реального платежа — 5–7 рабочих дней.







