Один кошелёк, один журнал и процесс, который не может потерять ни одного движения.
У каждого мерчанта один пополняемый кошелёк. Карты выпускаются из него, расходы списываются из него, выводы идут из него. Ничего не движется без сбалансированных проводок в журнале, куда можно только добавлять.
Кошельки
Один кошелёк на мерчанта, в целых минорных единицах.
Кошелёк мерчанта хранит баланс в целых минорных единицах — центах, а не дробях. В денежном потоке нет чисел с плавающей точкой, поэтому ошибка округления не накопится даже за миллион движений. Балансы вычисляются из журнала, а не берутся из накопительного итога, и ежечасная проверка пересчитывает их и сообщает о любом расхождении.
- Единица
- целые минорные единицы (BIGINT)
- Источник баланса
- вычисляется из записей журнала
- Контроль расхождений
- ежечасно, оповещает о несовпадении
Пополнения
Пополнение приходит в криптовалюте и зачисляется после подтверждения.
Мерчант запрашивает постоянный адрес пополнения для каждой сети. Средства, отправленные на него, зачисляются в кошелёк после подтверждения, как обычное сбалансированное движение. Расчёт по пополнению идёт в два этапа — провайдер уведомляет, затем платформа запрашивает достоверную запись, — поэтому уведомление без суммы никогда не зачислит неверную цифру. Ежечасная сверка идемпотентно перепроверяет всё, что пропустил вебхук.
- Адреса
- постоянные, для каждой сети
- Расчёт
- в два этапа: уведомление, затем запрос записи
- Резервный механизм
- ежечасная сверка, идемпотентно
Выпуск
Карты выпускаются по схеме: резерв, провайдер, расчёт.
При выпуске в кошельке резервируются первоначальное пополнение и комиссия за выпуск, лицензированный партнёр-эмитент вызывается вне транзакции базы данных, а при успехе движение записывается в журнал. Вызов провайдера никогда не выполняется внутри транзакции или блокировки, поэтому медленный или упавший эмитент не может держать кошелёк мерчанта открытым. Если партнёр выпускает асинхронно, вызов возвращает карту в статусе pending, а тот же расчёт выполняется позже — по вебхуку партнёра или при сверке, — по любому пути и только один раз.
- Процесс
- резерв → провайдер → расчёт
- Вызов провайдера
- никогда внутри транзакции или блокировки
- Асинхронный результат
- 202 pending, расчёт по вебхуку или сверке
Держатели карт
Данные личности хранятся один раз, зашифрованно, и используются повторно.
Данные держателя хранятся в реестре клиентов, а не отправляются заново с каждым запросом. Записи зашифрованы при хранении и передаются эмитенту только внутри запроса на выпуск. Номера карт и коды безопасности никогда не раскрываются через API и не сохраняются — ресурс карты содержит маскированный номер и последние четыре цифры, не более.
- Хранение
- зашифровано при хранении
- Номер карты / CVV
- никогда не раскрывается и не хранится
- Ресурс карты
- маскированный номер + последние четыре цифры
Авторизации
Расходы сводятся к проводкам с нулевой суммой.
Авторизация не меняет баланс напрямую. Она записывает движение с равными и противоположными дебетовой и кредитовой проводками, так что итог равен нулю, а баланс — это то, что показывает журнал при чтении. Исправления записываются новыми проводками, а не правками. В журнале ничего не обновляется и не удаляется.
- Журнал
- только добавление
- Каждое движение
- минимум две сбалансированные проводки
- Исправления
- записываются новыми проводками
Выводы
Деньги выводятся через цикл одобрения, а не вызовом API.
У выводов нет публичного API. Мерчант запрашивает вывод в кабинете, оператор платформы одобряет его, а завершение фиксируется с подтверждением выплаты. Каждое изменение статуса записывается в журнал аудита только для добавления с указанием исполнителя. Это сделано намеренно: эндпоинт, выводящий деньги с платформы, — единственный, до которого не должен дотянуться утёкший API-ключ.
- Публичный API
- нет — только кабинет и админка
- Порядок
- запрос → одобрение → завершение
- Аудит
- каждый переход, с исполнителем
Отчётность
Цифры читаются из журнала, а не из счётчика.
Ночные агрегаты строятся из записей журнала, а не из отдельной колонки выручки, поэтому отчёт и реальные деньги не могут расходиться. Тестовая активность исключается структурно — через join, а не фильтром, о котором нужно не забыть.
- Источник
- записи журнала
- Расписание
- ночью
- Тестовая активность
- исключена структурно
Где мы сейчас.
По умолчанию платформа работает с симулятором карточного провайдера. Первая реальная интеграция выпуска построена и сертифицирована в песочнице и перейдёт в продакшен после подтверждения учётных данных и секрета вебхука с партнёром. Подпись криптопополнений реализована и ожидает боевой сертификации.
Пока это не завершено, страница описывает реализованное и протестированное поведение, а не работающий боевой сервис выпуска. Лучше сказать это здесь, чем вы узнаете об этом во время интеграции.