Передача данных объекта из формы и внешней системы на сервер 1С
Содержание
Сам объект (ДокументОбъект, СправочникОбъект) с клиента на сервер 1С не передаётся: на тонком клиенте его просто нет. Передают данные объекта. Внутри формы это структура, ссылка или реквизит формы, который сервер превращает в объект через РеквизитФормыВЗначение(). Из внешней системы это JSON или XML, который принимает HTTP-сервис или Web-сервис, а сервер уже сам создаёт и записывает объект.
Ниже оба случая: обмен клиент–сервер внутри одной базы и передача объекта из другой программы или другой базы. С кодом, проверками и настройкой доступа.
Где ваш «клиент»: форма 1С или внешняя программа
Вопрос «как передать объект на сервер» задают в двух разных ситуациях. От ответа зависит весь инструмент.
- 🖥️ Клиент внутри 1С. Процедура формы с директивой
&НаКлиентедолжна отдать данные в&НаСервере. Сеть, протоколы и форматы тут не нужны: платформа сама передаёт значения при серверном вызове. Задача — выбрать передаваемый тип. - 🌐 Внешний клиент. Сайт, мобильное приложение, сервис на Python или другая база 1С отправляет данные на сервер 1С. Здесь нужен протокол (HTTP, SOAP, COM), формат (JSON, XML) и аутентификация.
Если коротко: в первом случае вы пишете два метода в модуле формы, во втором — публикуете сервис на веб-сервере.
Как передать данные объекта из формы на сервер
На клиенте доступны не все типы. Между &НаКлиенте и &НаСервере свободно ходят:
- примитивы:
Строка,Число,Дата,Булево,Неопределено; - ссылки:
ДокументСсылка.*,СправочникСсылка.*; - коллекции:
Структура,Массив,Соответствиеи их фиксированные варианты; ДвоичныеДанные,УникальныйИдентификатор;- данные формы: реквизиты формы, в том числе основной реквизит
Объект.
Не передаются объекты прикладных типов, ТаблицаЗначений, Запрос, МенеджерВременныхТаблиц. Попытка вернуть их с сервера на клиент даёт ошибку о том, что тип нельзя передать.
Способ 1. Структура в серверный метод без контекста
Самый лёгкий вызов. Форма не уходит на сервер целиком, передаются только нужные поля.
&НаКлиенте
Процедура СоздатьЗаказ(Команда)
Данные = Новый Структура;
Данные.Вставить("Контрагент", Объект.Контрагент);
Данные.Вставить("Сумма", 1500);
Данные.Вставить("Комментарий", "Заказ с формы");
НовыйЗаказ = СоздатьЗаказНаСервере(Данные);
ПоказатьЗначение(, НовыйЗаказ);
КонецПроцедуры
&НаСервереБезКонтекста
Функция СоздатьЗаказНаСервере(Данные)
ДокОбъект = Документы.ЗаказКлиента.СоздатьДокумент();
ЗаполнитьЗначенияСвойств(ДокОбъект, Данные);
ДокОбъект.Дата = ТекущаяДатаСеанса();
ДокОбъект.Записать(РежимЗаписиДокумента.Запись);
Возврат ДокОбъект.Ссылка;
КонецФункции
ЗаполнитьЗначенияСвойств перенесёт поля, имена которых совпадают с реквизитами документа. Обратно на клиент уходит ссылка, а не объект.
&НаСервереБезКонтекста не тащит на сервер данные формы. При частых вызовах это заметно экономит трафик и время, особенно на медленном канале.
Способ 2. Реквизит формы → объект → реквизит формы
Когда нужно вызвать экспортный метод модуля объекта или поменять табличную часть по правилам объекта, используют пару функций формы:
&НаСервере
Процедура ПересчитатьНаСервере()
ДокОбъект = РеквизитФормыВЗначение("Объект");
ДокОбъект.ПересчитатьСуммы(); // экспортная процедура модуля объекта
ЗначениеВРеквизитФормы(ДокОбъект, "Объект");
КонецПроцедуры
Здесь вызов идёт с контекстом: форма передаётся на сервер, там превращается в настоящий объект, а результат возвращается в форму. Записи в базу при этом нет, пока пользователь не нажмёт «Записать».
Вне формы, например в общем модуле, используют ДанныеФормыВЗначение(Данные, Тип("ДокументОбъект.ЗаказКлиента")) и обратную ЗначениеВДанныеФормы().
Способ 3. Временное хранилище для больших данных
Файл, картинку или большой массив передают через временное хранилище. На клиенте кладут значение и получают адрес, на сервер отправляют только строку адреса.
&НаКлиенте
Процедура ОтправитьФайл(ДвоичныеДанныеФайла)
Адрес = ПоместитьВоВременноеХранилище(ДвоичныеДанныеФайла, УникальныйИдентификатор);
ЗагрузитьНаСервере(Адрес);
КонецПроцедуры
&НаСервере
Процедура ЗагрузитьНаСервере(Адрес)
Данные = ПолучитьИзВременногоХранилища(Адрес);
УдалитьИзВременногоХранилища(Адрес);
// разбор и запись данных
КонецПроцедуры
Второй параметр — уникальный идентификатор формы: значение живёт, пока открыта форма. Без идентификатора срок хранения короче, и значение может исчезнуть раньше, чем сервер его заберёт.
Каким каналом передать объект во внешнюю базу 1С
Если клиент — внешняя система, выбирают протокол. Варианты у платформы 8.3 такие.
| Канал | Формат | Когда выбирать | Ограничения |
|---|---|---|---|
| HTTP-сервис | JSON, XML, любой | REST-интеграции: сайт, мобильное приложение, Python, другая 1С | Схему данных описываете и проверяете сами |
| Web-сервис (SOAP) | XML по пакету XDTO | Строгий контракт, интеграция с корпоративной шиной, Java/.NET-клиенты | Тяжелее в настройке, больше объём сообщений |
| Стандартный интерфейс OData | JSON, Atom | Нужно быстро открыть чтение и запись типовых объектов без программирования | Бизнес-логику не добавить, нужна настройка состава объектов |
| COM-соединение | Значения через COM | Две базы на одном Windows-сервере, разовые обработки | Только Windows, совпадение версий comcntr.dll, не для веба |
Для новой интеграции чаще всего берут HTTP-сервис. Он прост для внешних разработчиков: обычный POST с JSON, ответ с кодом состояния.
Web-сервис оправдан, когда заказчик требует WSDL и проверку сообщения по схеме ещё до вашего кода.
COM-соединение (Новый COMОбъект("V83.COMConnector")) удобно для обработки, которая из одной базы пишет в другую на том же сервере. Объект чужой базы напрямую в свою не передать: передают строки и числа или сериализуют данные в XML-строку.
JSON или XML: сериализация объекта 1С
Перед отправкой объект превращают в текст. Есть два подхода.
Свой формат. Вы собираете Структуру с нужными полями и пишете её в JSON. Внешняя система получает понятный документ без служебных полей 1С. Ссылки заменяете на коды, ИНН или GUID.
Функция ЗаказВJSON(ДокОбъект)
Данные = Новый Структура;
Данные.Вставить("id", Строка(ДокОбъект.Ссылка.УникальныйИдентификатор()));
Данные.Вставить("number", ДокОбъект.Номер);
Данные.Вставить("date", XMLСтрока(ДокОбъект.Дата));
Данные.Вставить("inn", ДокОбъект.Контрагент.ИНН);
Данные.Вставить("sum", ДокОбъект.СуммаДокумента);
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, Данные);
Возврат Запись.Закрыть();
КонецФункции
Дату лучше отдавать через XMLСтрока(): получится формат 2026-10-07T00:00:00, который поймёт любой парсер.
Сериализатор XDTO. Глобальный СериализаторXDTO пишет объект целиком: все реквизиты и табличные части, ссылки — в виде GUID. Подходит для обмена 1С ↔ 1С с одинаковой структурой метаданных.
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Запись, ДокОбъект);
ТекстXML = Запись.Закрыть();
На приёмной стороне СериализаторXDTO.ПрочитатьXML(ЧтениеXML) вернёт готовый объект, который остаётся записать. Есть и вариант в JSON — метод ЗаписатьJSON у того же сериализатора.
| Критерий | Свой JSON | XDTO (XML или JSON) |
|---|---|---|
| Получатель | Любая система | Только 1С с той же конфигурацией |
| Объём | Минимальный | Большой, все поля |
| Устойчивость к изменениям | Высокая, вы контролируете поля | Ломается при расхождении метаданных |
| Трудозатраты | Нужно описать поля | Одна строка кода |
Настройка HTTP-сервиса, который принимает объект
Порядок в конфигураторе.
- В дереве конфигурации откройте
Общие → HTTP-сервисыи добавьте сервис, напримерOrders. Укажите корневой URL —orders. - Добавьте шаблон URL, например
/doc, а в нём метод с HTTP-методом POST. - В свойствах метода нажмите на лупу у поля «Обработчик» — платформа создаст функцию в модуле сервиса.
- Опубликуйте базу:
Администрирование → Публикация на веб-сервере, отметьте флаг публикации HTTP-сервисов и нужный сервис. - Адрес для клиента:
https://сервер/имя_публикации/hs/orders/doc.
Пример обработчика, который принимает JSON и создаёт или обновляет заказ:
Функция DocPOST(Запрос)
Попытка
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
Данные = ПрочитатьJSON(Чтение, Истина); // Соответствие
Чтение.Закрыть();
Исключение
Возврат ОтветJSON(400, "Тело запроса не является JSON");
КонецПопытки;
Попытка
Ид = Новый УникальныйИдентификатор(Данные.Получить("id"));
Исключение
Возврат ОтветJSON(400, "Поле id должно содержать GUID");
КонецПопытки;
Ссылка = Документы.ЗаказКлиента.ПолучитьСсылку(Ид);
ДокОбъект = Ссылка.ПолучитьОбъект();
Если ДокОбъект = Неопределено Тогда
ДокОбъект = Документы.ЗаказКлиента.СоздатьДокумент();
ДокОбъект.УстановитьСсылкуНового(Ссылка);
ДокОбъект.Дата = ТекущаяДатаСеанса();
КонецЕсли;
ДокОбъект.Комментарий = Данные.Получить("comment");
// заполнение остальных реквизитов и табличной части
Возврат ЗаписатьЗаказ(ДокОбъект);
КонецФункции
Функция ОтветJSON(Код, Текст)
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, Новый Структура("code, message", Код, Текст));
Ответ = Новый HTTPСервисОтвет(Код);
Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Ответ.УстановитьТелоИзСтроки(Запись.Закрыть(), КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Возврат Ответ;
КонецФункции
Параметр Истина в ПрочитатьJSON возвращает Соответствие. С ним не упадёт ключ, который не годится в имя свойства структуры: order-id, 1c_code и подобные.
GUID от внешней системы плюс УстановитьСсылкуНового() делают приём идемпотентным. Повторная отправка того же заказа обновит документ, а не создаст дубль.
Со стороны другой базы 1С отправка выглядит так:
Соединение = Новый HTTPСоединение("server.example.ru", 443, "Обмен", Пароль, , 30, Новый ЗащищенноеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/trade/hs/orders/doc");
Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Запрос.УстановитьТелоИзСтроки(ЗаказВJSON(ДокОбъект), КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
ВызватьИсключение Ответ.ПолучитьТелоКакСтроку();
КонецЕсли;
Web-сервис и пакет XDTO для строгой схемы
Web-сервис принимает объект как XML по заранее описанной схеме. Платформа проверит структуру сообщения до того, как управление попадёт в ваш код.
Порядок:
Общие → XDTO-пакеты— создайте пакет со своим пространством имён, напримерhttp://example.ru/orders. Опишите тип объектаOrderсо свойствамиid,date,inn,sumи вложенным списком строк.Общие → Web-сервисы— добавьте сервис, задайте пространство имён URI и в свойстве «Пакеты XDTO» выберите созданный пакет.- Добавьте операцию
SaveOrder, параметрorderс типомOrder, тип возвращаемого значения —stringили свой тип ответа. - Опубликуйте базу с флагом публикации Web-сервисов. Описание будет по адресу
https://сервер/имя_публикации/ws/имя_сервиса?wsdl.
В обработчике операции параметр приходит как ОбъектXDTO. К свойствам обращаются через точку: order.inn, а повторяющиеся строки — коллекция, которую обходят циклом.
Клиент на 1С вызывает сервис через WSОпределения и WSПрокси. Внешние разработчики генерируют клиентский код по WSDL своими средствами.
После изменения XDTO-пакета меняется WSDL. Клиенты, которые сгенерировали код по старой схеме, начнут получать ошибки разбора. Меняйте схему версиями: новое пространство имён или новая операция.
Проверка данных и обработка ошибок на сервере
Данные с клиента считайте недоверенными. Даже если клиент — ваша же форма.
- ✅ Обязательные поля. До записи вызовите
ДокОбъект.ПроверитьЗаполнение(). Метод вернётЛожь, если не заполнены реквизиты с проверкой заполнения, а тексты замечаний попадут в сообщения пользователю. - 🔎 Поиск по ключам. ИНН, код или GUID из запроса ищите запросом к базе. Не нашли — возвращайте ошибку, а не создавайте пустой элемент справочника.
- 🔢 Типы и диапазоны. Число из JSON может прийти строкой. Приводите явно и проверяйте, что сумма не отрицательная.
- 🧾 Транзакция. Если запрос создаёт несколько объектов, оборачивайте запись в
НачатьТранзакцию()/ЗафиксироватьТранзакцию()сОтменитьТранзакцию()в исключении.
Функция записи с разбором замечаний:
Функция ЗаписатьЗаказ(ДокОбъект)
Если Не ДокОбъект.ПроверитьЗаполнение() Тогда
Тексты = Новый Массив;
Для Каждого Сообщение Из ПолучитьСообщенияПользователю(Истина) Цикл
Тексты.Добавить(Сообщение.Текст);
КонецЦикла;
Возврат ОтветJSON(422, СтрСоединить(Тексты, "; "));
КонецЕсли;
Попытка
ДокОбъект.Записать(РежимЗаписиДокумента.Проведение);
Исключение
Инфо = ИнформацияОбОшибке();
ЗаписьЖурналаРегистрации("Обмен.ПриёмЗаказа", УровеньЖурналаРегистрации.Ошибка, ,
ДокОбъект.Ссылка, ПодробноеПредставлениеОшибки(Инфо));
Возврат ОтветJSON(500, КраткоеПредставлениеОшибки(Инфо));
КонецПопытки;
Возврат ОтветJSON(200, Строка(ДокОбъект.Ссылка.УникальныйИдентификатор()));
КонецФункции
Подробности ошибки — в журнал регистрации, клиенту — короткий текст. Так вы не раскрываете наружу имена модулей и строки кода.
Защита канала и аутентификация
Сервис, который пишет в базу, — дверь в учёт. Настройте её сразу, а не после запуска.
- Только HTTPS. Пароль в Basic-аутентификации передаётся в заголовке почти открытым текстом. Без TLS его перехватит любой, кто видит трафик. Сертификат ставят на веб-сервер (IIS или Apache), 1С тут ничего не настраивает.
- Отдельный пользователь под обмен. Заведите в базе пользователя, например
Обмен, с ролью, где есть права ровно на нужные объекты: чтение справочников-ключей, добавление и проведение заказов. Интерактивный вход ему не нужен. - Не используйте
ПривилегированныйРежимбез нужды. Если обработчик включает его ради удобства, права пользователя обмена теряют смысл. - Не храните пароль в коде. На стороне 1С-клиента храните его в безопасном хранилище БСП или в константе с ограниченным доступом, а не в тексте модуля.
- Ограничьте доступ по сети. Если клиент один и с постоянным IP, разрешите обращения к адресу публикации только с него — средствами веб-сервера или межсетевого экрана.
Не публикуйте HTTP-сервисы базы в интернет под пользователем с полными правами. Одна утечка пароля — и посторонний может менять и проводить документы.
Для разовой отладки удобно временно опубликовать сервис только в локальной сети. Внешний доступ открывайте после того, как отработали проверки и логирование.
Частые вопросы
Можно ли вернуть с сервера на клиент ДокументОбъект?
ЗначениеВРеквизитФормы().Почему ТаблицаЗначений не передаётся на клиент?
Чем HTTP-сервис отличается от стандартного интерфейса OData?
Нужна ли отдельная лицензия для обращений к HTTP-сервису?
Как передать файл вместе с объектом через HTTP?
Base64Строка() и Base64Значение()). Большой лучше отправить отдельным запросом с двоичным телом и связать с объектом по GUID.