Nordlet

← Блог

Что определяет API неизменяемого бухгалтерского журнала с двойной записью

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

Nordlet Team · · 11 мин. чтения

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

Для платформы маркетплейса ответ прост: API неизменяемого журнала с двойной записью фиксирует каждое финансово значимое событие в виде сбалансированной проводки, проводит ее атомарно, никогда не перезаписывает данные и позволяет программно вычислять балансы, сверять их с внешними системами и экспортировать историю. Все остальное — лишь детали, надстраиваемые над этим фундаментом.

Сбалансированные проводки, а не поле текущего баланса

Самый надежный способ проверки — посмотреть, как API представляет баланс продавца. Если баланс представляет собой число, которое ваше приложение инкрементирует напрямую, перед вами не журнал с двойной записью. Если же баланс вычисляется на основе проведенных строк журнала, то это уже ближе к истине.

Каждая транзакция должна содержать равные дебетовые и кредитовые суммы. Когда покупатель оплачивает заказ на сумму €100, а комиссия маркетплейса составляет €15, журнал фиксирует дебет клирингового счета на €100 в корреспонденции с кредитом счета обязательств перед продавцом на €85 и кредитом счета выручки от комиссии на €15. Обе стороны всегда сходятся в единую сумму. Это структурное правило отсекает огромный пласт ошибок еще до того, как они попадут в отчетность.

Проводка журнала должна содержать как минимум следующие данные:

  • Уникальный неизменяемый идентификатор транзакции
  • Дебетовые и кредитовые строки, каждая с указанием счета, суммы и валюты
  • Дату совершения операции и метку времени проводки
  • Тип бизнес-события (продажа, возврат, выплата, чарджбэк)
  • Ключ идемпотентности
  • Ссылку на исходный заказ, платеж или событие провайдера
  • Статус (в обработке, проведена, сторнирована)
  • Сервис или учетные данные, создавшие запись

Доступные средства продавца в этом случае рассчитываются как запрос к этим строкам, а не как значение, обновленное кем-то в коде приложения. Это принципиально важно, поскольку прямое изменение баланса уничтожает причину каждого движения средств. Модель Nordlet рассматривает журнал с двойной записью как единственный авторитетный путь записи (write path): каждый документ создает сбалансированные проводки, а сама база данных на уровне ядра отвергает любые несбалансированные операции. Это правильное поведение по умолчанию для любой системы, встраивающей бухгалтерский учет в маркетплейс.

Проводка только на добавление с корректирующими сторно

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

API должен отклонять простые команды UPDATE и DELETE для уже проведенных бухгалтерских записей. Он может разрешать добавление нефинансовых метаданных (например, ссылки на тикет в техподдержке) при условии, что суммы, счета и метки времени остаются нетронутыми.

Полезно разделять три понятия, которые часто путают:

  • Операционная неизменяемость: пользователи приложения не могут изменять или удалять проведенные строки.
  • Аудиторская неизменяемость: система способна доказать, что история не подвергалась изменениям.
  • Юридический срок хранения: записи хранятся в течение срока, требуемого применимым законодательством.

Реляционная база данных, работающая только на добавление (append-only), со строгими правами доступа, резервными копиями и регламентированными процедурами сторнирования обеспечивает подлинную неизменяемость журнала. Блокчейн здесь вовсе не обязателен, а в контексте европейских бухгалтерских данных он обычно создает проблемы с конфиденциальностью и исправлением ошибок, которые перевешивают всю пользу от защиты от несанкционированного доступа.

Атомарность и идемпотентность

Событие на маркетплейсе должно проводиться атомарно. Либо фиксируются все строки проводки, либо ни одна. Запись поступления €100 без фиксации комиссии в €15 приводит к несбалансированному, искаженному результату, который кому-то придется распутывать позже. Nordlet обеспечивает это на уровне ниже слоя приложения: отложенный триггер базы данных проверяет сбалансированность каждой проводки в момент фиксации (commit), поэтому несбалансированная транзакция попросту не может быть записана.

Идемпотентность — это зона, где большинство интеграций незаметно дают сбой. Платежные системы повторяют запросы при сетевых сбоях, а файлы взаиморасчетов могут загружаться повторно. Без ключа идемпотентности, привязанного к клиенту (tenant) или аккаунту, один повторный запрос создаст дублирующую проводку. Повторный запрос с тем же ключом должен возвращать исходную транзакцию, а не создавать новую.

Ключ должен быть привязан к исходному событию, типу события, идентификатору события у провайдера, юридическому лицу и хэшу полезной нагрузки (payload) запроса. Если тот же ключ поступает с другой суммой или валютой, API должен расценивать это как коллизию и отклонять запрос, а не принимать новый контент молча. Молчаливое принятие — прямой путь к разрушению аудиторского следа. Заголовок Nordlet Idempotency-Key работает именно так: повторный запрос с тем же ключом и нагрузкой воспроизводит сохраненный ответ, а тот же ключ с другой нагрузкой отклоняется с ошибкой idempotency_key_reuse. Это небольшая деталь с огромным влиянием на качество сверки.

Многосторонняя раздельная бухгалтерия

Заказ на маркетплейсе не сводится к одному движению средств. Одна продажа может затрагивать деньги покупателя, выплату продавцу, комиссию маркетплейса, эквайринговые сборы, НДС с комиссии, доставку и резервы. Журнал должен использовать структуру счетов, которая держит их раздельно, а не сводит все к единой итоговой сумме.

Существует распространенное заблуждение, с которым стоит бороться: функция «раздельных выплат» (split payout) от платежного провайдера не заменяет бухгалтерский учет маркетплейса. Распределение денег между получателями лишь перенаправляет наличность. Оно не дает полной и неизменяемой картины заработанной комиссии, собранного НДС, подлежащих возврату средств или удержанных резервов. Вам по-прежнему необходим собственный журнал, и его все равно придется сверять с провайдером.

Бухгалтерский журнал маркетплейса также должен различать несколько состояний баланса продавца:

Статус баланса Что он означает
В ожидании (Pending) Средства, привязанные к событию, но еще не доступные для вывода
Доступно (Available) Средства, прошедшие правила разблокировки, резервирования, возвратов и споров
Удержано / в резерве (Held / reserved) Суммы, замороженные под чарджбэки, возвраты или меры борьбы с мошенничеством
Выплачено (Paid out) Суммы, переведенные продавцу
Отрицательный / к взысканию (Negative / recoverable) Суммы, которые продавец должен маркетплейсу из-за того, что возвраты или комиссии превысили доступные средства

Перевод средств из статуса «в ожидании» в «доступно» сам по себе должен оформляться как сбалансированная проводка, а не как простое переименование поля.

Сторно, возвраты и отрицательные балансы

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

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

Валюты и точность вычислений

Международные маркетплейсы требуют аккуратной работы с деньгами. Суммы должны выражаться в коде валюты по стандарту ISO 4217 и точных величинах — либо в минимальных денежных единицах в виде целых чисел, либо в виде десятичных строк с фиксированной точностью, но никогда через числа с плавающей запятой (floats). Никаких скрытых округлений. При конвертации валют журнал обязан сохранять исходную сумму, обменный курс, источник курса, метку времени и результирующую сумму, а разницы от округления должны относиться на строго определенный счет.

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

Сверка с внешними системами

Внутренне сбалансированный журнал не авторитетен сам по себе. Он должен сходиться с внешним миром: транзакциями платежных провайдеров, комиссиями провайдера, отчетами о взаиморасчетах, банковскими выписками, файлами выплат и отчетами по чарджбэкам.

Зрелый API поддерживает импорт внешних событий и такие статусы сопоставления, как сопоставлено, частично сопоставлено, не сопоставлено, дубликат, несоответствие сумм и требуется проверка. Расхождения при сверке должны приводить к созданию явных записей об исключениях или бухгалтерских проводок. Они ни в коем случае не должны тихо перезаписывать историю журнала. Подход Nordlet к банковской сверке и сопоставлению платежей строится именно на этом принципе: импортируемые выписки и экспорт из Stripe пропускают уже загруженные данные, платежные подсказки оцениваются по сумме, назначению платежа, контрагенту и IBAN, сопоставление в один клик закрывает стандартные случаи, а исключения выводятся наружу для ручной обработки, а не растворяются в системе.

Границы ЕС: какие ограничения API должен учитывать, а какие ему не по силам

Именно здесь маркетинговые заявления чаще всего расходятся с реальностью. Журнал помогает выполнять обязательства перед ЕС, но сам по себе он их не закрывает.

НДС (VAT). Журнал должен сохранять параметры, имеющие значение для налогообложения: юрисдикцию, ставку, налоговую категорию и способ определения ставки. Он должен разграничивать продажу продавца покупателю и комиссию маркетплейса, а также отделять НДС с комиссий от сумм, которые просто проходят транзитом. Nordlet берет на себя расчеты НДС по странам, проверку VIES и генерацию реестров i.SAF, а также сценарии OSS и IOSS, с которыми сталкиваются европейские маркетплейсы. Воспринимайте журнал как бухгалтерское доказательство и налоговый движок, но не как налоговую консультацию.

DAC7. Правила отчетности платформ требуют надежных связей между личными данными продавца, юрисдикцией, итоговыми оборотами по транзакциям, комиссиями, возвратами и выплатами. Сбалансированный журнал предоставляет доказательства в виде транзакций. Он не определяет, подлежит ли продавец отчетности, и не заменяет KYC, онбординг или рабочий процесс подготовки отчетов. Разделяйте учет транзакций и регуляторную отчетность.

PSD2 и хранение средств. Регистрация движения средств — это еще не статус лицензированного платежного сервиса или безопасного хранения средств. Журнал должен делать потоки денег и участников прозрачными. Сам по себе он не может предоставить авторизацию на оказание платежных услуг или доказать, что наличные хранятся на конкретном счете. Это вопросы вашей регуляторной роли и вашего платежного провайдера.

GDPR. Требование неизменяемости вступает в реальное противоречие с принципами защиты персональных данных. Самая безопасная архитектура — хранить финансовые факты в неизменяемом ядре, а персональные данные за его пределами. Используйте стабильные псевдонимизированные идентификаторы продавцов и покупателей в строках проводок. Храните изменяемые персональные данные в отдельной системе с контролем доступа, собственной политикой хранения и удаления. Понятие «неизменяемый» не означает разрешение хранить каждую платежную нагрузку вечно.

Чек-лист для оценки API журнала

Маркетинговые ярлыки стоят недорого. Проверьте реальное поведение в песочнице (sandbox). Запустите следующие сценарии и проверьте результаты:

  • Проведите заказ на €100 с разделением между продавцом и маркетплейсом и убедитесь в наличии сбалансированной проводки с четкими счетами.
  • Отправьте тот же запрос дважды и убедитесь, что создана ровно одна транзакция без дубликатов.
  • Попробуйте отредактировать уже проведенную запись и убедитесь, что система отклоняет запрос или ограничивает его только нефинансовыми метаданными.
  • Исправьте неверную комиссию и убедитесь в наличии связанного сторно вместе с корректной записью.
  • Оформите частичный возврат после выплаты и убедитесь, что возврат прослеживается, а у продавца появилась дебиторская задолженность или отрицательный баланс.
  • Повторно отправьте вебхук провайдера и убедитесь в срабатывании детектора дубликатов.
  • Обработайте многовалютные взаиморасчеты и проверьте наличие деталей по конвертации и соответствующей бухгалтерской проводки.
  • Запросите баланс продавца на конец периода и убедитесь, что результат воспроизводим и опирается на зафиксированную дату отсечки (cut-off).
  • Импортируйте взаиморасчеты провайдера и убедитесь, что сопоставление со статусом исключения оставляет историю нетронутой.
  • Экспортируйте данные за месяц активности и убедитесь в полноте, постраничности и повторяемости выгрузки.

Лучшее доказательство качества — это документация в сочетании с воспроизводимым тестом. Слова вроде «реального времени», «готово к аудиту» и «неизменяемый» не имеют никакого веса без подтверждения моделью данных, семантикой ошибок и правилами хранения.

С чего мы бы начали проверку в первую очередь

Если бы завтра мы выбирали API журнала для маркетплейса, мы бы начали с двух вещей, прежде чем смотреть на все остальное. Во-первых, убедились бы, что баланс продавца вычисляется на основе строк журнала, а не хранится в виде изменяемого поля, поскольку от этого зависит все остальное. во-вторых, повторно отправили бы тот же вебхук и проверили, что сформировался ровно один бухгалтерский результат. Эти два теста говорят о качестве базовой архитектуры больше, чем любой маркетинговый список функций.

После этого вступают в силу аспекты удобства API, влияющие на скорость разработки вашей команды: типизированные SDK, вебхуки для таких событий, как sale_invoice.paid, работающая песочница и блокировка периодов для защиты закрытых месяцев. Платформа Nordlet создана именно вокруг этой концепции: тот же набор возможностей доступен как через API, так и через приложение, что позволяет маркетплейсу вести готовую к аудиту бухгалтерию прямо внутри собственного продукта, не прикручивая сторонние чекауты. Чтобы получить более широкое представление о том, как такой журнал встраивается в стек маркетплейса, ознакомьтесь с нашим руководством по API журналов с двойной записью для бухгалтерского учета маркетплейсов.

FAQ

Гарантирует ли двойная запись правильность моего бухгалтерского учета?

Нет. Журнал может быть идеально сбалансирован, даже если проводки уходят не на те счета, применяется неверная ставка НДС или средства приписываются не тому продавцу. Баланс — это структурный контроль, который отсекает арифметические ошибки и отсутствие второй стороны транзакции. Он ничего не говорит о том, правильно ли ваша бизнес-логика сопоставила само событие. Именно поэтому тестирование в песочнице на реальных сценариях важнее простой проверки сходимости баланса.

Достаточно ли бухгалтерского журнала платежного провайдера для маркетплейса?

Как правило, нет. Платежный провайдер отслеживает средства внутри собственной системы, что удобно для движений и выплат. Вашему маркетплейсу по-прежнему нужны собственные записи по выручке от комиссий, обязательствам перед продавцами, НДС с комиссий, возвратам, резервам, спорам и управленческой отчетности. Обе системы должны сходиться, а отношение к данным провайдера как к вашей бухгалтерии оставляет пробелы, которые непременно всплывут во время аудита.

Нужен ли мне блокчейн, чтобы сделать журнал неизменяемым?

Нет. Реляционное хранилище, работающее только на добавление, со строгими правами на запись, контролируемыми процессами корректировок, аудиторским логом и надежными бэкапами обеспечивает как операционную, так и аудиторскую неизменяемость. Блокчейн добавляет распределенную защиту от манипуляций, но создает проблемы с конфиденциальностью, производительностью и исправлением ошибок, которые идут вразрез с требованиями европейского бухучета и GDPR. Для большинства маркетплейсов он решает проблему, которой у них нет.

Может ли неизменяемый журнал хранить данные вечно в соответствии с GDPR?

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