Имя: Пароль:
1C
1С v8
Отправка офлайн-конверсий в Яндекс Метрику
0 texnol063
 
22.12.22
12:53
Добрый день.
Столкнулся с проблемой отправки офлайн конверсий в Яндекс Метрику. Документация API есть (https://yandex.ru/dev/metrika/doc/api2/practice/offline-conv.html), но примеров решения на 1С найти не удалось. Пробовал несколько вариантов решения, но по каждому возвращается одна и та же ошибка "{"errors":[{"error_type":"invalid_uploading","message":"Не найден параметр запроса.","location":"file"}],"code":400,"message":"Не найден параметр запроса."}" - по ней находится пару ссылок, связанных с реализацией на php, где рекомендуют использовать "curl".

1.
    ВыходнойФайл = КаталогВременныхФайлов()+"data.csv";
    ФайлОтправки = Новый ЗаписьТекста(ВыходнойФайл, КодировкаТекста.ANSI, Символы.ВК + Символы.ПС);
    
    Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
    ФайлОтправки.ЗаписатьСтроку("--------------------------" + Boundary);
    ФайлОтправки.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""data.csv""");
    ФайлОтправки.ЗаписатьСтроку("Content-Type: text/csv");
    ФайлОтправки.ЗаписатьСтроку("ClientId,Target,DateTime");
    ФайлОтправки.ЗаписатьСтроку(СтрШаблон("%1,%2,%3", СтруктураСДанными.YM, СтруктураСДанными.Target, СтруктураСДанными.DateTime));
    ФайлОтправки.ЗаписатьСтроку("--------------------------" + Boundary + "--");
    ФайлОтправки.Закрыть();
    
    HTTPСоединение = Новый HTTPСоединение("api-metrika.yandex.ru",,,,,, Новый ЗащищенноеСоединениеOpenSSL());
    
    Ресурс = "management/v1/counter/" + СтруктураСДанными.НомерСчетчика + "/offline_conversions/upload?client_id_type=CLIENT_ID";
    HTTPЗапрос = Новый HTTPЗапрос(Ресурс);
    HTTPЗапрос.Заголовки.Вставить("Authorization", СтруктураСДанными.Токен);
    HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=------------------------" + Boundary);
    ВыбФайл = Новый Файл(ВыходнойФайл);
    HTTPЗапрос.Заголовки.Вставить("Content-Length", XMLСтрока(ВыбФайл.Размер()));
    HTTPЗапрос.УстановитьИмяФайлаТела(ВыходнойФайл);
    
    ТекстОшибки = "";
    Попытка
        Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
        Если Ответ.КодСостояния <> 200 Тогда
            ТекстОшибки = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
        КонецЕсли;
    Исключение
        ТекстОшибки = ОписаниеОшибки();
    КонецПопытки;
    
2. Сделал csv отдельным файлом

    ИмяФайлаCSV = КаталогВременныхФайлов()+"data.csv";
    ТекстовыйФайлЗапись = Новый ЗаписьТекста(ИмяФайлаCSV, КодировкаТекста.ANSI, Символы.ВК + Символы.ПС);
    ТекстовыйФайлЗапись.ЗаписатьСтроку("ClientId,Target,DateTime");
    ТекстовыйФайлЗапись.ЗаписатьСтроку(СтрШаблон("%1,%2,%3", СтруктураСДанными.YM, СтруктураСДанными.Target, СтруктураСДанными.DateTime));
    ТекстовыйФайлЗапись.Закрыть();
    ДД = Новый ДвоичныеДанные(ИмяФайлаCSV);
    
    Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");    
    имяФайлаОтправки = ПолучитьимяВременногоФайла("txt");
    ЗаписьДанных = Новый ЗаписьТекста(имяФайлаОтправки,КодировкаТекста.ANSI);
    ЗаписьДанных.ЗаписатьСтроку("--------------------------" + Boundary);
    ЗаписьДанных.ЗаписатьСтроку("Content-Disposition: form-data; name=""data""");
    ЗаписьДанных.ЗаписатьСтроку("Content-Type: text/csv");
    ЗаписьДанных.Записать(ДД);
    ЗаписьДанных.ЗаписатьСтроку("--------------------------" + Boundary + "--");
    ЗаписьДанных.Закрыть();
    
    HTTPСоединение = Новый HTTPСоединение("api-metrika.yandex.ru",,,,,, Новый ЗащищенноеСоединениеOpenSSL());
    
    HTTPЗапрос = Новый HTTPЗапрос("management/v1/counter/" + СтруктураСДанными.НомерСчетчика + "/offline_conversions/upload?client_id_type=CLIENT_ID");
    HTTPЗапрос.Заголовки.Вставить("Authorization", СтруктураСДанными.Токен);
    HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=------------------------" + Boundary);
    ВыбФайл = Новый Файл(имяФайлаОтправки);
    HTTPЗапрос.Заголовки.Вставить("Content-Length", XMLСтрока(ВыбФайл.Размер()));
    HTTPЗапрос.УстановитьИмяФайлаТела(имяФайлаОтправки);
    
    Попытка
        Результат = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
        ОтветСтрока = Результат.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
        Сообщить(ОтветСтрока);
    Исключение
        Сообщить(ОписаниеОшибки());
    КонецПопытки;
    
3. Через библиотеку "КоннекторHTTP" (https://infostart.ru/1c/articles/709325/)

    ИмяФайлаCSV = КаталогВременныхФайлов()+"data.csv";
    ТекстовыйФайлЗапись = Новый ЗаписьТекста(ИмяФайлаCSV, КодировкаТекста.ANSI, Символы.ВК + Символы.ПС);
    ТекстовыйФайлЗапись.ЗаписатьСтроку("ClientId,Target,DateTime");
    ТекстовыйФайлЗапись.ЗаписатьСтроку(СтрШаблон("%1,%2,%3", СтруктураСДанными.YM, СтруктураСДанными.Target, СтруктураСДанными.DateTime));
    ТекстовыйФайлЗапись.Закрыть();
    ДД = Новый ДвоичныеДанные(ИмяФайлаCSV);
    
    Файлы = Новый Структура;
    Файлы.Вставить("Имя", "data");
    Файлы.Вставить("ИмяФайла", "data.csv");
    Файлы.Вставить("Данные", ДД);
    Файлы.Вставить("Тип", "text/csv");
    
    ПараметрыЗапроса = Новый Структура;
    ПараметрыЗапроса.Вставить("client_id_type", "CLIENT_ID");
    
    Заголовки = Новый Соответствие;
    Заголовки.Вставить("Authorization", СтруктураСДанными.Токен);
    
    Результат = КоннекторHTTP.Post("https://api-metrika.yandex.ru/management/v1/counter/" + СтруктураСДанными.НомерСчетчика + "/offline_conversions/upload",
    Неопределено, Новый Структура("Файлы, Заголовки, ПараметрыЗапроса", Файлы, Заголовки, ПараметрыЗапроса));
1 polosov
 
22.12.22
13:32
(0) Инструменты: Fiddler и Curl.
Настраиваешь прокси в Fiddler'е. Отправляешь запрос из Curl (наверняка есть пример у тындекса).
Перехватываешь Fiddler'ом.
Делаешь запрос из 1С, перехватываешь и сравниваешь.
Добиваешься аналогичного результата запроса из Curl.
2 Kassern
 
22.12.22
13:37
(0) "де рекомендуют использовать "curl". " - берете постман и пихаете туда пример curl запроса. Постман его разберет и покажет, что куда пихнуть (что в тело, что в заголовки).
3 texnol063
 
26.12.22
12:42
(1) (2) Спасибо за советы - postman и fiddler помогли понять правильную структуру запроса (хоть и пришлось поразобраться, т.к. раньше с ними дел не имел). А проблема была в использовании "Символы.ВК" в разделителе строк объекта "ЗаписьТекста". Вот таким вариантом запрос отправляется без ошибок:

    ВыходнойФайл = КаталогВременныхФайлов()+"data.csv";
    ФайлОтправки = Новый ЗаписьТекста(ВыходнойФайл, КодировкаТекста.ANSI, Символы.ПС);
    
    Boundary = СтрЗаменить(Строка(Новый УникальныйИдентификатор()), "-", "");
    ФайлОтправки.ЗаписатьСтроку("--------------------------" + Boundary);
    ФайлОтправки.ЗаписатьСтроку("Content-Disposition: form-data; name=""file""; filename=""data.csv""");
    ФайлОтправки.ЗаписатьСтроку("Content-Type: text/csv");
    ФайлОтправки.ЗаписатьСтроку("");
    ФайлОтправки.ЗаписатьСтроку("CLIENT_ID,Target,DateTime");
    ФайлОтправки.ЗаписатьСтроку(СтрШаблон("%1,%2,%3", СтруктураСДанными.YM, СтруктураСДанными.Target, СтруктураСДанными.DateTime));
    ФайлОтправки.ЗаписатьСтроку("");
    ФайлОтправки.ЗаписатьСтроку("--------------------------" + Boundary + "--");
    ФайлОтправки.Закрыть();
    
    HTTPСоединение = Новый HTTPСоединение("api-metrika.yandex.net",,,,,, Новый ЗащищенноеСоединениеOpenSSL());
    
    Ресурс = "management/v1/counter/" + СтруктураСДанными.НомерСчетчика + "/offline_conversions/upload?client_id_type=CLIENT_ID";
    HTTPЗапрос = Новый HTTPЗапрос(Ресурс);
    HTTPЗапрос.Заголовки.Вставить("Authorization", СтруктураСДанными.Токен);
    HTTPЗапрос.Заголовки.Вставить("Content-Type", "multipart/form-data; boundary=------------------------" + Boundary);
    ВыбФайл = Новый Файл(ВыходнойФайл);
    HTTPЗапрос.Заголовки.Вставить("Content-Length", XMLСтрока(ВыбФайл.Размер()));
    HTTPЗапрос.УстановитьИмяФайлаТела(ВыходнойФайл);
    
    ТекстОшибки = "";
    Попытка
        Ответ = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос);
        Если Ответ.КодСостояния <> 200 Тогда
            ТекстОшибки = Ответ.ПолучитьТелоКакСтроку(КодировкаТекста.UTF8);
        КонецЕсли;
    Исключение
        ТекстОшибки = ОписаниеОшибки();
    КонецПопытки;
Компьютер — устройство, разработанное для ускорения и автоматизации человеческих ошибок.