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

До интеграции этой информации в 1С не было вообще. Дольщики получали информацию по своим счетам с задержкой до трёх дней.

Задача звучала просто: пусть движение по эскроу и расчётным счетам появляется в 1С само. Готового решения под эскроу‑часть не нашлось, поэтому интеграции со Сбербанк API и Альфа‑Банк API я писал с нуля. Банков два, и API у них разные — это приходится учитывать с первого дня. Ниже — не пересказ документации банка (её лучше читать в первоисточнике, она меняется), а то, из каких частей состоит такая интеграция на стороне 1С и какие решения я бы принял снова.

Из чего состоит интеграция

Если убрать детали, интеграция с банковским API на стороне 1С — это пять слоёв:

  1. Транспорт и авторизация. HTTPS‑запросы, получение и продление доступа к API.

  2. Клиент API. Тонкий слой: «получить список счетов», «получить операции за период», «получить сведения по эскроу‑счёту». Ничего не знает про документы 1С.

  3. Хранилище сырых ответов. Всё, что пришло от банка, сохраняется как есть — до разбора.

  4. Сопоставление. Счёт банка → банковский счёт организации в 1С, контрагент по ИНН, операция по эскроу → договор долевого участия.

  5. Отражение в учёте. Создание документов или записей регистров, идемпотентно.

У Сбербанка и Альфа‑Банка различалось всё, что касается первых двух слоёв: авторизация, устройство API, форматы данных. При таких различиях я бы держал транспорт и клиент API отдельными для каждого банка, а всё, что ниже, — общим: ответ любого банка приводится к одному внутреннему формату операции, и дальше сопоставление и отражение в учёте уже не знают, откуда пришли данные.

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

Слой 1. Аутентификация: токены живут своей жизнью

Банковские API почти всегда используют короткоживущий access‑токен и более долгоживущий refresh‑токен. На стороне 1С из этого следуют простые, но обязательные вещи:

  • токены хранятся в безопасном хранилище (ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище в БСП), а не в реквизите справочника;

  • обновление токена — одна точка в коде, с блокировкой: если два регламентных задания одновременно решат обновить токен, одно из них может получить уже недействительный refresh;

  • при ошибке «токен недействителен» — одна попытка обновить и повторить запрос, не больше. Бесконечный цикл ретраев против банковского API — плохая идея.

Функция ВыполнитьЗапросКБанку(Метод, Ресурс, Тело = Неопределено) Экспорт

    Ответ = HTTPЗапросСТокеном(Метод, Ресурс, Тело, ТекущийТокен());

    Если Ответ.КодСостояния = 401 Тогда
        ОбновитьТокенСБлокировкой();
        Ответ = HTTPЗапросСТокеном(Метод, Ресурс, Тело, ТекущийТокен());
    КонецЕсли;

    СохранитьСыройОтвет(Ресурс, Ответ); // до любой обработки
    Возврат Ответ;

КонецФункции

Процедура ОбновитьТокенСБлокировкой()

    Блокировка = Новый БлокировкаДанных;
    Элемент = Блокировка.Добавить("РегистрСведений.СостояниеИнтеграцииСБанком");
    Элемент.Режим = РежимБлокировкиДанных.Исключительный;

    НачатьТранзакцию();
    Попытка
        Блокировка.Заблокировать();
        // Пока ждали блокировку, токен мог обновить другой сеанс
        Если ТокенЕщёДействителен() Тогда
            ЗафиксироватьТранзакцию();
            Возврат;
        КонецЕсли;
        НовыеТокены = ЗапроситьТокеныПоRefresh();
        СохранитьТокены(НовыеТокены);
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        ВызватьИсключение;
    КонецПопытки;

КонецПроцедуры

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

Доступы и тестовый контур

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

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

Главная сложность: документация и реальное поведение API

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

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

Здесь же пригодятся сохранённые сырые ответы (о них — в следующем разделе): с ними на руках разговор идёт о конкретном запросе и конкретном ответе, а не о том, «как оно вроде бы работает».

Слой 3. Сохраняйте сырые ответы

Это правило я повторяю в каждой интеграции, но с банком оно особенно важно. Когда финансист спрашивает «почему в 1С эта сумма, а в банке другая», ответ должен начинаться с «вот что банк прислал в такое‑то время», а не с «давайте попробуем воспроизвести».

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

Слой 4. Сопоставление: эскроу — это не просто ещё один счёт

С расчётными счетами всё относительно привычно: операция, контрагент по ИНН, назначение платежа. С эскроу появляется ещё одна сущность — договор долевого участия, к которому привязан счёт, и события по нему: поступления от дольщика, раскрытие, закрытие.

Что здесь важно:

  • Ключ сопоставления — не назначение платежа. Текст назначения пишут люди, и он бывает любым. Надёжнее опираться на идентификаторы, которые отдаёт банк, и один раз связать их с объектами 1С.

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

  • Хешируйте ключи поиска. Составной ключ (например, счёт + дата + сумма + идентификатор операции), нормализованный и захешированный, превращает повторный поиск в одно обращение к индексу.

Функция КлючОперации(Операция)
    Части = Новый Массив;
    Части.Добавить(НРег(СокрЛП(Операция.НомерСчёта)));
    Части.Добавить(НРег(СокрЛП(Операция.ИдентификаторОперации)));
    Части.Добавить(Формат(Операция.Сумма, "ЧДЦ=2; ЧРД=.; ЧГ=0"));
    Хеш = Новый ХешированиеДанных(ХешФункция.SHA256);
    Хеш.Добавить(СтрСоединить(Части, "|"));
    Возврат ПолучитьHexСтрокуИзДвоичныхДанных(Хеш.ХешСумма);
КонецФункции

Обратите внимание на Формат суммы: без явного формата Строка(1500.5) на разных серверах может дать разный результат из‑за региональных настроек — и хеш «поплывёт».

Слой 5. Идемпотентность: одна операция — один документ

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

Для Каждого Операция Из Операции Цикл
    Ключ = КлючОперации(Операция);
    Если ОперацияУжеОтражена(Ключ) Тогда
        Продолжить;
    КонецЕсли;
    НачатьТранзакцию();
    Попытка
        Документ = СоздатьДокументПоОперации(Операция);
        ЗапомнитьКлюч(Ключ, Документ);
        ЗафиксироватьТранзакцию();
    Исключение
        ОтменитьТранзакцию();
        ПоставитьВОчередьРазбора(Операция, ИнформацияОбОшибке());
    КонецПопытки;
КонецЦикла;

Транзакция на каждую операцию, а не на всю выписку: одна проблемная строка не должна блокировать отражение остальных.

Время и даты

Отдельный пункт, потому что он тихий. Банк отдаёт даты в своём формате и часовом поясе; сервер 1С живёт в своём; пользователи — в своём. Договоритесь, какая дата считается датой операции для учёта, и приводите явно. Особенно внимательно — к операциям около полуночи и на границе месяца, где «не та дата» означает «не тот период».

Как это тестировать, не рискуя деньгами

Банковская интеграция — не то место, где хочется «проверить на проде». Порядок, который я считаю правильным:

  1. Тестовый контур банка — для транспорта, авторизации и формата ответов. Мы начинали именно с него.

  2. Копия рабочей базы 1С — для сопоставления и отражения. Именно на копии всплывают проблемы самих данных: контрагенты без КПП, опечатки в номерах банковских счетов организации и тому подобное.

  3. Прогон на реальных сырых ответах. Поскольку ответы банка сохраняются, их можно многократно «проигрывать» на копии, меняя логику сопоставления, — не дёргая банк.

Мониторинг: банк молчит — это тоже событие

Для банковской интеграции я бы выделил три сигнала, о которых ответственный должен узнавать сам, не открывая 1С:

  • ошибка аутентификации, которую не вылечило обновление токена, — чаще всего это истёкший сертификат или отозванные права приложения;

  • растущая очередь несопоставленных операций — значит, появился новый контрагент, счёт или договор, о котором 1С не знает;

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

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

Что получилось

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

Масштаб — около 24 000 счетов по 30 объектам строительства в двух банках (Сбербанк и Альфа‑Банк) с разными API.

Вместо выводов

Банковская интеграция — одна из самых «нервных» для 1С: в ней деньги. Она прощает медленную разработку и не прощает потерянную операцию или задвоенный документ. Поэтому порядок работы у меня такой: сначала хранилище сырых данных и идемпотентность, потом всё остальное. Отладка — на тестовом контуре банка и копии базы. И как можно раньше — живой контакт в банке, потому что документация не всегда совпадает с реальностью.

Если делаете похожую интеграцию и хотите обсудить детали — пишите в комментариях.