В общем, ладно, поспать все равно не получилось, может вечером получится не как обычно, в 2-3 часа ночи лечь, а хотя-бы часов в 12..
По порялку - я буду вставлять куски кода, "как они у меня есть", где-то на 1с77, гдето вставки скриптов... Разберетесь, 1с очень похожа на Дельфи, или чуть меньше на VB...Только возможности сильно "урезаны", даже по сравнению с "младшей сестрой - 1с8.Х"... Многих объектов не хватает, но, есть несколько "специфических", которым все равно в других ЯП есть аналоги...
Ладно, это все лирика, поехали...
Есть у меня такая обработка, проверка связи и получение токена.
Ну, тут по смыслу иожно понять, что она должна делать.
Что-бы было понятнее, дальше все буду делать через отладчик.
Жму кнопку "Выполнить проверку".
Попадаю сюда:
Процедура Сформировать()
Если Вопрос("Выполнить проверку связи с сервером ЦРПТ и попытку авторизации? Токен доступа будет получен новый. Продолжить?", 4, 10) = 6 Тогда
Если ФС.СуществуетФайл(КаталогИБ() + КодТекПольз + "_tokenCRPT.txt") = 1 Тогда
ФС.УдалитьФайл(КаталогИБ() + КодТекПольз + "_tokenCRPT.txt");
КонецЕсли;
СтрОшибка = "";
ЮрЛицо = глЗначениеПоУмолчанию("ОсновноеПодразделение");
КлючСессии = ПолучитьТокенЦРПТ(глПользователь.ЭЦП, ПрефиксВерсии, СтрОшибка);
Если ПустоеЗначение(КлючСессии) = 1 Тогда
Сообщить(СтрОшибка);
Возврат;
Иначе
Сообщить("Соединение с сервером ЦРПТ успешно установлено, ключ сессии получен!");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Что он там ищет и удаляет, не принципиально - это храненин готового токена в течении его срока жизни, сейчас, это не принципиально.
Дальше попадаю в функцию ПолучитьТокенЦРПТ(ВыбЭЦП, ПрефиксВерсии = "", СтрОшибка = "") где параметр "ВыбЭЦП" - это отпечаток ЭЦП, хранящийся в одном из справочников. Остальные параметры тут не принципиальны.
Следующим шагом попадаю в функцию /
/ Возвращает пары идентификатор-данные для запроса токена
ВернутьПаруЗапрТокена(УРЛ, ПрефиксВерсии = "", ЭДО = 0) - тут параметры тоже не принципиальны. не важно как, с помощью них получаю адрес запроса:
Url = "https://markirovka.crpt.ru/api/v3/true-api/auth/key"
Формирую заголовки запроса:
сзЗаголовки.ДобавитьЗначение("no-cache", "cache-control");
сзЗаголовки.ДобавитьЗначение("application/json", "Accept");
И далее сам запрос:
Ответ = глКарлик_ВыполнитьЗапрос("GET", Url,, сзЗаголовки, СтрОшибка);
чем Вы его тут будете делать - совершенно не принципиально, MS_WinHTTP, MS_XMLHTTP, cUrl, или чем-то своим - это как удобнее и привычнее. Раньше я делал через MS запросы, сейчас использую внешнюю компоненту для 1с77 - curl1c на базе curl, по сути - это курл, завернутый в оболочку ВК, и работа с ней ничем не отнличается от MS запросов, никаких "командных строк" и т.п., все просто и удобно, зато нет никаких гимороев с httpS как в случае с MS запросами.
Далее, куча кода по анализу ответа и разбор ошибок, если есть, но, это не интересно, опустим...
Короче, получили ответ - строку JSON, разобрали ее(тут тоже свои нюансы, 7.7 не знает ничего о JSON, приходится "извращаться"), имеем две строки:
uuid = "04fbe037-1a2d-4958-a1aa-50bae5bb6240"
code = "MPXHFICBNZHDRNAGQONJBYYCCOWMRB"
УУИД - это идентификатор токена, КОДЕ - строка "произвольных данных" для подписи.
НО!!! Вот тут надо четко понимать, что это не "произвольные данные" "от балды", как для формирования токена для CDN площадок, а данные сформированные сервером и "привязанные" к УУИД.
Далее идет функция:
Сигнатура = ПодписатьТекст(code,СокрЛП(ВыбЭЦП.Отпечаток),1); - три параметра, сама строка, отпечаток, и "1", это то, что она открепленная.
Сама функция:
// sThumbprint - отпечаток сертификата, используемого для подписи; строка, представляющая отпечаток в шестандцатеричном виде
Функция ПодписатьТекст(ТекстДляПодписи, sThumbprint,БезBOM=1, Откр = 0) Экспорт
infile = КаталогВременныхФайлов()+"infile.txt";
Если ФС.СуществуетФайл(infile) = 1 Тогда
Попытка
ФС.УдалитьФайл(infile);
Исключение
infile = КаталогВременныхФайлов() + "infile" + ГенераторGIUD() + ".txt";
КонецПопытки;
КонецЕсли;
outfile = КаталогВременныхФайлов()+"outfile.txt";
Если ФС.СуществуетФайл(outfile) = 1 Тогда
Попытка
ФС.УдалитьФайл(outfile);
Исключение
outfile = КаталогВременныхФайлов() + "outfile" + ГенераторGIUD() + ".txt";
КонецПопытки;
КонецЕсли;
Если Прав(ТекстДляПодписи,4) = ".xml" Тогда
infile = ТекстДляПодписи;
ПодписатьФайл(infile,ПолучитьСертификатПоОтпечатку(sThumbprint),outfile, Откр);
Если ФС.СуществуетФайл(outfile) = 1 Тогда
Возврат outfile;
Иначе
Возврат "";
КонецЕсли;
Иначе
Если БезBOM = 1 Тогда
ВремТекст = СоздатьОбъект("Текст");
ВремТекст.ДобавитьСтроку(ТекстДляПодписи);
ВремТекст.Записать(infile);
Иначе
АдоДБСтрим = СоздатьОбъект("ADODB.Stream");
АдоДБСтрим.Mode = 3;
АдоДБСтрим.Type = 2;//текст
АдоДБСтрим.charset="utf-8";
АдоДБСтрим.Open();
АдоДБСтрим.WriteText(ТекстДляПодписи);
АдоДБСтрим.Position=0;
АдоДБСтрим.SaveToFile(infile,2);
АдоДБСтрим.Close();
КонецЕсли;
ПодписатьФайл(infile,ПолучитьСертификатПоОтпечатку(sThumbprint),outfile, Откр);
Если ФС.СуществуетФайл(outfile) = 1 Тогда
Возврат outfile;
Иначе
Возврат "";
КонецЕсли;
КонецЕсли;
КонецФункции
Напрямую подписать строку у меня не получилось, поэтому через поток формирую временный файл, и его подписываю функцией ПодписатьФайл(infile,ПолучитьСертификатПоОтпечатку(sThumbprint),outfile, Откр);
Где:
infile = "C:\Users\MWW\AppData\Local\Temp\infile.txt"
А outfile получим после подписания.
Сертификат по отпечатку получаю так:
//https://www.cryptopro.ru/forum2/default.aspx?g=posts&m=95369
//https://www.cryptopro.ru/forum2/default.aspx?g=posts&t=10684
//Отпечаток - строка HEX
Функция ПолучитьСертификатПоОтпечатку(ОтпечатокСтр) Экспорт
Рез = ""; // Найденный сертификат (Com-объект)
CAPICOM_CURRENT_USER_STORE = 2; // 2 - Искать сертификат в ветке "Личное" хранилища.
CAPICOM_MY_STORE = "My"; // Указываем, что ветку "Личное" берем из хранилища текущего пользователя
CAPICOM_STORE_OPEN_READ_ONLY = 0; // Открыть хранилище только на чтение
oStore = СоздатьОбъект("CAPICOM.Store"); // Объект описывает хранилище сертификатов
oStore.Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_READ_ONLY); // Открыть хранилище сертификатов
Certs = oStore.Certificates;
Для СчСер = 1 По Certs.Count Цикл
ТекСертификат = Certs.Item (СчСер);
ТекОтпечаток = ТекСертификат.Thumbprint; // возвращается отпечаток в шестнадцатеричном виде
Если ВРЕГ(ТекОтпечаток) = ВРЕГ(ОтпечатокСтр) Тогда
Рез = ТекСертификат;
Прервать;
КонецЕсли;
КонецЦикла;
oStore.Close(); // Закрыть хранилище сертификатов и освободить объект
Возврат Рез;
КонецФункции
Пока хватит, а то месага слишком длинная будет, продолжение следует