1С JAVASCRIPT. 1С NODE JS
- Опубликовано Илья Низамов
- Разделы Blog
- Дата 19.04.2020
- Комментарии 2 комментария
Всем привет, с вами Низамов Илья! 1С позволяет нам расширять возможности платформы с помощью внешних компонент. Данная технология позволяет нам делать кроссплатформенные компоненты, которые будут работать на любых операционных системах.
Помимо внешних компонент, возможности 1С можно расширять и другими способами, в том числе и с помощью JavaScript. В данной статье рассмотрим интеграцию 1С JAVASCRIPT как на клиенте, так и на сервере.
Возможности JS я описывать не буду. Это достаточно мощный язык с развитым комьюнити и множеством готовых библиотек, уроков по нему предостаточно на Youtube.
В данном примере я буду его использовать для расчета hash с использованием hmac sha256. В интернете я нашел много примеров на 1С, но все они неправильно рассчитывали hash для доступа к REST API Amazon S3. Поэтому я стал использовать COM компоненту «System.Text.UTF8Encoding» и «System.Security.Cryptography.HMACSHA256»
Для начала я рекомендую посмотреть вам мои уроки, в которых я описываю процесс доступа к REST API Amazon.
Amazon S3 + 1C. Часть 1. Интерфейс
Amazon S3 + 1C. Часть 2. Получение списка файлов
В уроках получилась вот такая функция:
Функция HMAC_SHA256(InKey, String)
Текст = Новый COMОбъект("System.Text.UTF8Encoding");
Криптография = Новый COMОбъект("System.Security.Cryptography.HMACSHA256");
Если ТипЗнч(InKey) = Тип("Строка") Тогда
SecKey = Текст.GetBytes_4(InKey);
Иначе
SecKey = InKey;
КонецЕсли;
Криптография.Key = SecKey;
Возврат Криптография.ComputeHash_2(Текст.GetBytes_4(String));
КонецФункции
Но проблема данной функции в том, что она работает только на Windows. Для кроссплатформенности я решил использовать JavaScript.
1С JAVASCRIPT НА КЛИЕНТЕ
Для расчета хешей на JavaScript есть отличная библиотека Crypto-js. Вот ее и будем использовать. Саму функцию я разработал и протестировал в IDE WebStorm, она очень простая.
function getSignatureKey(JSONData) {
var data1s = JSON.parse(JSONData);
var kDate = CryptoJS.HmacSHA256(data1s.dateStamp, "AWS4" + data1s.key);
var kRegion = CryptoJS.HmacSHA256(data1s.regionName, kDate);
var kService = CryptoJS.HmacSHA256(data1s.serviceName, kRegion);
var kSigning = CryptoJS.HmacSHA256("aws4_request", kService);
var kSignature = CryptoJS.HmacSHA256(data1s.stringToSign, kSigning);
return JSON.stringify({"hash": kSignature.toString(CryptoJS.enc.Hex)});
}
В функцию передаем параметры для расчета и внутри нее вызываем необходимую функцию из библиотеки. Обратно отдаем результат в формате JSON.
Теперь эту функцию надо как-то вызвать из 1С. Для этого создаем реквизит формы с типом Строка и размещаем его на форме. Вид у поля указываем «Поле HTML документа».
Саму функцию JS я разместил в макете обработки. Тип макета «Текстовый документ» и скопировал туда функцию JS.
Как видите, в обработке присутствуют еще несколько макетов. Они содержат зависимые библиотеки на JavaScript. Все эти библиотеки так же скопированы в макеты типа «Текстовый документ»
Для доступа к функции JS, надо сформировать простой html документ. Делаю я это при создании формы.
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
hmac = ПолучитьТекстИзМакета("hmac");
cryptojs = ПолучитьТекстИзМакета("cryptojs");
encbase64 = ПолучитьТекстИзМакета("encbase64");
hmacsha256 = ПолучитьТекстИзМакета("hmacsha256");
ШаблонHTML = "
|<!DOCTYPE html>
|<html lang=""en"">
|<head>
| <meta charset=""UTF-8"">
| <title>HMAC</title>
| <script>%1</script>
| <script>%2</script>
| <script>%3</script>
| <script>%4</script>
|</head>
|<body>
|</body>
|</html>";
ПолеHTML = СтрШаблон(ШаблонHTML, cryptojs, hmacsha256, encbase64, hmac);
КонецПроцедуры
Сначала получаем код скриптов, а потом подставляем его в наш шаблон между тегами <script></script>
Теперь мы можем вызвать нашу функцию JS, но только из клиентских функций.
&НаКлиенте
Функция HMAC_JS(Данные, StringToSign)
ОкноДокумента = ЭтаФорма.Элементы.ПолеHTML.Документ.defaultView;
Если ОкноДокумента = Неопределено Тогда
Возврат "";
КонецЕсли;
ДанныеСтруктура = Новый Структура;
ДанныеСтруктура.Вставить("key", Данные["SecretAccessKey"]);
ДанныеСтруктура.Вставить("dateStamp", Данные["date"]);
ДанныеСтруктура.Вставить("regionName", Данные["Region"]);
ДанныеСтруктура.Вставить("serviceName", "s3");
ДанныеСтруктура.Вставить("stringToSign", StringToSign);
ДанныеJSON = СформироватьJSON(ДанныеСтруктура);
Результат = ПрочитатьДанныеИзJSON(ОкноДокумента.getSignatureKey(ДанныеJSON));
Возврат Результат["hash"];
КонецФункции
JAVASCRIPT НА СЕРВЕРЕ
Но некоторым возможно понадобится использовать данный расчет на сервере. К сожалению, JS можно без костылей использовать только на клиенте. Для использования на сервере у вас должен стоять Node.js.
Node.js — это JavaScript-окружение построенное на движке Chrome V8, спроектирован для построения масштабируемых сетевых приложений. Это просто офигенно быстрый сервер, который работает на всех платформах. Реализацию простейшего серверного скрипта вы можете посмотреть по ссылке. Запускать эти скрипты вы можете в командной строке.
Ниже приведен код моего скрипта. Данный скрипт запускает локальный web сервер на 3000 порту. Принимает GET запросы для проверки соединения и POST запросы для обработки данных.
function amazonSig(JSONData) {
MyObject = {
res: null,
err: null
};
try {
var CryptoJS = require("crypto-js");
var data1s = JSON.parse(JSONData);
var kDate = CryptoJS.HmacSHA256(data1s.dateStamp, "AWS4" + data1s.key);
var kRegion = CryptoJS.HmacSHA256(data1s.regionName, kDate);
var kService = CryptoJS.HmacSHA256(data1s.serviceName, kRegion);
var kSigning = CryptoJS.HmacSHA256("aws4_request", kService);
var kSignature = CryptoJS.HmacSHA256(data1s.stringToSign, kSigning);
MyObject.res = kSignature.toString(CryptoJS.enc.Hex);
} catch (e) {
MyObject.err = e.toString();
}
return MyObject;
}
var http = require("http");
http.createServer(function(request, response){
const { headers, method, url } = request;
let body = [];
// Устанавливаем заголовки
response.setHeader('Content-Type', 'application/json');
request.on('error', (err) => {
console.error(err);
response.statusCode = 404;
}).on('data', (chunk) => {
// Получаем тело запроса
body.push(chunk);
}).on('end', () => {
// Преобразуем тело запроса в строку
body = Buffer.concat(body).toString();
if (method == "POST") {
// Расчитываем hash и возвращаем результат
var res = amazonSig(body);
if ( res.err != null) {
response.statusCode = 404;
} else {
response.end(JSON.stringify(res));
}
} else {
response.end("OK");
}
});
}).listen(3000);
В 1С скрипт хранится макете обработки в виде zip архива. Он распаковывается во временную папку при запуске формы и из 1С выполняется команда для его запуска.
&НаСервереБезКонтекста
Функция ЗапуститьСерверNodeJSНаСервере()
Результат = ВыполнитьЗапросКСерверуNodeJS("GET");
Если Результат = Ложь ИЛИ Результат = Неопределено Тогда
Каталог = КаталогВременныхФайлов() + "nodesrv\";
ИмяАрхива = Каталог + "srv.zip";
ДД = Обработки.AmazonS3.ПолучитьМакет("nodejs");
ДД.Записать(ИмяАрхива);
Архив = Новый ЧтениеZipФайла(ИмяАрхива);
Архив.ИзвлечьВсе(Каталог);
ЗапуститьПриложение("node " + Каталог + "cp.js");
Результат = ВыполнитьЗапросКСерверуNodeJS("GET");
Если Результат = Неопределено Тогда
Возврат Ложь;
КонецЕсли;
КонецЕсли;
Возврат Истина;
КонецФункции
Потом идет отправка GET запроса к нему и если все ОК, то наш мини сервис готов к обработке данных.
&НаСервереБезКонтекста
Функция HMAC_JSСервер(Данные, StringToSign)
Каталог = КаталогВременныхФайлов();
ДанныеСтруктура = Новый Структура;
ДанныеСтруктура.Вставить("key", Данные["SecretAccessKey"]);
ДанныеСтруктура.Вставить("dateStamp", Данные["date"]);
ДанныеСтруктура.Вставить("regionName", Данные["Region"]);
ДанныеСтруктура.Вставить("serviceName", "s3");
ДанныеСтруктура.Вставить("stringToSign", StringToSign);
ДанныеJSON = СформироватьJSONСервер(ДанныеСтруктура);
Ответ = ВыполнитьЗапросКСерверуNodeJS("POST", ДанныеJSON);
Если НЕ Ответ = Неопределено Тогда
ДанныеJS = ПрочитатьДанныеИзJSONНаСервере(Ответ);
Возврат ДанныеJS["res"];
КонецЕсли;
Возврат Неопределено;
КонецФункции
&НаСервереБезКонтекста
Функция ВыполнитьЗапросКСерверуNodeJS(ВидЗапроса, Данные = Неопределено)
Попытка
HTTPСоединение = Новый HTTPСоединение("localhost", 3000,,,, 2);
HTTPЗапрос = Новый HTTPЗапрос("/");
Если НЕ Данные = Неопределено Тогда
HTTPЗапрос.УстановитьТелоИзСтроки(Данные);
КонецЕсли;
Ответ = HTTPСоединение.ВызватьHTTPМетод(ВидЗапроса, HTTPЗапрос);
Если Ответ.КодСостояния = 200 Тогда
Если ВидЗапроса = "POST" Тогда
Возврат Ответ.ПолучитьТелоКакСтроку();
Иначе
Возврат Истина;
КонецЕсли;
Иначе
Возврат Неопределено;
КонецЕсли;
Исключение
Возврат Неопределено;
КонецПопытки;
Возврат Неопределено;
КонецФункции
Теперь обработка отправки и получения файлов с облака Amazon работает на всех системах. Правильнее конечно написать на C++ внешнюю Native компоненту, но это уже будет в другой статье.
Разработать Native внешнюю компоненты вы сможете ознакомившись с циклом статей. Начните с этой.
Метка:WEB
2 Комментария
Спс. А как остановить сервер? (и как закрыть окно node )
Я умею программировать только на 1С и по-этому считаю, что данная статья шляпа, и мне ниче не понятно