Передача данных из клиентского кода и внешних программ на сервер 1С:Предприятия

· 9 мин

Содержание

Чтобы передать параметр с клиента на сервер 1С, вызовите из клиентской процедуры серверную процедуру формы (&НаСервере или &НаСервереБезКонтекста) либо экспортную функцию общего модуля с флагом «Вызов сервера» и передайте значение аргументом. Платформа сама сериализует его и доставит на сервер. Ограничение одно: тип значения должен быть доступен и на клиенте, и на сервере.

Если же «клиент» — это внешняя программа, сайт или другая база, параметры передают через HTTP-сервис, COM-соединение или веб-сервис SOAP. Ниже — оба уровня: код внутри конфигурации и интеграция снаружи, с рабочими примерами на встроенном языке.

Вызов сервера из клиентского кода: директивы и правила передачи

В управляемой форме каждая процедура помечается директивой компиляции. От неё зависит, где выполняется код и что уходит на сервер вместе с вызовом.

ДирективаГде выполняетсяЧто передаётся на сервер
&НаКлиентена клиентеничего
&НаСерверена серверепараметры + все данные формы
&НаСервереБезКонтекстана серверетолько параметры
&НаКлиентеНаСервереБезКонтекстатам, откуда вызванабез вызова сервера

Разница между &НаСервере и &НаСервереБезКонтекста ощутима. При контекстном вызове туда и обратно гоняются реквизиты формы, включая табличные части документа на 500 строк. Если серверу нужен только ИНН, берите вызов без контекста.

Пример: найти контрагента по ИНН из поля формы

На форме есть строковый реквизит ИННДляПоиска и команда «Найти». Клиент передаёт строку, сервер возвращает ссылку.

&НаКлиенте
Процедура НайтиПоИНН(Команда)
	Контрагент = НайтиКонтрагентаНаСервере(ИННДляПоиска);
	Если ЗначениеЗаполнено(Контрагент) Тогда
		Объект.Контрагент = Контрагент;
	Иначе
		Сообщить("Контрагент с ИНН " + ИННДляПоиска + " не найден");
	КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Функция НайтиКонтрагентаНаСервере(Знач ИНН)
	Запрос = Новый Запрос(
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	Контрагенты.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.Контрагенты КАК Контрагенты
	|ГДЕ
	|	Контрагенты.ИНН = &ИНН");
	Запрос.УстановитьПараметр("ИНН", СокрЛП(ИНН));
	Выборка = Запрос.Выполнить().Выбрать();
	Если Выборка.Следующий() Тогда
		Возврат Выборка.Ссылка;
	КонецЕсли;
	Возврат Справочники.Контрагенты.ПустаяСсылка();
КонецФункции

Зачем писать Знач

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

💡 Ставьте Знач перед каждым параметром, который сервер только читает. Это бесплатная экономия трафика, особенно для структур и массивов.

Какие типы можно передать

Сервер и клиент обмениваются только сериализуемыми значениями. Ориентир такой:

  • ✅ Можно: Строка, Число, Дата, Булево, Неопределено, Null, ссылки на объекты базы, перечисления, Структура, Массив, Соответствие, их фиксированные варианты, УникальныйИдентификатор, ДвоичныеДанные, ТабличныйДокумент, ХранилищеЗначения.
  • ❌ Нельзя: ТаблицаЗначений, ДеревоЗначений, Запрос, объекты (СправочникОбъект, ДокументОбъект), менеджеры записей, ОписаниеОповещения.

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

Таблицу значений с сервера на клиент возвращают одним из трёх путей:

  1. Складывают в реквизит формы с типом «ТаблицаЗначений» через ЗначениеВРеквизитФормы() и вызывают процедуру &НаСервере.
  2. Превращают в массив структур, по одной на строку.
  3. Кладут во временное хранилище и передают на клиент только адрес.

Параметры формы и временное хранилище

Передать значение при открытии формы

Самый частый случай: клиент открывает форму и передаёт ей значения, а форма читает их уже на сервере, в ПриСозданииНаСервере.

&НаКлиенте
Процедура ОткрытьПодбор(Команда)
	ПараметрыФормы = Новый Структура("Склад, Дата", Объект.Склад, Объект.Дата);
	ОткрытьФорму("Обработка.ПодборТоваров.Форма.Форма", ПараметрыФормы, ЭтаФорма);
КонецПроцедуры

В открываемой форме:

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
	Если Параметры.Свойство("Склад") Тогда
		Склад = Параметры.Склад;
	КонецЕсли;
КонецПроцедуры

Параметры объявите на закладке «Параметры» редактора формы, с типами. Необъявленные значения доступны только внутри ПриСозданииНаСервере, и опечатку в имени никто не подсветит.

⚠️ Не называйте локальную переменную Параметры в модуле формы: это имя уже занято свойством самой формы.

Большие данные — через временное хранилище

Файл на 20 МБ или табличный документ на тысячи строк неудобно таскать параметром при каждом вызове. Для этого есть временное хранилище:

  1. На стороне, где данные появились, вызовите ПоместитьВоВременноеХранилище(Значение, УникальныйИдентификатор). Второй аргумент — идентификатор формы, тогда хранилище очистится при её закрытии.
  2. Получите строку-адрес и передайте её параметром.
  3. На другой стороне прочитайте значение: ПолучитьИзВременногоХранилища(Адрес).

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

Тонкий и веб-клиент: что учесть при передаче

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

  • 🌐 Веб-клиент не создаёт COMОбъект и не работает с локальными файлами напрямую. Файлы пользователя сначала помещают на сервер через диалог выбора и временное хранилище.
  • 🔁 Каждый вызов сервера — это сетевой запрос. В локальной сети тонкий клиент переживёт десяток лишних вызовов. Через интернет и в веб-клиенте каждый добавит заметную задержку.
  • 🪟 Модальные окна в веб-клиенте ограничены. Результат диалога передают дальше через ОписаниеОповещения с дополнительными параметрами, а не через возвращаемое значение.

Пример передачи контекста в обработчик оповещения:

&НаКлиенте
Процедура УдалитьСтроку(Команда)
	ДопПараметры = Новый Структура("ИдентификаторСтроки", Элементы.Товары.ТекущаяСтрока);
	Оповещение = Новый ОписаниеОповещения("УдалитьСтрокуЗавершение", ЭтотОбъект, ДопПараметры);
	ПоказатьВопрос(Оповещение, "Удалить строку?", РежимДиалогаВопрос.ДаНет);
КонецПроцедуры

&НаКлиенте
Процедура УдалитьСтрокуЗавершение(Ответ, ДопПараметры) Экспорт
	Если Ответ = КодВозвратаДиалога.Да Тогда
		Строка = Объект.Товары.НайтиПоИдентификатору(ДопПараметры.ИдентификаторСтроки);
		Объект.Товары.Удалить(Строка);
	КонецЕсли;
КонецПроцедуры

Модуль управляемого приложения и общие клиентские модули не имеют своего «сервера». Оттуда сервер вызывают через общий модуль с флагами «Сервер» и «Вызов сервера».

HTTP-сервис: как передать параметры на сервер 1С из любой программы

Когда данные шлёт сайт, мобильное приложение или скрипт на Python, удобнее всего HTTP-сервис. Он создаётся в ветке Общие → HTTP-сервисы конфигуратора, публикуется на веб-сервере и доступен по адресу вида https://сервер/база/hs/корневойURL/....

Три места, где лежат параметры

ГдеПример запросаКак прочитать в 1С
Часть пути по шаблону /orders/{number}/hs/api/orders/123Запрос.ПараметрыURL.Получить("number")
Строка запроса?format=shortЗапрос.ПараметрыЗапроса.Получить("format")
Тело запроса (JSON, XML)POST с {"inn":"..."}Запрос.ПолучитьТелоКакСтроку()
ЗаголовкиX-Request-Id: ...Запрос.Заголовки.Получить("X-Request-Id")

Для POST с JSON обработчик выглядит так:

Функция ЗаказыPOST(Запрос)
	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
	Данные = ПрочитатьJSON(Чтение, Истина); // Истина — читать в Соответствие
	Чтение.Закрыть();

	Если ТипЗнч(Данные) <> Тип("Соответствие") Или Данные.Получить("inn") = Неопределено Тогда
		Ответ = Новый HTTPСервисОтвет(400);
		Ответ.УстановитьТелоИзСтроки("Не передан параметр inn");
		Возврат Ответ;
	КонецЕсли;

	// ... обработка Данные.Получить("inn")

	Ответ = Новый HTTPСервисОтвет(200);
	Ответ.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
	Ответ.УстановитьТелоИзСтроки("{""result"":""ok""}");
	Возврат Ответ;
КонецФункции

Вызов из другой базы 1С

Соединение = Новый HTTPСоединение("srv1c.local", 443, "api", "Пароль", , 30,
	Новый ЗащищенноеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/trade/hs/api/orders");
Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
Запрос.УстановитьТелоИзСтроки("{""inn"":""7701234567""}",
	КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния <> 200 Тогда
	ВызватьИсключение "Сервер вернул " + Формат(Ответ.КодСостояния, "ЧГ=0");
КонецЕсли;

Код выполняйте на сервере. Таймаут (здесь 30 секунд) задавайте всегда, иначе зависший сервис подвесит и вызывающий сеанс.

COM-соединение: параметры из Windows-программы

COM-соединение подходит, когда на той же Windows-машине работает другая программа: Excel, скрипт, вторая база 1С. Клиент подключается через компонент V83.COMConnector и вызывает экспортные функции общих модулей, у которых стоит флаг «Внешнее соединение».

Коннектор = Новый COMОбъект("V83.COMConnector");
База = Коннектор.Connect("Srvr=""srv1c"";Ref=""trade"";Usr=""Обмен"";Pwd=""***"";");
Остаток = База.ОбменДанными.ОстатокТовара("00-000123", ТекущаяДата());

Строки, числа, даты и булевы значения уходят как есть. Структуру или массив нужно создать уже в той базе: Параметры = База.NewObject("Структура").

Приёмы, которые экономят время:

  • 📦 Передавайте строку, а не объект. Каждое обращение к свойству COM-объекта — межпроцессный вызов. Сериализуйте данные в JSON или XML, отправьте одной строкой и разберите на стороне базы.
  • 🧩 Разрядность совпадает. 64-разрядная программа видит только 64-разрядный comcntr.dll. Компонент регистрируют командой regsvr32 из папки bin нужной версии платформы, от администратора.
  • 🔢 Версия платформы. Номер comcntr.dll должен совпадать с номером платформы сервера 1С, иначе соединение не установится.

COM работает только под Windows и только из толстого или тонкого клиента либо с сервера. Из веб-клиента и с Linux-сервера этот путь закрыт.

Веб-сервисы SOAP и планы обмена

SOAP: параметры со строгими типами

Веб-сервис описывают в ветке Общие → Веб-сервисы. У каждой операции есть список параметров с типами (xs:string, xs:decimal, xs:dateTime или типы из пакета XDTO). После публикации описание доступно по адресу .../ws/имя.1cws?wsdl.

Вызов из другой базы:

Определения = Новый WSОпределения("https://srv/trade/ws/orders.1cws?wsdl", "api", "Пароль");
Прокси = Новый WSПрокси(Определения, "http://example.org/orders", "Orders", "OrdersSoap");
Прокси.Пользователь = "api";
Прокси.Пароль = "Пароль";
Результат = Прокси.CreateOrder("7701234567", 15000);

Второй, третий и четвёртый аргументы WSПрокси — пространство имён, имя сервиса и имя точки подключения. Берите их из WSDL, а не угадывайте.

SOAP выбирают, когда второй стороне нужен формальный контракт и проверка типов. Для простых интеграций HTTP-сервис с JSON проще в отладке.

Планы обмена: когда нужен не параметр, а поток изменений

Если задача — регулярно передавать изменения справочников и документов, отдельные параметры не подходят. План обмена регистрирует изменения по узлам, а сообщение обмена несёт их пакетом в XML.

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

Внутри одной базы полезен ещё один приём: ДополнительныеСвойства объекта. Флаг, записанный в Объект.ДополнительныеСвойства.Вставить("ЗагрузкаИзОбмена", Истина), доступен в серверных обработчиках ПередЗаписью и ПриЗаписи этого объекта.

Внешние источники данных: параметры для чужой СУБД

Объект Общие → Внешние источники данных даёт серверу 1С прямой доступ к таблицам другой базы через ODBC. Параметры сюда передают двух видов.

Параметры соединения — строка подключения, логин, пароль. Их задают кодом на сервере:

ПараметрыСоединения = Новый ПараметрыСоединенияВнешнегоИсточникаДанных;
ПараметрыСоединения.СтрокаСоединения = "Driver={SQL Server};Server=sql01;Database=crm;";
ПараметрыСоединения.АутентификацияСтандартная = Истина;
ПараметрыСоединения.ИмяПользователя = "reader";
ПараметрыСоединения.Пароль = "***";
ВнешниеИсточникиДанных.CRM.УстановитьОбщиеПараметрыСоединения(ПараметрыСоединения);
ВнешниеИсточникиДанных.CRM.УстановитьСоединение();

Параметры запроса — как в обычном запросе 1С: &Дата, &Клиент, значения через Запрос.УстановитьПараметр(). Не склеивайте текст запроса со строкой от пользователя: параметр защищает от подстановки чужого кода, конкатенация — нет.

Клиентский код к внешнему источнику не обращается. Значение с формы сначала уходит на сервер обычным вызовом, а уже там подставляется в запрос.

Скорость и безопасность передачи параметров

Как не тормозить

  • 🎯 Один вызов вместо пяти. Соберите всё нужное в Структуру и получите ответ за одно обращение к серверу.
  • 🪶 Без контекста, где можно. &НаСервереБезКонтекста не тащит форму.
  • 📎 Знач для входных параметров, адрес временного хранилища для тяжёлых данных.
  • 🧹 Не вызывайте сервер в ПриАктивизацииСтроки без обработчика ожидания: при прокрутке списка это десятки вызовов в секунду.

Как не открыть дыру

Всё, что пришло с клиента, считайте недоверенным. Пользователь с доступом к отладке или внешней обработкой может вызвать серверную функцию с любыми аргументами.

  1. Проверяйте права внутри экспортной функции модуля «Вызов сервера»: ПравоДоступа("Изменение", Метаданные.Документы.Заказ).
  2. Не включайте привилегированный режим для всей функции. Включите его на минимальный участок и выключите сразу после.
  3. Никогда не передавайте в Выполнить() и Вычислить() строку, пришедшую от клиента или извне.
  4. Для HTTP и SOAP — только HTTPS и отдельный пользователь с минимальной ролью. Пароль не кладите в URL.
  5. Проверяйте тип и диапазон: ТипЗнч(Параметр) = Тип("Число"), длину строки, заполненность ссылки.
Откуда приходит параметр?

Частые вопросы

Как передать параметры в фоновое задание?
Массивом в вызове ФоновыеЗадания.Выполнить("ИмяМодуля.ИмяПроцедуры", МассивПараметров). Процедура должна быть экспортной в серверном общем модуле, а результат удобно вернуть через временное хранилище.
Как передать значение параметра в отчёт на СКД?
Через настройки компоновщика: КомпоновщикНастроек.Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("Период", Значение). Имя должно совпадать с параметром схемы.
Можно ли изменить параметр сеанса с клиента?
Напрямую нет: параметры сеанса живут на сервере. Вызовите серверную функцию, которая проверит права и установит значение.
Почему значение параметра на клиенте изменилось после вызова сервера?
Параметр был объявлен без Знач, и серверная процедура его изменила. Платформа вернула новое значение обратно. Добавьте Знач, если такое поведение не нужно.
Сколько данных можно передать одним вызовом?
Жёсткого предела на уровне языка нет, но всё передаётся по сети. Данные больше нескольких мегабайт кладите во временное хранилище, а при интеграции разбивайте на пакеты.