Автоматическая сверка платежей с 1С: как убрать расхождения
Автоматическая сверка платежей с 1С строится на простой идее: у каждой оплаты есть уникальный ключ, и по этому ключу система сопоставляет три источника, то есть заказ на сайте, операцию в платёжной системе и документ в учёте. Расхождения возникают там, где ключа нет, где он теряется при обмене или где одну и ту же операцию обработали дважды. Если закрыть эти три места, ручная сверка превращается в разбор редких исключений, а не в ежедневную рутину бухгалтера.
Откуда на самом деле берутся расхождения
Прежде чем что-то автоматизировать, полезно понять природу проблемы. В проектах такого рода я обычно вижу одни и те же причины, и почти никогда это не ошибка в «математике».
Первая причина: платёж прошёл у провайдера, а сайт об этом не узнал. Покупатель закрыл вкладку до возврата на страницу магазина, уведомление не дошло или было обработано с ошибкой. В платёжной системе деньги есть, в учёте заказ висит неоплаченным.
Вторая: уведомление пришло дважды, и в 1С создалось два поступления. Об этом отдельно написано в материале про идемпотентность повторных уведомлений, здесь отмечу только, что без защиты от дублей сверка всегда будет показывать излишки.
Третья: разница между суммой заказа и суммой, которая реально поступила на счёт. Комиссия эквайринга удерживается из выплаты, поэтому поступление на расчётный счёт почти никогда не равно сумме заказов за день. Это не расхождение, а ожидаемая разница, но её нужно уметь объяснить цифрами.
Четвёртая: частичные возвраты, отмены и повторные попытки оплаты. Один заказ может иметь несколько платёжных операций, и сопоставление «один к одному» ломается.
Пятая: временные границы. Операция в 23:58 по одному часовому поясу попадает в другие сутки по другому. Реестры провайдера и учёт могут жить в разных зонах, и на стыке дней возникает «потерянная» сумма, которая назавтра сама находится.
Три слоя данных и один ключ
Надёжная сверка опирается на три слоя. Их удобно представить как схему.
- Слой заказа: внутренний номер заказа на сайте, сумма, статус, время создания.
- Слой платёжной операции: идентификатор операции у провайдера, сумма, статус, время, тип (оплата, возврат).
- Слой учёта: документ в 1С (поступление, реализация, приходный ордер или иной, в зависимости от схемы), ссылка на заказ и на операцию.
Связывает их ключ. Лучше всего, когда у вас есть собственный идентификатор платежа, который вы передаёте провайдеру при создании операции и получаете обратно в уведомлении и в реестрах. Тогда любой документ в 1С можно найти по этому значению. Если ключа нет и вы сопоставляете «по сумме и дате», это источник ложных совпадений: два заказа на одну сумму в один день неизбежно перепутаются.
На практике я рекомендую хранить на стороне сайта отдельную таблицу платежей, а не просто поле «оплачен» в заказе. Минимальный набор полей выглядит так.
CREATE TABLE payments (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
order_id BIGINT NOT NULL,
provider VARCHAR(32) NOT NULL,
provider_txn VARCHAR(128) NULL,
amount DECIMAL(12,2) NOT NULL,
currency CHAR(3) NOT NULL,
status VARCHAR(16) NOT NULL,
kind VARCHAR(16) NOT NULL DEFAULT 'payment',
created_at DATETIME NOT NULL,
confirmed_at DATETIME NULL,
exported_1c DATETIME NULL,
UNIQUE KEY uq_provider_txn (provider, provider_txn)
);
Уникальный индекс по паре «провайдер и идентификатор операции» не даст создать дубль даже при гонке двух запросов. Поле exported_1c фиксирует момент, когда платёж ушёл в учёт, и позволяет быстро найти всё, что не ушло.
Как устроен поток: от оплаты до документа
Хороший процесс разделяет три действия: принять событие, подтвердить его и передать в учёт. Смешивать их в одном обработчике соблазнительно, но именно это приводит к потерям.
Сначала вы принимаете уведомление от провайдера и сразу записываете его как есть в журнал. Затем проверяете подпись и статус, обращаясь при необходимости к API провайдера за актуальным состоянием операции (какие методы есть, смотрите в документации конкретной системы, у каждой они свои). Потом переводите платёж в подтверждённое состояние. И только после этого отдельная задача по расписанию берёт подтверждённые платежи с пустым exported_1c и передаёт их в 1С.
Такой разрыв нужен, потому что 1С может быть недоступна: идёт обновление, перезапуск сервера, блокировка базы. Если передача синхронная и жёстко связана с приёмом уведомления, вы либо потеряете событие, либо заставите провайдера бесконечно повторять запросы. Очередь на своей стороне решает проблему. Подробнее о способах обмена между системами я писал в статье про вебхуки и опрос по расписанию.
Передача в 1С чаще всего идёт через HTTP-сервис или обмен файлами. Если вы выбираете первый путь, посмотрите, как устроены HTTP-сервисы в 1С, чтобы заранее понимать ограничения по авторизации и формату данных.
Сверка по реестрам: второй контур защиты
Даже идеально построенный поток событий не отменяет сверки по итоговым данным. События могут теряться по причинам, которых вы не контролируете. Поэтому нужен второй контур: регулярное сравнение с реестром операций от провайдера или с банковской выпиской.
Принцип такой. Раз в сутки (или чаще, если оборот высокий) вы получаете список операций за период и сравниваете его с вашей таблицей платежей. Результат сравнения даёт четыре группы:
- операция есть и там и там, суммы и статусы совпадают: всё в порядке;
- операция есть у провайдера, но нет у вас: пропущенное уведомление, нужно создать платёж и провести заказ;
- операция есть у вас, но нет у провайдера: подозрительный случай, возможно, статус выставлен ошибочно, требуется ручная проверка;
- операция есть везде, но суммы или статусы различаются: частичный возврат, отмена или ошибка конвертации.
Для первой группы ничего делать не нужно, для второй работает автоматическое исправление, а третья и четвёртая попадают в очередь на разбор человеком. Идея в том, чтобы человек видел только исключения, а не весь поток.
Доступность реестров, их формат и периодичность различаются у разных провайдеров и банков. Какие именно выгрузки вам доступны, нужно уточнять в документации и у менеджера провайдера.
Деньги, комиссии и округление
Отдельный источник боли, когда сверка вроде бы работает, а копейки не сходятся. Несколько правил, которые я считаю обязательными.
Храните суммы в десятичном типе или в минимальных единицах (целое число), но не во float. Накопленная ошибка округления на потоке операций проявляется именно в виде мелких расхождений, которые невозможно объяснить.
Комиссию храните отдельным полем, а не вычитайте молча из суммы. Тогда можно показать цепочку: сумма заказа, комиссия, сумма к выплате. Если провайдер сообщает комиссию в реестре, используйте его значение, а не пересчитывайте по своей формуле. Тарифы меняются, и расчёт «по памяти» устареет.
Возвраты записывайте как отдельные операции со своим типом и со ссылкой на исходный платёж. Так в учёте можно получить корректную картину по заказу: оплачено, возвращено, итог.
Для сверки с банковской выпиской учитывайте, что выплата приходит пакетом за несколько дней, за вычетом комиссии. Сопоставлять нужно не отдельный заказ, а реестр выплаты с суммой поступления на счёт. Как именно ваш эквайер группирует выплаты, выясняйте у него.
Что делать на стороне 1С
В учёте тоже есть чему помочь процессу. Несколько практик, которые экономят время.
В документах поступления сохраняйте идентификатор платежа и номер заказа сайта в отдельных реквизитах, а не в комментарии. Поиск и отбор по реквизиту работают быстро и предсказуемо, а парсить комментарий потом никто не захочет.
Сделайте отчёт или обработку «Неподтверждённые поступления»: список платежей из сайта, которым нет соответствующего документа, и наоборот. Это ваш рабочий инструмент бухгалтера на каждый день.
Проверьте, как в вашей конфигурации устроена связь с контрагентом при розничных онлайн-оплатах. Часто используют обобщённого покупателя, и тогда идентификатор платежа становится единственным способом найти конкретную операцию.
Если в вашей конфигурации этого нет «из коробки», это стандартная небольшая доработка. Из чего складывается её стоимость, описано в материале про стоимость доработки 1С.
Журнал и наблюдаемость
Сверка без журнала превращается в гадание. Каждое изменение статуса платежа должно оставлять запись: что изменилось, когда, по какому событию, кто или что инициировало. Минимальный журнал помогает ответить на вопрос «почему этот заказ в таком статусе» за минуту, а не за вечер.
Добавьте простые сигналы. Количество платежей, застрявших в статусе «ожидает» дольше разумного срока. Количество подтверждённых, но не переданных в учёт. Разницу между суммами за сутки по сайту и по реестру. Если какой-то показатель выходит за обычные рамки, это повод посмотреть на систему, не дожидаясь жалобы бухгалтера.
Типичные ошибки при внедрении
Сопоставление по сумме и дате без уникального ключа. Работает, пока заказов мало, потом начинает тихо ломаться.
Один обработчик, который принимает уведомление, ходит в 1С и меняет статус заказа. Любой сбой посередине оставляет данные в неопределённом состоянии.
Отсутствие ручной очереди исключений. Автоматика не должна пытаться «угадать» спорные случаи, лучше показать их человеку с контекстом.
Игнорирование часовых поясов и границ периодов. Сверяйте окна времени явно и храните время в одном поясе, преобразуя при выводе.
Автоматическое исправление «на лету» без записи в журнал. Если система сама поправила статус, это должно быть видно потом.
Частые вопросы
Можно ли обойтись без сверки по реестрам, если уведомления приходят стабильно?
Можно, пока всё работает, но это ставка на то, что ни одно событие не потеряется. Реестр нужен как страховка: он стоит недорого в реализации и закрывает редкие случаи, которые иначе обнаружатся при закрытии периода.
С чего начать, если сейчас всё сверяется вручную в Excel?
Начните с ключа. Добавьте в заказ и в учёт общий идентификатор платежа, затем заведите таблицу платежей на стороне сайта. Автоматические отчёты о расхождениях строятся уже на этой основе, а передачу в 1С можно подключить следующим шагом.
Нужно ли сверять возвраты отдельно?
Да. Возврат это самостоятельная операция со своим идентификатором и суммой, и в реестре она отражается отдельной строкой. Если не вести её отдельно, итог по заказу и итог по выплате будут различаться.
Как часто запускать сверку?
Зависит от объёма и требований бухгалтерии. Часто достаточно раза в сутки, ночью, с отчётом утром. При большом потоке или при риске мошенничества имеет смысл сверять чаще, но сначала стоит убедиться, что ограничения API провайдера это позволяют.
Если нужна помощь с такой задачей, посмотрите страницу об интеграциях платёжных систем или напишите мне в Telegram.