Saltar a contenido

Caso de uso: firma masiva de documentos

Flujo de 3 pasos: encolar el lote, consultar su estado hasta que termine, y descargar el zip con los documentos firmados. Requisito previo: el dni_firmante debe tener un certificado principal cargado, igual que en la firma individual.

1. Encolar el lote

PDF1_BASE64=$(base64 -w0 archivo-1.pdf)
PDF2_BASE64=$(base64 -w0 archivo-2.pdf)

curl -X POST http://localhost:8080/api/firma/masiva \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "nombre_zip": "bloque1.zip",
    "dni_firmante": "12345678",
    "archivos": [
      {
        "nombre": "archivo-1.pdf",
        "base64": "'"$PDF1_BASE64"'",
        "nivel_firma": "PAdES-BT",
        "firma_visual": {
          "type": "TEXTO",
          "ubicacion_x": "40",
          "ubicacion_y": "40",
          "largo": "220",
          "alto": "50",
          "pagina": "1",
          "motivo": "Aprobación de expediente",
          "texto": "[FIRMANTE]&[MOTIVO]&[FECHA]"
        }
      },
      {
        "nombre": "archivo-2.pdf",
        "base64": "'"$PDF2_BASE64"'",
        "nivel_firma": "PAdES-B"
      }
    ]
  }' \
  -o encolado.json

Respuesta 202 ACCEPTED:

{
  "success": true,
  "mensaje": "2 documentos en cola para firma masiva",
  "solicitud": "K3F9QZ1B7C",
  "verificar_firmado": "GET /firma/estado/K3F9QZ1B7C"
}

SOLICITUD=$(jq -r '.solicitud' encolado.json)

2. Consultar el estado

curl http://localhost:8080/api/firma/estado/$SOLICITUD \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..."

Mientras se procesa:

{
  "success": true,
  "solicitud": "K3F9QZ1B7C",
  "estado": "PROCESANDO",
  "mensaje": "Procesando documentos",
  "progreso": { "procesados": 1, "total": 2 }
}

Cuando termina:

{
  "success": true,
  "solicitud": "K3F9QZ1B7C",
  "estado": "COMPLETADO",
  "mensaje": "Documentos firmados",
  "progreso": { "procesados": 2, "total": 2 },
  "descargar_firmado": "GET /firma/zip/K3F9QZ1B7C"
}

Para lotes chicos el procesamiento suele terminar en pocos segundos; para lotes grandes conviene consultar el estado con un intervalo (por ejemplo cada 5-10 segundos) en vez de en un loop cerrado.

3. Descargar el zip

curl http://localhost:8080/api/firma/zip/$SOLICITUD \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  -o zip_respuesta.json

jq -r '.zip_base64' zip_respuesta.json | base64 -d > bloque1.zip
unzip -l bloque1.zip

Dentro del zip: archivo-1.pdf, archivo-2.pdf (firmados) y manifest.json con el detalle de checksums, pesos y fecha de firma de cada uno (ver formato del manifest).

Errores frecuentes

Situación Respuesta
Más de 100 archivos, o el peso total decodificado supera 300MB 400 BAD_REQUEST (no se crea ninguna solicitud)
GET /estado o GET /zip con un código que no existe, o que pertenece a otro dni 404 NOT_FOUND
GET /zip antes de que la solicitud termine de procesarse 409 CONFLICT
Uno o más archivos del lote fallan al firmar (ej. certificado revocado a mitad del lote, PDF corrupto) La solicitud igual llega a COMPLETADO_CON_ERRORES; el zip se genera con los que sí se firmaron, y manifest.json documenta el error de los que fallaron

Variante: consultar y descargar en un solo script

until [ "$(curl -s http://localhost:8080/api/firma/estado/$SOLICITUD \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." | jq -r '.estado')" \
  =~ ^(COMPLETADO|COMPLETADO_CON_ERRORES|ERROR)$ ]]; do
  sleep 5
done

curl http://localhost:8080/api/firma/zip/$SOLICITUD \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiJ9..." \
  | jq -r '.zip_base64' | base64 -d > bloque1.zip