En este artículo, mostraré cómo implementar la formación de un documento electrónico legalmente significativo en la interfaz web sin la necesidad de modificar el backend. Esto puede ser de interés para quienes se enfrentan, por ejemplo, con las siguientes tareas y tienen recursos y tiempo limitados:
- es necesario agregar la capacidad de enviar solicitudes oficiales o apelaciones al sitio web de la empresa;
- es necesario agregar la posibilidad de firmar un acuerdo de conexión a la interfaz web del portal
- es necesario implementar una recepcionista en línea.
Como una buena ventaja, la capacidad de recibir documentos firmados por EDS por correo electrónico.
Se tratará de los certificados EDS emitidos por la NCA RK .
Formularé la tarea de la siguiente manera: sobre la base de una plantilla previamente acordada, crearé un documento electrónico en la interfaz web, brindaré la oportunidad de firmarlo con un EDS, transferirlo para su procesamiento a un grupo de gerentes y asegurar la importancia legal en de conformidad con la legislación de la República de Kazajstán.
Usaré:
- Vue.js para facilitar el desarrollo (intentaré no escribir nada específico, para que pueda cambiar fácilmente a cualquier otro);
- Bootstrap para un estilo básico (casi invisible);
- axios para simplificar la creación de redes;
- 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);
});
},
, , :
<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' },
},
);
, . .
:
- generar un documento electrónico en la interfaz web basado en una plantilla previamente acordada, implementada como una página web estática y una pequeña cantidad de código JS;
- brindar la oportunidad de firmar su EDS - implementado utilizando el software certificado recomendado;
- transferirlo a un grupo de gerentes para su procesamiento, implementado enviando documentos firmados a la dirección de correo electrónico de los gerentes responsables;
- garantizar la importancia legal de acuerdo con la legislación de la República de Kazajstán, implementada utilizando la API del servicio SIGEX.