HTTP-запрос из 1С 8.3: GET, POST, JSON, авторизация

Дата: 18.09.2026 23:23:09
HTTP
REST API
JSON
Интеграция
Base64
HTTPСоединение
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Любые

HTTP-запрос из 1С — основной способ связать базу с внешними сервисами: забрать заказы с сайта, отправить остатки на маркетплейс, узнать статус доставки по REST API. Ниже — GET и POST с JSON, Basic- и Bearer-авторизация, коды ответа, ошибки и обёртка для общего модуля.

Примеры рассчитаны на платформу 8.3.9 и новее при режиме совместимости конфигурации не ниже 8.3.9 или без него (свойство конфигурации «Режим совместимости»). В режиме совместимости 8.2 или 8.3.5 и ниже (так на платформе 8.3 работают, например, УТ 10.3, БП 2.0 и ЗУП 2.5) нет функций СтрНайти, СтрШаблон, ПолучитьДвоичныеДанныеИзСтроки и объектов JSON даже на свежей платформе. Модуль не скомпилируется с ошибкой «Процедура или функция с указанным именем не определена (СтрНайти)». Там СтрНайти меняют на Найти, СтрШаблон — на сложение строк, а для JSON и Base64 из строки нужны обходные пути.

Из чего собирается запрос

Соединение и запрос — разные объекты: одно соединение обслуживает несколько запросов к хосту.

ОбъектЗачем нужен
HTTPСоединениеСервер, порт, учётные данные, прокси, таймаут, защищённое соединение. Методы Получить (GET), ОтправитьДляОбработки (POST), Записать (PUT), Изменить (PATCH), Удалить (DELETE) и универсальный ВызватьHTTPМетод.
HTTPЗапросАдрес ресурса (путь и параметры), заголовки, тело.
HTTPОтветРезультат вызова: КодСостояния, Заголовки, тело в виде строки, двоичных данных или файла.
ЗащищенноеСоединениеOpenSSLНужен для адресов https.
ИнтернетПроксиПараметры прокси, если выход в интернет идёт через него.

Выполняйте запросы на сервере — в процедуре с директивой &НаСервереБезКонтекста или в серверном общем модуле. На клиенте синхронный вызов подвешивает интерфейс, пока сервис не ответит, а асинхронные методы (ПолучитьАсинх, ОтправитьДляОбработкиАсинх, ВызватьHTTPМетодАсинх) появились только в 8.3.21.

GET-запрос в 1С: минимальный пример

Короткий рабочий вариант — получить JSON по адресу https://api.example.com/v1/rates?base=RUB:

&НаСервереБезКонтекста
Функция ПолучитьКурсыНаСервере()

	ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(, Новый СертификатыУдостоверяющихЦентровОС);
	Соединение = Новый HTTPСоединение("api.example.com", 443, , , , 30, ЗащищенноеСоединение);

	Запрос = Новый HTTPЗапрос("/v1/rates?base=RUB");
	Запрос.Заголовки.Вставить("Accept", "application/json");

	Ответ = Соединение.Получить(Запрос);

	Если Ответ.КодСостояния < 200 Или Ответ.КодСостояния >= 300 Тогда
		ВызватьИсключение СтрШаблон("Сервис вернул код %1", Ответ.КодСостояния);
	КонецЕсли;

	Возврат Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);

КонецФункции

Что здесь важно:

  • Первый параметр HTTPСоединение — только имя хоста: без https://, пути и слеша в конце.
  • Шестой параметр — таймаут в секундах.
  • СертификатыУдостоверяющихЦентровОС включает проверку сертификата сайта по хранилищу ОС сервера 1С; без него платформа сертификат не проверяет.

Параметры HTTP-запроса в адресе

Параметры GET дописываются к адресу после знака вопроса. Отдельного метода для них у HTTPЗапрос нет, поэтому значения экранируйте сами — особенно кириллицу, пробелы и символы &, =, +:

АдресРесурса = "/v1/orders?status="
	+ КодироватьСтроку(Статус, СпособКодированияСтроки.КодировкаURL)
	+ "&page=" + XMLСтрока(НомерСтраницы);

Числа переводите в строку через XMLСтрока(Число) или Формат(Число, "ЧГ=0"), а не простой конкатенацией: обычное строковое представление разделяет разряды неразрывным пробелом (Символы.НПП), и вместо 1000 сервер получит «1 000». СтрЗаменить(Стр, " ", "") такой пробел не уберёт, а КодироватьСтроку превратит его в %C2%A0.

HTTP POST-запрос из 1С с JSON в теле

Тело POST задаётся строкой. Данные удобно собрать в структуру и сериализовать через ЗаписьJSON; про даты, ссылки и вложенные коллекции — в статье о работе с JSON.

&НаСервереБезКонтекста
Функция ОтправитьЗаказНаСервере(НомерЗаказа, Сумма)

	Данные = Новый Структура;
	Данные.Вставить("number", НомерЗаказа);
	Данные.Вставить("amount", Сумма);

	Запись = Новый ЗаписьJSON;
	Запись.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет));
	ЗаписатьJSON(Запись, Данные);
	ТекстJSON = Запись.Закрыть();

	Запрос = Новый HTTPЗапрос("/v1/orders");
	Запрос.Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
	Запрос.Заголовки.Вставить("Accept", "application/json");
	Запрос.УстановитьТелоИзСтроки(ТекстJSON, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);

	ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(, Новый СертификатыУдостоверяющихЦентровОС);
	Соединение = Новый HTTPСоединение("api.example.com", 443, , , , 30, ЗащищенноеСоединение);

	Ответ = Соединение.ОтправитьДляОбработки(Запрос);

	Возврат Ответ.КодСостояния;

КонецФункции

Два последних параметра УстановитьТелоИзСтроки задают UTF-8 без метки BOM. Без заголовка Content-Type часть API отвечает 415 Unsupported Media Type.

Авторизация: Basic и Bearer

Basic через параметры соединения

Логин и пароль можно передать третьим и четвёртым параметрами конструктора, заголовок платформа сформирует сама:

Соединение = Новый HTTPСоединение("api.example.com", 443, Логин, Пароль, , 30, ЗащищенноеСоединение);

Нюанс: учётные данные обычно уходят только в ответ на 401 с заголовком WWW-Authenticate. Если API сразу отвечает 403 или 401 без него, авторизация «не срабатывает», и заголовок собирают вручную.

Basic вручную: заголовок Authorization

Значение заголовка — слово Basic, пробел и строка «логин:пароль» в кодировке Base64. Строку сначала переводим в двоичные данные UTF-8, затем кодируем:

// Формирует значение заголовка Authorization для Basic-авторизации.
Функция ЗаголовокBasic(Логин, Пароль) Экспорт

	ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(Логин + ":" + Пароль, КодировкаТекста.UTF8);
	Строка64 = Base64Строка(ДвоичныеДанные);
	// Base64Строка переносит длинный результат на новые строки - убираем переносы
	Строка64 = СтрЗаменить(Строка64, Символы.ВК, "");
	Строка64 = СтрЗаменить(Строка64, Символы.ПС, "");
	Возврат "Basic " + Строка64;

КонецФункции

// Использование:
// Запрос.Заголовки.Вставить("Authorization", ЗаголовокBasic(Логин, Пароль));

На длинных значениях переносы сломают заголовок, поэтому удаляем их всегда.

Base64 в 1С: строка, файл и обратно

Те же функции нужны, когда API ждёт текст или файл в Base64 внутри JSON. Переносы там тоже лучше убрать: не каждый сервис их пропускает.

// Строка -> Base64 (без переносов строк)
Строка64 = Base64Строка(ПолучитьДвоичныеДанныеИзСтроки(Текст, КодировкаТекста.UTF8));
Строка64 = СтрЗаменить(СтрЗаменить(Строка64, Символы.ВК, ""), Символы.ПС, "");

// Base64 -> строка
Текст = ПолучитьСтрокуИзДвоичныхДанных(Base64Значение(Строка64), КодировкаТекста.UTF8);

// Файл -> Base64, например для поля "file" в JSON (код выполняется на сервере)
Строка64 = Base64Строка(Новый ДвоичныеДанные(ПутьКФайлу));
Строка64 = СтрЗаменить(СтрЗаменить(Строка64, Символы.ВК, ""), Символы.ПС, "");

Bearer-токен

С токеном проще: Запрос.Заголовки.Вставить("Authorization", "Bearer " + Токен). Токены живут ограниченное время: получив 401, запросите новый и повторите вызов один раз, а не в цикле.

Логины, пароли и токены не храните в коде и константах. В конфигурациях на БСП (в том числе 3.x) для этого есть безопасное хранилище: ОбщегоНазначения.ЗаписатьДанныеВБезопасноеХранилище и ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища. Оба метода работают на сервере в привилегированном режиме, который включает вызывающий код:

// НастройкаОбмена - ссылка-владелец, например элемент справочника настроек интеграции
УстановитьПривилегированныйРежим(Истина);
Токен = ОбщегоНазначения.ПрочитатьДанныеИзБезопасногоХранилища(НастройкаОбмена, "Токен");
УстановитьПривилегированныйРежим(Ложь);

Коды ответа: что считать успехом

Ответ 404 или 500 — не исключение, а обычный HTTPОтвет. Исключение бывает, только когда ответа нет: хост не найден, соединение оборвалось, истёк таймаут. Поэтому код проверяйте всегда — диапазоном 200–299, а не сравнением с 200.

КодЧто означаетЧто делать
200 OKУспех, результат в телеРазбирать тело
201 CreatedОбъект созданИдентификатор обычно в теле или в заголовке Location
204 No ContentУспех, тела нетНе пытаться разбирать JSON
400 Bad RequestОшибка в запросе: формат, обязательные поляИскать причину в теле ответа
401 / 403Не авторизован / нет правПроверить логин, токен, права ключа
404 Not FoundНеверный путь или объект не найденПроверить адрес ресурса
429 Too Many RequestsПревышен лимит запросовПовторить после паузы, которую часто указывают в заголовке Retry-After
5xxОшибка на стороне сервисаПовторить позже, записать в журнал

Универсальная функция для HTTP-запросов

Чтобы не повторять одно и то же в каждой интеграции, вынесите всё в серверный общий модуль, например HTTPКлиент:

// Общий модуль HTTPКлиент (флаг "Сервер").
// Платформа 8.3.9+, режим совместимости конфигурации не ниже 8.3.9.

// Возвращает структуру настроек для функции ВыполнитьHTTPЗапрос.
Функция НовыеНастройкиHTTP() Экспорт

	Настройки = Новый Структура;
	Настройки.Вставить("Таймаут", 30);                   // секунды
	Настройки.Вставить("Логин", "");                     // Basic-авторизация
	Настройки.Вставить("Пароль", "");
	Настройки.Вставить("Токен", "");                     // Bearer, приоритетнее Basic
	Настройки.Вставить("Заголовки", Новый Соответствие); // дополнительные заголовки
	Настройки.Вставить("Прокси", Неопределено);          // ИнтернетПрокси или Неопределено
	Настройки.Вставить("КодировкаОтвета", "");           // например "windows-1251", если сервис не указывает charset
	Возврат Настройки;

КонецФункции

// Выполняет HTTP-запрос и возвращает результат в виде структуры.
// Исключений наружу не выбрасывает: при любой ошибке Успех = Ложь.
//
// Параметры:
//  Метод     - Строка - GET, POST, PUT, PATCH, DELETE.
//  URL       - Строка - полный адрес, например "https://api.example.com/v1/orders?page=2".
//  Данные    - Строка - тело отправляется как есть;
//              Структура, Соответствие, Массив - сериализуются в JSON;
//              Неопределено - запрос без тела.
//  Настройки - Структура - см. НовыеНастройкиHTTP().
//
// Возвращаемое значение:
//  Структура:
//   * Успех        - Булево - Истина, если код ответа 200-299 и тело,
//                    похожее на JSON, прочитано без ошибок.
//   * КодСостояния - Число - 0, если ответ не получен.
//   * Тело         - Строка - тело ответа.
//   * Данные       - Соответствие, Массив, Неопределено - прочитанный JSON;
//                    Неопределено, если тело пустое или это не JSON.
//   * ТекстОшибки  - Строка - описание ошибки.
//
Функция ВыполнитьHTTPЗапрос(Знач Метод, Знач URL, Знач Данные = Неопределено, Знач Настройки = Неопределено) Экспорт

	Результат = Новый Структура;
	Результат.Вставить("Успех", Ложь);
	Результат.Вставить("КодСостояния", 0);
	Результат.Вставить("Тело", "");
	Результат.Вставить("Данные", Неопределено);
	Результат.Вставить("ТекстОшибки", "");

	Если Настройки = Неопределено Тогда
		Настройки = НовыеНастройкиHTTP();
	КонецЕсли;
	Метод = ВРег(СокрЛП(Метод));

	Попытка
		Адрес = РазобратьURL(URL);
	Исключение
		Результат.ТекстОшибки = "Некорректный адрес: " + URL + " ("
			+ КраткоеПредставлениеОшибки(ИнформацияОбОшибке()) + ")";
		Возврат Результат;
	КонецПопытки;

	ЗащищенноеСоединение = Неопределено;
	Если Адрес.Защищенное Тогда
		ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(, Новый СертификатыУдостоверяющихЦентровОС);
	КонецЕсли;

	Заголовки = Новый Соответствие;
	Заголовки.Вставить("Accept", "application/json");
	Если ЗначениеЗаполнено(Настройки.Токен) Тогда
		Заголовки.Вставить("Authorization", "Bearer " + Настройки.Токен);
	ИначеЕсли ЗначениеЗаполнено(Настройки.Логин) Тогда
		Заголовки.Вставить("Authorization", ЗаголовокBasic(Настройки.Логин, Настройки.Пароль));
	КонецЕсли;
	Для Каждого Заголовок Из Настройки.Заголовки Цикл
		Заголовки.Вставить(Заголовок.Ключ, Заголовок.Значение);
	КонецЦикла;
	Если Данные <> Неопределено И Заголовки.Получить("Content-Type") = Неопределено Тогда
		Заголовки.Вставить("Content-Type", "application/json; charset=utf-8");
	КонецЕсли;

	Запрос = Новый HTTPЗапрос(Адрес.АдресРесурса, Заголовки);

	Если Данные <> Неопределено Тогда
		Если ТипЗнч(Данные) = Тип("Строка") Тогда
			ТекстТела = Данные;
		Иначе
			Попытка
				ТекстТела = ЗначениеВСтрокуJSON(Данные);
			Исключение
				// например, в данных оказалась ссылка или ХранилищеЗначения
				Результат.ТекстОшибки = "Не удалось преобразовать данные в JSON: "
					+ КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
				Возврат Результат;
			КонецПопытки;
		КонецЕсли;
		Запрос.УстановитьТелоИзСтроки(ТекстТела, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
	КонецЕсли;

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

	Кодировка = ?(ЗначениеЗаполнено(Настройки.КодировкаОтвета), Настройки.КодировкаОтвета,
		КодировкаОтвета(Ответ.Заголовки));
	Попытка
		Тело = Ответ.ПолучитьТелоКакСтроку(Кодировка);
	Исключение
		// указана кодировка, которую платформа не знает
		Тело = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
	КонецПопытки;
	Если Тело = Неопределено Тогда
		Тело = ""; // например, ответ 204 без тела
	КонецЕсли;

	Результат.КодСостояния = Ответ.КодСостояния;
	Результат.Тело = Тело;
	Результат.Успех = (Ответ.КодСостояния >= 200 И Ответ.КодСостояния < 300);

	Если Не Результат.Успех Тогда
		Результат.ТекстОшибки = СтрШаблон("Сервер вернул код %1: %2", Ответ.КодСостояния, Лев(Тело, 1000));
		ЗаписьЖурналаРегистрации("HTTPКлиент", УровеньЖурналаРегистрации.Предупреждение, , ,
			Метод + " " + Адрес.Сервер + Адрес.АдресРесурса + Символы.ПС + Результат.ТекстОшибки);
		Возврат Результат;
	КонецЕсли;

	ПервыйСимвол = Лев(СокрЛ(Тело), 1);
	Если ПервыйСимвол = "{" Или ПервыйСимвол = "[" Тогда
		Попытка
			Результат.Данные = СтрокаJSONВЗначение(Тело);
		Исключение
			// код ответа успешный, но пользоваться таким результатом нельзя
			Результат.Успех = Ложь;
			Результат.ТекстОшибки = "Ответ не удалось прочитать как JSON: "
				+ КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
		КонецПопытки;
	КонецЕсли;

	Возврат Результат;

КонецФункции

// Формирует значение заголовка Authorization для Basic-авторизации.
Функция ЗаголовокBasic(Логин, Пароль) Экспорт

	ДвоичныеДанные = ПолучитьДвоичныеДанныеИзСтроки(Логин + ":" + Пароль, КодировкаТекста.UTF8);
	Строка64 = Base64Строка(ДвоичныеДанные);
	Строка64 = СтрЗаменить(Строка64, Символы.ВК, "");
	Строка64 = СтрЗаменить(Строка64, Символы.ПС, "");
	Возврат "Basic " + Строка64;

КонецФункции

// Возвращает кодировку из параметра charset заголовка Content-Type.
// Если сервис кодировку не указал, возвращает UTF-8.
Функция КодировкаОтвета(Заголовки)

	Для Каждого Заголовок Из Заголовки Цикл
		Если НРег(Заголовок.Ключ) <> "content-type" Тогда
			Продолжить;
		КонецЕсли;
		Позиция = СтрНайти(НРег(Заголовок.Значение), "charset=");
		Если Позиция = 0 Тогда
			Прервать;
		КонецЕсли;
		Кодировка = Сред(Заголовок.Значение, Позиция + 8);
		Позиция = СтрНайти(Кодировка, ";");
		Если Позиция > 0 Тогда
			Кодировка = Лев(Кодировка, Позиция - 1);
		КонецЕсли;
		Кодировка = СокрЛП(СтрЗаменить(Кодировка, """", ""));
		Если ЗначениеЗаполнено(Кодировка) Тогда
			Возврат Кодировка;
		КонецЕсли;
	КонецЦикла;

	Возврат КодировкаТекста.UTF8;

КонецФункции

// Разбирает полный URL на части для HTTPСоединение и HTTPЗапрос.
Функция РазобратьURL(Знач URL)

	Результат = Новый Структура("Защищенное, Сервер, Порт, АдресРесурса", Ложь, "", 0, "/");

	URL = СокрЛП(URL);
	Позиция = СтрНайти(URL, "#"); // фрагмент серверу не передаётся
	Если Позиция > 0 Тогда
		URL = Лев(URL, Позиция - 1);
	КонецЕсли;

	Позиция = СтрНайти(URL, "://");
	Если Позиция > 0 Тогда
		Схема = НРег(Лев(URL, Позиция - 1));
		URL = Сред(URL, Позиция + 3);
	Иначе
		Схема = "http";
	КонецЕсли;
	Результат.Защищенное = (Схема = "https");

	// Имя хоста заканчивается на первом "/" или "?"
	Позиция = СтрНайти(URL, "/");
	ПозицияВопроса = СтрНайти(URL, "?");
	Если ПозицияВопроса > 0 И (Позиция = 0 Или ПозицияВопроса < Позиция) Тогда
		Позиция = ПозицияВопроса;
	КонецЕсли;

	Если Позиция > 0 Тогда
		ХостИПорт = Лев(URL, Позиция - 1);
		Путь = Сред(URL, Позиция);
		Если Лев(Путь, 1) <> "/" Тогда
			Путь = "/" + Путь;
		КонецЕсли;
		Результат.АдресРесурса = Путь;
	Иначе
		ХостИПорт = URL;
	КонецЕсли;

	Если СтрНайти(ХостИПорт, "@") > 0 Тогда
		ВызватьИсключение "Логин и пароль в адресе не поддерживаются, "
			+ "передайте их в Настройки.Логин и Настройки.Пароль";
	КонецЕсли;

	Позиция = СтрНайти(ХостИПорт, ":");
	Если Позиция > 0 Тогда
		Результат.Сервер = Лев(ХостИПорт, Позиция - 1);
		Результат.Порт = Число(Сред(ХостИПорт, Позиция + 1));
	Иначе
		Результат.Сервер = ХостИПорт;
		Результат.Порт = ?(Результат.Защищенное, 443, 80);
	КонецЕсли;

	Если Не ЗначениеЗаполнено(Результат.Сервер) Тогда
		ВызватьИсключение "Не указан сервер в адресе " + URL;
	КонецЕсли;

	Возврат Результат;

КонецФункции

Функция ЗначениеВСтрокуJSON(Значение)

	Запись = Новый ЗаписьJSON;
	Запись.УстановитьСтроку(Новый ПараметрыЗаписиJSON(ПереносСтрокJSON.Нет));
	ЗаписатьJSON(Запись, Значение);
	Возврат Запись.Закрыть();

КонецФункции

Функция СтрокаJSONВЗначение(Текст)

	Чтение = Новый ЧтениеJSON;
	Чтение.УстановитьСтроку(Текст);
	Значение = ПрочитатьJSON(Чтение, Истина); // Истина - читать в Соответствие
	Чтение.Закрыть();
	Возврат Значение;

КонецФункции

Так выглядит вызов:

// Пример 1. GET с параметрами и Bearer-токеном
Процедура ЗагрузитьНовыеЗаказы(ТокенДоступа) Экспорт

	Настройки = HTTPКлиент.НовыеНастройкиHTTP();
	Настройки.Токен = ТокенДоступа;

	URL = "https://api.example.com/v1/orders?status="
		+ КодироватьСтроку("новый", СпособКодированияСтроки.КодировкаURL)
		+ "&page=" + XMLСтрока(1);

	Результат = HTTPКлиент.ВыполнитьHTTPЗапрос("GET", URL, , Настройки);
	Если Не Результат.Успех Тогда
		ВызватьИсключение Результат.ТекстОшибки;
	КонецЕсли;

	// Успешный ответ ещё не гарантирует JSON-объект: тело может быть пустым,
	// текстом или массивом верхнего уровня
	Если ТипЗнч(Результат.Данные) <> Тип("Соответствие") Тогда
		ВызватьИсключение "Сервис вернул не JSON-объект";
	КонецЕсли;

	Заказы = Результат.Данные.Получить("items");
	Если ТипЗнч(Заказы) <> Тип("Массив") Тогда
		Возврат;
	КонецЕсли;

	Для Каждого Заказ Из Заказы Цикл
		// Заказ - Соответствие: Заказ.Получить("id"), Заказ.Получить("amount")
	КонецЦикла;

КонецПроцедуры

// Пример 2. POST с JSON-телом и Basic-авторизацией
Функция ОтправитьЗаказ(НомерЗаказа, Сумма, Логин, Пароль) Экспорт

	Заказ = Новый Структура;
	Заказ.Вставить("number", НомерЗаказа);
	Заказ.Вставить("amount", Сумма);

	Настройки = HTTPКлиент.НовыеНастройкиHTTP();
	Настройки.Логин = Логин;
	Настройки.Пароль = Пароль;

	Результат = HTTPКлиент.ВыполнитьHTTPЗапрос("POST", "https://api.example.com/v1/orders", Заказ, Настройки);
	Если Не Результат.Успех Тогда
		ВызватьИсключение Результат.ТекстОшибки;
	КонецЕсли;

	// 201 Created - в теле обычно идентификатор созданного объекта, 204 - тела нет
	Если ТипЗнч(Результат.Данные) = Тип("Соответствие") Тогда
		Возврат Результат.Данные.Получить("id");
	КонецЕсли;

	Возврат Неопределено;

КонецФункции

Разбор ключевых строк

  • РазобратьURL делит адрес на хост, порт и путь с параметрами и отбрасывает фрагмент #…. Адрес вида user:pass@host не принимается.
  • Нестроковые данные сериализуются в JSON, строка уходит как есть. Для XML или form-urlencoded передайте свой Content-Type в Настройки.Заголовки именно в таком написании: ключи соответствия чувствительны к регистру.
  • Кодировка ответа берётся из Настройки.КодировкаОтвета, если она задана, иначе из charset в заголовке Content-Type, по умолчанию — UTF-8.
  • Исключения наружу не уходят: ошибки пишутся в журнал регистрации, а вызывающий код смотрит на Успех. Если ключ API передаётся в адресе, уберите его из текста записи.
  • Нечитаемый JSON даёт Успех = Ложь, а пустое тело или текст при успешном коде — Данные = Неопределено, поэтому тип Данные проверяйте, как в примерах.
  • JSON читается в Соответствие: ключи вида order-id в структуру не лягут.

В конфигурации с БСП адрес разбирает ОбщегоНазначенияКлиентСервер.СтруктураURI, а прокси из настроек программы возвращает ПолучениеФайловИзИнтернета.ПолучитьПрокси.

Ошибка выполнения HTTP-запроса в 1С: причины и решение

Если запрос не дошёл до сервера или ответ не получен, платформа вызывает исключение с текстом вида «Ошибка при вызове метода контекста (Получить): Ошибка работы с Интернет: …». Причина — в конце сообщения. Формулировки в разных версиях платформы немного отличаются:

Текст в сообщенииПричинаЧто сделать
Couldn't resolve host nameВ параметр «Сервер» передан адрес с протоколом или путём; DNS на сервере 1С не знает имяПередавать только хост; проверить разрешение имени с машины сервера 1С
Couldn't connect to server, Failed to connectПорт закрыт, фаервол, выход в интернет только через проксиПроверить доступность порта с сервера 1С; настроить прокси
Timeout was reachedСервис не ответил за отведённое времяУвеличить таймаут; большие выгрузки делить на пачки
SSL connect errorНе удалось TLS-рукопожатие: ЗащищенноеСоединениеOpenSSL передано для http-порта, сервер не поддерживает версию TLS или шифры платформы, сервис работает только по ГОСТ-TLSПроверить схему и порт, обновить платформу; для ГОСТ-TLS нужен криптопровайдер
SSL certificate problem, Peer certificate cannot be authenticatedКорневого сертификата нет в хранилище ОС сервера 1С (часто — у российских УЦ), сертификат сайта просрочен или выдан на другое имяУстановить корневой сертификат на сервер 1С или передать СертификатыУдостоверяющихЦентровФайл (PEM); проверить срок и имя в сертификате
Failure when receiving data from the peer, Empty reply from serverСервер оборвал соединение: запрос без ЗащищенноеСоединениеOpenSSL ушёл на https-порт, прокси или фаервол режет трафикПроверить схему и порт, попробовать без прокси

Nginx на https-порту незашифрованный запрос не обрывает, а отвечает кодом 400 «The plain HTTP request was sent to HTTPS port» — это обычный ответ, не исключение. Решение то же: схема https и ЗащищенноеСоединениеOpenSSL.

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

HTTP-запрос не отправлен, хотя в браузере всё открывается

Код с директивой &НаСервере выполняет сервер 1С, а не компьютер пользователя: в клиент-серверном варианте у него своя учётная запись службы, прокси, фаервол и хранилище сертификатов. Проверяйте доступ именно оттуда.

Ещё причины:

  • код внешней обработки работает в безопасном режиме или в кластере включены профили безопасности — доступ к интернет-ресурсу нужно явно разрешить (в БСП — запросом разрешений на внешние ресурсы);
  • вызов идёт из веб-клиента: до 8.3.21 HTTPСоединение там недоступно, с 8.3.21 синхронные методы вызывают исключение «Метод недоступен в веб-клиенте», а браузер заблокирует запрос к сервису без CORS-заголовков.

Прокси

Прокси = Новый ИнтернетПрокси(Ложь);
// Прокси задаётся отдельно для каждого протокола назначения
Прокси.Установить("http", "proxy.company.local", 3128);
Прокси.Установить("https", "proxy.company.local", 3128);
Прокси.НеИспользоватьПроксиДляЛокальныхАдресов = Истина;
// Логин и пароль прокси - четвёртый и пятый параметры метода Установить

Настройки = HTTPКлиент.НовыеНастройкиHTTP();
Настройки.Прокси = Прокси;

Конструктор Новый ИнтернетПрокси(Истина) берёт системные настройки, а у службы сервера 1С это настройки её учётной записи.

Типичные ошибки

  • В параметр «Сервер» у HTTPСоединение передан полный адрес вместо имени хоста.
  • Не задан таймаут: зависший сервис держит сеанс или регламентное задание сколько угодно долго.
  • В начале тела стоит BOM: без ИспользованиеByteOrderMark.НеИспользовать сервис отвечает 400 на внешне правильный JSON.
  • Ответ разбирается без проверки типа: при пустом теле обращение к Данные.Получить даёт ошибку «Значение не является значением объектного типа».
  • Внешний сервис вызывается из проведения или записи объекта: пока он думает, транзакция держит блокировки (см. статью о конфликтах блокировок). Надёжнее ставить задание в очередь (регистр сведений) и отправлять регламентным заданием.
  • Исключение гасится пустым блоком Попытка … Исключение … КонецПопытки, и ошибку никто не видит. Пишите её хотя бы в журнал регистрации.

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

Как отправить файл?

Если сервис ждёт файл как тело запроса, используйте УстановитьТелоИзДвоичныхДанных или УстановитьИмяФайлаТела. Для multipart/form-data тело собирают вручную: граница, заголовки частей и двоичные данные файла.

Почему в ответе нечитаемые символы вместо кириллицы?

Тело прочитано не в той кодировке. Обёртка берёт её из charset в заголовке Content-Type. Если старый сервис отвечает в windows-1251, но кодировку не указывает, передайте её явно: Настройки.КодировкаОтвета = "windows-1251", а при работе с HTTPОтвет напрямую — Ответ.ПолучитьТелоКакСтроку("windows-1251").

Как не подвешивать интерфейс на долгом запросе?

Запускайте обмен в фоновом задании: в БСП 3.x для этого есть модуль ДлительныеОперации, без БСП — ФоновыеЗадания.Выполнить с экспортной процедурой серверного общего модуля. Если и в фоне медленно, ищите узкое место по статье о диагностике тормозов.

Как посмотреть, что реально уходит на сервер?

Временно запишите в журнал регистрации адрес, заголовки и тело запроса, замаскировав значение Authorization:

ТекстЗаголовков = "";
Для Каждого Заголовок Из Запрос.Заголовки Цикл
	// учётные данные в журнал не пишем
	Значение = ?(НРег(Заголовок.Ключ) = "authorization", "***", Заголовок.Значение);
	ТекстЗаголовков = ТекстЗаголовков + Заголовок.Ключ + ": " + Значение + Символы.ПС;
КонецЦикла;

ЗаписьЖурналаРегистрации("HTTPКлиент.Отладка", УровеньЖурналаРегистрации.Информация, , ,
	Запрос.АдресРесурса + Символы.ПС + ТекстЗаголовков + Запрос.ПолучитьТелоКакСтроку());

Полную картину даст отладочный прокси: он должен быть доступен с сервера 1С и указан в ИнтернетПрокси. Для https добавьте его корневой сертификат в доверенные на машине, где выполняется код.

Когда проще заказать

Одиночный запрос к API пишется быстро, а надёжный обмен с очередью, повторами, журналом ошибок и сопоставлением справочников — задача другого масштаба. Для него посмотрите услугу обмена 1С с сайтом или разместите задачу: оценка бесплатная, ответ в течение рабочего дня.

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.