Saltar al contenido principal

Integra el componente Legalesign Signer en tu sitio web

Habilitar para tu equipo

El componente Signer requiere activación. Contacta con soporte para habilitarlo para tu equipo.

El Legalesign Signer es un componente web agnóstico de plataforma que proporciona una experiencia completa y fluida de firma de documentos desde tu propia aplicación. Funciona con HTML vanilla, React, Vue, Angular o cualquier framework web.

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

Instalación

Carga directamente desde el CDN (no requiere instalación):

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

Instalación en React

Instala 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 peer.

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 usas Vue con Vite, añade isCustomElement: (tag) => tag.startsWith('ls-') a la configuración del plugin Vue para suprimir las advertencias de elementos desconocidos.

aviso

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

Nuxt 3

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

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

Autenticación

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

  1. GraphQL generateComponentToken — Llama con component: LS_SIGNER y ya sea un recipientId o sessionId en el scope del signer (proporciona uno, no ambos).
  2. REST API — Llama a GET /signer/{signerId}/component-token/ con tu clave API.

Ambos retornan el token y sessionId que el componente necesita. Consulta Widget Authorization para el flujo completo del token del lado servidor.

Opción 1: GraphQL (Node.js)

Usando recipientId (más común — usar cuando conoces al destinatario pero aún no tienes 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 tienes 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();

Pasa 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 Customer CSS)
brandingbooleantrueRemover la marca Legalesign
languagestringForzar un idioma específico y ocultar el selector de idioma (ver Internationalisation)

Eventos

Evento componente webPropiedad ReacteventTypeCuándo
signingSuccessonSuccess"success"Documento firmado con éxito
signingFailonFail"failure"Firma fallida, rechazada, expirada, cancelada, eliminada o removida
fieldChangeonChange"ready"Documento e imágenes cargadas completamente
fieldChangeonChange"save"Se guardó un valor de campo
fieldChangeonChange"select"Se seleccionó o enfocó un campo

signingSuccess / onSuccess

{
eventType: 'success';
documentId: string;
recipientId: string;
}

signingFail / onFail

{
eventType: 'failure';
failureReason: FailureReason;
error: string;
documentId?: string;
recipientId: string;
}
failureReasonCausa
documentExpiredDocumento expirado o fecha de expiración pasada
sessionExpiredAPI devolvió 401 o 403
cancelledEstado del documento es "cancelled"
deletedDocumento ha sido eliminado
rejectedDestinatario rechazó el documento
removedAPI devolvió 404
signingErrorCualquier otro error durante la carga o firma

fieldChange / onChange

Los tres valores eventType comparten el mismo evento. Usa eventType para distinguir:

// eventType: 'ready' — document fully loaded
{ eventType: 'ready'; document: { documentId, name, state, recipientId, pageCount, expires?, isApprover, isWitness, canReassign, doOfferReject } }

// eventType: 'save' — field value saved
{ eventType: 'save'; uuid: string; saved: boolean; field: Record<string, any> }

// eventType: 'select' — field selected or focused
{ eventType: 'select'; uuid: string; field: Record<string, any> }

Propiedades React

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

PropTipoRequeridoDescripción
recipientIdstringIdentificador del destinatario
privateKeystringClave privada del mutation generateComponentToken
sessionIdstringIdentificador de sesión
colourLsSignerColourColor del tema
brandingbooleanMostrar marca Legalesign. Por defecto true.
languagestringForzar un idioma específico (ver Internationalisation)
onSuccess(data: { eventType: 'success'; documentId: string; recipientId: string }) => voidLlamado tras firma exitosa
onFail(data: { eventType: 'failure'; failureReason: FailureReason; error: string; documentId?: string; recipientId: string }) => voidLlamado tras fallo en la firma
onChange(data: { eventType: 'ready' | 'save' | 'select'; document?: DocumentSummary; uuid?: string; saved?: boolean; field?: Record<string, any> }) => voidLlamado en eventos de campos y carga del documento

Manejo global (depuración y prototipado)

Como cada evento incluye eventType, puedes 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);

Tematización

Define 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 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 enfoque
60Color primario (botones, enlaces, estados activos)
70Estado hover
80Acentos oscuros/fuertes

CSS personalizado

El componente expone propiedades CSS personalizadas que pueden ser sobrescritas para personalizar la apariencia más allá del tema de color. Este conjunto de propiedades es limitado actualmente, contáctanos para más detalles.

<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

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

Nota: Para inyección completa de CSS personalizado (dirigido a elementos internos directamente, sobrescribir tamaños de fuente, radio de bordes, espaciados, etc.), esta es una función planeada a futuro. Por favor contáctanos si estás interesado.

Internacionalización

El componente soporta 17 idiomas con traducciones incluidas en el build. 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.

Establece el atributo language para forzar un idioma específico. Cuando se proporciona, el selector integrado se oculta y se ignora 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 tanto latest como números de versión 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.0/ls-signer.esm.js"></script>

Recomendamos usar latest — esto asegura que tu integración reciba automáticamente correcciones de errores, parches de seguridad y nuevas funcionalidades. Usa una versión fija si necesitas bloquear una versión conocida durante una congelación de QA o despliegue controlado. Consulta el historial completo de versiones en npm para 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 (últimas versiones)
  • Firefox (últimas versiones)
  • Safari (últimas versiones)
  • Navegadores móviles (iOS Safari, Chrome Mobile)

Recursos

Vídeo: Migrar de iframe al componente Signer