Начну с описания задачи; в этот раз она касается разработки ПО и вполне себе реальная. Есть ООО, недавно начавшее деятельность и являющееся субъектом малого бизнеса, но уже имеющее пока что совсем небольшой объём операций на паре счетов в разных банках. И есть сайт, оказывающий платные услуги преимущественно юрлицам.
Принцип работы, если сильно не вдаваться в детали, прост:
- клиент заказал на сайте услугу, получил счёт, оплатил его;
- как только деньги пришли, появились обязательства, услугу надо подключить согласно заказу.
Если выставление счетов более или менее автоматизировано, то с подключением услуги сложнее.
Это делает вручную сотрудник, который отсматривает два клиент-банка, проверяет входящие платежи и подключает услуги, а также выгружает выписки в файлы и загружает их в бухгалтерскую конфигурацию 1С для последующего учёта в бухгалтерии.
Естественно, это (пока потенциально, но задуматься об этом уже пора) небезошибочно, особенно с предстоящим потенциальным увеличением количества входящих операций.
Возникло желание сей процесс автоматизировать.
Некоторые очень продвинутые банки вроде Тинькофф имеют API для получения выписок. Это позволяет делать программы, которые сами периодически (например, раз в 10 минут) отправляют на сервер банка запросы на получение выписок, ищут в результатах запроса новые платежи и при их обнаружении забирают данные и автоматически, вообще без участия человека их обрабатывают.
С точки зрения оперативности и экономии трудовых ресурсов это самый хороший вариант реализации. Но банка у нас два разных. Не все банки имеют удобную реализацию такого API; некоторым для его работы требуется даже квалифицированная электронная подпись, что добавляет технических сложностей в реализацию.
И, кроме того, каждый банк разрабатывает спецификацию и реализует API самостоятельно – т. е., очень грубо говоря, один и тот же реквизит платёжки будет у одного банка называться так, у другого эдак, как конкретный разработчик в банке придумает. То есть, под каждый банк надо или писать свои компоненты для запроса выписок, или где-то искать или покупать готовые, если работа идёт на каком-то готовом стандартном движке.
Со временем, надеюсь, и здесь это сделать получится, но пока что нужно более быстрое решение, желательно в количестве одной универсальной штуки.
Решение на первом этапе просматривается простое. Если уж сотрудник выгружает из клиент-банков файлы выписок для загрузки в 1С, почему бы ему эти файлы сразу не загружать ещё и на сайт? Помимо своих форматов, есть единый формат формирования банковских выписок от 1С, и большинство банков умеет выгружать выписки в нём.
Соответственно, решили сделать загрузку файлов из этого формата. Опыта работы с файлами банковских выписок раньше у меня не было, тем интереснее было попробовать. Тем не менее, был очень приличный опыт работы с описаниями форматов и реализации чтения и формирования файлов отчётности в ПФР и ФНС по описаниям, так что я имел основания считать, что задача в общем тривиальная и не особо сложная. Но по ходу работы начались сюрпризы.
Начинается такая работа с изучения документации и (или) примеров. Нагуглил описание формата файлов на сайте фирмы 1С, выпросил немного файлов загрузки из клиент-банков, откуда предполагалось брать файлы выписок, заодно выгрузил у себя (как ИП, я тоже имею клиент-банк и могу выгружать аналогичные выписки, только банк другой) и сел читать, смотреть и экспериментировать.
Сюрпризы начались с самого начала файла выгрузки. Вот первые три строки:
1CClientBankExchange
ВерсияФормата=1.03
Кодировка=Windows
В формате на эту тему сказано следующее:
Уважаемые коллеги из 1С, подскажите, пожалуйста, как это понимать? Любому (ну или почти любому) прикладному разработчику известно, что, хотя в кодировках DOS и Windows каждый символ кодируется одним числом в диапазоне от 0 до 255 (такое число помещается в 1 байт памяти), но при этом одинаковыми числами в обеих этих кодировках кодируются только латинские буквы и большинство символов, а русские буквы кодируются по-разному. Таким образом, слова «Кодировка» и «ВерсияФормата» соответственно в третьей и второй строках файла могут быть представлены разными значениями в зависимости от того, в какой из этих двух кодировок сформирован файл.
Получается, что мне после проверки содержания первой строки на наличие внутреннего признака файла обмена (чтобы убедиться, что загрузили именно файл обмена с клиент-банком, а не что-то ещё) надо:
- идти сразу в третью строку, там сравнивать её значение с заранее сформированными вариантами строк в кодировках DOS и Windows;
- в зависимости от результата сравнения перекодировать хотя бы вторую строку файла (а лучше все) в единую кодировку, с которой работает уже моя программа;
- и только после всего этого я смогу определить версию формата и понять, умеет ли в данный момент программа с ней работать (с более поздними или ранними версии работать без намеренной их реализации небезопасно).
Простите, назову уж вещи своими именами: изврат, да и только. Но это ладно – во всяком случае, более или менее реализуемо. Цветочки, что называется. Дальше пойдёт про ягодки.
После заголовка файла (в нём помимо вышеперечисленных реквизитов есть ещё несколько, но для моей задачи они не важны) по формату идёт секция передачи остатков по расчетному счету (их, по идее, может быть несколько, но для конкретно моей задачи они не важны), а затем одна или много секций с платёжными документами (вот они меня максимально интересуют).
В теории моя задача – построчно перебрать каждую из содержащихся в файле секций платёжного документа, получить из них хотя бы необходимый для работы минимум реквизитов платёжки и пустить в дальнейшую работу. Практика показала, что в плане получения реквизитов не всё так просто.
Спойлер: задача в общем была выполнена и запущена, но пока что находится на внимательном контроле, т. к. не все возможные особенности учтены, в том числе из-за малого объёма текущей работы.
Сразу оговорюсь, что я не являюсь ни бухгалтером, ни специалистом по банковскому делу. И понимаю, что в своих суждениях, местами довольно резких, могу быть неправ. Так что не уверен, что дальнейшая критика от меня будет полностью справедливой, и не хочу прямо обвинять кого-то в косяках, тем более, не зная истории развития обмена и внутренней кухни. Если что, приглашаю сведущих читателей в комменты пояснить или поправить. Ну и, конечно, готов к конструктивной критике.
Понимаю, что читать меня будут не только бухгалтеры, но и несколько более отвлечённые от этих вещей айтишники. Для них сделаю небольшое лирическое отступление с подробностями.
Чтобы бухгалтер клиента смог произвести безналичную оплату услуги, он должен составить и подать в банк платёжное поручение, в которое подставит из полученного счёта или другого документа данные получателя платежа, а именно:
- название (или ФИО, если это ИП);
- ИНН, КПП (для юрлиц);
- банковские реквизиты: название банка, его БИК (уникальный код), номер корреспондентского счёта банка в Банке России (для проведения платежей между разными банками, по умолчанию ставится всегда) и номер расчётного счёта получателя в этом банке.
Также платёжка содержит аналогичные реквизиты отправителя денег, сумму и назначение платежа (текстовое поле), в котором указывается, за что и на основании какого документа делается платёж. Это, что называется, необходимый минимум.
Есть ещё некоторые служебные реквизиты и тонкости заполнения отдельных видов платёжек (или по отдельным клиентам), но это тема отдельная и не самая простая; подробнее о заполнении платёжек можно почитать в приложении № 1 к Положению Банка России от 19 июня 2012 года № 383-П «О правилах осуществления перевода денежных средств».
Бухгалтерские программы обычно имеют возможность загрузки полученных из своего банка клиентских платёжек и по-максимуму реквизитов из них. Это позволяет не только учитывать поступления, но и, например, делать электронные платёжки на полный или частичный возврат средств по уже имеющимся в базе реквизитам отправителя. Но для этого, разумеется, надо, чтобы эти реквизиты (хотя бы те, что я перечислил выше; другие в рамках задачи запоминать смысла нет) были корректными.
Чтобы максимально соблюсти эту самую корректность, хотелось бы иметь платёжку клиента в оригинале, как она была отправлена им в банк, со всеми реквизитами в нужных местах. Но здесь вот возникают трудности.
Посмотрим на описание изучаемого формата обмена с 1С в части реквизитов, а именно реквизитов плательщика (получателем являемся мы сами, это менее критично, хотя и не скажу, что приятно):
По реквизитам ПлательщикСчет и ДатаСписано вопросов и проблем нет; описаны они нормально, а второй из них так нам и вообще в работе не нужен. А вот реквизит Плательщик, который по формату содержит наименование и ИНН плательщика, вообще не прописан как обязательный при импорте из клиент-банка в 1С (на это указывает слово «нет» в третьей графе таблицы).
Как делятся наименование и ИНН в данном необязательном реквизите и насколько условна эта необязательность, тоже непонятно. При этом из соседнего, уже обязательного реквизита ПлательщикИНН можно более или менее гарантированно извлечь ИНН плательщика (спрашивается, и зачем дублировать?). Но, по идее, для бухгалтерской программы этого маловато; причины в лирическом отступлении я изложил. Да и для нас не то чтобы много, пусть даже меня больше интересует назначение платежа с номером оплачиваемого счёта, а остальным будут заниматься отдельные компетентные люди.
Идём дальше. С пометкой «В случае непрямых расчетов» (это каких?) идёт стопка необязательных реквизитов (т. е., которые в теории можно не указывать). Про то, как они названы и как название реквизита соответствует описанию, уже говорить не буду; посмотрите сами в таблице, а у меня цензурных слов не оставалось после того, как я всё это прочитал.
Задам только опять же вопрос уважаемым коллегам из 1С: правильно ли я понимаю, что разработчики формата в процессе разработки (кстати, сколько лет назад её делали?) предполагали полноценно использовать только секцию передачи остатков и максимум считать в бухгалтерской программе количество операций и итоги, а за всем остальным предлагать пользователю лезть в клиент-банк?
Ну... не знаю даже, как-то слишком много напрашивается вариантов, когда файл формально соответствует описанию, но при этом не содержит достаточно реквизитов для последующих возможных действий. Если, к примеру, банк подошёл к реализации выгрузки в формат формально, сменим банк или будем постоянно у клиентов копии платёжек просить?
Теперь посмотрим на то, как в практике реализовывали формат банки на примере реальных выгрузок (опять же, в части описания платёжек) – т. е., на примеры выгрузок. Сначала глянем, что называется, на «выгрузку здорового человека» с платёжкой от ООО со счёта в банке Тинькоф в адрес ИП на его предпринимательский счёт в банке Уралсиб (выгружено получателем из клиент-банка Уралсиба; чёрным цветом замазана часть информации, которую не очень-то хочется раскрывать, но там указаний на проблемы точно нет):
Итак, здесь мы видим, что необязательного реквизита Плательщик в файле нет. Но есть заполненное поле ПлательщикИНН, а название плательщика пристроено в поле Плательщик1, которое «в случае непрямых расчетов». КПП плательщика (который является юрлицом) помещён в реквизит ПлательщикКПП, который является обязательным, но в формате записан в разделе «Дополнительные реквизиты для платежей в бюджетную систему Российской Федерации» (спрашивается: ИП – это бюджетная система?).
Название банка пристроено в реквизит ПлательщикБанк1, его БИК находится в реквизите ПлательщикБИК, корсчёт в ПлательщикКорсчет (все эти реквизиты – для непрямых платежей по формату, обязательными не являются, а у корсчета и БИК в описании формата сказано, что это корсчет и БИК РЦ банка, а не самого банка). Формально в полном соответствии с форматом из банковских реквизитов плательщика заполнено только поле ПлательщикСчет.
Но, по крайней мере, все перечисленные реквизиты контрагента из выписки можно извлечь; с этим более или менее можно жить. Вопрос в том, что по другим банкам: будут они делать так же или расставлять реквизиты по-своему?
С имеющимся количеством операций по ещё одному банку (это ростовский филиал АльфаБанка) полноценной выписки со множеством платёжек добыть для анализа и проверки пока не удалось ввиду малого объёма операций; получил пока только выписку, содержащую только одну входящую платёжку. Но зато, что называется, платёжку курильщика. И какую...
Если что, вот попрошенный для разбора ситуации скрин этой же платёжки «в бухгалтерски читаемом виде» из клиент-банка (или из 1С, точно не знаю):
Скрин этот я попросил уже после того, как увидел файл выгрузки. Не знаю, насколько корректно этот файл удалось загрузить в 1С, но заполнение платёжки впечатляет.
Думаю, знающий бухгалтерский глаз уже за много чего зацепился, а для непричастных поясню имеющиеся проблемы:
- В поле Плательщик и бумажного, и электронного варианта (если что, это не кредитная организация) указано не наименование и ИНН, как по формату файла (ну и по заполнению бумажного варианта в соответствии с вышеуказанным положением Банка России тоже сомнения есть), а наименование, номер расчётного счёта, название и БИК банка плательщика.
- В абсолютном большинстве случаев номер расчетного счета организации или ИП начинается на цифру 4 (последующие четыре цифры отличаются в зависимости от того, юрлицо это, физлицо или ИП). Здесь же в поле счета плательщика, где в норме указывается расчетный счет этого самого плательщика, мы видим номер с первыми пятью цифрами 30302. Согласно Плану счетов бухгалтерского учета для кредитных организаций (утвержден Положением Банка России от 27 февраля 2017 г. № 579-П), эти цифры подписаны как «Внутрибанковские требования по переводам клиентов».
- Название банка плательщика указано как ФИЛИАЛ «РОСТОВСКИЙ» АО «АЛЬФА-БАНК» г. Ростов-на-Дону, его БИК и корсчет указаны на сайте АльфаБанка как реквизиты этого филиала (у каждого филиала свои). Но, насколько мы понимаем, клиент платил со счёта в Сбере; большая часть реквизитов указана в названии плательщика, но корсчёта Сбера как исходного банка нет нигде от слова совсем.
Электронная версия отличается не сильно. Как вы уже видели, в случае непрямых расчетов в необязательное поле ПлательщикРасчСчет вроде как (если поле есть) ставится корсчет банка плательщика. Но там вместо него стоит значение, совпадающее с таковым в поле ПлательщикСчет (собственно расчетный счет) и являющееся внутренним счетом банка (Альфы? Сбера?). Корсчет и БИК плательщика, которые в уралсибовской выгрузке стояли в полях для РЦ, указаны там же, но не сберовские, как у плательщика, а альфовские (точнее, филиала). Опять же: корсчёта Сбера там нет. Вообще.
Конечно, возникло множество вопросов. Если вдруг мне потребуется сформировать возвратную платёжку, и я просто возьму и скопирую в реквизиты получателя реквизиты плательщика из этой платёжки и отправлю её в тот же ростовский АльфаБанк, там платёжку примут и обработают? Или сразу завернут, или сначала засмеют её отправителя?
Как-то не верится, что именно с такими реквизитами клиент при оплате заказа отправил платёжку в Сбер, и у него её приняли и обработали. Откуда и на чьей стороне такая самодеятельность? И зачем постороннему лицу (клиенту банка) в выписке по сути внутренняя кухня банка в виде его внутреннего счета?
Ну и да. Это была первая и единственная платёжка Альфы, которую я видел в своей жизни в электронном виде. Если будет кто из АльфаБанка, подскажите плиз, это какой-то ваш особенный порядок приёма платёжек из других банков с заменой реквизитов, или какой-то отдельный случай (косяк или просто что-то особенно-нештатное, ну или особенности работы с платёжками из Сбера)?
Пока что в основном реквизиты даже из такой платёжки вытащить удалось, если не считать корсчёта (который в теории можно стащить с какой-нибудь открытой базы банков), но как-то такой подход мне не очень нравится. Или такие вопросы у меня возникают из-за незнания приёмов работы банков изнутри (чего в общем я и не отрицаю)?
И, наверное, в заключение обращусь к коллегам из 1С. Может быть, я не прав, но формат обмена в таком виде уже сильно устарел. Как бы вы смотрели на то, чтобы выпустить новую версию формата, переработав его в стороны упрощения, структурирования, перевода в какой-нибудь современный структурированный язык (XML, JSON или ещё что-то аналогичное) и актуализации/корректировки названий реквизитов в соответствии с нынешними порядками в ЦБ? При необходимости готов помочь с обсуждением и в чём-то реализацией проекта, только бы кого-нибудь из компетентных банковских специалистов в помощь привлечь. Спасибо.
Комментарии
1Монументальный труд