Перейти к содержанию
STONS

Чек-лист перед продом

Пройдите его, прежде чем принимать реальные платежи. Каждый пункт закрывает известный способ потерять деньги. Порядок работ по интеграции — в интеграции под ключ.

Ключи и доступ

  • Ключ API хранится в менеджере секретов и используется только на сервере. Его нет в браузере, мобильном приложении, репозитории и логах.
  • Секрет вебхуков хранится так же и отдельно от ключа API. Тот же секрет подписывает вебхуки и редиректы со страницы оплаты.
  • Продукт обращается к API только по https://: по http:// ключ ушёл бы открытым текстом ещё до перенаправления — см. аутентификацию.
  • Адрес вебхуков в настройках проекта начинается с https://: кабинет принимает и http://, но тогда события идут открытым текстом.

Вебхуки

  • Подпись проверяется по сырому телу запроса, до разбора JSON — см. подпись.
  • Подписи сравниваются за постоянное время.
  • Вебхуки с X-Timestamp, отличающимся от текущего времени больше чем на 5 минут, отклоняются.
  • Решение отдать товар принимается по ответу API — GET /v1/invoices/{id}, — а не по телу вебхука.
  • Пополнение per_user зачисляется пользователю только после того, как GET /v1/deposits/{tx_hash} показал его перевод со status = confirmed и credited = true, — см. проверку перевода.
  • Дубли отбрасываются по id события, и повторная доставка того же события не приводит к повторной выдаче товара.
  • Обработчик не зависит от порядка событий: invoice.confirmed может прийти раньше invoice.seen.
  • Обработчик отвечает 2xx за 10 секунд, в том числе на типы событий, которые не обрабатывает, а тяжёлую работу выполняет асинхронно — см. доставку.

Платежи

  • Товар отдаётся, только когда статус инвойса confirmed или settled, — не при seen и не при первом появлении транзакции, см. статусы.
  • Продукт определил, что делает при underpaid, при paid_late и при переплате — confirmed с amount_received больше amount_expected.
  • При partially_paid товар не отдаётся. Если продукт показывает оплату сам, покупатель видит amount_remaining и тот же адрес, см. частичную оплату.
  • Суммы обрабатываются как строки или целые числа в минимальных единицах, никогда как числа с плавающей точкой.
  • Число знаков после запятой берётся для конкретного актива и не зашивается в код: у USDT в BNB Chain их 18, а не 6. Сумма в ответе API содержит после точки ровно столько цифр, сколько знаков у её актива.
  • Продукт сверяет свою цену с amount_requested, а у покупателя просит amount_expected — см. комиссии.
  • Каждый заказ создаёт инвойс со своим order_id, а повтор запроса после таймаута использует тот же order_id с теми же полями.

Отображение

  • Адрес показывается пользователю целиком, без сокращений, вместе с сетью и активом — см. показ адреса.
  • Пользователь предупреждён, что перевод в другой сети или другого токена не зачисляется автоматически.
  • Интеграция принимает несколько переводов в одной транзакции и отрицательный log_index, отличный от -1: платёж нативной монетой EVM-сети, который отправил смарт-контракт, например ETH или BNB со смарт-кошелька, мультиподписи или с вывода биржи, приходит с -2, -3 и далее, — см. что приходит на адрес.
  • Инвойс, созданный без asset, оплачивается только через checkout_url: пока покупатель не выбрал токен, адреса у него нет.

Страница оплаты

  • Если используется страница оплаты, адреса возврата и отмены заданы в настройках проекта: без них страница не вернёт покупателя — см. адреса возврата.
  • Подпись редиректа и окно ts в 5 минут проверяются, а товар по редиректу не отдаётся — см. подпись.
  • Переход на адрес отмены со status=created, status=seen или status=partially_paid не отменяет заказ: инвойс ещё можно оплатить.

Выплаты

  • Адреса для выплат заранее внесены в вайтлист: их вносит оператор, и новый адрес становится доступен только после задержки — по умолчанию через 24 часа.
  • Адрес для выплаты берётся из вайтлиста и никогда — из истории транзакций.
  • Каждая выплата создаётся со своим reference, а повтор использует тот же reference.
  • pending_review обрабатывается как принятая выплата, которая ждёт человека, а не как ошибка, а исход берётся из GET /v1/payouts/{id}.

Проверка

  • Весь сценарий — создание инвойса, оплата, вебхук, проверка статуса через API и выдача товара — пройден на небольшой сумме до приёма реальных платежей.