В современной разработке интеграция «1С:Предприятия» с веб-сайтами, интернет-магазинами и внешними сервисами (такими как VK API, Telegram, платежные шлюзы) стала повседневной задачей. Формат JSON является стандартом де-факто для обмена данными в веб-среде благодаря своей легкости и универсальности. В этой статье мы подробно, шаг за шагом, разберем, как организовать двусторонний обмен данными между 1С и внешними системами.
Мы рассмотрим два принципиально разных сценария интеграции:
Представьте ситуацию, когда при оформлении заказа на сайте данные должны мгновенно попадать в базу 1С. Для этого в конфигураторе 1С создается специальный объект — HTTP-сервис. Мы публикуем нашу базу на веб-сервере (Apache или IIS), после чего внешняя система может отправлять нам POST-запросы с телом в формате JSON.
Давайте проанализируем пример кода обработчика POST-запроса в 1С, который принимает JSON, преобразует его в структуру и возвращает ответ клиенту:
Функция TestTest(Запрос)
Попытка
// Инициализируем объект для чтения JSON
ЧтениеJSON = Новый ЧтениеJSON;
// Получаем тело POST-запроса в виде потока и открываем его
ЧтениеJSON.ОткрытьПоток(Запрос.ПолучитьТелоКакПоток);
// Читаем данные JSON в структуру 1С
Данные = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Проверяем корректность формата полученных данных
Если ТипЗнч(Данные) <> ТипЗнч(Новый Структура) Тогда
ВызватьИсключение "Получены данные в неправильном формате! Ожидалась структура.";
КонецЕсли;
// Здесь выполняется обработка структуры "Данные" (создание документов, справочников и т.д.)
// Например: Справочники.Номенклатура.СоздатьЭлемент() и т.д.
Исключение
// В случае ошибки формируем ответ с кодом 500 и описанием ошибки
ТекЗаписьJSON = Новый ЗаписьJSON;
ТекЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ТекЗаписьJSON, Новый Структура("message", ОписаниеОшибки()));
ТекстJSON = ТекЗаписьJSON.Закрыть();
Ответ = Новый HTTPСервисОтвет(500);
Ответ.УстановитьТелоИзСтроки(ТекстJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ.Заголовки.Вставить("Content-Type", "application/json");
Возврат Ответ;
КонецПопытки;
// В случае успеха возвращаем статус 200 OK
ТекЗаписьJSON = Новый ЗаписьJSON;
ТекЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ТекЗаписьJSON, Новый Структура("message", "все хорошо"));
ТекстJSON = ТекЗаписьJSON.Закрыть();
Ответ = Новый HTTPСервисОтвет(200);
Ответ.УстановитьТелоИзСтроки(ТекстJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ.Заголовки.Вставить("Content-Type", "application/json");
Возврат Ответ;
КонецФункции
Разберем этот код подробнее. Мы используем объект ЧтениеJSON и метод ПрочитатьJSON() для автоматической десериализации входящего JSON-пакета в коллекцию 1С (в данном случае, в Структура). Очень важно помещать весь блок разбора в конструкцию Попытка... Исключение, чтобы при получении некорректного JSON-файла сервер не прекращал работу аварийно, а возвращал клиенту понятную ошибку со статусом 500.
Теперь рассмотрим обратную задачу: нам нужно получить информацию с внешнего ресурса, например, получить профиль пользователя из VK API или курсы валют. Данный код можно привязать к обработчику нажатия обычной кнопки на управляемой форме.
Давайте посмотрим на пример реализации исходящего POST-запроса:
// Шаг 1. Формируем тело запроса в формате JSON
ЗаписьJSON = Новый ЗаписьJSON;
ПараметрыJSON = Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет, " ", Истина);
ЗаписьJSON.УстановитьСтроку(ПараметрыJSON);
СтруктураJSON = Новый Структура;
СтруктураJSON.Вставить("last_name", "Иванов");
СтруктураJSON.Вставить("first_name", "Иван");
ЗаписатьJSON(ЗаписьJSON, СтруктураJSON);
strJSON = ЗаписьJSON.Закрыть();
// Шаг 2. Настраиваем безопасное SSL-соединение для HTTPS
ssl = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено);
// Шаг 3. Создаем HTTP-соединение с указанием домена и защищенного соединения
Соединение = Новый HTTPСоединение("api.vk.com",,,,, 5, ssl);
// Шаг 4. Создаем HTTP-запрос (указываем только относительный путь внутри сайта)
HTTPЗапрос = Новый HTTPЗапрос("/method/users.get");
HTTPЗапрос.Заголовки.Вставить("Content-type", "application/json");
HTTPЗапрос.УстановитьТелоИзСтроки(strJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
// Шаг 5. Отправляем запрос и обрабатываем ответ
HTTPОтвет = Соединение.ОтправитьДляОбработки(HTTPЗапрос);
КодОшибки = HTTPОтвет.КодСостояния;
ОтветСтрока = HTTPОтвет.ПолучитьТелоКакСтроку();
Если КодОшибки = 200 Тогда
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ОтветСтрока);
Данные = ПрочитатьJSON(ЧтениеJSON);
ЧтениеJSON.Закрыть();
// Здесь мы работаем с полученными данными из структуры "Данные"
Иначе
ВызватьИсключение "Ошибка обращения к сервису! Код состояния: " + КодОшибки;
КонецЕсли;
При работе с внешними API крайне важно разделять доменное имя и относительный путь. В конструктор объекта HTTPСоединение передается исключительно хост (например, api.vk.com), в то время как относительный путь к конкретному методу (например, /method/users.get) указывается в конструкторе HTTPЗапрос. Попытка указать полный адрес в запросе приведет к ошибке.
Большинство начинающих разработчиков допускают серьезную ошибку, всегда считывая JSON в объект типа Структура. В 1С ключи структуры обязаны соответствовать жестким правилам именования переменных: они не могут содержать дефисы, точки, спецсимволы и не могут начинаться с цифр. Однако внешние API очень часто присылают ключи вида first-name, user.id или 1_index.
Если попытаться прочесть такой JSON стандартным методом ПрочитатьJSON(ЧтениеJSON), платформа выдаст фатальную ошибку. Чтобы этого избежать, всегда читайте JSON в объект типа Соответствие. Для этого достаточно передать значение Истина во второй параметр функции ПрочитатьJSON:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ОтветСтрока);
// Второй параметр "Истина" указывает платформе читать JSON в Соответствие, а не в Структуру
Данные = ПрочитатьJSON(ЧтениеJSON, Истина);
ЧтениеJSON.Закрыть();
// Теперь мы можем безопасно обращаться к любым ключам:
ИмяПользователя = Данные.Получить("first-name");
Идентификатор = Данные.Получить("user.id");
Формат JSON изначально не поддерживает тип данных «Дата», поэтому все даты передаются как обычные строки. 1С предоставляет мощные механизмы для автоматического преобразования таких строк в стандартный тип Дата 1С.
Если вы заранее знаете имена полей, в которых передается дата в формате ISO, вы можете перечислить их через запятую в третьем параметре функции ПрочитатьJSON:
// Платформа автоматически преобразует указанные поля в тип Дата
Данные = ПрочитатьJSON(ЧтениеJSON, Ложь, "created_at, updated_at", ФорматДатыJSON.ISO);
Если формат даты нестандартный (например, Unix timestamp или специфическая строка), можно использовать функцию восстановления дат. Для этого в общем модуле создается экспортная функция, имя которой передается в параметры чтения JSON:
// Пример вызова с указанием имени функции восстановления
Данные = ПрочитатьJSON(ЧтениеJSON, Ложь, , , "МойМодульИнтеграции.ВосстановитьДатуJSON");
При настройке HTTPСоединение для работы по защищенному протоку HTTPS разработчики часто копируют примеры из синтакс-помощника, содержащие инициализацию сертификатов Windows с интерактивным выбором. Настоятельно рекомендуем избегать использования конструкций вида СпособВыбораСертификатаWindows.Выбирать.
Если этот код будет выполнен на стороне сервера (например, в фоновом задании, регламентном задании или в обработчике HTTP-сервиса), сессия аварийно завершится с ошибкой отсутствия графического интерфейса. Для фоновой серверной работы всегда используйте параметры по умолчанию:
ssl = Новый ЗащищенноеСоединениеOpenSSL(Неопределено, Неопределено);
Если в вашей конфигурации установлена Библиотека стандартных подсистем (БСП), то самым надежным и простым решением будет вызов стандартного метода:
ssl = ОбщегоНазначенияКлиентСервер.НовоеЗащищенноеСоединение();
Стандартный метод ПрочитатьJSON() загружает весь файл в оперативную память целиком (так называемая DOM-модель парсинга). Если внешний сайт вернет вам массив из десятков тысяч элементов (например, полную базу товаров или логов), оперативная память сервера может быстро переполниться, что приведет к аварийной остановке рабочего процесса.
Для решения этой проблемы мы можем использовать потоковое чтение (StAX-парсер). В этом режиме мы считываем JSON пошагово, обрабатывая элементы один за другим в цикле, не загружая весь файл в память:
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(ОтветСтрока);
Пока ЧтениеJSON.Прочитать() Цикл
Если ЧтениеJSON.ТипУзла = ТипУзлаJSON.ИмяСвойства И ЧтениеJSON.ИмяСвойства = "item_id" Тогда
// Читаем следующее значение, которое является значением свойства "item_id"
ЧтениеJSON.Прочитать();
ИдентификаторТовара = ЧтениеJSON.Значение;
// Обрабатываем полученный идентификатор без перегрузки памяти...
КонецЕсли;
КонецЦикла;
ЧтениеJSON.Закрыть();
Применяя эти правила и используя предложенные шаблоны кода, вы сможете построить отказоустойчивую, быструю и безопасную систему интеграции вашей базы 1С с любыми современными веб-ресурсами и API.