This commit is contained in:
David Arranz 2026-01-30 14:12:05 +01:00
parent e7aea83bdb
commit 1a76b4aa22
4 changed files with 50 additions and 14 deletions

View File

@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "factuges-document-signing-service"
version = "0.1.1"
version = "0.1.3"
description = "FastAPI service for signing PDF documents using external secret managers"
requires-python = ">=3.11"
@ -14,7 +14,7 @@ dependencies = [
"fastapi>=0.110",
"uvicorn[standard]>=0.27",
"pyhanko>=0.25",
"pyhanko>=0.32",
"cryptography>=42",
# Infisical SDK for secret management

View File

@ -66,7 +66,7 @@ fi
# --- Detectar nombre y versión de la API ---
IMAGE_NAME=$(node -p "require('${PROJECT_DIR}/setup.cfg').name" 2>/dev/null || echo "factuges-document-signing-service")
IMAGE_VERSION=$(node -p "require('${PROJECT_DIR}/setup.cfg').version" 2>/dev/null || echo "0.1.2")
IMAGE_VERSION=$(node -p "require('${PROJECT_DIR}/setup.cfg').version" 2>/dev/null || echo "0.1.3")
PORT="8000" # valor por defecto

View File

@ -1,7 +1,7 @@
[metadata]
name = "factuges-document-signing-service"
version = "0.1.2"
version = "0.1.3"
description = "FastAPI service for signing PDF documents using external secret managers"
author = Rodax Software
author_email = info@rodax-software.com

View File

@ -1,11 +1,15 @@
import base64
from csv import writer
import io
from pydoc import doc
from datetime import datetime, timezone
from pyhanko import stamp
from pyhanko.sign import fields, signers
from pyhanko.sign import signers
from pyhanko.pdf_utils import text
from pyhanko.pdf_utils.incremental_writer import IncrementalPdfFileWriter
from signing_service.domain.ports.pdf_signer import PDFSignerPort
@ -19,6 +23,9 @@ class PyHankoPDFSigner(PDFSignerPort):
# 1⃣ Decodificar certificado
pfx_bytes = base64.b64decode(certificate)
# 3⃣ Preparar PDF en modo incremental
writer = IncrementalPdfFileWriter(io.BytesIO(pdf_bytes))
# 2⃣ Cargar clave y certificado
signer = signers.SimpleSigner.load_pkcs12_data(
pkcs12_bytes=pfx_bytes,
@ -26,16 +33,45 @@ class PyHankoPDFSigner(PDFSignerPort):
other_certs=[],
)
# 3⃣ Preparar PDF
input_pdf = IncrementalPdfFileWriter(io.BytesIO(pdf_bytes))
# 3⃣ Extract certificate info (from signer)
cert = signer.signing_cert
subject = cert.subject.native.get('common_name', 'Desconocido')
# 5⃣ Define signature field position
fields.append_signature_field(
writer,
sig_field_spec=fields.SigFieldSpec(
sig_field_name="Signature1",
on_page=-1,
box=(380, 100, 560, 160), # x, y, x+width, y+height
)
)
# 4⃣ Signature metadata (panel de firmas)
meta = signers.PdfSignatureMetadata(
field_name="Signature1",
name=subject,
)
pdf_signer = signers.PdfSigner(
meta, signer=signer, stamp_style=stamp.TextStampStyle(
stamp_text='Firmado digitalmente por: %(signer)s\nFecha: %(ts)s',
text_box_style=text.TextBoxStyle(
border_width=0,
font_size=12
#font=opentype.GlyphAccumulatorFactory('path to font police.ttf'),
),
#background=images.PdfImage('path to img.jpg')
)
)
# 4⃣ Firmar
signed_pdf: io.BytesIO = await signers.async_sign_pdf(
input_pdf,
signers.PdfSignatureMetadata(
field_name="Signature1"
),
signer=signer,
signed_pdf: io.BytesIO = await pdf_signer.async_sign_pdf(
writer,
)
# 5⃣ Obtener PDF firmado