siip-whatsapp-notifications.../consulta a Gemini.txt
DANYDHSV 84a25a829c Feat(Plugin): Implementación Microservicio PDF, Integración MinIO, Fix Recorte y Overlay de Pagos
Descripción:

Se ha realizado una refactorización mayor del sistema de notificaciones y generación de comprobantes para eliminar dependencias legacy (Imagick/FTP) y modernizar la arquitectura.

🚀 Nuevas Características (Features)
Microservicio PDF (pdf-cropper):

Nuevo servicio en Python (FastAPI + Poppler) desplegado en Docker (Puerto 8050) para la conversión de PDF a Imagen.
Reemplaza la librería Imagick de PHP, aislando el procesamiento pesado fuera del plugin.
Modo Full: Garantiza la conversión del PDF completo respetando su relación de aspecto original (sin recortes ni "square crop").
Overlay de Texto: Capacidad nativa en el backend para sobreescribir texto dinámicamente (ej. cambiar "Tarjeta de crédito Stripe" por "OXXO Pay") basado en parámetros.
Integración S3 / MinIO:

Implementación de
MinioStorageService
.
Los comprobantes (JPG) y Vouchers OXXO se suben automáticamente a MinIO en lugar de usar FTP.
Generación de URLs públicas seguras.
🧹 Mantenimiento y Limpieza (Chores/Refactor)
Limpieza Automática (Cleanup):

Se implementó lógica para eliminar archivos temporales locales (PDFs descargados, JPGs generados) inmediatamente después de una subida exitosa a MinIO.
Aplica tanto para comprobantes de pago como para Vouchers OXXO.
Refactor
ClientCallBellAPI
:

Eliminación de código muerto relacionado con FTP de WordPress.
Implementación de cliente HTTP Guzzle para comunicación con pdf-cropper.
Cache Busting: Se añade Timestamp al nombre de archivo (_time()) para evitar caché agresivo en WhatsApp/Navegadores.
Detección de Método: Lógica preliminar para detectar "OXXO" o "Transferencia" en notas de pago y aplicar Overlay.
Docker Infraestructura:

Actualización de
docker-compose.yml
 para incluir pdf-cropper.
Instalación de fuentes (fonts-dejavu-core) para renderizado correcto de texto.
🐛 Correcciones (Bug Fixes)
Fix Recorte de Imagen: Se eliminó la restricción de relación de aspecto 1:1 (cuadrado) que cortaba headers y footers en documentos rectangulares.
Standardización de Notas: Actualización de
AbstractStripeOperationsFacade
 para incluir explícitamente "OXXO" o "Transferencia" en las notas de pago de UCRM (preparación para lógica de plantillas).
2026-01-14 22:56:17 -06:00

175 lines
5.0 KiB
Plaintext

Pregunta: Algún microservicio que pueda levantar con docker compose y que funcione como API para pasarle un PDF y me devuelva una imagen y recortada en ciertas coordenadas o ajustada a formato cuadrado.
Respuesta: Para lo que necesitas, la mejor opción no es una herramienta genérica (como Gotenberg), ya que estas suelen convertir la página entera pero no permiten recortar por coordenadas en la misma petición.
La solución más limpia y eficiente es crear un microservicio ligero en Python (usando FastAPI y pdf2image) que puedas levantar con Docker. Python tiene las mejores librerías para manipulación de PDFs e imágenes.
Aquí tienes la solución completa "Copy-Paste":
1. Estructura del proyecto
Crea una carpeta (ej. pdf-cropper) con estos 3 archivos:
Dockerfile
main.py
docker-compose.yml
2. El Código (Python + FastAPI)
Este script recibe el PDF, lo convierte a imagen y aplica el recorte o ajuste cuadrado según lo que le pidas.
Archivo: main.py
Python
from fastapi import FastAPI, UploadFile, File, Form
from pdf2image import convert_from_bytes
from PIL import Image
import io
app = FastAPI()
@app.post("/process")
async def process_pdf(
file: UploadFile = File(...),
mode: str = Form("square"), # 'square' o 'coords'
x: int = Form(0),
y: int = Form(0),
w: int = Form(500),
h: int = Form(500)
):
# 1. Leer el archivo PDF en memoria
pdf_bytes = await file.read()
# 2. Convertir la primera página a imagen
# poppler_path no es necesario si se instala en el sistema (ver Dockerfile)
images = convert_from_bytes(pdf_bytes, fmt="jpeg")
if not images:
return {"error": "No se pudo leer el PDF"}
img = images[0] # Tomamos la primera página
# 3. Lógica de recorte
if mode == "square":
# Recorte cuadrado centrado automático
width, height = img.size
new_dim = min(width, height)
left = (width - new_dim) / 2
top = (height - new_dim) / 2
right = (width + new_dim) / 2
bottom = (height + new_dim) / 2
img = img.crop((left, top, right, bottom))
# Opcional: Redimensionar al tamaño final deseado
img = img.resize((w, h))
elif mode == "coords":
# Recorte por coordenadas exactas
img = img.crop((x, y, x + w, y + h))
# 4. Devolver la imagen procesada
img_byte_arr = io.BytesIO()
img.save(img_byte_arr, format='JPEG', quality=90)
img_byte_arr.seek(0)
from starlette.responses import StreamingResponse
return StreamingResponse(img_byte_arr, media_type="image/jpeg")
3. El Dockerfile
Es crucial instalar poppler-utils, que es el motor que procesa el PDF.
Archivo: Dockerfile
Dockerfile
FROM python:3.9-slim
# Instalar poppler (necesario para pdf2image)
RUN apt-get update && apt-get install -y poppler-utils && rm -rf /var/lib/apt/lists/*
WORKDIR /app
# Instalar dependencias de Python
RUN pip install fastapi uvicorn python-multipart pdf2image Pillow
COPY main.py .
# Ejecutar la API
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
4. Docker Compose
Para levantarlo.
Archivo: docker-compose.yml
YAML
services:
pdf-cropper:
build: .
ports:
- "8080:8000"
restart: always
Comando para iniciar:
Bash
docker compose up -d --build
5. Cómo usarlo desde PHP
Ahora tienes una API corriendo en http://localhost:8080/process. Aquí tienes el script PHP para enviarle un PDF y guardar la imagen recortada.
Archivo: cliente.php
PHP
<?php
$pdfPath = 'documento.pdf';
$outputPath = 'resultado.jpg';
// URL de tu microservicio docker
$url = 'http://localhost:8080/process';
$curl = curl_init();
$fields = [
'file' => new CURLFile($pdfPath, 'application/pdf', 'documento.pdf'),
// OPCIÓN A: Recorte cuadrado automático (centrado)
'mode' => 'square',
'w' => 800, // Tamaño final del cuadrado (px)
'h' => 800,
// OPCIÓN B: Coordenadas específicas (descomentar para usar)
// 'mode' => 'coords',
// 'x' => 100, // Píxeles desde la izquierda
// 'y' => 200, // Píxeles desde arriba
// 'w' => 500, // Ancho del recorte
// 'h' => 300 // Alto del recorte
];
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $fields,
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($curl);
$httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
if ($httpCode == 200) {
file_put_contents($outputPath, $response);
echo "Imagen guardada exitosamente en $outputPath";
} else {
echo "Error: " . curl_error($curl);
echo "Respuesta del servidor: " . $response;
}
curl_close($curl);
?>
¿Por qué esta solución?
Atomocidad: Hace la conversión y el recorte en un solo paso de memoria (RAM), sin guardar archivos temporales en disco.
Control: Puedes ajustar la lógica de "cuadrado" (si quieres que sea centrado o desde la esquina superior) modificando fácilmente el main.py.
Ligero: La imagen Docker pesará poco y consumirá memoria solo cuando procese un archivo.