[Разработка веб-сайтов, JavaScript] Юридически значимый электронный документ (для РК) из веб формы без серверного кода
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
В этой статье я покажу как реализовать формирование юридически значимого электронного документа в веб интерфейсе без необходимости дорабатывать бекенд. Это может быть интересно тем, кто столкнулся, к примеру, со следующими задачами и ограничен в ресурсах и времени:
- необходимо добавить на сайт предприятия возможность подавать официальные заявки или обращения;
- необходимо добавить в веб интерфейс портала возможность подписывать договор присоединения;
- необходимо реализовать онлайн приемную.
В качестве приятного бонуса — возможность получать подписанные ЭЦП документы на электронную почту.
Речь будет идти о сертификатах ЭЦП, выпущенных НУЦ РК.
Задачу я сформулирую следующим образом: на основе заранее согласованного шаблона сформировать в веб интерфейсе электронный документ, предоставить возможность подписать его ЭЦП, передать его для обработки группе менеджеров и обеспечить юридическую значимость в соответствии с законодательством РК.
Я буду использовать:
- Vue.js для удобства разработки (постараюсь не писать ничего специфического, так, чтобы можно было легко переключиться на любой другой);
- Bootstrap для базового оформления (его практически не будет заметно);
- axios для упрощения сетевого взаимодействия;
- pdfmake для создания PDF из JS;
- ncalayer-js-client для взаимодействия с NCALayer;
- SIGEX для проверки подписей и отправки документов по электронной почте.
Для реализации мне потребуются:
- шаблон электронного документа, состоящий из фиксированной части и полей, которые должен заполнять пользователь;
- действующий сертификат ЭЦП НУЦ РК;
- установленный NCALayer.
В самой статье я приведу только ключевые части кода, а с полной реализацией можно ознакомиться тут: https://github.com/sigex-kz/example-sign-web-form
Веб форма
В первую очередь размещу на странице веб форму, в которую пользователи будут вводить данные:
<form v-on:submit.prevent="compilePDF">
<h2>{{ formHeader }}</h2>
<p>{{ formIntro }}</p>
<div v-for="formItem in formItems" class="form-group">
<label>{{ formItem.label }}</label>
<input v-model="formItem.value" type="text" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Сформировать документ</button>
</form>
Фиксированные части формы буду заполнять в объекте данных Vue.js для того, чтобы их можно было использовать и в HTML и в PDF:
new Vue({
...
data: {
formHeader: 'Документ №1',
formIntro: 'Этот документ сформирован в браузере из данных веб формы, является примером, он никого ни к чему не обязывает и ничего не гарантирует, несмотря на то, что он может быть подписан ЭЦП.',
formItems: [
{ label: 'Первый вопрос', value: '', },
{ label: 'Второй вопрос', value: '', },
{ label: 'Третий вопрос', value: '', },
],
...
},
...
Генерация PDF в JS
Для формирования PDF воспользуюсь библиотекой pdfmake, она создает PDF файл из определения — объекта JS.
Сначала сформирую объект определения и наполню его данными, после этого передам его в pdfmake и получу байты PDF файла в base64 кодировке:
async compilePDF() {
const pdfDefinition = {
content: [
{ text: this.formHeader, fontSize: 20, bold: true, alignment: 'center', margin: [ 0, 0, 0, 20 ] },
{ text: this.formIntro, fontSize: 15, margin: [ 0, 0, 0, 20 ] },
],
};
for (const formItem of this.formItems) {
pdfDefinition.content.push(`${formItem.label}: ${formItem.value}`);
}
this.dataB64 = await new Promise((resolve) => {
const pdfDocGenerator = pdfMake.createPdf(pdfDefinition);
pdfDocGenerator.getBase64(resolve);
});
},
Подписание PDF цифровой подписью
Чтобы повысить доверие пользователей к разрабатываемой системе, предоставлю им возможность ознакомиться с подписываемым документом, разместив на странице ссылку на скачивание сформированного документа:
<p>Вы подписываете документ <a v-bind:href="`data:application/octet-stream;base64,${dataB64}`" target="_blank" v-bind:download="title">{{ title }}</a>.</p>
НУЦ РК предоставляет сертифицированное средство ЭЦП — приложение NCALayer, его и буду использовать для формирования подписи. NCALayer — это WebSocket сервер, чтобы не писать обработку отправки и получения команд вручную, воспользуюсь библиотекой ncalayer-js-client.
NCALayer поддерживает, как файловые хранилища ключей ЭЦП, так и защищенные аппаратные хранилища (токены и карты). Чтобы не перегружать пользователя излишними вопросами в первую очередь спрошу обнаружил ли NCALayer аппаратные хранилища. В том случае, если аппаратных хранилищ не обнаружено, переключусь на файловое:
const storageTypes = await this.ncaLayer.getActiveTokens();
if (storageTypes.length == 0) {
this.storageType = 'PKCS12';
} else {
this.storageType = storageTypes[0];
}
Теперь можно подписать PDF. В зависимости от типа запрошенного хранилища, NCALayer отобразит соответствующий пользовательский интерфейс и завершит процедуру:
const signature = await this.ncaLayer.createCMSSignatureFromBase64(this.storageType, this.dataB64);
В том случае, если все прошло хорошо, на данный момент у меня имеются:
- электронный документ в виде PDF файла;
- цифровая подпись под электронным документом.
Проверка подписи и пересылка электронного документа по электронной почте
В соответствии с Законом "Об электронном документе и электронной цифровой подписи" и Правилами проверки подлинности электронной цифровой подписи, для обеспечения юридической значимости электронного документа информационная система должна выполнить проверку подписи под документом в момент его приема.
Я воспользуюсь API сервиса SIGEX для выполнения проверки, а сервис обеспечит возможность долгосрочного хранения электронного документа путем получения метки времени и информации о статусе сертификата. Так же я запрошу отправку уведомления по электронной почте.
let response = await axios.post(
`${this.sigexURL}/api`,
{
title: this.title,
description: this.description,
signature,
emailNotifications: { to: ['some-manager@example.kz', this.email] },
},
);
this.sigexId = response.data.documentId;
Я запрошу отправку уведомлений не только своим коллегам менеджерам, но так же на тот адрес, который указал пользователь, так как пользователю подписанный электронный документ тоже может быть нужен.
Вторым этапом передам сервису на проверку подписанный документ:
const dataToSend = Uint8Array.from(atob(this.dataB64), c => c.charCodeAt(0)).buffer;
response = await axios.post(
`${this.sigexURL}/api/${this.sigexId}/data`,
dataToSend,
{
headers: { 'Content-Type': 'application/octet-stream' },
},
);
Сервис не хранит самих подписанных документов, только электронные подписи под ними. Электронные документы будут отправлены по электронной почте на указанные адреса.
Итог
Проверим соответствие поставленной задаче:
- на основе заранее согласованного шаблона сформировать в веб интерфейсе электронный документ — реализовано в виде статической веб страницы и небольшого количества JS кода;
- предоставить возможность подписать его ЭЦП — реализовано с использованием рекомендуемого сертифицированного ПО;
- передать его для обработки группе менеджеров — реализовано путем отправки подписанных документов на электронный адрес ответственных менеджеров;
- обеспечить юридическую значимость в соответствии с законодательством РК — реализовано с помощью API сервиса SIGEX.
===========
Источник:
habr.com
===========
Похожие новости:
- [JavaScript, Программирование, ReactJS] React-компоненты шаблонов проектирования (перевод)
- [Open source, JavaScript, Программирование, TypeScript] 5 фактов о том, как Microsoft приватизировала открытый исходный код, убивая JavaScript в процессе (перевод)
- [Разработка веб-сайтов, .NET, C#, Функциональное программирование] От внедрения зависимостей к отказу от зависимостей
- [Разработка веб-сайтов, JavaScript, Клиентская оптимизация, ReactJS] iresine, нормализация данных на клиенте
- [JavaScript, Node.JS, Angular, TypeScript] Angular Universal: проблемы реального приложения
- [JavaScript] Квест для прогеров на Java script
- [Высокая производительность, Разработка веб-сайтов, PHP, Программирование] Теория программирования: пакетные принципы и метрики
- [JavaScript, Программирование] Как написать интерфейс пользователя (UI) PlayStation 5 на JavaScript (перевод)
- [Информационная безопасность, JavaScript] JavaScript prototype pollution: практика поиска и эксплуатации
- [Веб-дизайн, Разработка веб-сайтов, Интерфейсы, Usability, Дизайн] Метод Content Brick. Как создать структуру веб-сайта быстрее и проще чем это было раньше? (перевод)
Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_javascript, #_kazahstan (казахстан), #_etsp (эцп), #_tsifrovaja_podpis (цифровая подпись), #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_javascript
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:26
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
В этой статье я покажу как реализовать формирование юридически значимого электронного документа в веб интерфейсе без необходимости дорабатывать бекенд. Это может быть интересно тем, кто столкнулся, к примеру, со следующими задачами и ограничен в ресурсах и времени:
В качестве приятного бонуса — возможность получать подписанные ЭЦП документы на электронную почту. Речь будет идти о сертификатах ЭЦП, выпущенных НУЦ РК. Задачу я сформулирую следующим образом: на основе заранее согласованного шаблона сформировать в веб интерфейсе электронный документ, предоставить возможность подписать его ЭЦП, передать его для обработки группе менеджеров и обеспечить юридическую значимость в соответствии с законодательством РК. Я буду использовать:
Для реализации мне потребуются:
В самой статье я приведу только ключевые части кода, а с полной реализацией можно ознакомиться тут: https://github.com/sigex-kz/example-sign-web-form Веб форма В первую очередь размещу на странице веб форму, в которую пользователи будут вводить данные: <form v-on:submit.prevent="compilePDF">
<h2>{{ formHeader }}</h2> <p>{{ formIntro }}</p> <div v-for="formItem in formItems" class="form-group"> <label>{{ formItem.label }}</label> <input v-model="formItem.value" type="text" class="form-control"> </div> <button type="submit" class="btn btn-primary">Сформировать документ</button> </form> Фиксированные части формы буду заполнять в объекте данных Vue.js для того, чтобы их можно было использовать и в HTML и в PDF: new Vue({
... data: { formHeader: 'Документ №1', formIntro: 'Этот документ сформирован в браузере из данных веб формы, является примером, он никого ни к чему не обязывает и ничего не гарантирует, несмотря на то, что он может быть подписан ЭЦП.', formItems: [ { label: 'Первый вопрос', value: '', }, { label: 'Второй вопрос', value: '', }, { label: 'Третий вопрос', value: '', }, ], ... }, ... Генерация PDF в JS Для формирования PDF воспользуюсь библиотекой pdfmake, она создает PDF файл из определения — объекта JS. Сначала сформирую объект определения и наполню его данными, после этого передам его в pdfmake и получу байты PDF файла в base64 кодировке: async compilePDF() {
const pdfDefinition = { content: [ { text: this.formHeader, fontSize: 20, bold: true, alignment: 'center', margin: [ 0, 0, 0, 20 ] }, { text: this.formIntro, fontSize: 15, margin: [ 0, 0, 0, 20 ] }, ], }; for (const formItem of this.formItems) { pdfDefinition.content.push(`${formItem.label}: ${formItem.value}`); } this.dataB64 = await new Promise((resolve) => { const pdfDocGenerator = pdfMake.createPdf(pdfDefinition); pdfDocGenerator.getBase64(resolve); }); }, Подписание PDF цифровой подписью Чтобы повысить доверие пользователей к разрабатываемой системе, предоставлю им возможность ознакомиться с подписываемым документом, разместив на странице ссылку на скачивание сформированного документа: <p>Вы подписываете документ <a v-bind:href="`data:application/octet-stream;base64,${dataB64}`" target="_blank" v-bind:download="title">{{ title }}</a>.</p>
НУЦ РК предоставляет сертифицированное средство ЭЦП — приложение NCALayer, его и буду использовать для формирования подписи. NCALayer — это WebSocket сервер, чтобы не писать обработку отправки и получения команд вручную, воспользуюсь библиотекой ncalayer-js-client. NCALayer поддерживает, как файловые хранилища ключей ЭЦП, так и защищенные аппаратные хранилища (токены и карты). Чтобы не перегружать пользователя излишними вопросами в первую очередь спрошу обнаружил ли NCALayer аппаратные хранилища. В том случае, если аппаратных хранилищ не обнаружено, переключусь на файловое: const storageTypes = await this.ncaLayer.getActiveTokens();
if (storageTypes.length == 0) { this.storageType = 'PKCS12'; } else { this.storageType = storageTypes[0]; } Теперь можно подписать PDF. В зависимости от типа запрошенного хранилища, NCALayer отобразит соответствующий пользовательский интерфейс и завершит процедуру: const signature = await this.ncaLayer.createCMSSignatureFromBase64(this.storageType, this.dataB64);
В том случае, если все прошло хорошо, на данный момент у меня имеются:
Проверка подписи и пересылка электронного документа по электронной почте В соответствии с Законом "Об электронном документе и электронной цифровой подписи" и Правилами проверки подлинности электронной цифровой подписи, для обеспечения юридической значимости электронного документа информационная система должна выполнить проверку подписи под документом в момент его приема. Я воспользуюсь API сервиса SIGEX для выполнения проверки, а сервис обеспечит возможность долгосрочного хранения электронного документа путем получения метки времени и информации о статусе сертификата. Так же я запрошу отправку уведомления по электронной почте. let response = await axios.post(
`${this.sigexURL}/api`, { title: this.title, description: this.description, signature, emailNotifications: { to: ['some-manager@example.kz', this.email] }, }, ); this.sigexId = response.data.documentId; Я запрошу отправку уведомлений не только своим коллегам менеджерам, но так же на тот адрес, который указал пользователь, так как пользователю подписанный электронный документ тоже может быть нужен. Вторым этапом передам сервису на проверку подписанный документ: const dataToSend = Uint8Array.from(atob(this.dataB64), c => c.charCodeAt(0)).buffer;
response = await axios.post( `${this.sigexURL}/api/${this.sigexId}/data`, dataToSend, { headers: { 'Content-Type': 'application/octet-stream' }, }, ); Сервис не хранит самих подписанных документов, только электронные подписи под ними. Электронные документы будут отправлены по электронной почте на указанные адреса. Итог Проверим соответствие поставленной задаче:
=========== Источник: habr.com =========== Похожие новости:
Разработка веб-сайтов ), #_javascript |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:26
Часовой пояс: UTC + 5