Подключение оплаты выглядит как строчка в смете: «эквайринг — настройка». На практике это самая ответственная часть интернет-магазина: здесь ошибка стоит не позиций в выдаче, а денег и претензий от покупателей. Разберём, что реально происходит между нажатием кнопки и поступлением на расчётный счёт, и где именно это ломается.
Две схемы, и выбор между ними не про дизайн
Форма оплаты бывает двух видов. Первая — платёжная страница провайдера: сайт создаёт платёж через API, получает ссылку и уводит покупателя на домен банка или платёжного сервиса. Вторая — своя форма на сайте, когда номер карты вводится в ваших полях.
Второй вариант почти никому не нужен, и вот почему: как только реквизиты карты попадают на ваш сервер, вы попадаете под требования PCI DSS — с сертификацией, сканированием периметра и отдельным бюджетом на всё это. Поэтому в девяноста девяти случаях из ста используется редирект на страницу провайдера или его виджет, который рендерится в iframe с чужого домена. Карта вводится не у вас, ответственность тоже не у вас.
Если подрядчик предлагает «сделать красивую форму оплаты прямо в корзине, чтобы покупатель никуда не уходил» — уточните, где именно будет вводиться номер карты. Если на вашем домене и без виджета провайдера, это не красота, а нарушение.
Как устроен платёж по шагам
Протоколы у провайдеров разные в деталях, но последовательность одна. На примере логики, общей для ЮKassa, эквайринга Т-Банка, CloudPayments и Robokassa:
- Сайт создаёт заказ у себя и фиксирует сумму — дальше она не должна меняться
- Сайт вызывает API провайдера: сумма, валюта, описание, адрес возврата, данные чека
- В ответ приходит идентификатор платежа и ссылка на оплату
- Покупатель уходит на страницу оплаты, вводит карту, проходит подтверждение банка
- Провайдер присылает на ваш адрес уведомление о смене статуса — вебхук
- Сайт проверяет статус платежа запросом к API и только тогда меняет статус заказа
- Покупателя возвращает на сайт по адресу возврата — страница «спасибо»
Шестой пункт — тот самый, на котором всё держится. Разберём его отдельно, потому что именно он чаще всего сделан неправильно.
Возврат на сайт — не событие оплаты
Самая распространённая ошибка в самодельных интеграциях: заказ помечается оплаченным в тот момент, когда браузер покупателя пришёл на адрес возврата. Это неверно по трём причинам.
Во‑первых, покупатель может закрыть вкладку сразу после успешной оплаты и на сайт не вернуться — заказ останется неоплаченным, хотя деньги списаны. Во‑вторых, адрес возврата можно открыть руками, не платя вообще. В‑третьих, провайдер возвращает покупателя и после неудачной попытки — на тот же адрес.
Правильно так: страница возврата только показывает человеку текст и, если статус ещё не пришёл, формулировку «платёж обрабатывается». Статус заказа меняет исключительно серверная логика — по вебхуку, с обязательной перепроверкой через API по идентификатору платежа. Вебхук в этой схеме не источник истины, а всего лишь сигнал «пойди посмотри».
Что проверять в вебхуке
- Подпись или IP-адрес отправителя — список подсетей провайдер публикует
- Сумму из ответа API против суммы заказа в своей базе, до копейки
- Валюту — редко, но бывает важно
- Что заказ ещё не обработан: уведомление может прийти несколько раз
- Что статус именно succeeded, а не waiting_for_capture или pending
Про повторную доставку стоит сказать прямо: провайдер будет повторять уведомление, пока не получит код 200. Если обработчик не идемпотентен, один платёж превращается в три письма покупателю, три записи в учёте и три чека. Защита простая — уникальный ключ в таблице платежей по идентификатору провайдера и обработка в транзакции.
Отдельная деталь, которую забывают: при создании платежа многие API требуют заголовок ключа идемпотентности. Если его не передавать, повторный запрос из‑за таймаута создаст второй платёж на ту же сумму. Покупатель оплатит дважды, и разбираться с этим будете вы.
Одностадийный и двухстадийный платёж
При одностадийной схеме деньги списываются сразу. При двухстадийной сначала идёт авторизация — сумма блокируется на карте, а списание делается отдельным вызовом. Статус платежа между этими шагами как раз waiting_for_capture, и срок на подтверждение ограничен — обычно около недели, дальше блокировка снимается сама.
Двухстадийная схема нужна там, где наличие товара подтверждается после заказа: товар под заказ, позиция с длинным сроком поставки, сборный комплект. Логика такая: заблокировали, проверили остаток в учётной системе, подтвердили списание или отменили блокировку. Отмена блокировки для покупателя гораздо приятнее возврата: деньги не уходили со счёта, ждать трое суток не нужно.
Цена вопроса — связка с остатками. Если обмен с 1С идёт раз в сутки, двухстадийная схема теряет смысл: к моменту подтверждения вы всё равно не знаете, есть товар или нет.
Чек по 54-ФЗ: кто его формирует
При оплате на сайте покупателю обязан уйти фискальный чек. Технически его можно пробить двумя путями: через платёжный сервис, у которого есть собственное решение онлайн-кассы, либо через отдельный облачный сервис фискализации, подключённый к вашей кассе.
В обоих случаях сайт передаёт состав чека вместе с платежом, и состав этот сложнее, чем «название и цена». На каждую позицию нужны:
- Наименование — не длиннее лимита кассы, иначе чек не пробьётся
- Количество, цена за единицу и сумма — с точностью до копейки и без расхождения с итогом
- Ставка НДС отдельным кодом: без НДС, 0, 10, 20 — и это не одно и то же
- Признак предмета расчёта: товар, услуга, платёж, иной
- Признак способа расчёта: полный расчёт, аванс, предоплата
- Контакт покупателя — электронная почта или телефон, иначе чек некуда отправить
Два места, где это регулярно ломается. Первое — доставка. Она должна быть отдельной позицией чека с собственным признаком предмета расчёта; если её «растворить» в цене товара, итог чека не сойдётся с суммой платежа и касса откажет. Второе — смешанный НДС: товары с разной ставкой в одном чеке допустимы, но ставку нужно брать из карточки товара, а не подставлять одну на весь магазин.
Если в карточках товара не заведена ставка НДС и признак предмета расчёта — подключение кассы упрётся в это раньше, чем в технику. Это данные учёта, и заполнить их должен тот, кто ведёт учёт.
Способы оплаты: что подключать кроме карты
Карта — уже не единственный и не всегда основной способ. Что имеет смысл включать и почему:
- СБП по QR-коду или ссылке — комиссия заметно ниже карточной, оспаривание операций практически отсутствует
- Оплата по счёту для юрлиц — не эквайринг вообще, но для B2B это основной канал, и счёт лучше формировать на сайте
- Рассрочка и оплата частями — отдельный договор, в корзине появляется как ещё один способ
- Сохранённая карта для повторных покупок — провайдер возвращает токен метода оплаты, сам номер вы не храните
- Оплата при получении — не платёж на сайте, но в чеке и в учёте ведёт себя иначе, и это надо развести на старте
Важное про сохранённые карты: списание по токену без участия покупателя — это рекуррентный платёж, и подключается он отдельно, с показом условий списания. Технически несложно, юридически требует внимания.
Возвраты
Возврат делается через API провайдера по идентификатору исходного платежа и бывает частичным. Два правила, которые сэкономят время: возврат нельзя сделать на сумму больше исходной и нельзя сделать по платежу, который ещё не в статусе успешного. Звучит очевидно, но интерфейс в админке обычно позволяет попробовать и то и другое.
Вместе с возвратом денег пробивается чек возврата — с теми же позициями, что были в исходном. Поэтому состав чека нужно сохранять у себя на момент оплаты, а не собирать заново из текущего состояния заказа: цены к моменту возврата могут уже измениться.
Сверка, о которой вспоминают в конце квартала
На счёт приходит не сумма заказов, а сумма минус комиссия, и приходит она реестром за период, а не по каждой операции. Пока в учёте нет документа эквайринговой операции, бухгалтерия будет каждый месяц сводить вручную.
Минимально рабочая схема: сайт хранит у каждого заказа идентификатор платежа провайдера, в учётную систему уходит и он, и сумма. Тогда реестр выплат сопоставляется с заказами по одному полю, а не по дате и сумме «на глаз». Это настраивается в рамках интеграции сайта с учётной системой и стоит дешевле, чем кажется, если заложить сразу.
Что нужно до подключения — и это не код
Платёжный сервис проверяет сайт перед активацией, и отказы на модерации случаются чаще, чем технические проблемы. Что смотрят:
- Реквизиты юридического лица или ИП на сайте, в подвале или на отдельной странице
- Описание товаров с ценами — пустой каталог «в разработке» не пройдёт
- Условия доставки и возврата отдельными страницами
- Политика обработки персональных данных и согласие в формах
- Соответствие заявленного вида деятельности тому, что реально продаётся
- Работающие контакты — телефон берут и проверяют
Планируйте модерацию отдельным этапом: несколько рабочих дней, иногда с запросом документов. Закладывать подключение оплаты в последний день перед запуском — верный способ сдвинуть запуск.
Чек-лист перед тем, как включить приём денег
- Статус заказа меняется по вебхуку с перепроверкой через API, а не по возврату браузера
- Сумма из ответа провайдера сравнивается с суммой заказа
- Повторный вебхук не создаёт второй оплаты, письма и чека
- При создании платежа передаётся ключ идемпотентности
- Все обращения к API и все уведомления пишутся в журнал с сырым телом запроса
- Состав чека сохраняется на момент оплаты и переиспользуется при возврате
- Доставка — отдельная позиция чека, НДС берётся из карточки товара
- Проверены сценарии в песочнице: успех, отказ банка, отмена, таймаут, двойное нажатие
- Настроено оповещение, если вебхуки перестали приходить вовсе
Последний пункт недооценивают. Молчание вебхуков выглядит как «заказов стало меньше», а на самом деле означает, что оплаты идут, а заказы висят неоплаченными. Такое мониторится вместе с остальной доступностью сайта и входит в поддержку.
Мы подключаем эквайринг и фискализацию на 1С-Битрикс, WordPress с WooCommerce и своих решениях, разбираем чужие интеграции, в которых теряются платежи, и выводим идентификаторы платежей в учёт, чтобы сверка перестала быть ручной работой. Если магазин только проектируется, оплату и кассу считаем частью проекта, а не доработкой после запуска.