В этой статье мы подробно разберем, как наладить взаимодействие между 1С и API криптовалютной биржи EXMO. Основная сложность при такой интеграции заключается в правильной аутентификации запросов, которая требует формирования специальной цифровой подписи. Мы рассмотрим весь процесс по шагам: от получения ключей до создания функции для вызова любых методов API, включая получение баланса и создание торговых ордеров.
Проанализируем ключевые моменты: формирование POST-запроса, генерацию подписи с помощью алгоритма HMAC-SHA512 и обработку ответов от сервера биржи.
Для работы с приватными методами API, такими как получение информации о балансе или управление ордерами, необходимы API-ключи. Получить их можно в настройках вашего профиля на сайте биржи EXMO.
Вам понадобятся два ключа:
K-7cc97c89aed2a2fd9ed7792d48d63f65800c447b.S-3855d9a2915e4793e3fc5410a06b53e547263335.Важный момент: на момент написания статьи, основной домен API api.exmo.com мог быть заблокирован. Для подключения используйте актуальное зеркало — api.exmo.me.
Это самый ответственный этап. Каждый запрос к приватным методам API должен сопровождаться заголовком Sign. Значение этого заголовка — это тело POST-запроса, подписанное вашим секретным ключом с использованием алгоритма HMAC-SHA512.
В стандартных средствах 1С нет встроенной функции для такого хэширования, поэтому воспользуемся COM-объектами. Ниже представлена рабочая функция для генерации подписи.
Функция HMAC_SHA512(СекретныйКлюч, Строка) Экспорт
Текст = Новый COMОбъект("System.Text.UTF8Encoding");
Криптография = Новый COMОбъект("System.Security.Cryptography.HMACSHA512");
Криптография.Key = Текст.GetBytes_4(СекретныйКлюч);
ХешБайт = Криптография.ComputeHash_2(Текст.GetBytes_4(Строка)).Выгрузить;
HTML = Новый COMОбъект("htmlfile");
HTML.Open("text/html");
// Важно! В этой строке не должно быть лишних пробелов
HTML.Write("ПреобразоватьСтроку = function(x,y){return x.toString(y?y:16)}");
ЯваСкрипт = HTML.documentElement.document.Script;
Хеш = "";
Для Каждого Байт Из ХешБайт Цикл
Символ = ЯваСкрипт.ПреобразоватьСтроку(Байт);
Хеш = Хеш + ?(СтрДлина(Символ) = 2, Символ, "0"+Символ);
КонецЦикла;
Возврат Хеш;
КонецФункции
Как это работает:
htmlfile и небольшим JavaScript-кодом. Это позволяет получить результат в нужном формате.Если возникают ошибки вида "Поле объекта не обнаружено ПреобразоватьСтроку", в первую очередь проверьте строку HTML.Write(...) на наличие лишних пробелов.
В качестве альтернативы JavaScript можно использовать функцию на чистом 1С для преобразования десятичного числа в шестнадцатеричное:
Функция DecToHex(Знач _Число)
База = 16;
Результат = "";
Пока _Число <> 0 Цикл
Поз = _Число % База;
Результат = Сред("0123456789ABCDEF", Поз + 1, 1) + Результат;
_Число = Цел(_Число / База);
КонецЦикла;
Если СтрДлина(Результат) = 1 Тогда
Результат = "0" + Результат;
КонецЕсли;
Возврат Результат;
КонецФункции
В этом случае цикл в основной функции будет выглядеть так: Символ = DecToHex(Байт); Хеш = Хеш + Символ;
Теперь создадим функцию, которая будет формировать запрос, подписывать его и отправлять на сервер. Она будет принимать на вход имя API-метода (например, "user_info") и параметры запроса.
Для всех запросов обязательным параметром является nonce (number used once) — целое число, которое должно увеличиваться с каждым новым запросом. Самый надежный способ его генерации — использовать UNIX-время в миллисекундах.
Функция ПолучитьНонс()
// Разница в секундах между 01.01.1970 и 01.01.0001
КонстантаСмещения = 62135596800;
// Текущая дата в секундах + смещение, умноженное на 1000 для получения миллисекунд
Nonce = (УниверсальноеВремя(ТекущаяДата()) + КонстантаСмещения) * 1000;
Возврат Формат(Nonce, "ЧГ=0");
КонецФункции
Теперь напишем саму функцию для вызова API. Она будет принимать имя метода и структуру с параметрами.
Функция ВызовФункцииAPIЭксмо(ИмяМетода, ПараметрыЗапроса = Неопределено)
// Вставьте сюда свои ключи
apikey = "K-ВАШ_ПУБЛИЧНЫЙ_КЛЮЧ";
apisecret = "S-ВАШ_СЕКРЕТНЫЙ_КЛЮЧ";
// Формируем тело POST-запроса
ПостСообщение = "nonce=" + ПолучитьНонс();
Если ПараметрыЗапроса <> Неопределено Тогда
Для Каждого Элемент Из ПараметрыЗапроса Цикл
ПостСообщение = ПостСообщение + "&" + Элемент.Ключ + "=" + Элемент.Значение;
КонецЦикла;
КонецЕсли;
// Генерируем подпись
Сигнатура = HMAC_SHA512(apisecret, ПостСообщение);
// Формируем заголовки
ЗаголовокHTTP = Новый Соответствие;
ЗаголовокHTTP.Вставить("Sign", Сигнатура);
ЗаголовокHTTP.Вставить("Key", apikey);
ЗаголовокHTTP.Вставить("Content-Type", "application/x-www-form-urlencoded");
// Для отправки используем более современный объект HTTPЗапрос
HTTPЗапрос = Новый HTTPЗапрос("/v1/" + ИмяМетода);
HTTPЗапрос.Заголовки = ЗаголовокHTTP;
HTTPЗапрос.УстановитьТелоИзСтроки(ПостСообщение, КодировкаТекста.UTF8);
SSL = Новый ЗащищенноеСоединениеOpenSSL;
HTTPСоединение = Новый HTTPСоединение("api.exmo.me", , , , , , SSL);
Попытка
HTTPОтвет = HTTPСоединение.ОтправитьДляОбработки(HTTPЗапрос,);
Если HTTPОтвет.КодСостояния = 200 Тогда
Возврат HTTPОтвет.ПолучитьТелоКакСтроку();
Иначе
Сообщить("Ошибка HTTP: " + HTTPОтвет.КодСостояния);
Сообщить(HTTPОтвет.ПолучитьТелоКакСтроку());
Возврат Неопределено;
КонецЕсли;
Исключение
Сообщить(ОписаниеОшибки());
Возврат Неопределено;
КонецПопытки;
КонецФункции
Теперь, имея универсальную функцию, мы можем легко вызывать различные методы API.
Для этого используется метод user_info, который не требует дополнительных параметров.
Процедура ПолучитьБаланс()
РезультатJSON = ВызовФункцииAPIЭксмо("user_info");
Если РезультатJSON <> Неопределено Тогда
// Для удобной работы с JSON преобразуем его в структуру или соответствие
ЧтениеJSON = Новый ЧтениеJSON;
ЧтениеJSON.УстановитьСтроку(РезультатJSON);
Данные = ПрочитатьJSON(ЧтениеJSON);
// Теперь можно обращаться к балансам
Сообщить("Баланс USD: " + Данные.balances.USD);
Сообщить("Баланс BTC: " + Данные.balances.BTC);
КонецЕсли;
КонецПроцедуры
Для создания ордера используется метод order_create. Ему необходимо передать параметры: валютную пару, количество, цену и тип ордера.
Процедура СоздатьОрдер()
// Создаем структуру с параметрами
ПараметрыОрдера = Новый Структура;
ПараметрыОрдера.Вставить("pair", "BTC_USD");
ПараметрыОрдера.Вставить("quantity", "0.01"); // Количество BTC
ПараметрыОрдера.Вставить("price", "20000"); // Цена за 1 BTC в USD
ПараметрыОрдера.Вставить("type", "buy"); // Тип ордера - покупка
РезультатJSON = ВызовФункцииAPIЭксмо("order_create", ПараметрыОрдера);
Если РезультатJSON <> Неопределено Тогда
Сообщить("Ответ сервера на создание ордера:");
Сообщить(РезультатJSON);
КонецЕсли;
КонецПроцедуры
Error 40005: Authorization error, Incorrect signature.
Самая частая ошибка. Означает, что подпись, которую вы сгенерировали, не совпадает с той, которую ожидает сервер. Проверяйте:
apisecret).ПостСообщение, передаваемой в функцию HMAC_SHA512, телу POST-запроса.ПолучитьНонс (значение должно постоянно расти).EXMO.COM API SERVER Please read API documentation
Такой ответ обычно приходит, если тело POST-запроса пустое или имеет неверный формат, либо если вы обращаетесь к корневому адресу API, а не к конкретному методу (например, к /v1/ вместо /v1/user_info).
Убедитесь, что вы используете правильный адрес сервера (api.exmo.me) и что он доступен с вашего компьютера или сервера 1С.
Следуя этой инструкции, вы сможете успешно интегрировать вашу систему на 1С с API биржи EXMO и автоматизировать торговые операции или получение аналитических данных.