Saltar al contenido principal

Integrar el firmante de Legalesign en su sitio web

Habilitar para su equipo

El componente Firmante requiere activación. Contacte con soporte para habilitarlo para su equipo.

Versión actual: v1.1.7 — registro de cambios

El firmante de Legalesign es un componente web independiente de la plataforma que ofrece una experiencia completa y fluida para la firma de documentos desde su propia aplicación. Funciona con HTML puro, React, Vue, Angular o cualquier framework web.

Inserte este componente donde sus usuarios necesiten firmar documentos — dentro de un CRM, portal de clientes o cualquier aplicación interna que renderice HTML.

Instalación​

Cárguelo directamente desde el CDN (no se requiere instalación):

<script type="module" src="https://cdn.legalesign.io/signer/latest/ls-signer.esm.js"></script>

Instalación en React​

Instale mediante un gestor de paquetes:

npm install legalesign-signer
# or
pnpm add legalesign-signer

Integración Básica​

HTML y JavaScript​

<ls-signer
recipient-id="abc123"
private-key="key"
session-id="session"
></ls-signer>

<script>
const signer = document.querySelector('ls-signer');
signer.addEventListener('signingSuccess', (e) => console.log('Signed:', e.detail.eventType, e.detail.documentId));
signer.addEventListener('signingFail', (e) => console.error('Failed:', e.detail.failureReason, e.detail.error));
signer.addEventListener('fieldChange', (e) => console.log('Field event:', e.detail.eventType));
</script>

React​

import { useEffect, useState } from 'react';
import { LsSigner } from 'legalesign-signer/react';
import 'legalesign-signer/react.css';

function SigningPage() {
const [signerData, setSignerData] = useState(null);

useEffect(() => {
fetch('/your-backend/to-get-token')
.then(res => res.json())
.then(setSignerData);
}, []);

if (!signerData) return <p>Loading...</p>;

return (
<LsSigner
recipientId={signerData.recipientId}
privateKey={signerData.token}
sessionId={signerData.sessionId}
onSuccess={({ eventType, documentId }) => console.log(eventType, documentId)}
onFail={({ eventType, failureReason, error }) => console.error(eventType, failureReason, error)}
onChange={({ eventType, uuid, saved, field, document }) => console.log('Event:', eventType)}
/>
);
}

React requiere react y react-dom (v18 o v19) como dependencias pares.

Vue​

<template>
<ls-signer
ref="signer"
:recipient-id="recipientId"
:private-key="privateKey"
:session-id="sessionId"
/>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount } from 'vue';

const signer = ref(null);

function handleSuccess(e) {
console.log('Signed:', e.detail);
}
function handleFail(e) {
console.error('Failed:', e.detail);
}

onMounted(() => {
signer.value.addEventListener('signingSuccess', handleSuccess);
signer.value.addEventListener('signingFail', handleFail);
});

onBeforeUnmount(() => {
signer.value?.removeEventListener('signingSuccess', handleSuccess);
signer.value?.removeEventListener('signingFail', handleFail);
});
</script>
sugerencia

Si utiliza Vue con Vite, añada isCustomElement: (tag) => tag.startsWith('ls-') a la configuración del plugin Vue para suprimir advertencias de elementos desconocidos.

aviso

Vue 3 convierte a minúsculas los nombres de eventos en elementos personalizados, por lo que @signingSuccess no funcionará. Use addEventListener en la referencia al elemento como se muestra arriba.

Nuxt 3

Envuelva <ls-signer> en <ClientOnly> para evitar errores SSR. Añada la configuración para elementos personalizados en nuxt.config.ts:

export default defineNuxtConfig({
vue: {
compilerOptions: {
isCustomElement: (tag) => tag.startsWith('ls-'),
},
},
});

Autenticación​

El componente firmante requiere un token de corta duración desde su backend. Hay dos opciones:

  1. GraphQL generateComponentToken — Llame con component: LS_SIGNER y ya sea un recipientId o sessionId en el ámbito del firmante (proporcione uno, no ambos).
  2. REST API — Llame a GET /signer/{signerId}/component-token/ con su clave API.

Ambos retornan el token y sessionId necesarios para el componente. Consulte Autorización de Widget para el flujo completo del token en el servidor.

Opción 1: GraphQL (Node.js)​

Usando recipientId (lo más común — úselo cuando conozca al destinatario pero aún no tenga sesión):

const response = await fetch('https://graphql.uk.legalesign.com/graphql', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${process.env.LEGALESIGN_API_KEY}`,
},
body: JSON.stringify({
query: `mutation MintSignerToken($input: GenerateComponentTokenInput!) {
generateComponentToken(input: $input) {
token
tokenType
sessionId
expiresIn
expiresAt
}
}`,
variables: {
input: {
component: 'LS_SIGNER',
signer: { recipientId: '<recipient-id>' }
}
}
})
});

const { data } = await response.json();
const { token, sessionId } = data.generateComponentToken;

Alternativamente, si ya tiene un sessionId de una llamada previa:

variables: {
input: {
component: 'LS_SIGNER',
signer: { sessionId: '<session-id>' }
}
}

Opción 2: REST API​

const response = await fetch(
`https://eu-api.legalesign.com/api/v1/signer/${signerId}/component-token/`,
{
headers: {
Authorization: `Bearer ${process.env.LEGALESIGN_API_KEY}`,
},
}
);

const { token, sessionId } = await response.json();

Pase token como private-key y sessionId como session-id al componente.

Atributos Requeridos​

AtributoTipoDescripción
recipient-idstringIdentificador del destinatario (base64, prefijo rec, o UUID)
private-keystringToken retornado por generateComponentToken
session-idstringID de sesión retornado por generateComponentToken

Atributos Opcionales​

AtributoTipoPredeterminadoDescripción
colourstringblueNombre del color del tema (ver Theming)
stylestring``Alteraciones de estilo (ver Custom CSS)
brandingbooleantrueMostrar branding de Legalesign. Configure false para retirarlo.
languagestring—Forzar un idioma específico y ocultar el selector de idioma (ver Internationalisation)

Eventos​

Propiedad ReactEvento del componente webeventTypeCuándo
onSuccesssigningSuccess"success"Documento firmado exitosamente
onFailsigningFail"failure"Firma fallida, rechazada, expiró, cancelada, eliminada, retirada o ya completada en otro lugar
onChangefieldChange"ready"Documento e imágenes completamente cargados
onChangefieldChange"save"Un valor de campo fue guardado
onChangefieldChange"select"Un campo fue seleccionado o enfocado

onSuccess / signingSuccess​

Se dispara cuando el destinatario firma el documento con éxito.

{
eventType: 'success';
documentId: string; // UUID of the signed document
recipientId: string; // UUID of the recipient
}

React:

<LsSigner
onSuccess={({ eventType, documentId, recipientId }) => {
console.log(eventType); // "success"
console.log(documentId);
console.log(recipientId);
}}
/>

Componente web:

signer.addEventListener('signingSuccess', (e) => {
console.log(e.detail.eventType); // "success"
console.log(e.detail.documentId);
console.log(e.detail.recipientId);
});

onFail / signingFail​

Se dispara cuando la firma falla — ya sea por rechazo del documento o error durante el proceso de firma (ej. error de red, sesión expirada, conflicto de estado del documento).

{
eventType: 'failure';
failureReason: FailureReason;
error: string; // Human-readable error message
documentId?: string; // UUID of the document (if available)
recipientId: string; // UUID of the recipient
}
failureReasonCausa
documentExpiredEl state del documento es "expired" o la fecha de expires está en el pasado
sessionExpiredLa API retornó 401 o 403 al cargar el documento
cancelledEl state del documento es "cancelled"
deletedLa bandera is_deleted del documento es true
rejectedEl destinatario rechazó el documento (is_rejected es true)
removedLa API retornó 404 — el documento ya no existe
documentCompletedLa API de firma retornó completed — el documento ya fue firmado, probablemente en otro navegador o dispositivo. El componente muestra un mensaje informativo al destinatario en lugar de un error.
signingErrorCualquier otro error durante la carga o firma

React:

<LsSigner
onFail={({ eventType, failureReason, error, documentId, recipientId }) => {
console.log(eventType); // "failure"
console.log(failureReason); // e.g. "documentExpired"
console.log(error);
}}
/>

Componente web:

signer.addEventListener('signingFail', (e) => {
console.log(e.detail.eventType); // "failure"
console.log(e.detail.failureReason); // e.g. "documentExpired"
console.log(e.detail.error);
});

onChange / fieldChange​

Los tres valores de eventType comparten el mismo evento. Use eventType para distinguir.

eventType: "ready"​

Se dispara una sola vez cuando el documento y todas las imágenes de página están completamente cargadas y la interfaz de firma está lista para interactuar.

{
eventType: 'ready';
document: {
documentId: string; // UUID of the document
name: string; // Document name
state: string; // Document state (e.g. "signing")
recipientId: string; // UUID of the recipient
recipientRole?: string; // Role of the recipient (e.g. "witness")
pageCount: number; // Number of pages
expires?: string; // Expiry date (ISO string, if set)
isApprover: boolean; // Whether the recipient is an approver
isWitness: boolean; // Whether the recipient is a witness
canReassign: boolean; // Whether the recipient can reassign
doOfferReject: boolean; // Whether the reject option is shown
};
}

React:

<LsSigner
onChange={({ eventType, document }) => {
if (eventType === 'ready') {
console.log('Ready to sign:', document.documentId, document.name);
console.log('Pages:', document.pageCount);
console.log('Expires:', document.expires);
}
}}
/>

Componente web:

signer.addEventListener('fieldChange', (e) => {
if (e.detail.eventType === 'ready') {
console.log('Ready to sign:', e.detail.document.documentId, e.detail.document.name);
}
});

eventType: "save"​

Se dispara después de que un valor de campo haya sido guardado en el servidor.

{
eventType: 'save';
uuid: string; // UUID of the field
saved: boolean; // Whether the save was successful
field: Record<string, any>; // Full field object (see Field Properties below)
}

React:

<LsSigner
onChange={({ eventType, uuid, saved, field }) => {
if (eventType === 'save') {
console.log(uuid, saved, field.value);
}
}}
/>

Componente web:

signer.addEventListener('fieldChange', (e) => {
if (e.detail.eventType === 'save') {
console.log(e.detail.uuid, e.detail.saved, e.detail.field.value);
}
});

eventType: "select"​

Se dispara cuando un campo es seleccionado o enfocado — desencadenado por un click del usuario, navegación por teclado, avance automático, o interacción con la barra lateral.

{
eventType: 'select';
uuid: string; // UUID of the selected field
field: Record<string, any>; // Full field object (see Field Properties below)
}

React:

<LsSigner
onChange={({ eventType, uuid, field }) => {
if (eventType === 'select') {
console.log('selected', uuid, field.fieldtype);
}
}}
/>

Componente web:

signer.addEventListener('fieldChange', (e) => {
if (e.detail.eventType === 'select') {
console.log('selected', e.detail.uuid, e.detail.field.fieldtype);
}
});

Propiedades del Campo​

El objeto field incluido en los eventos save y select contiene las siguientes propiedades:

PropiedadTipoDescripción
uuidstringIdentificador único del campo
fieldtypestringTipo de campo (ej. "text", "signature", "date", "checkbox")
valuestringValor actual del campo
statebooleanSi el campo ha sido guardado con éxito
optionalbooleanSi el campo es opcional
pagenumberNúmero de página donde aparece el campo
labelstringEtiqueta del campo (si está configurada)
validationnumberCódigo de tipo de validación
logicactionstringTipo de acción lógica ("1" = radio, "2" = suma, "3" = condicional)
logicgroupstringIdentificador del grupo lógico
maptostringGrupo objetivo para la lógica (campos controladores)
autobooleanSi el campo se autocompleta
dirtybooleanSi el campo tiene cambios locales no guardados

Props de React​

El componente React usa props en camelCase y callbacks en lugar de eventos DOM:

PropTipoRequeridoDescripción
recipientIdstring✅Identificador del destinatario
privateKeystring✅Clave privada de la mutación generateComponentToken
sessionIdstring✅Identificador de sesión
colourLsSignerColour❌Color del tema
brandingboolean❌Mostrar branding de Legalesign. Por defecto true.
languagestring❌Forzar un idioma específico (ver Internationalisation)
onSuccess(data: { eventType: 'success'; documentId: string; recipientId: string }) => void❌Llamado al firmar exitosamente
onFail(data: { eventType: 'failure'; failureReason: FailureReason; error: string; documentId?: string; recipientId: string }) => void❌Llamado al fallar la firma
onChange(data: { eventType: 'ready' | 'save' | 'select'; document?: DocumentSummary; uuid?: string; saved?: boolean; field?: Record<string, any> }) => void❌Llamado en eventos de campo y cuando el documento está listo

Manejador universal (depuración y prototipado)​

Dado que cada evento incluye eventType, puede enlazar una única función a todos los eventos:

React:

const handleSignerEvent = (e) => {
switch (e.eventType) {
case 'success': console.log('Signed:', e.documentId); break;
case 'failure': console.log('Failed:', e.failureReason, e.error); break;
case 'ready': console.log('Ready:', e.document?.name); break;
case 'save': console.log('Saved field:', e.uuid, e.saved); break;
case 'select': console.log('Selected field:', e.uuid); break;
}
};

<LsSigner
onSuccess={handleSignerEvent}
onFail={handleSignerEvent}
onChange={handleSignerEvent}
/>

Componente web:

const handleSignerEvent = (e) => {
switch (e.detail.eventType) {
case 'success': console.log('Signed:', e.detail.documentId); break;
case 'failure': console.log('Failed:', e.detail.failureReason, e.detail.error); break;
case 'ready': console.log('Ready:', e.detail.document?.name); break;
case 'save': console.log('Saved field:', e.detail.uuid, e.detail.saved); break;
case 'select': console.log('Selected field:', e.detail.uuid); break;
}
};

signer.addEventListener('signingSuccess', handleSignerEvent);
signer.addEventListener('signingFail', handleSignerEvent);
signer.addEventListener('fieldChange', handleSignerEvent);

Theming​

Configura un tema de color con la prop colour. Todos los tonos se derivan automáticamente.

Colores disponibles​

pink · blue · purple · indigo · teal · green · lightblue · burnt · aubergine · red · yellow · cyan · lime · trueGreen

Omitir la prop para obtener el azul por defecto.

<ls-signer colour="pink" ...></ls-signer>
<LsSigner colour="pink" ... />

La prop colour establece un atributo data-ls-theme en la raíz del componente. Las propiedades CSS personalizadas definen una escala de tonos de 10 a 100 para cada color:

TonoUso
10Fondos claros, rellenos sutiles
20Bordes sutiles
30Anillos de foco
60Color primario (botones, enlaces, estados activos)
70Estado hover
80Acentos oscuros/fuertes

CSS personalizado​

El componente expone propiedades CSS personalizadas que pueden sobrescribirse para personalizar la apariencia más allá del tema de color. Este conjunto de propiedades es limitado actualmente; contáctenos para más.

<ls-signer
style="--ls-font-family: 'Inter', sans-serif; --ls-color-primary-60: #e91e63;"
recipient-id="abc123"
private-key="key"
session-id="session"
></ls-signer>

Propiedades disponibles​

PropiedadPredeterminadoDescripción
--ls-font-family'IBM Plex Sans', sans-serifFamilia tipográfica principal
--ls-color-primary-10 a --ls-color-primary-100—Escala completa de color primario (sobrescribe tema)
--ls-color-error#f64a44Color para estado de error
--ls-color-error-light#fff0f0Fondo de error
--ls-color-success#46dbaaColor para estado de éxito
--ls-color-success-light#effff9Fondo de éxito
--ls-color-warning#fad232Color para estado de advertencia
--ls-color-warning-light#fffcefFondo de advertencia
--ls-color-border#d8d9dcColor predeterminado de borde
--ls-color-border-subtle#e0e2e5Color sutil de borde
--ls-color-bg-subtle#f7f8faColor sutil de fondo

Nota: Para inyección completa de CSS personalizado (dirigido a elementos internos directamente, sobrescribiendo tamaños de fuente, radios de borde, espaciados, etc.), esta es una función planificada futura. Por favor contacte con nosotros si está interesado.

Internacionalización​

El componente soporta 17 idiomas con traducciones incluidas en la compilación. El idioma se detecta automáticamente desde el navegador. Un selector de idioma integrado en la UI de firma permite al destinatario cambiar el idioma en cualquier momento.

Configure el atributo language para forzar un idioma específico. Cuando se proporciona, el selector integrado de idiomas se oculta y se omite la detección del navegador.

<ls-signer language="fr" recipient-id="abc123" private-key="key" session-id="session"></ls-signer>
<LsSigner language="fr" recipientId="abc123" privateKey="key" sessionId="session" />

Orden de prioridad: prop language → idioma del navegador → inglés por defecto.

CódigoIdiomaCódigoIdioma
enInglésnlNeerlandés
frFrancésfiFinés
bgBúlgaroitItaliano
esEspañolheHebreo
deAlemánsvSueco
gsGaélico escocéscyGalés
arÁrabeisIslandés
elGriegoiwHebreo (legado)
ptPortugués
roRumano

Versionado CDN​

La URL del CDN soporta números de versión latest y fijos:

<!-- Always get the most recent version (recommended) -->
<script type="module" src="https://cdn.legalesign.io/signer/latest/ls-signer.esm.js"></script>

<!-- Pin to a specific version -->
<script type="module" src="https://cdn.legalesign.io/signer/v1.1.7/ls-signer.esm.js"></script>

Recomendamos usar latest — así su integración recibirá automáticamente correcciones de errores, parches de seguridad y nuevas funciones. Use una versión fija si necesita un lanzamiento conocido durante un período de congelación QA o despliegue controlado. Vea el historial completo de versiones en npm para las versiones disponibles.

Ejemplo Completo​

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document Signing</title>
<script type="module" src="https://cdn.legalesign.io/signer/latest/ls-signer.esm.js"></script>
</head>
<body>
<ls-signer
recipient-id="abc123"
private-key="key"
session-id="session"
colour="teal"
></ls-signer>

<script>
const signer = document.querySelector('ls-signer');

signer.addEventListener('signingSuccess', (event) => {
console.log('Document signed:', event.detail.documentId);
window.location.href = '/thank-you';
});

signer.addEventListener('signingFail', (event) => {
console.error('Signing failed:', event.detail.failureReason, event.detail.error);
});

signer.addEventListener('fieldChange', (event) => {
if (event.detail.eventType === 'ready') {
console.log('Ready to sign:', event.detail.document.name);
}
});
</script>
</body>
</html>

Soporte de Navegadores​

  • Chrome/Edge (última versión)
  • Firefox (última versión)
  • Safari (última versión)
  • Navegadores móviles (iOS Safari, Chrome Mobile)

Registro de Cambios​

VersiónFechaResumen
v1.1.720 Oct 2026Motivo documentCompleted; mejoras en guardado de campo; correcciones de posicionamiento; mejor captura de eventos de fallo
v1.1.022 Jul 2026Evento onChange / fieldChange; prop language; campos condicionales; salto automático; QES
v1.0.1220 Jul 2026Evento onChange / fieldChange con ready, save, select; valores de failureReason; validación con regex
v1.0.1115 Jul 2026Prop language; campos condicionales, desplegables, checkbox; entrada telefónica; orden de campos
v1.0.69 Jun 2026Prop branding añadida
v1.0.315 May 2026Prop colour; propiedades CSS personalizadas; corrección de errores
v1.0.011 May 2026Lanzamiento estable inicial

Recursos​

Video: Migrando de iframe al componente Firmante​