HMAC, nonce и идемпотентность: как сайт и микросервис обмениваются деньгами, не доверяя друг другу

Когда логика TON-кошельков вынесена в отдельный микросервис, а основной сайт обращается к нему только по REST API, именно API становится границей доверия.

Прямого доступа к базе данных микросервиса основной сайт не имеет — вся связь идёт через API. Ниже — схема защиты, применённая в связке «сайт ↔ TON-микросервис», без привязки к конкретному коду, чтобы принцип был переносим на любой другой стек.

Подпись запроса, а не просто ключ в заголовке

Обычного API-ключа в заголовке недостаточно: если его перехватят, запросы можно будет отправлять от имени клиента. Вместо этого каждый запрос подписывается по HMAC-SHA256, причём подписывается не тело запроса, а его каноническое представление: HTTP-метод, путь, query string, SHA-256 от тела, timestamp, nonce и idempotency-key, склеенные в фиксированном порядке. Секрет для подписи не покидает две доверенные стороны и не передаётся в запросе.

Если хоть один элемент этой цепочки изменится — путь, тело, время, — подпись перестанет совпадать, и запрос будет отклонён ещё до того, как долетит до бизнес-логики.

Timestamp + nonce: защита от повторного воспроизведения

Подписанный запрос всё ещё можно перехватить и отправить повторно, если не ограничить его во времени. Поэтому у каждого запроса есть timestamp, допустимое отклонение от которого — не более нескольких минут, и nonce — одноразовое значение, которое сервер запоминает и повторно не принимает. «Истёк по времени» + «уже был использован» закрывает окно для replay-атаки даже с корректной подписью.

Idempotency-Key: другая задача, тот же принцип

Nonce защищает от атаки, idempotency-key — от собственных сетевых проблем. Если ответ на запрос не дошёл из-за таймаута, при повторной отправке того же запроса с тем же idempotency-key микросервис обязан вернуть результат первой попытки, а не выполнить операцию второй раз. Для денежных операций сетевой сбой не должен превращаться в двойное списание или зачисление.

IP allowlist и единый контракт ошибок

Дополнительный слой — allowlist разрешённых IP для каждого API-клиента: даже с валидной подписью запрос с неожиданного адреса отклоняется. А все возможные отказы возвращаются в едином JSON-формате с success, error_code и message — клиент API принимает решения по статус-коду и error_code, а не парсит текст ошибки; ответы 5xx никогда не раскрывают внутренние детали.

Итог: два независимых сервиса, обменивающихся деньгами по сети, могут быть уверены, что запрос пришёл от легитимного партнёра, не был перехвачен и повторён, а сбой сети не превратится в задвоенную операцию. Для финансового backend это разница между системой, которую можно спокойно эксплуатировать в проде, и системой, которая рано или поздно потеряет чьи-то деньги на ровном месте.

Обсудить задачу

Если у вас есть проект, связанный с Laravel, CRM, Telegram, AI/RAG, API-интеграциями, автоматизацией или TON/GRAM-логикой — напишите в свободной форме, что нужно сделать.

Можно описать задачу коротко: что есть сейчас, что не работает, какой результат нужен и какие сервисы уже используются.


Сделать заказ

| необходим для связи с вами
В кротчайшие сроки я свяжусь с вами.

Также вы можетете связать со мной:
telegram: @ifwcom