Имя: Пароль:
1C
 
1С взаимодействие с Telegram. Установка Webhook
0 Oldman06
 
24.01.25
10:49
Приветствую.
Устанавливаю адрес сервиса обслуживания Webhook для телеграм-бота. Для сервиса используется самоподписной сертификат. Код:
&НаКлиенте
Процедура setWebhook()
	ДанныеСертификата = Неопределено;
	Если ЗначениеЗаполнено(ИмяФайлаСертификата) Тогда
		ДанныеСертификата = Новый Структура;
		
		СтруктураИмяФайла = ОбщегоНазначенияКлиентСервер.РазложитьПолноеИмяФайла(ИмяФайлаСертификата);
		
		ДанныеСертификата.Вставить("ИмяФайла", СтруктураИмяФайла.Имя);
		ДанныеСертификата.Вставить(
			"Адрес",
			ПоместитьВоВременноеХранилище(
				Новый ДвоичныеДанные(ИмяФайлаСертификата),
				УникальныйИдентификатор
			)
		);
		
	КонецЕсли;
	
	setWebhookНаСервере(ДанныеСертификата);
	
КонецПроцедуры

&НаСервере
Процедура setWebhookНаСервере(ДанныеСертификата)
	Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
	
	Поток = Новый ПотокВПамяти;
	ЗаписьДанных = Новый ЗаписьДанных(Поток);
	
	Если ДанныеСертификата <> Неопределено Тогда
		ЗаписьДанных.ЗаписатьСтроку("--" + Boundary); 
		ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""certificate""; filename=""" + ДанныеСертификата.ИмяФайла + """");
		ЗаписьДанных.ЗаписатьСтроку("Content-Type: application/x-octet-stream"); 
		ЗаписьДанных.ЗаписатьСтроку("");
		
		ДДСертификата = ПолучитьИзВременногоХранилища(ДанныеСертификата.Адрес);
		ЗаписьДанных.Записать(ДДСертификата);
		
	КонецЕсли;
	
	ЗаписьДанных.ЗаписатьСтроку("--" + Boundary);
	ЗаписьДанных.ЗаписатьСтроку("Content-disposition: form-data; name=""url""" + Символы.ПС); 
	ЗаписьДанных.ЗаписатьСтроку(WebHookURL); 
	
	ЗаписьДанных.ЗаписатьСтроку("--" + Boundary);
	ЗаписьДанных.ЗаписатьСтроку("Content-disposition: form-data; name=""secret_token""" + Символы.ПС); 
	ЗаписьДанных.ЗаписатьСтроку(ТокенWebHook);
	
	ЗаписьДанных.ЗаписатьСтроку("--" + Boundary + "--");
	
	ЗаписьДанных.Закрыть();
	
	ТелоЗапроса = Поток.ЗакрытьИПолучитьДвоичныеДанные();
	
	ПараметрыПодключения = СервисыВзаимодействияПовтИсп.ПараметрыПодключения(
		Перечисления.КаналыВзаимодействий.Telegram
	);
	
	Соединение = Новый HTTPСоединение(
		ПараметрыПодключения.Host,
		443, , , ,
		5,
		Новый ЗащищенноеСоединениеOpenSSL()
	);
	
	URLЗапроса = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
		"bot%1/%2",
		ПараметрыПодключения.Token,
		"setWebhook"
	);
	
	Запрос = Новый HTTPЗапрос(URLЗапроса);
	Запрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);
	Запрос.УстановитьТелоИзДвоичныхДанных(ТелоЗапроса);
	
	Попытка 
		Ответ = Соединение.ОтправитьДляОбработки(Запрос);
		Если Ответ.КодСостояния = 200 Тогда			
			ОтветСервиса = Ответ.ПолучитьТелоКакСтроку();
			
		Иначе
			ОтветСервиса = Ответ.ПолучитьТелоКакСтроку("UTF-8");
			
		КонецЕсли;
		
	Исключение
		
	КонецПопытки;
	
КонецПроцедуры


Если устанавлюваю Webhook без передачи открытого ключа сертификата, то Webhook устанавливается, но с ошибкой SSL:
Ответ метода setWebhook:
{
"ok": true,
"result": true,
"description": "Webhook was set"
}

Вывод getWebhookInfo: {
"ok": true,
"result": {
"url": "https://ххх.ххх.ххх.ххх:8443/telegram ,
"has_custom_certificate": false,
"pending_update_count": 0,
"last_error_date": 1737703195,
"last_error_message": "SSL error {error:0A000086:SSL routines::certificate verify failed}",
"max_connections": 40,
"ip_address": "ххх.ххх.ххх.ххх"
}
}


Если при установке указываю публичный ключ самоподписного сертификата, то ответ следующий:
{
"ok": true,
"result": true,
"description": "Webhook is already deleted"
}


как будто я вызываю метод deleteWebhook, когда Webhook не установлен.
В чем может быть дело?
1 Vostochnick
 
24.01.25
11:01
(0) ну и вопросики в пятницу )
2 CepeLLlka
 
24.01.25
11:07
(0)Попробуйте сначала загрузить файл сертификата на сервера телеграмма и потом уже при установке ВебХука передайте в параметр Айди файла
3 Oldman06
 
24.01.25
11:20
(2) Не могу в документации найти метод позволяющий загрузить файл и получить его Id. Нахожу только методы отправки какому-либо контакту. Если не сложно, ткните.
4 CepeLLlka
 
24.01.25
11:28
(3)Так и есть. Пусть ваш бот отправит вам файл сертификата.
5 Oldman06
 
24.01.25
21:17
Короче, вот так все работает:
&НаСервере
Процедура setWebhookНаСервере(ДанныеСертификата)
    Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
    
    Поток = Новый ПотокВПамяти;
    ЗаписьТекста = Новый ЗаписьТекста(Поток, КодировкаТекста.UTF8);
    
    ЗаписьТекста.ЗаписатьСтроку("--" + Boundary);
    ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""url""");
    ЗаписьТекста.ЗаписатьСтроку("");
    ЗаписьТекста.ЗаписатьСтроку(WebHookURL);
    
    Если ДанныеСертификата <> Неопределено Тогда
        ЗаписьТекста.ЗаписатьСтроку("--" + Boundary);
        ЗаписьТекста.ЗаписатьСтроку("Content-Disposition: form-data; name=""certificate""; filename=""" + ДанныеСертификата.ИмяФайла + """");
        ЗаписьТекста.ЗаписатьСтроку("");
        
        ДДСертификата = ПолучитьИзВременногоХранилища(ДанныеСертификата.Адрес);
        ПотокДанныхСертификата = ДДСертификата.ОткрытьПотокДляЧтения();
        
        ЧтениеТекста = Новый ЧтениеТекста(ПотокДанныхСертификата, КодировкаТекста.UTF8);
        ЗаписьТекста.Записать(ЧтениеТекста.Прочитать());
        
        
        ЧтениеТекста.Закрыть();
        
        ПотокДанныхСертификата.Закрыть();
        
    КонецЕсли;
    
    ЗаписьТекста.ЗаписатьСтроку("--" + Boundary + "--");
    
    ЗаписьТекста.Закрыть();
    
    ТелоЗапроса = Поток.ЗакрытьИПолучитьДвоичныеДанные();
    
    ПараметрыПодключения = СервисыВзаимодействияПовтИсп.ПараметрыПодключения(
        Перечисления.КаналыВзаимодействий.Telegram
    );
    
    Соединение = Новый HTTPСоединение(
        ПараметрыПодключения.Host,
        443, , , ,
        5,
        Новый ЗащищенноеСоединениеOpenSSL()
    );
    
    URLЗапроса = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
        "bot%1/%2",
        ПараметрыПодключения.Token,
        "setWebhook"
    );
    
    Запрос = Новый HTTPЗапрос(URLЗапроса);
    Запрос.Заголовки.Вставить("Connection", "keep-alive");
    Запрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=" + Boundary);
    Запрос.УстановитьТелоИзДвоичныхДанных(ТелоЗапроса);
    
    Попытка
        Ответ = Соединение.ОтправитьДляОбработки(Запрос);
        Если Ответ.КодСостояния = 200 Тогда            
            ОтветСервиса = Ответ.ПолучитьТелоКакСтроку("UTF-8");
            
        Иначе
            ОтветСервиса = Ответ.ПолучитьТелоКакСтроку("UTF-8");
            
        КонецЕсли;
        
    Исключение
        
    КонецПопытки;
    
КонецПроцедуры
6 CepeLLlka
 
24.01.25
22:48
(5)Красава