Транзакция — это неизменяемая запись об изменении баланса внутреннего счёта покупателя: пополнение, списание при оплате заказа или ручная корректировка. Из таких записей складывается вся история движения средств, а их сумма и есть текущий баланс. Разберём, где они хранятся, как устроена каждая запись и как создавать транзакции программно, не «ломая» баланс.
Что такое транзакция по счёту
Внутренний счёт покупателя в Битрикс — это не отдельное число, которое кто-то «перезаписывает», а журнал операций. Каждое зачисление или списание оформляется как отдельная транзакция, а баланс счёта — это агрегат всех транзакций в конкретной валюте. Механизм входит в модуль sale (Интернет-магазин) и работает в связке с сущностью счёта.
Такой подход даёт прозрачность: по истории всегда видно, откуда взялись деньги на счёте и куда они ушли — пополнение через платёжную систему, возврат средств за отменённый заказ, оплата нового заказа с баланса или административная корректировка. Транзакции по своей природе неизменяемы: вы не редактируете старую запись, а добавляете новую, компенсирующую её.
b_sale_user_transact) и транзакции платёжных систем — записи о статусе платежа во внешнем шлюзе. Первые описывают движение по балансу покупателя внутри сайта, вторые фиксируют результат оплаты у эквайера.Где смотреть транзакции
В административной панели список счетов открывается по пути Магазин → Покупатели → Внутренние счета покупателей (страница sale_account.php). Здесь виден текущий баланс каждого покупателя в разрезе валют.
История операций доступна отдельным списком транзакций — по каждому счёту можно раскрыть все зачисления и списания с датами, суммами и описаниями. Оттуда же администратор вручную корректирует баланс: форма запрашивает сумму, валюту и комментарий, а система сама создаёт соответствующую транзакцию.
- Баланс — суммарное состояние счёта пользователя в валюте;
- История транзакций — хронология всех операций с описанием;
- Ручная корректировка — административное пополнение или списание с обязательным комментарием.
На стороне покупателя история видна в личном кабинете, в разделе внутреннего счёта — там он видит только собственные операции и итоговый баланс.
Структура записи транзакции
Все транзакции хранятся в таблице b_sale_user_transact, а сами счета — в b_sale_user_account (по строке на пару «пользователь + валюта»). В D7 к ним обращаются через \Bitrix\Sale\Internals\UserTransactTable и \Bitrix\Sale\Internals\UserAccountTable. Ключевые поля записи:
| Поле | Назначение |
|---|---|
USER_ID | Покупатель, которому принадлежит счёт |
TRANSACT_DATE | Дата и время операции |
AMOUNT | Сумма операции (положительная — приход, отрицательная — расход) |
CURRENCY | Валюта счёта |
DEBIT | Флаг Y/N — зачисление или списание |
ORDER_ID | Заказ, с которым связана операция (если есть) |
PAYMENT_ID | Платёж, породивший транзакцию |
DESCRIPTION | Текстовое пояснение к операции |
Поле DEBIT дублирует знак суммы на уровне флага и удобно для фильтрации: по нему легко отделить все пополнения от всех списаний, не разбирая знак AMOUNT.
Пополнение и списание
Содержательно все транзакции сводятся к двум типам операций, но поводов для них несколько:
- Пополнение (приход, DEBIT=Y) — покупатель внёс деньги через платёжную систему, администратор начислил бонус или вернул средства за отменённый заказ;
- Списание (расход, DEBIT=N) — оплата заказа с внутреннего счёта, ручное административное списание или коррекция ошибочного начисления.
Обратите внимание: баланс счёта не может уйти в минус штатными средствами. Если на счёте недостаточно средств, система не позволит списать больше, чем есть, — оплата заказа с баланса просто не пройдёт полностью. Поэтому «отрицательный баланс» почти всегда сигнал о некорректных прямых операциях с таблицей в обход API.
b_sale_user_account без парной транзакции в b_sale_user_transact рассинхронизирует счёт: сумма истории перестанет сходиться с балансом, и сверка станет невозможной.Работа с транзакциями через API
Правильный способ изменить баланс — всегда через API, которое атомарно обновляет и счёт, и историю. Классический метод — CSaleUserAccount::UpdateAccount(): он принимает пользователя, сумму, валюту, тип операции, номер заказа и описание, а внутри сам создаёт транзакцию и пересчитывает баланс.
CSaleUserAccount::UpdateAccount($userID, $sum, $currency, $transactType, $orderID, $description)— начисление или списание со счёта;CSaleUserAccount::Pay($userID, $sum, $currency, $orderID, $bPay)— оплата заказа с баланса и возврат средств обратно на счёт;CSaleUserAccount::GetByUserID($userID, $currency)— получить текущий баланс покупателя.
В параметре $sum знак определяет направление: положительное значение зачисляет средства, отрицательное — списывает. В новом ядре аналогичные операции решаются через объекты заказа и оплаты, но для точечных начислений (бонус, компенсация) удобнее прямой вызов UpdateAccount() — он гарантирует согласованность счёта и журнала транзакций.
Оплата заказа с внутреннего счёта
Чтобы покупатель мог платить с баланса, в магазине подключается платёжная система с обработчиком inner («Внутренний счёт» / «Оплата с внутреннего счёта»). Настраивается она в разделе Магазин → Настройки → Платёжные системы и привязывается к нужным типам плательщиков.
При выборе этого способа оплаты и подтверждении платежа Битрикс списывает сумму заказа со счёта и создаёт транзакцию DEBIT=N с привязкой к ORDER_ID и PAYMENT_ID. Если заказ отменяют или платёж снимают, средства возвращаются на счёт обратной транзакцией — так баланс всегда отражает реальное состояние.
Типичные проблемы и сверка
Большинство инцидентов со счётом — это расхождение баланса и истории, и почти всегда причина в операциях мимо штатного API.
- Баланс не сходится с суммой транзакций — правили
b_sale_user_accountнапрямую или создавали транзакцию без обновления счёта; - Двойное списание — событие оплаты обработано дважды из-за повторного колбэка платёжной системы;
- Пропала связь с заказом — транзакция создана без
ORDER_ID, и операцию сложно объяснить при разборе; - Разные валюты на одном пользователе — счёт ведётся по валютам, и суммировать транзакции в разных валютах нельзя.
Для контроля полезна регулярная сверка: сумма всех AMOUNT по пользователю и валюте должна совпадать с балансом в b_sale_user_account. Любое начисление, тем более импортированное из внешней системы, стоит проводить только через UpdateAccount() и обязательно с осмысленным описанием.
Итог
Транзакции по счёту покупателя в 1С-Битрикс — это неизменяемый журнал движения средств, из которого складывается баланс. Записи хранятся в b_sale_user_transact, счёт — в b_sale_user_account, а корректный способ их менять — только через API (CSaleUserAccount::UpdateAccount() и Pay()), которое одновременно пишет транзакцию и пересчитывает баланс. Прямая правка базы почти всегда приводит к рассинхронизации и невозможности сверки.
Если внутренний счёт — часть вашей логики лояльности, возвратов или расчётов с оптовиками, важно, чтобы начисления, списания и интеграции с внешними системами работали согласованно. Мы в B2Bsite настраиваем и дорабатываем механику счёта и транзакций на Битрикс, а также сопровождаем магазин, чтобы баланс всегда сходился с историей.
Частые вопросы
В какой таблице хранятся транзакции по счёту?
Транзакции лежат в таблице b_sale_user_transact, а сами счета покупателей — в b_sale_user_account по строке на пару пользователь и валюта. В D7 к ним обращаются через UserTransactTable и UserAccountTable.
Как правильно начислить средства на счёт покупателя?
Используйте метод CSaleUserAccount::UpdateAccount() с положительной суммой, валютой и описанием. Он атомарно создаёт транзакцию и пересчитывает баланс, поэтому история и счёт остаются согласованными.
Что означает поле DEBIT в транзакции?
DEBIT — это флаг направления операции: Y для зачисления (прихода) и N для списания (расхода). Он дублирует знак суммы AMOUNT и удобен для фильтрации пополнений и списаний.
Можно ли редактировать существующую транзакцию?
Нет, транзакция по своей природе неизменяема. Чтобы исправить ошибку, создают новую компенсирующую операцию, а не правят старую запись.
Почему баланс счёта не совпадает с суммой транзакций?
Обычно причина в том, что баланс или транзакцию меняли напрямую в базе в обход API. Корректный баланс — это сумма всех AMOUNT по пользователю и валюте, и она должна совпадать со значением в b_sale_user_account.
Как настроить оплату заказа с внутреннего счёта?
Подключите платёжную систему с обработчиком inner в разделе Магазин, Настройки, Платёжные системы и привяжите её к нужным типам плательщиков. При оплате Битрикс спишет сумму со счёта и создаст транзакцию с DEBIT=N.
Может ли баланс внутреннего счёта уйти в минус?
Штатными средствами нет: система не даст списать больше, чем есть на счёте. Отрицательный баланс почти всегда означает некорректные прямые операции с таблицей в обход API.
Учитываются ли разные валюты на одном счёте?
Да, счёт ведётся отдельно по каждой валюте — на пользователя может быть несколько балансов. Складывать транзакции в разных валютах нельзя, сверку делают по каждой валюте отдельно.
Поможем с настройкой и поддержкой 1С-Битрикс: Управление сайтом
Поможем с настройкой, доработкой и поддержкой 1С-Битрикс: Управление сайтом.