Выгрузка данных на сайт из 1С через Django REST framework

10.06.24

Интеграция - Сайты и интернет-магазины

Пример одностороннего обмена с сайтом Django через Django REST framework.

Привет всем. Ко мне обратился заказчик из стоматологии с просьбой сделать интеграцию с системой ЛоялМед. Это система лояльности для медицинских клиник у них есть чат-бот и система начисления бонусов за оказанные услуги.

После детального изучения выяснилось: необходим односторонний обмен - выгрузка данных пациентов, их записей на прием, приемов, платежей на сайт ЛоялМеда. Со стороны ЛоялМед настроено Django REST framework(далее DRF) для приема данных в JSON.

Конфигурация заказчика БИТ.Стоматология 2.0

Решение было следующее:

В отдельном расширении создан регистр сведений для регистрации очереди на выгрузку в DRF.

Подписки на события при записи объектов: справочник Клиенты, документ Заявка, документ ОказаниеУслуг

Регламентное задание на выгрузку DRF, если выгрузка объекта удачна - запись удаляется из регистра, если нет в логах DRF - пишется описание ошибки.

Авторизация идет по токену, хост и токен положил в константы.

Выгрузка сперва идет методом POST, если объект уже создан, то выгрузка идет методом PUT.

Ниже пример выгрузки клиента на сайт:

Процедура ВыгрузитьКлиента(Клиент, ТокенЛМ, ХостЛМ) 
	Попытка
		Соединение  =  Новый HTTPСоединение(ХостЛМ,,"","",,,Новый ЗащищенноеСоединениеOpenSSL()
		);
		Запрос = Новый Запрос;
		Запрос.Текст = 
		"ВЫБРАТЬ
		|	Клиенты.Код КАК Код,
		|	Клиенты.Фамилия КАК Фамилия,
		|	Клиенты.Имя КАК Имя,
		|	Клиенты.Отчество КАК Отчество,
		|	Клиенты.ДатаРождения КАК ДатаРождения,
		|	Клиенты.ДатаСоздания КАК ДатаСоздания,
		|	Клиенты.Пол КАК Пол,
		|	Клиенты.КлиентЛМ КАК КлиентЛМ,
		|	Клиенты.ДатаЛМ КАК ДатаЛМ,
		|	Клиенты.ЗаконныйПредставитель КАК ЗаконныйПредставитель,
		|	ЕСТЬNULL(КонтактнаяИнформация.Представление, """") КАК Телефон,
		|	Клиенты.ЗаконныйПредставитель.Код КАК ЗаконныйПредставительКод
		|ИЗ
		|	Справочник.Клиенты КАК Клиенты
		|		ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация
		|		ПО Клиенты.Ссылка = КонтактнаяИнформация.Объект
		|			И (КонтактнаяИнформация.Вид = &Вид)
		|ГДЕ
		|	Клиенты.Ссылка = &Ссылка";
		Запрос.УстановитьПараметр("Ссылка", Клиент);
		Запрос.УстановитьПараметр("Вид",  Справочники.ВидыКонтактнойИнформации.ТелефонСотовый); 
		Результат = Запрос.Выполнить();
		Контрагент = Результат.Выбрать();
		Пока Контрагент.Следующий() Цикл
			//Формируем структуру с данными
			СтруктураЗапроса = Новый Структура; 
			КК = ПолучитьЧислоИзСтроки(Контрагент.Код);
			СтруктураЗапроса.Вставить("id", КК);
			СтруктураЗапроса.Вставить("lastname", Контрагент.Фамилия);
			СтруктураЗапроса.Вставить("firstname", Контрагент.Имя);
			СтруктураЗапроса.Вставить("midname", Контрагент.Отчество);
			Если ЗначениеЗаполнено(Контрагент.ДатаРождения) Тогда
				СтруктураЗапроса.Вставить("birthdate", Формат(Контрагент.ДатаРождения,"ДФ=гггг-ММ-дд"));
			КонецЕсли;
			СтруктураЗапроса.Вставить("created_in_mis", ?(ЗначениеЗаполнено(Контрагент.ДатаСоздания),Формат(Контрагент.ДатаСоздания,"ДФ=гггг-ММ-ддTЧЧ:мм:сс"), Формат(ТекущаяДата(),"ДФ=гггг-ММ-ддTЧЧ:мм:сс")));
			СтруктураЗапроса.Вставить("gender", ПолучитьПол(Контрагент.Пол));
			СтруктураЗапроса.Вставить("loyalmed_type", ?(Контрагент.КлиентЛМ = Истина,1,0));
			
			Тел = Контрагент.Телефон;
			Тел = ПолучитьЧислоИзСтроки(Тел);  
			Если Лев(Тел,1) = "8" Тогда
				Тел = Сред(Тел,2);
				Тел = "7"+Тел;
			КонецЕсли;
			СтруктураЗапроса.Вставить("phone1", Тел);
			
			Если ЗначениеЗаполнено(Контрагент.ДатаЛМ) Тогда
				СтруктураЗапроса.Вставить("loyalmed_enabled_timestamp", Формат(Контрагент.ДатаЛМ,"ДФ=гггг-ММ-ддTЧЧ:мм:сс"));
			КонецЕсли;
			
			СтруктураЗапроса.Вставить("updated_in_mis", Формат(ТекущаяДата(),"ДФ=гггг-ММ-ддTЧЧ:мм:сс"));
			
			Если ЗначениеЗаполнено(Контрагент.ЗаконныйПредставитель) И ТипЗнч(Контрагент.ЗаконныйПредставитель) = Тип("СправочникСсылка.Клиенты") Тогда
				СтруктураЗапроса.Вставить("representative_id", ПолучитьЧислоИзСтроки(Контрагент.ЗаконныйПредставительКод));
			КонецЕсли;
			
			//Преобразуем полученную структура в JSON
			ЗаписьJSON = Новый ЗаписьJSON;
			ЗаписьJSON.УстановитьСтроку();
			ЗаписатьJSON(ЗаписьJSON, СтруктураЗапроса);
			СтрокаЗапроса = ЗаписьJSON.Закрыть();
			
			HTTPОтвет = ОтправитьPOSTЗапрос(Соединение, СтрокаЗапроса, ТокенЛМ, "clients");
			//если объект успешно создан DRF возвращает код 201, иначе отправляем PUT
			Если HTTPОтвет.КодСостояния = 201 Тогда
				//удаляем объект из регистра очереди
				УдалитьОбъектИзОчереди(Клиент);
			Иначе
				HTTPОтвет = ОтправитьPUTЗапрос(Соединение, СтрокаЗапроса, ТокенЛМ, "clients", КК);
				//если обновление объекта прошло - возращается код 200, иначе сохраняем ответ в спец регистр
				Если HTTPОтвет.КодСостояния = 200 Тогда
					УдалитьОбъектИзОчереди(Клиент);
				Иначе
					ТелоОтвета = HTTPОтвет.ПолучитьТелоКакСтроку();
					ЗаписатьОтвет(Контрагент, ТелоОтвета);
				КонецЕсли;
				
			КонецЕсли;
		КонецЦикла;	
	Исключение
		ЗаписатьОшибку(Контрагент, ОписаниеОшибки());
		//ЖурналРегистрации.
	КонецПопытки;
	
	
КонецПроцедуры

Процедура УдалитьОбъектИзОчереди(Объект)
	ЗаписьCOM = РегистрыСведений.ОбъектыДляВыгрузкиВЛМ.СоздатьМенеджерЗаписи();
	ЗаписьCOM.ОбъектДляВыгрузки		  = Объект;
	ЗаписьCOM.Удалить();
КонецПроцедуры

Функция ОтправитьPOSTЗапрос(Соединение, СтрокаЗапроса, ТокенЛМ, ТипОбъекта)
	HTTPЗапрос = Новый HTTPЗапрос("/"+ТипОбъекта+"/");
	HTTPЗапрос.Заголовки.Вставить("Content-type", "application/json");
	//Авторизация идет по токену, токен выдали на стороне DRF
	HTTPЗапрос.Заголовки.Вставить("Authorization", "token "+ТокенЛМ+"");
	HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
			
	HTTPОтвет = Соединение.ОтправитьДляОбработки(HTTPЗапрос);   
	Возврат HTTPОтвет; 
КонецФункции

Функция ОтправитьPUTЗапрос(Соединение, СтрокаЗапроса, ТокенЛМ, ТипОбъекта, ИдОбъекта)
	HTTPЗапрос = Новый HTTPЗапрос("/"+ТипОбъекта+"/"+ИдОбъекта+"/");
	HTTPЗапрос.Заголовки.Вставить("Content-type", "application/json");
	HTTPЗапрос.Заголовки.Вставить("Authorization", "token "+ТокенЛМ+"");
	HTTPЗапрос.УстановитьТелоИзСтроки(СтрокаЗапроса, КодировкаТекста.UTF8, ИспользованиеByteOrderMark.НеИспользовать);
	HTTPОтвет = Соединение.ВызватьHTTPМетод("PUT",HTTPЗапрос);   
	Возврат HTTPОтвет;
	
КонецФункции

 

обмен DRF HTTP-Запрос

См. также

Сайты и интернет-магазины Платформа 1С v8.3 1С:Розница 2 Розничная и сетевая торговля (FMCG) Россия Платные (руб)

Готовое интеграционное решение для оплаты покупок Долями в 1C:Розница 2.3. Реализовано в виде расширения. Интеграция сервиса dolyame.ru для приема платежей в рассрочку. Присутствует возможность работы подсистемы как с использованием в составе РИБ (распространение расширения в составе обновления Распределенной информационной базы, работа в рамках РИБ), так и отдельно.

20400 руб.

19.12.2023    2671    19    6    

18

Сайты и интернет-магазины Интеграция WEB-интеграция Платформа 1С v8.3 Конфигурации 1cv8 Управленческий учет Платные (руб)

Интеграция 1С и Битрикс 24. Разработка имеет двухстороннюю синхронизацию 1С и Bitrix24 задачами. Решение позволяет создавать пользователя в 1С из Битрикс24 и наоборот. Данная разработка технически подходит под все основные конфигурации линейки продуктов 1С:Предприятие 8.3 (платформа начиная с 8.3.23). При приобретении предоставляется 1 месяц бесплатных обновлений разработки. Доступна демо-версия продукта с подключением Вашего Битрикс24

5040 руб.

04.05.2021    18732    10    15    

16

Сайты и интернет-магазины WEB-интеграция Системный администратор Программист Пользователь Платформа 1С v8.3 Конфигурации 1cv8 1С:Управление торговлей 11 Автомобили, автосервисы Россия Управленческий учет Платные (руб)

Интеграционный модуль обмена между конфигурацией Альфа Авто 5 и Альфа Авто 6 и порталом AUTOCRM. Данный модуль универсален. Позволяет работать с несколькими обменами AUTOCRM разных брендов в одной информационной базе в ручном и автоматическом режиме.

36000 руб.

03.08.2020    16499    15    18    

15

Сайты и интернет-магазины Платформа 1С v8.3 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х 1С:Управление нашей фирмой 3.0 Россия Управленческий учет Платные (руб)

Расширение для 1С Управление торговлей, реализует: а) Загрузку номенклатуры с сайта с нужными параметрами. б) Позволяет быстро обновлять цены и остатки из 1С в Веб сайт на Битрикс, на лету. (онлайн). в) Моментально прогружать заказы и создавать реализации.

30000 руб.

29.03.2024    736    1    1    

0

Сайты и интернет-магазины Программист Бухгалтер Руководитель проекта Платформа 1С v8.3 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Розничная и сетевая торговля (FMCG) Россия Управленческий учет Платные (руб)

В обработке реализован механизм интеграции между системой поставщика на базе конфигураций 1с(управление торговлей 11) и Личным кабинетом Hoff. Реализован обмен остатками. Обработка реализована и тестировалась для УТ 11.4 Система позволяет выгружать из базы 1с поставщика хофф остатки товаров и другие данные в систему Hoff Преимущества: оперативное и регулярное обновление информации на сайте, уходит двойная работа по вводу остатков в разных системах (1С и личном кабинете HOFF), что чревато возникновением большого количества ошибок в управленческом учете. А также сократятся трудозатраты и повысится прибыль предприятия от продаж. Целевая аудитория: отделы маркетинга, продаж и склад, управленцы из сферы крупного, среднего бизнеса и мелкие предприниматели, владельцы ИП.

29880 руб.

16.11.2022    6504    1    5    

2

Оптовая торговля Розничная торговля Сайты и интернет-магазины Программист Платформа 1С v8.3 Управляемые формы 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Управленческий учет Платные (руб)

С начала момента разработки мы спарсили более 300 сайтов и записали эти товары в 1С. В итоге на свет появился универсальный парсер, который поможет Вам спарсить интернет-магазин, товары, цены и данные каталога, и при этом не написать ни строчки кода.

9600 руб.

19.10.2018    52927    220    101    

112
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Nikola23 700 10.06.24 17:25 Сейчас в теме
Прошу уточнить, при чем тут Jango, если пример демонстрирует формирование HTTP запроса?
Не сомневаюсь, что на той стороне джанго существует, но разве это имеет какое-то значение?
В примере это не раскрыто

А из своего опыта, я понимаю, что никакой особой разницы, какой там фреймворк - нет
2. gea29021988 5 10.06.24 17:37 Сейчас в теме
(1) Насколько я знаю именно строка адреса запроса формируется у всех по-разному, здесь именно Django REST Framework, это не джанго чистый это API к Django и здесь я показываю запрос именно к этому API вида
"/"+ТипОбъекта+"/"+ИдОбъекта+"/"
Знаю точно что в других API есть где ИдОбъекта пихается в тело запроса, а не в адрес.
3. Nikola23 700 10.06.24 22:52 Сейчас в теме
(2) Я абсолютно не против статей, где раз за разом показывают одно и тоже
Но вот без указания, что фишка статьи вот в этой строке
"/"+ТипОбъекта+"/"+ИдОбъекта+"/"
- как-то я совсем не догадался.
Может как-то выделить это?)
8. RocKeR_13 1340 11.06.24 16:30 Сейчас в теме
(3)
что фишка статьи вот в этой строке

Это не фишка, это обычная строка адреса запроса, правило формирования которой должно быть изложено в документации. Фишкой в свое время было описание формирования тела запроса multipart/form-data. А это именно то, что вы и написали сначала:

пример демонстрирует формирование HTTP запроса
4. gybson 11.06.24 00:02 Сейчас в теме
Такие огромные попытки зло и здесь очень хорошо видно почему. Если исключение произойдет при установке соединения, то при попытке сформировать сообщение об ошибке произойдет исключение. И даже если исключение обработается, то из него не очень будет понятно где и что произошло.

Если получен код 4** или 500, то смысл продолжать?

Конкатенация строк вместо шаблона.

Транзакции нет.

ОбъектыДляВыгрузкиВЛМ не используется в запросе

Как-то вообще все не так.
5. gea29021988 5 11.06.24 07:21 Сейчас в теме
(4) Если получен код 4** или 500, то смысл продолжать?
Если метод POST возвращает 400, то запускается PUT редактирование объекта
6. RocKeR_13 1340 11.06.24 16:24 Сейчас в теме
(4)
Транзакции нет.

Про транзакцию не понял: зачем она тут? В остальном согласен: много воды, вопросов и ничего нового.
7. gybson 11.06.24 16:28 Сейчас в теме
(6) чтобы не снимать с регистрации без положительного ответа сервиса
10. RocKeR_13 1340 11.06.24 16:35 Сейчас в теме
(7)
чтобы не снимать с регистрации без положительного ответа сервиса

А транзакция-то тут при чем?) Отправили запрос - пришел ответ: если ок, то сняли, если ошибка - продолжили. Единственный смысл - это открыть транзакцию перед началом цикла, но она, наоборот, в этом случае будет только вредить: транзакция в случае ошибки будет откатываться исключительно в 1С, а на стороне http-сервиса успешные запросы не откатятся; в итоге если на 5 запросе придет ошибка, то в 1С регистрация не снимется, но первые 4 запроса так и останутся успешно обработанными на стороне сервиса - в итоге 4 запроса при следующей выгрузке лишний раз будут продублированы
13. gybson 11.06.24 18:44 Сейчас в теме
(10) несомненно именно так и будет, если так сделать


Имеется в виду объединение в транзакцию удаление записи из регистра и запрос на сервис. Если запрос вызвал исключение, то записи не будет. А исключение он может дать запросто. Например сервис закроет соединение за спам или по таймауту.
14. RocKeR_13 1340 11.06.24 21:10 Сейчас в теме
(13) Ну отвалится по таймауту и ладно, транзакция зачем?) Транзакция нужна, чтобы данные в базе изменялись согласованно и при возникновении ошибки отменялись все изменения, произведённые в рамках транзакции. А тут по сути 2 действия: запрос к стороннему сервису и удаление записи регистра; первое действие не производит никаких действий в базе и отмена транзакции никак на него не может повлиять. Тут простая проверка условия: запрос выполнен успешно - удаляем запись; иначе делаем другие манипуляции или пишем ошибку в журнал. Транзакция не нужна для этого
9. Nikola23 700 11.06.24 16:33 Сейчас в теме
(8)
(6)
много воды, вопросов и ничего нового


Вот и я в первом сообщении завуалировал эту мысль.
Но не хотелось быть токсиком, поэтому не стал хэйтить, пошел вокруг)
11. RocKeR_13 1340 11.06.24 16:40 Сейчас в теме
(9) Ну можно же не минусовать) Ну познакомился человек с http-запросами - отлично и полезно. А мы тут подскажем, что не так и, может быть, подскажем, что сделать, чтобы было другим полезно и интересно))
12. Nikola23 700 11.06.24 16:59 Сейчас в теме
(11) а при чем тут минуса? Это не ко мне
15. RocKeR_13 1340 11.06.24 21:11 Сейчас в теме
Оставьте свое сообщение