Внешний сервис не отвечает из 1С: как найти, где именно рвётся обмен

· 10 мин

Содержание

Проверить веб-сервис в 1С быстрее всего в три хода. Сначала вызовите его вне 1С (curl или Postman) с того компьютера, где выполняется код. Потом повторите тот же запрос минимальной процедурой на HTTPСоединение или WSПрокси. И сравните код состояния и тело ответа. Если снаружи сервис отвечает, а из 1С нет, виноваты код, сертификат или прокси. Если не отвечает и снаружи — дело в сети или в самом сервисе.

Ниже порядок, который работает для REST и SOAP на платформе 8.3. Он одинаков для любой конфигурации: БП, ЗУП, УТ, ERP. Отличаются только модули, где лежит код обмена.

Что подготовить перед проверкой веб-сервиса

Без исходных данных тест превращается в угадывание. Соберите их до того, как открывать Конфигуратор.

  • 🌐 Адрес. Полный URL метода, например https://api.example.ru/v1/orders. Для SOAP — адрес WSDL, обычно с окончанием ?wsdl.
  • 🔑 Авторизация. Логин и пароль, токен, ключ API или клиентский сертификат. И где их передают: в заголовке, в параметре адреса, в теле.
  • 📄 Пример запроса и ответа из документации сервиса. Метод (GET, POST, PUT), заголовок Content-Type, образец тела.
  • 🖥 Место выполнения кода. В клиент-серверной базе обмен почти всегда идёт на сервере 1С. Значит, проверять сеть нужно с сервера, а не с компьютера бухгалтера.
  • 🧱 Сетевые ограничения. Есть ли прокси, белый список IP у поставщика сервиса, закрытые исходящие порты.

Тест вне 1С: отделяем сеть от кода

Это главный приём. Зайдите на сервер 1С (или на рабочую станцию для файловой базы) и выполните запрос из командной строки. В Windows 10 и Windows Server 2019 и новее curl уже встроен:

curl -v -H "Authorization: Bearer ВАШ_ТОКЕН" https://api.example.ru/v1/orders

Ключ -v покажет всё: разрешение имени, рукопожатие TLS, заголовки и код ответа. Для POST добавьте -X POST -H "Content-Type: application/json" -d @body.json.

Если удобнее графический инструмент, подойдёт Postman для REST и SoapUI для SOAP. Только запускайте их на том же компьютере, где работает код 1С.

Служба сервера 1С работает от отдельной учётной записи, обычно USR1CV8. Если прокси или сертификаты настроены только в профиле вашего пользователя Windows, из curl всё пройдёт, а из 1С нет. Это частая причина расхождений.

Если проверяете свой опубликованный сервис

Бывает и обратная задача: убедиться, что веб-сервис самой базы 1С опубликован. Откройте в браузере http://сервер/имя_публикации/ws/ИмяСервиса?wsdl. Пришёл XML с описанием — публикация работает. Для HTTP-сервисов адрес строится через /hs/ и корневой URL сервиса. Ответ 404 обычно значит, что сервис не отмечен при публикации на веб-сервере или указано не то имя.

Минимальный код HTTP-соединения для проверки

Не тестируйте сервис сразу через большую обработку обмена. Напишите отдельную процедуру на 15–20 строк во внешней обработке и выполняйте её на сервере.

Объект HTTPСоединение принимает имя хоста без схемы и пути: api.example.ru, а не https://api.example.ru/v1. Путь передаётся отдельно, в HTTPЗапрос.

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

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

	Заголовки = Новый Соответствие;
	Заголовки.Вставить("Authorization", "Bearer " + ПолучитьТокен());
	Заголовки.Вставить("Accept", "application/json");

	Запрос = Новый HTTPЗапрос("/v1/orders?limit=1", Заголовки);
	Ответ = Соединение.Получить(Запрос);

	Возврат СтрШаблон("Код: %1
	|Тело: %2", Ответ.КодСостояния, Ответ.ПолучитьТелоКакСтроку("UTF-8"));

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

Что здесь важно для проверки:

  1. Таймаут (шестой параметр, 30 секунд). Без него при зависшем сервисе сеанс 1С висит неопределённо долго, и вы не поймёте, что произошло.
  2. Защищённое соединение нужно для любого адреса на https. Без него запрос уйдёт по обычному HTTP и на порт 443 придёт ошибка.
  3. Порт указывайте явно, если сервис слушает нестандартный, например 8443.
  4. Токен не храните в тексте модуля. Для проверки можно временно подставить строку, но в рабочий код — только из защищённого хранилища или константы с ограниченными правами.

Прокси

Если в организации выход в интернет идёт через прокси, передайте его пятым параметром:

Прокси = Новый ИнтернетПрокси;
Прокси.Установить("https", "proxy.local", 3128);
Соединение = Новый HTTPСоединение("api.example.ru", 443, , , Прокси, 30, ЗащищенноеСоединение);

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

Как отправить запрос к веб-сервису и не потерять тело

Метод Получить подходит для GET. Для остальных:

ЗадачаМетод объекта HTTPСоединение
Получить данные (GET)Получить(Запрос)
Создать или передать данные (POST)ОтправитьДляОбработки(Запрос)
Заменить ресурс (PUT)Записать(Запрос)
Удалить (DELETE)Удалить(Запрос)
Любой другой метод (PATCH и др.)ВызватьHTTPМетод("PATCH", Запрос)

Тело задают до отправки:

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

Отключайте BOM в теле запроса. Без третьего параметра 1С может добавить в начало строки служебные байты. Многие API отвечают на это 400 Bad Request с невнятным текстом про некорректный JSON, хотя глазами тело выглядит правильно.

JSON удобнее собирать не склейкой строк, а через ЗаписьJSON:

Данные = Новый Структура("number, amount", "А-15", 1250.50);
Запись = Новый ЗаписьJSON;
Запись.УстановитьСтроку();
ЗаписатьJSON(Запись, Данные);
ТекстJSON = Запись.Закрыть();

Так не будет ошибок с кавычками, разделителем дробной части и экранированием.

SOAP-сервис через WSПрокси

Для SOAP код короче, если сервис отдаёт WSDL:

Определения = Новый WSОпределения("https://soap.example.ru/service?wsdl", Логин, Пароль, , 30);
Прокси = Новый WSПрокси(Определения, "http://example.ru/ns", "OrderService", "OrderServiceSoap");
Прокси.Пользователь = Логин;
Прокси.Пароль = Пароль;
Результат = Прокси.GetOrder("А-15");

Пространство имён, имя сервиса и точки подключения берите из WSDL: атрибут targetNamespace, элементы service и port. Ошибка в любом из трёх — и прокси не создастся.

Альтернатива — объект метаданных «WS-ссылка» в ветке Общие дерева конфигурации. Его создают импортом WSDL. Подходит для постоянной интеграции, но при смене WSDL ссылку придётся обновлять в конфигурации.

Разбор ответа: коды состояния и что с ними делать

HTTPСоединение не выбрасывает исключение на кодах 4xx и 5xx. Запрос «успешно» выполнился, просто сервис ответил отказом. Поэтому код всегда проверяют явно:

Если Ответ.КодСостояния <> 200 И Ответ.КодСостояния <> 201 Тогда
	ВызватьИсключение СтрШаблон("Сервис вернул %1: %2", Ответ.КодСостояния, Ответ.ПолучитьТелоКакСтроку("UTF-8"));
КонецЕсли;
КодЧто значитКуда смотреть
200, 201, 204Успех (204 — без тела)Разбирать тело, если есть
301, 302, 307Ресурс переехалЗаголовок Location в Ответ.Заголовки, повторить запрос по новому адресу
400Сервис не понял запросТело, кодировка, BOM, формат дат и чисел
401Нет авторизации или она невернаТокен, логин, формат заголовка Authorization
403Авторизован, но доступа нетПрава учётной записи, белый список IP
404Нет такого адресаПуть, версия API в адресе, опечатки
405Метод не поддерживаетсяPOST вместо GET или наоборот
415Не тот тип содержимогоЗаголовок Content-Type
429Слишком много запросовПауза между вызовами, пакетная отправка
500, 502, 503, 504Сбой на стороне сервиса или шлюзаПовторить позже, написать поставщику с временем запроса

Тело ответа при ошибке читайте всегда. Хорошие API пишут туда конкретную причину: какое поле не прошло проверку, какой токен просрочен.

Для JSON-ответа разбор такой:

Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку("UTF-8"));
Результат = ПрочитатьJSON(Чтение, Истина);
Чтение.Закрыть();

Второй параметр Истина вернёт Соответствие, а не Структуру. Это спасает, когда ключи в ответе содержат дефис или начинаются с цифры: в Структуру такие ключи не попадут, и чтение упадёт.

Диагностика: выберите симптом

Сертификаты и безопасность HTTPS-соединения

Большинство проблем с HTTPS в 1С сводится к доверию: сервер 1С должен знать удостоверяющий центр, который выпустил сертификат сервиса.

Какой источник сертификатов выбрать

ОбъектОткуда берёт сертификатыКогда использовать
СертификатыУдостоверяющихЦентровОСХранилище операционной системыОбычные публичные сервисы, если корневые сертификаты на сервере актуальны
СертификатыУдостоверяющихЦентровФайлФайл с сертификатами в формате PEMСамоподписанные или корпоративные сертификаты, Linux-сервер без нужного корня
Не указывать второй параметрПроверка цепочки не выполняетсяТолько разовая диагностика в тестовой базе

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

Хранилище ОС для службы 1С — это хранилище компьютера, а не текущего пользователя. Сертификат, установленный двойным щелчком «для текущего пользователя», служба не увидит. Устанавливайте его в «Локальный компьютер → Доверенные корневые центры сертификации».

Для российских сервисов, которые перешли на сертификаты Национального удостоверяющего центра Минцифры, корневой и промежуточный сертификаты НУЦ нужно поставить на сервер отдельно: в стандартном наборе Windows их нет.

Клиентский сертификат

Некоторые сервисы требуют, чтобы и 1С предъявила сертификат. Тогда первый параметр защищённого соединения — файл сертификата клиента с паролем:

СертКлиента = Новый СертификатКлиентаФайл("C:\certs\client.pfx", ПарольКСертификату);
ЗащищенноеСоединение = Новый ЗащищенноеСоединениеOpenSSL(СертКлиента, Новый СертификатыУдостоверяющихЦентровОС);

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

Отладчик и журнал регистрации при проверке обмена

Пошаговая отладка

Код обмена выполняется на сервере, поэтому точка останова сработает только при включённой серверной отладке. В файловой базе её достаточно разрешить в параметрах отладки Конфигуратора. В клиент-серверной базе служба агента сервера должна быть запущена с ключом -debug.

Чтобы добавить ключ -debug, службу агента сервера 1С перезапускают. При этом оборвутся сеансы всех пользователей кластера. Делайте это на тестовом сервере или вне рабочего времени.

Ставьте точку останова сразу после строки с Получить или ОтправитьДляОбработки. В табло вычислите Ответ.КодСостояния, Ответ.ПолучитьТелоКакСтроку() и переберите Ответ.Заголовки. Так видно, что именно вернул сервис, а не то, что успела интерпретировать обработка дальше по коду.

Запись в журнал регистрации

На рабочей базе отладчик не подключишь. Здесь выручает журнал регистрации: записывайте запрос и ответ при каждом неуспешном обмене.

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

Если Ответ.КодСостояния >= 400 Тогда
	ЗаписьЖурналаРегистрации("Обмен.ВнешнийСервис", УровеньЖурналаРегистрации.Предупреждение, , ,
		СтрШаблон("Код %1. Тело ответа: %2", Ответ.КодСостояния, Ответ.ПолучитьТелоКакСтроку("UTF-8")));
КонецЕсли;

Смотреть записи удобно отбором по имени события Обмен.ВнешнийСервис. В типовых конфигурациях журнал открывается из Администрирование → Обслуживание → Журнал регистрации.

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

Подсмотреть трафик снизу

Если непонятно, что 1С на самом деле отправляет, пропустите запрос через отладочный прокси вроде Fiddler. Укажите в ИнтернетПрокси адрес 127.0.0.1 и порт, на котором слушает Fiddler (по умолчанию 8888). Для HTTPS придётся временно доверить корневой сертификат Fiddler. После проверки удалите его из хранилища.

Частые причины сбоев при подключении к веб-сервису

Здесь то, что не видно по кодам ответа и чаще всего съедает время.

  • 🔀 Код выполняется не там, где вы думаете. Процедура с директивой &НаКлиенте пойдёт с компьютера пользователя, &НаСервере — с сервера 1С. Сеть и сертификаты у них разные.
  • 🕐 Время на сервере сбито. Подписанные токены (JWT) и TLS-рукопожатие чувствительны к часам. Расхождение в несколько минут даёт 401 при верном токене.
  • 🧾 Безопасный режим. Код во внешней обработке, подключённой в безопасном режиме, или в расширении без нужных прав не может открывать интернет-соединения. Ошибка будет про недостаточные права, а не про сеть.
  • 🔁 Повторная отправка после таймаута. Сервис мог принять заказ, но не успеть ответить. Повтор создаст дубль. Проверяйте, поддерживает ли API ключ идемпотентности или поиск по вашему номеру документа.
  • 🧩 Регистр заголовков и пробелы. Лишний пробел в Bearer токен или перевод строки в конце токена из файла дают 401.
  • 📦 Большой пакет. Сервис принимает 100 позиций за вызов, а 1С шлёт 5 000. Ответ — 413 или обрыв соединения. Делите выгрузку на части.
Проверка перед запуском обмена в рабочей базе
Выполнено: 0 / 6

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

Можно ли проверить веб-сервис без доступа к Конфигуратору?
Да. Вызовите сервис через curl или Postman с сервера 1С. Если он отвечает, проблема в настройках обмена или в коде, и дальше нужен разработчик с правами на конфигурацию.
Почему в файловой базе обмен работает, а после перехода на клиент-сервер перестал?
Код теперь выполняется на сервере 1С под учётной записью службы. У неё свои настройки прокси, свои сертификаты и свои сетевые правила. Повторите тест вне 1С именно на сервере.
Чем HTTP-сервис отличается от веб-сервиса в 1С?
Веб-сервис в терминах 1С работает по SOAP и описывается WSDL. HTTP-сервис — это REST-подобный интерфейс с произвольным форматом, обычно JSON. Проверяются они разными инструментами: SoapUI и Postman.
Как посмотреть заголовки ответа?
Ответ.Заголовки — это соответствие. Переберите его циклом Для Каждого и выведите ключ и значение, либо раскройте в табло отладчика.
Нужно ли закрывать HTTPСоединение после запроса?
Явного метода закрытия нет. Соединение освобождается, когда переменная выходит из области видимости. Для серии запросов к одному хосту создавайте объект один раз и вызывайте его повторно.