> Источник: https://apipay.kz/guides/bezopasnost-integratsii-cheklist · Обновлено: 2026-08-26 · apipay.kz
> ApiPay — независимый сервис приёма платежей поверх вашего Kaspi Pay.

# Чек-лист безопасности интеграции ApiPay

**TL;DR.** Безопасная интеграция держится на четырёх вещах: API-ключ живёт **только на сервере** (никогда в браузере, боте-клиенте или репозитории), входящие вебхуки проверяются **подписью по сырому телу запроса** (`X-Webhook-Signature: sha256=<hex>`), одинаковые запросы защищены **идемпотентностью** (`external_order_id_idempotency` → 409 на дубль, пока прежний счёт жив), а секреты вы **сохраняете один раз при создании** и ротируете при утечке. Ниже — 12 пунктов: у каждого «зачем» и «как проверить у себя». Смена API-ключа и смена секрета подписи — **две разные операции**: перегенерация ключа вебхук-секрет не трогает.

## 1. API-ключ — только на сервере

**Зачем.** `X-API-Key` даёт право создавать счета от имени вашей организации, а при включённом флаге — управлять кассирами. Попав в браузер, публичный репозиторий или клиентскую часть Telegram-бота, ключ становится доступен любому.

**Как проверить.** Прогоните `git grep` по значению ключа во всей истории репозитория; убедитесь, что `.env` в `.gitignore`; откройте DevTools на своём сайте и проверьте, что в сетевых запросах фронтенда нет заголовка `X-API-Key` — запрос в ApiPay должен уходить **с вашего бэкенда**, а не из браузера покупателя.

## 2. Проверяйте подпись вебхука по сырому телу

**Зачем.** Без проверки подписи любой, кто узнал ваш webhook URL, пришлёт фейковое «счёт оплачен». Подпись — единственная гарантия, что уведомление действительно от ApiPay.

**Как проверить.** Считайте HMAC до того, как фреймворк распарсит и пересоберёт JSON: перестановка полей или пробелы изменят байты и сломают сверку. Формула и примеры кода — в статье «[Настройка вебхуков ApiPay](/guides/nastroyka-webhookov-apipay)». Нажмите в кабинете «Проверить уведомления» на карточке ключа — придёт тестовое событие с боевой подписью; убедитесь, что ваш обработчик её принял.

## 3. Не путайте API-ключ и секрет подписи

**Зачем.** Это две разные строки с разными ролями. **API-ключ** (`X-API-Key`) — в заголовке ваших **исходящих** запросов к ApiPay. **Секрет подписи вебхука** (webhook secret) — для проверки **входящих** уведомлений (`X-Webhook-Signature`). Ключ наружу не показывают; секрет наружу тоже не показывают — но перепутать их местами означает, что ни аутентификация, ни проверка подписи не сработают. Подробный разбор — в статье «[API-ключ и секрет подписи вебхука](/guides/api-klyuch-i-webhook-secret)».

## 4. Защититесь от дублей идемпотентностью

**Зачем.** Сетевой сбой или ретрай на вашей стороне не должен превращаться во второй счёт покупателю. Передавайте `external_order_id_idempotency` (до 191 символа, уникален в пределах организации). Повтор с тем же ключом, пока прежний счёт жив, вернёт **409 `duplicate_idempotency_key`** с `invoice_id` и статусом ранее созданного счёта.

Исключение — перевыставление: если прежний счёт с этим ключом уже в `expired`, `cancelled` или `error`, будет создан **новый** счёт, а не отдан 409. Один и тот же ключ идемпотентности может дать вам несколько счетов подряд — не считайте 409 единственным возможным ответом на повтор.

**Как проверить.** Отправьте один и тот же запрос дважды подряд, пока первый счёт в `pending`: первый — 201, второй — 409 с прежним `invoice_id`. Гонка двух параллельных запросов тоже безопасна: второй запрос получит `409` с тем же `invoice_id`.

## 5. При утечке ключа — «Сменить ключ» (секрет при этом НЕ меняется)

**Зачем.** Если ключ мог утечь — не ждите. В кабинете: **Настройки → Подключение → карточка ключа → меню «Ещё» → «Сменить ключ»**. Старый ключ мгновенно перестаёт работать. **Важно:** смена ключа **не трогает** секрет подписи вебхука — если утёк и он, смените его отдельной кнопкой **«Сгенерировать»** у поля «Секретный ключ».

**Как проверить.** После смены ключа убедитесь, что старый возвращает 401, а новый работает; после смены секрета — что ваш обработчик пересчитывает подпись новым значением.

## 6. Ключ и секрет показываются только один раз

**Зачем.** Позже в карточке виден лишь хвост — `****key_hint`. Восстановить полное значение нельзя, только перегенерировать.

**Как проверить.** Сразу при создании сохраните ключ и секрет в секрет-менеджер (Vault, GitHub Actions Secrets, переменные окружения хостинга) — не в заметки и не в код.

## 7. Ревизуйте доступы к кабинету

**Зачем.** В организацию можно пригласить до **10 сотрудников** — лимит один на менеджеров и разработчиков. Уволенный сотрудник с доступом — это открытая дверь.

**Как проверить.** Раз в квартал открывайте в кабинете ApiPay пункт меню **«Сотрудники»** и убирайте тех, кто больше не должен иметь доступ.

## 8. Не путайте контуры песочницы и рабочего режима

**Зачем.** У клиента личного кабинета организация одна, и при переключении «песочница ↔ рабочий режим» API-ключ, Webhook URL и секрет остаются теми же. Значит ключ, которым вы тестировали, после переключения начнёт выставлять **реальные** счета реальным покупателям.

**Как проверить.** До переключения в рабочий режим уберите из конфигурации тестовые номера и сценарии, разведите контуры разными переменными окружения и проверьте, что боевой процесс не ходит по тестовым данным. Что происходит с тестовыми данными при переходе — «[Песочница и рабочий режим](/guides/pesochnitsa-i-rabochiy-rezhim)».

## 9. Не логируйте полные ключи

**Зачем.** Логи утекают чаще, чем базы. Полный ключ в логе приложения = утечка.

**Как проверить.** В своих логах маскируйте секреты до последних 4 символов (`****key_hint` — ровно то, что показывает кабинет). Настройте фильтр логгера, который вырезает заголовки `X-API-Key` и `X-Webhook-Signature`.

## 10. Доверяйте подписи, а не IP

**Зачем.** Подлинность отправителя гарантирует **подпись**, а не IP-адрес. Ставьте **HTTPS**: `http` формально принимается, но тело и подпись поедут открытым каналом. Указывайте постоянный домен своего сервиса — не шортенер и не временную заглушку.

**Как проверить.** Не фильтруйте вебхуки по «белому списку IP» — фиксированный список адресов мы не публикуем. Единственная надёжная проверка — HMAC-подпись из пункта 2.

## 11. Ограничьте право ключа управлять кассирами

**Зачем.** У API-ключа есть флаг «управление кассирами». По умолчанию он **выключен**, и включить его может **только владелец**. Иначе утёкший ключ смог бы отключить кассира и остановить приём платежей.

**Как проверить.** Оставляйте флаг выключенным для всех ключей, которым это не нужно (обычные интеграции создания счетов в нём не нуждаются).

## 12. Ротируйте по расписанию и при смене команды

**Зачем.** Даже неутёкший ключ стоит менять периодически и обязательно — при уходе разработчика, у которого он мог остаться.

**Как проверить.** Заведите регламент: плановая ротация ключей и секретов, внеплановая — при любом кадровом или инфраструктурном изменении. Механика — пункт 5.

## Вопросы и ответы

**Смена API-ключа меняет секрет подписи вебхука?**
Нет. Это две разные операции над записью ключа: «Сменить ключ» меняет только сам ключ, кнопка «Сгенерировать» у поля «Секретный ключ» — только секрет. Вебхук продолжает работать со старым секретом, пока вы не смените его отдельно.

**Можно ли восстановить потерянный ключ или секрет?**
Нет, они показываются один раз при создании. Потеряли — перегенерируйте (это сделает старое значение недействительным).

---

ApiPay — независимый сервис и не аффилирован с АО «Kaspi Bank». Kaspi и Kaspi Pay — товарные знаки их правообладателя.
База знаний: https://apipay.kz/guides
