Saltar a contenido

Guía del Usuario - SSigner API REST

¿Qué es SSigner API REST?

SSigner API REST es un servicio web que permite integrar firmas digitales en tus aplicaciones o sistemas. Actúa como un intermediario que facilita el proceso de firma de documentos PDF sin que necesites conocer los detalles técnicos del motor de firma.


¿Qué puedes hacer con la API?

  • Firmar documentos PDF de forma masiva
  • Gestionar grupos de firma para procesar múltiples documentos juntos
  • Autenticar usuarios con seguridad JWT
  • Administrar clientes que usan el sistema de firma

Requisitos Previos

Conocimientos

  • Conceptos básicos de APIs REST
  • Cómo enviar solicitudes HTTP (POST, GET)
  • Manejo de tokens de autenticación

Software necesario

  • Java 17 o superior
  • PostgreSQL 12 o superior
  • Servidor de aplicaciones (Spring Boot integrado)

Primeros Pasos

1. Instalación y Configuración

Variables de Entorno

La API se configura mediante variables de entorno. Estas son las más importantes:

Variable Descripción Valor por defecto
SERVER_PORT Puerto donde se ejecuta el servicio 8087
DB_URL URL de conexión a PostgreSQL changeme
DB_USERNAME Usuario de la base de datos changeme
DB_PASSWORD Contraseña de la base de datos changeme
JWT_SECRET_KEY Clave secreta para tokens JWT changeme
SSIGNER_BASE_PATH Ruta base donde se almacenan archivos /opt/ssigner/users

Configuración de la Base de Datos

La API requiere una base de datos PostgreSQL. Asegúrate de:

  1. Crear una base de datos llamada ssigner
  2. Crear un usuario con permisos de lectura/escritura
  3. Configurar las variables DB_URL, DB_USERNAME y DB_PASSWORD

Clave JWT

La clave JWT debe ser una cadena Base64 de 64 caracteres. Puedes generar una con:

openssl rand -base64 64

Importante: Guarda esta clave de forma segura. Si la pierdes, todos los tokens existentes serán inválidos.


2. Autenticación

Antes de usar cualquier endpoint protegido, necesitas autenticarte.

Registrar un usuario

Si es la primera vez que usas el sistema, registra un usuario:

POST /auth/registrar
Content-Type: application/json

{
  "email": "usuario@empresa.com",
  "password": "tu_contraseña_segura",
  "name": "Nombre del Usuario"
}

Respuesta:

{
  "jwtToken": "eyJhbGciOiJIUzI1NiJ9...",
  "refreshToken": "eyJhbGciOiJIUzI1NiJ9..."
}

Iniciar sesión

Si ya tienes un usuario registrado:

POST /auth/acceder
Content-Type: application/json

{
  "email": "usuario@empresa.com",
  "password": "tu_contraseña_segura"
}

Usar el token

Todos los endpoints protegidos requieren el token en el header:

Authorization: Bearer eyJhbGciOiJIUzI1NiJ9...

Refrescar el token

Los tokens expiran después de 24 horas. Para continuar usando la API:

POST /auth/refrescar
Authorization: Bearer <refresh_token>

Recibirás nuevos tokens de acceso y refresh.


Flujo Completo de Firma de Documentos

El proceso de firma de documentos sigue estos pasos:

1. Autenticarse
   └── Obtener JWT token

2. Iniciar grupo de firma
   ├── Subir documentos
   └── Definir configuraciones

3. Generar hashes de prefirma
   └── Obtener hashes para firmar localmente

4. Firmar localmente (en el cliente)
   └── Usar certificado digital para firmar los hashes

5. Insertar hashes firmados
   └── Enviar hashes firmados al servidor

6. Verificar y descargar
   └── Confirmar que los documentos están firmados

Endpoints Disponibles

Autenticación (públicos)

Método Ruta Descripción
POST /auth/registrar Crear nueva cuenta de usuario
POST /auth/acceder Iniciar sesión
POST /auth/refrescar Renovar token de acceso

Grupos de Firma (requieren autenticación)

Método Ruta Descripción
POST /api/v2/grupo-proceso-firma/iniciar-grupo Crear grupo y subir documentos
POST /api/v2/grupo-proceso-firma/iniciar-grupo-v2 Crear grupo mediante formulario (multipart)
GET /api/v2/grupo-proceso-firma/{id}/estado Consultar estado del grupo
GET /api/v2/grupo-proceso-firma/{id}/documentos Ver documentos del grupo
GET /api/v2/grupo-proceso-firma/verificar-grupo-firmado/{idGP} Verificar si el grupo está firmado
GET /api/v2/grupo-proceso-firma/cancelar-grupo/{idGP} Cancelar un grupo en proceso

SSigner (requieren autenticación)

Método Ruta Descripción
POST /api/v2/ssigner/generar-hash Generar hashes para prefirma
POST /api/v2/ssigner/insertar-hash-firmado Enviar hashes ya firmados
POST /api/v2/ssigner/obtener-configuracion Obtener configuración del firmante

Documentos (requieren autenticación)

Método Ruta Descripción
GET /api/v2/documento/descargar-firmado-blob/{id} Descargar documento firmado
GET /api/v2/documento/descargar-firmado/{id} Descargar documento firmado como Base64
POST /api/v2/documento/{id}/confirmar-descarga Confirmar resultado de descarga

Usuarios y Clientes (requieren autenticación)

Método Ruta Descripción
GET /api/v2/users Listar usuarios del sistema
GET /api/v2/clientes Listar clientes
GET /api/v2/clientes/{id} Obtener cliente
POST /api/v2/clientes Crear nuevo cliente
PUT /api/v2/clientes/{id} Actualizar cliente
PATCH /api/v2/clientes/{id}/estado Activar/desactivar cliente

Ejemplo Práctico: Firmar un Documento

Paso 1: Autenticarse

curl -X POST http://localhost:8087/auth/acceder \
  -H "Content-Type: application/json" \
  -d '{"email":"admin@empresa.com","password":"MiPass123"}'

Respuesta:

{
  "jwtToken": "eyJhbGciOiJIUzI1NiJ9.eyJpZCI6MSwibmFtZSI6IkFkbWluIiwi...",
  "refreshToken": "eyJhbGciOiJIUzI1NiJ9..."
}

Paso 2: Iniciar Grupo de Firma

curl -X POST http://localhost:8087/api/v2/grupo-proceso-firma/iniciar-grupo \
  -H "Authorization: Bearer <tu_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "idFirmante": "12345678",
    "idProceso": 1,
    "documentos": [
      {
        "nombre": "contrato.pdf",
        "codigo": "CTR001",
        "contenido": "<base64_del_pdf>",
        "configuraciones": ["firma.estilo=texto-imagen-derecha", "firma.visible=true"]
      }
    ],
    "configuracionesComunes": ["firma.texto=Firmado por [CN]"]
  }'

Respuesta:

{
  "gruProFirId": 123,
  "estado": true,
  "mensaje": "Operacion exitosa",
  "propiedades": {
    "firma.repositorio": "Windows-MY",
    "firma.visible": "true"
  }
}

Paso 3: Generar Hash

curl -X POST http://localhost:8087/api/v2/ssigner/generar-hash \
  -H "Authorization: Bearer <tu_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "idGP": "123",
    "idFirmante": "12345678",
    "certifcadoPublicoFirmante": "<base64_del_certificado>",
    "userMotivo": "Firma de contrato",
    "userLocacion": "Lima, Peru"
  }'

Respuesta:

{
  "hashes": ["YWZhZ2VmMmpqamtrbG5tb3BwcXJycw==..."],
  "estado": true,
  "mensaje": "Operacion exitosa",
  "algoritmo": "SHA256",
  "nombresDocumentos": ["contrato.pdf"]
}

Paso 4: El cliente firma el hash localmente

Este paso se hace fuera de la API, usando el certificado digital del usuario.

Paso 5: Insertar Hash Firmado

curl -X POST http://localhost:8087/api/v2/ssigner/insertar-hash-firmado \
  -H "Authorization: Bearer <tu_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "idpg": 123,
    "hashesFirmados": ["<hash_firmado_base64>"]
  }'

Paso 6: Verificar y Descargar

# Verificar estado
curl -X GET http://localhost:8087/api/v2/grupo-proceso-firma/123/estado \
  -H "Authorization: Bearer <tu_token>"

# Descargar documento
curl -X GET http://localhost:8087/api/v2/documento/descargar-firmado-blob/1 \
  -H "Authorization: Bearer <tu_token>" \
  -o contrato_firmado.pdf

Estados del Grupo de Firma

Durante el proceso, el grupo pasa por diferentes estados:

Estado Valor Significado
CANCELLED 0 El grupo fue cancelado
INITIATED 1 Grupo creado, esperando generar hashes
DICHARGED 2 Hashes generados, esperando hashes firmados. El nombre conserva la ortografia del codigo.
CONFIGGETTER 3 Configuración recuperada
UPLOADED 4 Hashes firmados recibidos, documentos listos
FINALIZED 5 Documentos descargados, proceso completado

Estructura de Carpetas

La API organiza los archivos de cada firmante así:

{SSIGNER_BASE_PATH}/
└── {idFirmante}/
    ├── entrada/
    │   ├── documento.pdf
    │   ├── documento.pdf.prefirma
    │   └── documento.pdf.prefirma.sha256
    ├── salida/
    │   └── documento_signed.pdf
    ├── imagen/
    │   └── firma.png
    ├── cache/
    │   └── certificado.pem
    └── config/
        └── *.properties

Configuración del Motor de Firma

La API utiliza un archivo de configuración predeterminado que puedes personalizar:

Propiedad Descripción Valor típico
firma.perfil Perfil textual PAdES, CAdES o PKCS7 PAdES-B
firma.creador Nombre de producto o versión registrado como metadata de creador en la firma PDF SSigner v2.5.2
firma.creador.habilitar Agregar u omitir la metadata de creador en la firma PDF true
firma.imagen.modo Modo de ajuste de imagen; actualmente equivale a escalar escalar
firma.imagen.mantener.proporcion Mantener proporción al limitar dimensiones de imagen true
firma.coordenadas.unidad Unidad de coordenadas pixeles
glosa.habilitar Habilitar glosa legal true
glosa.url URL de verificación (según proveedor)
glosa.qr.habilitar Incluir código QR true
tsa.habilitar Habilitar sello de tiempo 0 o 1
tsa.url URL del servidor TSA (según proveedor)

Para más opciones de configuración, consulta la documentación del Motor SSigner.


Códigos de Error Comunes

Código Significado
401 No autenticado o token expirado
403 Sin permisos para acceder al recurso
404 Recurso no encontrado (grupo, documento, etc.)
400 Solicitud inválida (datos mal formados)
500 Error interno del servidor

Límites y Recomendaciones

Tamaño de archivos

  • Tamaño máximo de imagen de firma: 2 MB
  • Formatos de imagen soportados: PNG, JPG

Rendimiento

  • Máximo de conexiones simultáneas: 10000
  • Hilos de procesamiento: 300
  • Cola de aceptación: 100

Buenas prácticas

  1. Reutiliza el token: No solicites uno nuevo para cada petición
  2. Refresca antes de expirar: Renueva el token cuando queden ~2 horas
  3. Agrupa documentos: Usa grupos para firmar múltiples documentos juntos
  4. Verifica el estado: Comprueba el estado del grupo antes de descargar

Soporte y Recursos

  • Documentación del Motor: Consulta ssigner-motor/docs/configuracion.md para todas las opciones de firma
  • Tokens JWT: Los tokens expiran en 24 horas; usa refresh token para continuar
  • Logs: El nivel de logging se configura con ssigner.log.level