Интеграция 1С и CMS WordPress посредством Rest API сайта. Первый шаг.
Интеграция 1С и CMS WordPress посредством функционала Rest API. Используем только язык программирования 1С и штатный функционал Rest API предоставляемый CMS, без дополнительных библиотек и плагинов. Процедуры и функции 1С с комментариями внутри.
Преамбула.
Эта статья является логическим продолжением и дополнением этой моей статьи. А также полностью с ней взаимосвязанной, отсылки к ней будут периодически здесь появляться.
Рейтинг CMS.
Как и в предыдущей статье WordPress занимает лидирующие позиции по количеству установок и работающих сайтов в мире, и не только не сдает своих позиций, но и понемногу растет:
А так как WordPress является платформой для электронной коммерции, соответственно магазин WooCommerce, так же занимает лидирующие позиции в другом мировом рейтинге:
Это конечно прекрасно, но помимо достоинств, описанных в этой статье, есть еще один немаловажный фактор, о котором мне хотелось бы сообщить. Это формат обмена данными между 1С и сайтом электронной коммерции.
JSON vs. XML
Почему JSON и XML? XML является стандартом де-факто в 1С. JSON, на мой взгляд, имеет значительно больше перспектив, проще, удобнее.
От настольных компьютеров до веб-и мобильных устройств, почти все компьютерные приложения, которые мы используем сегодня, полагаются на один из двух основных стандартов сообщений: JSON и XML. Сегодня JSON является наиболее широко используемым форматом, но он обогнал XML только за последние пять лет. Быстрый онлайн-поиск «JSON vs. XML» принесет бесчисленное количество статей и постов в блогах, сравнивающих эти два стандарта и составляющих постепенно расширяющуюся предвзятость, восхваляющую простоту JSON и критикующую многословие XML. Многие статьи настаивают на том, что JSON превосходит XML из-за его краткой семантики и дисконтирует XML как неэффективный и запутанный стандарт прошлого, и здесь мне тяжело не согласиться.
Почему JSON стал более популярным, чем XML
Я на деюсь все знают, что JSON-это родной формат данных в приложениях JavaScript. Написание приложений на JavaScript почти полностью требует использования JSON для обмена данными. Возможны и другие форматы, но они требуют больше усилий, чем в случае с JSON. По мере того как JavaScript набирал популярность для разработки приложений, JSON вплотную следовал за ним как простой в использовании и изначально интегрированный формат обмена данными.
История и эволюционный путь интернета сыграли значительную роль в популяризации JSON. Согласно Stack Overflow, теперь больше вопросов задается о JSON, чем о других форматах обмена данными.
Согласно Google Trends, похожая ситуация наблюдается при сравнении интереса поиска для JSON и XML.
Основная разница между JSON и XML
JSON
|
XML
|
JSON-объект имеет тип
|
XML-данные не содержат типов
|
Типы JSON: строка, число, массив, логическое значение
|
Все данные XML должны быть строковыми
|
Данные легко доступны в виде объектов JSON.
|
Данные XML должны быть проанализированы.
|
JSON поддерживается большинством браузеров.
|
Кросс-браузерный анализ XML может быть сложным
|
JSON не имеет возможностей отображения.
|
XML предлагает возможность отображения данных, потому что это язык разметки.
|
JSON поддерживает только текстовые и числовые данные.
|
XML поддерживает различные типы данных, такие как число, текст, изображения, диаграммы, графики и т. Д. Он также предоставляет параметры для передачи структуры или формата данных с фактическими данными.
|
Получить значение легко
|
Получить значение сложно
|
Поддерживается многими инструментами Ajax
|
Не полностью поддерживается инструментарием Ajax
|
Полностью автоматизированный способ десериализации / сериализации JavaScript.
|
Разработчики должны написать код JavaScript для сериализации / десериализации из XML
|
Нативная поддержка объекта.
|
Объект должен быть выражен соглашениями - в основном пропущено использование атрибутов и элементов.
|
Он поддерживает только кодировку UTF-8.
|
Он поддерживает различные кодировки.
|
Это не поддерживает комментарии.
|
Поддерживает комментарии.
|
Файлы JSON легко читаются по сравнению с XML.
|
XML-документы относительно сложнее для чтения и интерпретации.
|
Он не обеспечивает никакой поддержки пространств имен.
|
Он поддерживает пространства имен.
|
Это менее защищено.
|
Это более безопасно, чем JSON.
|
JSON Code vs XML Code
Пример JSON
{
“firstName”: “Jonathan”,
“lastName”: “Freeman”,
“loginCount”: 4,
“isWriter”: true,
“worksWith”: [“Spantree Technology Group”, “InfoWorld”],
“pets”: [
{
“name”: “Lilly”,
“type”: “Raccoon”
}
]
}
Приведенная выше структура четко определяет некоторые атрибуты человека. Он включает в себя имя и фамилию, количество раз, когда человек вошел в систему, является ли этот человек писателем, список компаний, с которыми он работает, и список домашних животных этого человека (в данном случае только один). Структура, подобная приведенной выше, может быть передана с сервера в веб-браузер или мобильное приложение, которое затем выполнит некоторые действия, такие как отображение данных или сохранение их для последующего использования.
Пример XML
<?xml version="1.0"?>
<person>
<first_name>Jonathan</first_name>
<last_name>Freeman</last_name>
<login_count>4</login_count>
<is_writer>true</is_writer>
<works_with_entities>
<works_with>Spantree Technology Group</works_with>
<works_with>InfoWorld</works_with>
</works_with_entities>
<pets>
<pet>
<name>Lilly</name>
<type>Raccoon</type>
</pet>
</pets>
</person>
Помимо того, что XML является более подробным (в данном случае ровно в два раза более подробным), он также вносит некоторую двусмысленность при синтаксическом анализе в удобную для JavaScript структуру данных. Преобразование XML в объект JavaScript (да и в 1С будет не мало) может занять от десятков до сотен строк кода и в конечном счете требует настройки на основе конкретного анализируемого объекта. Преобразование JSON в объект JavaScript занимает одну строку кода (и в 1С три) и не требует каких-либо предварительных знаний о анализируемом объекте.
С точки зрения обычного человека выбор здесь очевиден. Ведь даже судя по размеру встроенной справки 1С по работе с XML и JSON можно сделать вывод, что с JSON работать проще.
За последние 15 лет JSON стал повсеместным в интернете. Сегодня этот формат является наиболее предпочтительным практически для всех общедоступных веб-сервисов, а также часто используется для частных веб-сервисов.
JSON затмил XML как предпочтительный формат обмена данными для веб-приложений и веб-служб.
Возможно, многим покажется, что здесь избыточно рассказывается о преимуществах JSON. Безусловно, у JSON есть свои недостатки, у XML есть свои преимущества. Но я рассказываю об этом «со своей колокольни». Что касается WordPress, там естественно имеется поддержка XML. Но безусловные преимущества JSON над XML, такие как: простота написания кода, объем передаваемых данных, перспектива, однозначно предопределили мой выбор.
Думаю, что, почитав подробнее в интернете об JSON vs. XML, вы тоже сделаете свой выбор.
Но хватит про выбор, давайте начнем и сделаем что-нибудь.
Запрос данных из WordPress из 1С посредством REST API.
С момента написания прошлой статьи ничего лучше плагина Advanced Access Manager (ААМ) не появилось, поэтому продолжим с ним. Все подробности по настройке можно прочитать здесь.
Весь приводимый ниже код использовался в обработке написанной под управляемые формы. С таким же успехом его можно использовать в обычных формах (версия платформы 1С должна быть не ниже 8.3.6).
Условно постоянные значения, используемые в обработке (константы).
1. СоединениеССайтом_JWTServer. Строка подключения к сайту (host) без https://
2. СоединениеССайтом_JWToken. Токен полученный от сайта
3. СоединениеССайтом_Таймаут. Таймаут (секунд) подключения к сайту
4. СоединениеССайтом_ЭтоHTTPS_Соединение. Флаг указывающий на HTTPS-соединение.
В свой конфигурации вам надо будет их создать.
Небольшая ремарка, HTTP-соединение тестировалось, работает как надо.
Используемые маршруты WordPress.
- /wp-json/aam/v2. Выдает полный перечень сервисов плагина авторизации.
- /wp-json/aam/v2/jwt/validate. Валидация (проверка валидности) имеющегося токена.
- /wp-json/aam/v2/jwt/refresh. Обновление токена.
- /wp-json/aam/v2/jwt/revoke. Отзыв токена.
- /wp-json/aam/v2/authenticate. Аутентикация пользователя на сайте посредством пары «логин : пароль».
- /wp-json/wp/v2/categories/. Запрос категорий постов сайта.
- /wp-json/wp/v2/media/. Запрос списка картинок сайта.
- /wp-json/wp/v2/posts/. Запрос списка постов сайта.
- /wp-json/wp/v2/pages/. Запрос списка страниц сайта
В контексте данной статьи п.п. 3, 4, 5 не используются, за ненадобность (но вы можете поэкспериментировать самостоятельно, «authenticate» работает точно). Остальные приведены справочно, для демонстрации работоспособности кода. См. видео в конце статьи.
Конечные точки WordPress.
- POST.
- GET.
Процедуры и функции используемые в модуле формы.
ПриОткрытии и ПриОткрытииНаСервере используются для получения констант сайта и токена.
&НаСервере
Функция ПриОткрытииНаСервере(ЗначениеКонстанты)
Возврат Константы[ЗначениеКонстанты].Получить();
КонецФункции
&НаКлиенте
Процедура ПриОткрытии(Отказ)
СоединениеССайтом_JWTServer=ПриОткрытииНаСервере("СоединениеССайтом_JWTServer");
СоединениеССайтом_JWToken=ПриОткрытииНаСервере("СоединениеССайтом_JWToken");
КонецПроцедуры
ПриОткрытии и ПриОткрытииНаСервере используются для получения констант сайта и токена.
ПослатьЗапросНаСайт и ПослатьЗапросНаСайтНаСервере
&НаКлиенте
Процедура ПослатьЗапросНаСайт(Команда)
ПослатьЗапросНаСайтНаСервере();
КонецПроцедуры
&НаСервере
Процедура ПослатьЗапросНаСайтНаСервере()
СтруктураПараметров=Новый Структура;
СтруктураПараметров.Вставить("Token",СоединениеССайтом_JWToken);
СтруктураПараметров.Вставить("Server",СоединениеССайтом_JWTServer);
СтруктураПараметров.Вставить("Маршрут",Маршрут);
СтруктураПараметров.Вставить("КонечнаяТочка",КонечнаяТочка);
Если ЗначениеЗаполнено(jwt) Тогда
СтруктураПараметров.Вставить("jwt",jwt);
КонецЕсли;
Если ЗначениеЗаполнено(username) Тогда
СтруктураПараметров.Вставить("username",username);
КонецЕсли;
Если ЗначениеЗаполнено(password) Тогда
СтруктураПараметров.Вставить("password",password);
КонецЕсли;
////СтруктураПараметров.Вставить("",);
СтруктураОтветаССайта = РеквизитФормыВЗначение("Объект").рс_публикация_ПодсистемаWordPressПостыСтраницы(СтруктураПараметров);
КодСостояния=СтруктураОтветаССайта["КодСостояния"];
ОписаниеОтвета=СтруктураОтветаССайта["ОписаниеОтвета"];
ПолучитьВрДеревоНаСервере(СтруктураОтветаССайта);
ЭтаФорма.Элементы.РезультатКонвертацииИзJSON.Обновить();
КонецПроцедуры
используются соответственно для посылки запроса на сайт. Связаны с кнопкой «Послать запрос на сайт». Здесь мы упаковываем исходные данные в структуру и передаем в модуль объекта для обработки, и отсылки на сайт. Получаем ответ также в виде структуры, частично обрабатываем его и передаем ответ от сайта в процедуру «ПолучитьВрДеревоНаСервере». Описание структуры ответа ниже по тексту.
ПолучитьВрДеревоНаСервере
&НаСервере
Процедура ПолучитьВрДеревоНаСервере(СтруктураОтветаССайта)
ЗначениеВРеквизитФормы(СтруктураОтветаССайта["ЗначениеОтвета"],"РезультатКонвертацииИзJSON");
КонецПроцедуры
ПолучитьВрДеревоНаСервере процедура конвертации дерева значений ответа в реквизит формы «дерево значений», для наглядной демонстрации полученных результатов.
Процедуры и функции, используемые в модуле объекта.
Подготовка данных перед отправкой на сайт.
Функция рс_ПолучитьТиповыеЗаголовкиХТТП()
&НаСервере
Функция рс_ПолучитьТиповыеЗаголовкиХТТП() Экспорт
ОсновныеЗаголовкиХТТП = Новый Соответствие;
ОсновныеЗаголовкиХТТП.Вставить("Content-Type","application/json"); ///Заголовок 1:
ОсновныеЗаголовкиХТТП.Вставить("Accept","application/json"); ///Заголовок 2:
ОсновныеЗаголовкиХТТП.Вставить("Cache-Control","no-cache"); ///Заголовок 3:
ОсновныеЗаголовкиХТТП.Вставить("User-Agent","OsiW-1Cv8.3-RAPI-Agent/v0.1"); ///Заголовок 4:
Возврат ОсновныеЗаголовкиХТТП;
КонецФункции // рс_ПолучитьТиповыеЗаголовкиХТТП()
Здесь формируем типовые заголовки http-запроса, которые используются практически во всех запросах к сайту. Иногда к ним могут добавиться другие, например при посылке картинки на сайт. Четвертый мой, персональный, для понимания логов сайта, можно не использовать.
Функция рс_подготовка_КонвертироватьВСоответствие(ВходДанные)
Функция рс_подготовка_КонвертироватьВСоответствие(ВходДанные) Экспорт
ИсхСоответствие=Новый Соответствие;
Если ТипЗнч(ВходДанные)=Тип("ТаблицаЗначений") Тогда
Для каждого СтрокаТЗ Из ВходДанные Цикл
ИсхСоответствие.Вставить(СтрокаТЗ.Ключ,СтрокаТЗ.Значение);
КонецЦикла;
ИначеЕсли ТипЗнч(ВходДанные)=Тип("Структура") Тогда ////преобразовываем ключи
Для каждого СтрокаСтруктуры Из ВходДанные Цикл
ИсхСоответствие.Вставить(СтрокаСтруктуры.Ключ,СтрокаСтруктуры.Значение);
КонецЦикла;
ИначеЕсли ТипЗнч(ВходДанные)=Тип("Соответствие") Тогда
ИсхСоответствие=ВходДанные;
КонецЕсли;
Возврат ИсхСоответствие;
КонецФункции
Предварительная конвертация в соответствие из "таблицы значений" и "структуры" для последующей конвертации в JSON. Если вы будете использовать только соответствие, можно не использовать.
Функция рс_подготовка_ОбъектВJSON
&НаСервере
Функция рс_подготовка_ОбъектВJSON(ПереданноеДерево) Экспорт ////// если ПереданноеДерево - соответсвие, сразу в JSON
Если ТипЗнч(ПереданноеДерево)=Тип("ДеревоЗначений") Тогда
лОбъектJSON = рс_подготовка_НовыйОбъектПоДереву(ПереданноеДерево);
ИначеЕсли ТипЗнч(ПереданноеДерево)=Тип("СтрокаДереваЗначений") Тогда
Если ПереданноеДерево.Значение="[Массив]" Тогда
ЭтоМассив = Истина;
Иначе
ЭтоМассив = Ложь;
КонецЕсли;
лОбъектJSON = рс_подготовка_НовыйОбъектПоДереву(ПереданноеДерево,ЭтоМассив);
ИначеЕсли ТипЗнч(ПереданноеДерево)=Тип("Структура") Тогда
лОбъектJSON = рс_подготовка_КонвертироватьВСоответствие(ПереданноеДерево);
Иначе ////соответствие
лОбъектJSON = ПереданноеДерево;
КонецЕсли;
///// Привет XML парсеру
ЗаписьJSON = Новый ЗаписьJSON;
ЗаписьJSON.УстановитьСтроку();
ЗаписатьJSON(ЗаписьJSON, лОбъектJSON);
Возврат ЗаписьJSON.Закрыть();
///// Привет XML парсеру
КонецФункции
&НаСервере
Функция рс_подготовка_НовыйОбъектПоДереву(Дерево,ЭтоМассив= Ложь)
Возврат рс_подготовка_ВосстановитьОбъект(Дерево, ЭтоМассив);
КонецФункции
&НаСервере
Функция рс_подготовка_ВосстановитьОбъект(Дерево, ЭтоМассив = Ложь)
Рез = ?(ЭтоМассив, Новый Массив, Новый Структура);
Для Каждого Стр Из Дерево.Строки Цикл
Если Стр.Значение = "[Массив]" Тогда
Значение = рс_подготовка_ВосстановитьОбъект(Стр, Истина);
ИначеЕсли Стр.Значение = "Null" Тогда
Значение = null;
ИначеЕсли Стр.Строки.Количество() = 0 Тогда
Значение = Стр.Значение;
ИначеЕсли Стр.Строки.Количество() > 0 Тогда
Значение = рс_подготовка_ВосстановитьОбъект(Стр, Ложь);
КонецЕсли;
Если ЭтоМассив Тогда
Рез.Добавить(Значение);
Иначе
Рез.Вставить(Стр.Свойство, Значение);
КонецЕсли;
КонецЦикла;
Возврат Рез;
КонецФункции
Здесь происходит конвертация данных в JSON. И дополнительный обработчик конвертации, на случай если вдруг "прилетела" "структура", "дерево значений" или строка "дерева значений". Если иные данные кроме соответствия не используются можно оставить только строки "лОбъектJSON = ПереданноеДерево;" и код внутри комментария "///// Привет XML парсеру".
Функция рс_подготовка_ПолучитьЗапросHTTP
&НаСервере
Функция рс_подготовка_ПолучитьЗапросHTTP(_Маршрут_, Заголовки = Неопределено, ТелоЗапроса = Неопределено) Экспорт
Если НЕ ЗначениеЗаполнено(Заголовки) ИЛИ ТипЗнч(Заголовки) <> Тип("Соответствие") Тогда
Заголовки = Новый Соответствие;
КонецЕсли;
Запрос = Новый HTTPЗапрос(_Маршрут_, Заголовки);
Если ТипЗнч(ТелоЗапроса)=Тип("ЗаписьТекста") ИЛИ ТипЗнч(ТелоЗапроса)=Тип("Файл") Тогда
Запрос.УстановитьИмяФайлаТела(ТелоЗапроса);
ИначеЕсли ЗначениеЗаполнено(ТелоЗапроса) И ТипЗнч(ТелоЗапроса)=Тип("Строка") Тогда
Запрос.УстановитьТелоИзСтроки(ТелоЗапроса);
ИначеЕсли ЗначениеЗаполнено(ТелоЗапроса) И ТипЗнч(ТелоЗапроса)=Тип("ДвоичныеДанные") Тогда
Запрос.УстановитьТелоИзДвоичныхДанных(ТелоЗапроса);
КонецЕсли;
Возврат Запрос;
КонецФункции
Здесь формируется штатный запрос 1С "Новый HTTPЗапрос" и в соответствии с входящими данными получаем тот или иной вид. Его чуть позже пошлем на сайт.
Функция рс_подготовка_СоздатьСтруктуруВозвращаемогоОтвета
&НаСервере
//// <Создает структуру возвращаемого ответа>
//// Возвращает фиксированную структуру
//// ЗначениеОтвета - ДеревоЗначений или Текст в JSON
//// КодСостояния - код ответа сайта, число, например 200
//// ОписаниеОтвета - описание ответа из Контроль_РезультатHTTPЗапросаСодержитОшибку
Функция рс_подготовка_СоздатьСтруктуруВозвращаемогоОтвета() Экспорт
ВозвращаемыйОтвет=Новый Структура;
ВозвращаемыйОтвет.Вставить("ЗначениеОтвета",Неопределено);
ВозвращаемыйОтвет.Вставить("КодСостояния",999);
ВозвращаемыйОтвет.Вставить("ОписаниеОтвета","Отсутствует");
Возврат ВозвращаемыйОтвет;
КонецФункции
Ну и последняя функция подготовки, здесь формируем "структуру" ответа от сайта для последующей обработки в модуле формы.
Отправка данных на сайт.
Функция рс_публикация_ПолучитьСоединениеHTTPS
&НаСервере
Функция рс_публикация_ПолучитьСоединениеHTTPS(Сервер, Порт=443, ЭтоHTTPS = Истина, Логин = Неопределено, Пароль = Неопределено, Таймаут = 90, Прокси = Неопределено) Экспорт
ЭтоHTTPS=Константы.СоединениеССайтом_ЭтоHTTPS_Соединение.Получить();
Таймаут=Константы.СоединениеССайтом_Таймаут.Получить();
Если Таймаут<5 Тогда
Таймаут=120;
КонецЕсли;
Если ЭтоHTTPS Тогда
Порт=443;
ssl = Новый ЗащищенноеСоединениеOpenSSL();
Иначе
Порт=80;
ssl = Неопределено;
КонецЕсли;
Если Прокси = Неопределено Тогда
Прокси = Новый ИнтернетПрокси(Ложь);
КонецЕсли;
Соединение = Новый HTTPСоединение(Сервер, Порт, Логин, Пароль, Прокси, Таймаут, ssl);
Возврат Соединение;
КонецФункции
Здесь, мое мнение, комментарии излишни, штатная процедура 1С.
Функция рс_публикация_ПодсистемаWordPressПостыСтраницы, комментарии по спойлером
Функция рс_публикация_ПодсистемаWordPressПостыСтраницы(_ВхСтруктураПараметров) Экспорт
/////_ВхСтруктураПараметров структура данных необходимых для действий на сайте, не нужные удаляются
ВозвращаемыйОтвет=рс_подготовка_СоздатьСтруктуруВозвращаемогоОтвета();
Если ТипЗнч(_ВхСтруктураПараметров)<>Тип("Структура") Тогда ////проверка
ВозвращаемыйОтвет.Вставить("ОписаниеОтвета","Входящие параметры не соответствуют типу данных <Структура>");
Возврат ВозвращаемыйОтвет;
КонецЕсли;
///// в этом блоке получаем и удаляем из структуры данные необходимые для подготовки к публикации
_token_ =_ВхСтруктураПараметров["Token"];
_JWTServer_ =_ВхСтруктураПараметров["Server"];
_Маршрут_ =_ВхСтруктураПараметров["Маршрут"];
_КонечнаяТочка_ =_ВхСтруктураПараметров["КонечнаяТочка"];
_ВхСтруктураПараметров.Удалить("Token");
_ВхСтруктураПараметров.Удалить("Server");
_ВхСтруктураПараметров.Удалить("Маршрут");
_ВхСтруктураПараметров.Удалить("КонечнаяТочка");
///// в этом блоке получаем и удаляем из структуры данные необходимые для подготовки к публикации
_ТелоЗапроса_=Неопределено;
Если _ВхСтруктураПараметров.Количество()>0 Тогда ///// здесь остаются только данные которы надо непосредственно отослать на сайт, статья, товар и т.д.
_БодиПубликации_=рс_подготовка_КонвертироватьВСоответствие(_ВхСтруктураПараметров); ////создаем боди/тело с данными для подстановки в ЗапросHTTP
_ТелоЗапроса_ =рс_подготовка_ОбъектВJSON(_БодиПубликации_); ////конвертируем боди в JSON
КонецЕсли;
_ЗаголовкиHTTP_ = рс_ПолучитьТиповыеЗаголовкиХТТП(); ////штатные заголовки ЗапросHTTP
_ЗаголовкиHTTP_.Вставить("Authentication", "Bearer "+_token_); ////Добавляем заголовок для авторизации
Запрос =рс_подготовка_ПолучитьЗапросHTTP(_Маршрут_, _ЗаголовкиHTTP_, _ТелоЗапроса_); ////получаем ЗапросHTTP
Результат =рс_публикация_ПослатьГотовыйЗапросНаСайт(_КонечнаяТочка_, _JWTServer_, Запрос); ////посылаем запрос на сайт и получаем результат HTTPОтвет
/////---получаем результат ответа - соответствие
РезультатРасшифровка=Контроль_РезультатHTTPЗапросаСодержитОшибку(Результат); ////Расшифровываем ответ от сайта
/////// преобразовываем JSON результат ответа в "дерево значений"
РезультатОтветаДерево=рс_ПостОбработка_ЗаполнитьДеревоJSON(Результат.ПолучитьТелоКакСтроку());
ВозвращаемыйОтвет.Вставить("ЗначениеОтвета",РезультатОтветаДерево); ////дерево с ответом из рс_ПостОбработка_ЗаполнитьДеревоJSON
ВозвращаемыйОтвет.Вставить("КодСостояния",РезультатРасшифровка["КодСостояния"]); //// код состояния 200, 201, 404, и т.д. из Контроль_РезультатHTTPЗапросаСодержитОшибку
ВозвращаемыйОтвет.Вставить("ОписаниеОтвета",РезультатРасшифровка["ОписаниеОшибки"]); //// краткое описание ошибки из Контроль_РезультатHTTPЗапросаСодержитОшибку
Возврат ВозвращаемыйОтвет;
КонецФункции // ПодсистемаWordPressПостыСтраницы()
Функция рс_публикация_ПослатьГотовыйЗапросНаСайт
&НаСервере
//// <Штатная функция работы с запросами по СоединениеHTTPS>
//
// Параметры:
// <Стандартные> - <Тип.ЛюбоеЗначение>
//
// Возвращаемое значение: Результат
// <Тип.HTTPОтвет> - <HTTPОтвет>
//
Функция рс_публикация_ПослатьГотовыйЗапросНаСайт(ТипЗапроса, СтрокаПодключенияСервера, Запрос) Экспорт
СоединениеССервером = рс_публикация_ПолучитьСоединениеHTTPS(СтрокаПодключенияСервера, , , , , ,);
Если ВРег(ТипЗапроса) = "POST" Тогда
Результат = СоединениеССервером.ОтправитьДляОбработки(Запрос);
ИначеЕсли ВРег(ТипЗапроса) = "GET" Тогда
Результат = СоединениеССервером.Получить(Запрос);
ИначеЕсли ВРег(ТипЗапроса) = "PUT" Тогда
////Результат = СоединениеССервером.Записать(Запрос); /////Эта функция не работает
Результат = СоединениеССервером.Изменить(Запрос);
ИначеЕсли ВРег(ТипЗапроса) = "PATCH" Тогда
Результат = СоединениеССервером.Изменить(Запрос);
ИначеЕсли ВРег(ТипЗапроса) = "HEAD" Тогда
Результат = СоединениеССервером.ПолучитьЗаголовки(Запрос);
ИначеЕсли ВРег(ТипЗапроса) = "DELETE" Тогда
Результат = СоединениеССервером.Удалить(Запрос);
КонецЕсли;
Возврат Результат;
КонецФункции //
Посылаем запрос на сайт штатными средствами и получаем ответ.
Ну и последнее.
Постобработка ответа с сайта.
Функция Контроль_РезультатHTTPЗапросаСодержитОшибку
//// (РезультатHttpЗапроса)----возвращаемое значение - Структура
//
// Параметры:
// <РезультатHttpЗапроса> - <Тип.HTTPОтвет > - <HTTPОтвет >
//
// Возвращаемое значение:
// <ВозращаемоеСоответствие> - <<Тип.Структура>
//
//////-----первое ключ - КодСостояния, значение - Номер ошибки
//////-----второе ключ - ОписаниеОшибки, значение - ОписаниеСостояния
Функция Контроль_РезультатHTTPЗапросаСодержитОшибку(РезультатHttpЗапроса) Экспорт
ВозращаемоеСоответствие=Новый Структура;
////1xx: Informational (информационные):
Если РезультатHttpЗапроса.КодСостояния = 100 Тогда
ОписаниеСостояния = "Continue («продолжай»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 101 Тогда
ОписаниеСостояния = "Switching Protocols («переключение протоколов»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 102 Тогда
ОписаниеСостояния = "Processing («идёт обработка»)";
/////2xx: Success (успешно):
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 200 Тогда
ОписаниеСостояния = "OK («Запрос выполнен успешно»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 201 Тогда
ОписаниеСостояния = "Created («создано»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 202 Тогда
ОписаниеСостояния = "Accepted («принято»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 203 Тогда
ОписаниеСостояния = "Non-Authoritative Information («информация не авторитетна»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 204 Тогда
ОписаниеСостояния = "No Content («нет содержимого»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 205 Тогда
ОписаниеСостояния = "Reset Content («сбросить содержимое»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 206 Тогда
ОписаниеСостояния = "Partial Content («частичное содержимое»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 207 Тогда
ОписаниеСостояния = "Multi-Status («многостатусный»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 208 Тогда
ОписаниеСостояния = "Already Reported («уже сообщалось»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 226 Тогда
ОписаниеСостояния = "IM Used («использовано IM»)";
////3xx: Redirection (перенаправление):
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 300 Тогда
ОписаниеСостояния = "Multiple Choices («множество выборов»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 301 Тогда
ОписаниеСостояния = "Moved Permanently («перемещено навсегда»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 302 Тогда
ОписаниеСостояния = "Moved Temporarily («перемещено временно»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 302 Тогда
ОписаниеСостояния = "Found («найдено»)[7]";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 303 Тогда
ОписаниеСостояния = "See Other («смотреть другое»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 304 Тогда
ОписаниеСостояния = "Not Modified («не изменялось»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 305 Тогда
ОписаниеСостояния = "Use Proxy («использовать прокси»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 306 Тогда
ОписаниеСостояния = "зарезервировано (код использовался только в ранних спецификациях)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 307 Тогда
ОписаниеСостояния = "Temporary Redirect («временное перенаправление»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 308 Тогда
ОписаниеСостояния = "Permanent Redirect («постоянное перенаправление»)";
////4xx: Client Error (ошибка клиента):
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 400 Тогда
ОписаниеСостояния = "Bad Request («плохой, неверный запрос»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 401 Тогда
ОписаниеСостояния = "Unauthorized («не авторизован»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 402 Тогда
ОписаниеСостояния = "Payment Required («необходима оплата»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 403 Тогда
ОписаниеСостояния = "Forbidden («запрещено»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 404 Тогда
ОписаниеСостояния = "Not Found («не найдено»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 405 Тогда
ОписаниеСостояния = "Method Not Allowed («метод не поддерживается»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 406 Тогда
ОписаниеСостояния = "Not Acceptable («неприемлемо»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 407 Тогда
ОписаниеСостояния = "Proxy Authentication Required («необходима аутентификация прокси»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 408 Тогда
ОписаниеСостояния = "Request Timeout («истекло время ожидания»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 409 Тогда
ОписаниеСостояния = "Conflict («конфликт»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 410 Тогда
ОписаниеСостояния = "Gone («удалён»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 411 Тогда
ОписаниеСостояния = "Length Required («необходима длина»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 412 Тогда
ОписаниеСостояния = "Precondition Failed («условие ложно»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 413 Тогда
ОписаниеСостояния = "Payload Too Large («полезная нагрузка слишком велика»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 414 Тогда
ОписаниеСостояния = "URI Too Long («URI слишком длинный»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 415 Тогда
ОписаниеСостояния = "Unsupported Media Type («неподдерживаемый тип данных»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 416 Тогда
ОписаниеСостояния = "Range Not Satisfiable («диапазон не достижим»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 417 Тогда
ОписаниеСостояния = "Expectation Failed («ожидание не удалось»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 418 Тогда
ОписаниеСостояния = "I’m a teapot («я — чайник»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 421 Тогда
ОписаниеСостояния = "Misdirected Request [10]";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 422 Тогда
ОписаниеСостояния = "Unprocessable Entity («необрабатываемый экземпляр»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 423 Тогда
ОписаниеСостояния = "Locked («заблокировано»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 424 Тогда
ОписаниеСостояния = "Failed Dependency («невыполненная зависимость»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 426 Тогда
ОписаниеСостояния = "Upgrade Required («необходимо обновление»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 428 Тогда
ОписаниеСостояния = "Precondition Required («необходимо предусловие»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 429 Тогда
ОписаниеСостояния = "Too Many Requests («слишком много запросов»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 431 Тогда
ОписаниеСостояния = "Request Header Fields Too Large («поля заголовка запроса слишком большие»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 444 Тогда
ОписаниеСостояния = "Закрывает соединение без передачи заголовка ответа. Нестандартный код";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 449 Тогда
ОписаниеСостояния = "Retry With («повторить с»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 451 Тогда
ОписаниеСостояния = "Unavailable For Legal Reasons («недоступно по юридическим причинам»)";
////5xx: Server Error (ошибка сервера):
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 500 Тогда
ОписаниеСостояния = "Internal Server Error («внутренняя ошибка сервера»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 501 Тогда
ОписаниеСостояния = "Not Implemented («не реализовано»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 502 Тогда
ОписаниеСостояния = "Bad Gateway («плохой, ошибочный шлюз»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 503 Тогда
ОписаниеСостояния = "Service Unavailable («сервис недоступен»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 504 Тогда
ОписаниеСостояния = "Gateway Timeout («шлюз не отвечает»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 505 Тогда
ОписаниеСостояния = "HTTP Version Not Supported («версия HTTP не поддерживается»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 506 Тогда
ОписаниеСостояния = "Variant Also Negotiates («вариант тоже проводит согласование»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 507 Тогда
ОписаниеСостояния = "Insufficient Storage («переполнение хранилища»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 508 Тогда
ОписаниеСостояния = "Loop Detected («обнаружено бесконечное перенаправление»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 509 Тогда
ОписаниеСостояния = "Bandwidth Limit Exceeded («исчерпана пропускная ширина канала»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 510 Тогда
ОписаниеСостояния = "Not Extended («не расширено»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 511 Тогда
ОписаниеСостояния = "Network Authentication Required («требуется сетевая аутентификация»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 520 Тогда
ОписаниеСостояния = "Unknown Error («неизвестная ошибка»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 521 Тогда
ОписаниеСостояния = "Web Server Is Down («веб-сервер не работает»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 522 Тогда
ОписаниеСостояния = "Connection Timed Out («соединение не отвечает»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 523 Тогда
ОписаниеСостояния = "Origin Is Unreachable («источник недоступен»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 524 Тогда
ОписаниеСостояния = "A Timeout Occurred («время ожидания истекло»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 525 Тогда
ОписаниеСостояния = "SSL Handshake Failed («квитирование SSL не удалось»)";
ИначеЕсли РезультатHttpЗапроса.КодСостояния = 526 Тогда
ОписаниеСостояния = "Invalid SSL Certificate («недействительный сертификат SSL»)";
Иначе
ОписаниеСостояния = "";
КонецЕсли;
ВозращаемоеСоответствие.Вставить("КодСостояния", РезультатHttpЗапроса.КодСостояния);
ВозращаемоеСоответствие.Вставить("ОписаниеОшибки", ОписаниеСостояния);
Возврат ВозращаемоеСоответствие;
КонецФункции
Обработчик ответа от сайта, получаем код успеха/ошибки и описание.
Функция рс_ПостОбработка_ЗаполнитьДеревоJSON
Функция рс_ПостОбработка_ЗаполнитьДеревоJSON(ТекстJSON,ИмяКорневогоОбъекта="") Экспорт
лОбъектJSON = рс_ПостОбработка_JsonВОбъект(ТекстJSON);
нДерево = ЗаполнитьДеревоЖсон(лОбъектJSON);
Возврат нДерево;
КонецФункции
Функция рс_ПостОбработка_JsonВОбъект(СтрокаJSON,В_Соответствие=Истина) Экспорт
ПрочитанныйОбъект="";
/////-----Привет XML парсер
Попытка
Чтение = Новый ЧтениеJSON;
Чтение.УстановитьСтроку(СтрЗаменить(СтрокаJSON,"==","NevW"));
ПрочитанныйОбъект=ПрочитатьJSON(Чтение,В_Соответствие,);
Исключение
ПрочитанныйОбъект="";
КонецПопытки;
Возврат ПрочитанныйОбъект;
КонецФункции
Сначала конвертируем "сырой" ответ из JSON в соответствие.
Функция ЗаполнитьДеревоЖсон
Функция ЗаполнитьДеревоЖсон(лОбъектJSON)
Дерево= новый ДеревоЗначений;
Дерево.Колонки.Добавить("Свойство");
Дерево.Колонки.Добавить("Значение");
Дерево.Колонки.Добавить("Тип");
СформироватьПодстрокиДерева(лОбъектJSON, Дерево);
Возврат Дерево;
КонецФункции
Функция СформироватьПодстрокиДерева(ИтераторИзJson, ТекущаяСтрокаДерева, ИндексЭлементаМассива = 0)
Для каждого Элемент из ИтераторИзJson цикл
ДочерняяСтрокаДерева=ТекущаяСтрокаДерева.Строки.Добавить();
//у типа итератора только два варианта: массив или соответствие
Если ТипЗнч(ИтераторИзJson) = Тип("Массив") Тогда
ДочерняяСтрокаДерева.Свойство = "[" +ТипЗнч(Элемент)+" "+ ИндексЭлементаМассива + "]";
ИндексЭлементаМассива = ИндексЭлементаМассива + 1;
Значение = Элемент;//элементы массива: примитивы, соответствия, массивы
Иначе //итератор - соответствие, элементы - ключ и значение
ЭлСтруктурыКлюч=Элемент.Ключ;
НовыйКлюч=ЭлСтруктурыКлюч;
ДочерняяСтрокаДерева.Свойство = НовыйКлюч;
Значение = Элемент.Значение;//значения: примитивы, соответствия, массивы
КонецЕсли;
Если ТипЗнч(Значение)=Тип("Соответствие") Тогда
ДочерняяСтрокаДерева.Значение="{" + Значение.Количество() +"}";
ДочерняяСтрокаДерева.Тип = "Запись";
СформироватьПодстрокиДерева(Значение, ДочерняяСтрокаДерева);
ИначеЕсли ТипЗнч(Значение)=Тип("Массив") Тогда
ДочерняяСтрокаДерева.Значение="[" + Значение.Количество() + "]";
ДочерняяСтрокаДерева.Тип = "Массив";
СформироватьПодстрокиДерева(Значение, ДочерняяСтрокаДерева);
Иначе //примитив
ДочерняяСтрокаДерева.Значение=Значение;
ДочерняяСтрокаДерева.Тип = ТипЗнч(Значение);
КонецЕсли;
КонецЦикла;
КонецФункции
Потом конвертируем "соответствие" в "дерево значений" для последующей обработки. Кому оно не нравится может использовать что-то иное. Мне очень удобно. Функция не моя, скачал здесь, на Инфостарте, понравилась, спасибо, правда не помню кому.
Возвращаем структуру с ответом в модуль формы для последующего понятного отображения.
Хочу отметить, что самый важный код - это Функция рс_публикация_ПодсистемаWordPressПостыСтраницы. А здесь самое важное - создание тела публикации "_БодиПубликации_". Сколько шишек здесь было набито... Отладите его, дальше всё пойдет как по маслу. И использоваться эта функция будет практически для всего, что надо отправить на сайт, или получить с сайта.
Ну и на последок видео, без него сейчас никуда.
На этом всё, первый шаг сделан, подставляйте свои маршруты и дерзайте.
Желаю приятных экспериментов на ниве обмена из 1С с сайтом WordPress.
Плюсуем, не стесняемся, делимся, комментируем.
Продолжение следует.
Обработка тестировалась:
Тестировалось на моем сайте: перейти.
Версия WordPress: 5.4
PHP Версия : 7.3.15
Платформа: 1С:Предприятие 8.3 (8.3.13.1644).
Минимально необходимый релиз: 8.3.6.
Источники
- toptal
- guru99
- infoworld
- itrack
- builtwith
- WordPress