Выгрузка данных на сайт из 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 для приема платежей в рассрочку. Поддерживает работу от разных юридических лиц. Работа: в составе РИБ, отдельно от РИБ, тонкий, толстый клиент, web-клиент (через интернет-браузер).

22440 руб.

19.12.2023    5526    40    11    

37

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

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

36000 руб.

03.08.2020    18019    18    22    

17

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

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

7200 руб.

04.05.2021    20164    13    19    

18

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

Программа позволяет одним кликом настроить сбор цен ваших конкурентов или дилеров в интернете. Автоматически собирает данные результата поиска Яндекса (вам не придется вручную добавлять каждый сайт, за которым нужно следить). Обновление цен происходит по заданному вами расписанию автоматически. Можете легко отслеживать позиции вашего сайта в Яндексе по ключевым словам и фразам. Этот инструмент даст вам лучшее понимание того, как ваша SEO-стратегия влияет на видимость вашего сайта в поисковой выдаче, и поможет вам улучшить контент и структуру сайта для повышения его позиций. Функция доступна во всех тарифах.

19950 руб.

23.09.2019    31104    7    12    

30

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

В настоящее время система СБП очень часто стала использоваться в повседневной жизни. Одна из систем интеграции СБП через СБЕР. Данная конфигурация является инструментом интеграции СБП в Альфа Авто. Данная система не просто формирует статический QR, а динамический, а значит, в системе будет привязка и на покупателя, и на документ.

7200 руб.

25.10.2022    6429    32    4    

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

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

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

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

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

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

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

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

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

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

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


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


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