Внешний сервис не отвечает из 1С: как найти, где именно рвётся обмен
Содержание
Проверить веб-сервис в 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"));
КонецФункции
Что здесь важно для проверки:
- Таймаут (шестой параметр, 30 секунд). Без него при зависшем сервисе сеанс 1С висит неопределённо долго, и вы не поймёте, что произошло.
- Защищённое соединение нужно для любого адреса на
https. Без него запрос уйдёт по обычному HTTP и на порт 443 придёт ошибка. - Порт указывайте явно, если сервис слушает нестандартный, например 8443.
- Токен не храните в тексте модуля. Для проверки можно временно подставить строку, но в рабочий код — только из защищённого хранилища или константы с ограниченными правами.
Прокси
Если в организации выход в интернет идёт через прокси, передайте его пятым параметром:
Прокси = Новый ИнтернетПрокси;
Прокси.Установить("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 или обрыв соединения. Делите выгрузку на части.