Pull to refresh

Интеграция 1С и B2B системы, с помощью HTTPS

Reading time5 min
Views10K
Привет Хабраюзер хочу поделиться своим недавним опытом интеграции двух различных систем.

Возникла задача о передаче данных между 1С (разработка и настройка была отдана на аутсорсинг), которую планируется использовать как основную систему электронного документооборота (ЭДО) и B2B системой (внутренняя разработка), которая написана на PHP (Symfony) и выполняет функции первичного ввода информации в компании.

У меня уже был опыт интеграции B2B с другой B2B. Суть заключалась к передаче JSONа при помощи cURL. Затем возникла задача интеграции системы «Borlas», основанная на Oracle, где также был применен данный подход. На стороне Oracle, правда, использовался свой пакет — аналог cURL в PHP (если будет интересно, могу описать в новой статье).

Как я выяснил, 1С 8.2 тоже умеет посылать GET и POST запросы. Предположил, что если уже все настроено и работает с другими системами, значит, и тут должно сработать. JSON отвергли разработчики 1С, сказав, что формат неподходящий и они признают только XML. Комментарии о том, что это нам даст минимум в размере при передаче данных, а данных действительно получалось очень много, были отвергнуты. В итоге приступили в подготовке 2 систем на основе XML.

Cо своей стороны я написал приемщик запросов из 1С и возврат результатов. Функция по приему переменной в POST, в которой 1Сники должны были подставлять XML.
Формат примерно следующий:

<xml version="1.0">
<KEY>123ABC456</KEY> //ключ авторизации
<MODE>get_last_orders </MODE> //операцию что хотят выполнить
<LIMIT>4000</LIMIT>//лимит записей что хотят отобрать
</xml>


обработчик, который возвращает уже отобранные по условиям записи и формирует XML вида:

<?xml version="1.0" encoding="utf-8" ?>
<data>
<order>
<type1>1</type1>
<type>OPS</type>
<ref></ref>
<id_doc>4853352</id_doc>
<start_date>01.01.2013</start_date>
<validity>1</validity>
<description>Загружено из b2b</description>
<additional>
<Param>
<ParamName>СНИЛС</ParamName>
<ParamValue>999999999</ParamValue>
</Param>
<Param>
<ParamName>ФИО клиента</ParamName>
<ParamValue>МИХАЙЛОВ МИХАИЛ ЕВГЕНЬЕВИЧ</ParamValue>
</Param>
<Param>
<ParamName>Дата заявления</ParamName>
<ParamValue>01.01.2013</ParamValue>
</Param>
</additional>
</order>
<order>
...
</order>
</data>


Данные могут быть переданные только через HTTPS соединение.

На первый взгляд, кажется, что все просто, но в процессе возникло несколько проблем:
1) аутсорсеры сообщили, что малознакомы с запросами такого рода, и попытались предложить старую проверенную схему:
1. импорт файла из B2B,
2. Загрузка в 1С,
3. Экспорт файла с указанием, что смогли обработать, что нет из 1С,
4. Импорт в Б2Б,
5. и с самого начала…
Схему отвергли, так как нужно быстро, и без участия человека и всяких «кнопочек».

Тогда попросили пример кода. В интернете я «нагуглил» следующий пример:

Сервер = "test.com";
Порт = "443";
Попытка
НТТР = Новый HTTPСоединение(Сервер, Порт, , , , Истина);
Иначе
НТТР = Новый HTTPСоединение(Сервер, Порт);
КонецЕсли;
АдресСкрипта = "/gateway/GetData1C/";
Попытка
НТТР.ОтправитьДляОбработки(ИмяФайлаОтправки, АдресСкрипта, ИмяФайлаОтвета, ЗаголовокHTTP);
Исключение
Сообщить("Неудачная попытка соединения: " + ОписаниеОшибки());
Иначе
ЗаписьЖурналаРегистрации("HTTPСоединение", УровеньЖурналаРегистрации.Ошибка, , , "Неудачная попытка соединения: " + ОписаниеОшибки());
КонецЕсли
Возврат;
КонецПопытки;


На сервер стали приходить данные, но пустые, то есть GET и POST были пустые. Я добавил запись что приходит в логи и успешно забыл об этом. Спустя 4 месяца мне была поставлена срочная задача — довести интеграцию до результата (так как прошло много времени, разработчики 1С работают, работают, но в ответ ничего не приходит). Мне поставили 1С и я начал «ковыряться».

Первое — решил поставить Fiddler, чтобы понять что происходит. Заметил, что соединение идет по HTTP, а затем сервер редиректит на HTTPS. Предположил, что по этой причине данные получаются пустыми. Попробовал в Chrome воспроизвести, и получил подтверждение, что данные в POST запросе теряются при редиректе.

Так как разрешать работу по HTTP нельзя, начал изучать почему, ведь указано, что:

НТТР = Новый HTTPСоединение(Сервер, Порт, , , , Истина);
Параметр «Истина» означает что использовать HTTPS, и тут дошло что срабатывает
НТТР = Новый HTTPСоединение(Сервер, Порт);


В итоге это «Иначе» было выкинуто, и получил ошибку, что некорректный сертификат. Сертификат был само подписной. Разработка интеграции велась на внутренних серверах, где официально купленного сертификата от «Thawte SSL CA» в отличии от PROD сервера. Импорт сертификата во все возможные хранилища не привел к результату.

Поиск по ресурсам привел к тому, что все сертификаты корневые у 1С свои, и на основе них она уже проверяет остальные. Они лежат в тестовом виде в файле «cacert.pem», который расположен в папке «bin», где стоит 1С. Импорт, не так прост, как оказалось.

Для начала надо экспортировать нужный нам сертификат в файл (он у меня уже был в личном хранилище). Запустив «certmgr.msc», найдя сертификат, делаем его экспорт в файл *.cer.

Далее качаем программку Win32OpenSSL и преобразовываем его в тестовый вид.
У меня это получилось так:

C:\OpenSSL-Win64\bin>openssl x509 -inform der -in С:\fiddler.cer -out С:\fiddler.pem -text -fingerprint -md5
WARNING: can't open config file: /usr/local/ssl/openssl.cnf
MD5 Fingerprint=13:BF:73:43:BB:69:19:BA:22:5D:C7:2E:44:85:91:7F

MD5 сохраняем, он нам понадобится.
Далее открываем файл «cacert.pem».
Спускаемся в самый низ и добавляем сперва MD5, а потом все содержимое, что получилось в файле «fiddler.pem».
Сохраняем файл.
Перезапускаем 1С (возможно и не надо, но у меня не заработало, поэтому я перезапустил все.

Исходный файл в 1С был приведен в такой вид:

Процедура ПослатьЗапросНажатие(Элемент)
        Соединение = ПолучитьHTTPСоединение();
        Если Соединение = Неопределено Тогда
                Сообщить("Не удалось подключиться к серверу, указанному в настройке обмена! Обработка прервана!");
        Иначе
                Источник = АдресФайла;
        КонецЕсли;
        ИмяФайла = ФайлРезультат;
        ИмяПостФайла = ПостФайл;
        ФайлОтправки = Новый Файл(ИмяПостФайла);
        РазмерФайлаОтправки = XMLСтрока(ФайлОтправки.Размер());
        Заголовки = Новый Соответствие();
        Заголовки.Вставить("Content-Type", "application/x-www-form-urlencoded");
        Заголовки.Вставить("Content-Lenght", РазмерФайлаОтправки);
        Попытка
        Соединение.ОтправитьДляОбработки(ИмяПостФайла, Источник, ИмяФайла, Заголовки);
        Исключение
                Сообщить(ОписаниеОшибки());
        КонецПопытки
КонецПроцедуры

Функция ПолучитьHTTPСоединение() Экспорт
        Попытка
                Соединение = Новый HTTPСоединение(HTTPСервер,"443",,,,Истина);
        Исключение
                Сообщить(ОписаниеОшибки());
                Соединение = Неопределено;
        КонецПопытки;
        Возврат Соединение;
КонецФункции

Процедура ПриОткрытии()
        HTTPСервер = "test.com";
        АдресФайла = "/gateway/GetData1C";
        ПостФайл = "C:\POST_1C\post.txt";
    ФайлРезультат = "C:\POST_1C\result.xml";
КонецПроцедуры


После нажатия на кнопку, пошел запрос по HTTPS и на выходе был получен корректный XML.

Искал, как работает 1С по HTTPS, достаточно много материала, но вот как работать по само подписному сертификату не нашел.

Готов поделиться информацией о злоключениях с настройкой Oracle и B2B.
Там использовался тот же механизм, передача данных в POST запросе, но были свои подводные камни. В принципе, там оказалось все проще.
Tags:
Hubs:
0
Comments10

Articles

Change theme settings