erp-construccion-backend-v2/src/modules/payment-terminals/controllers/mercadopago-webhook.controller.ts
Adrian Flores Cortes 0493d4b8bd [PROP-CORE-004] feat: Add Phase 6 modules from erp-core
Propagated modules:
- payment-terminals: MercadoPago + Clip TPV
- ai: Role-based AI access (ADMIN, SUPERVISOR_OBRA, RESIDENTE, ALMACENISTA)
- mcp: 18 ERP tools for AI assistants

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-25 02:45:03 -06:00

57 lines
1.8 KiB
TypeScript

/**
* MercadoPago Webhook Controller
*
* Endpoint público para recibir webhooks de MercadoPago
*/
import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { MercadoPagoService } from '../services/mercadopago.service';
export class MercadoPagoWebhookController {
public router: Router;
private mercadoPagoService: MercadoPagoService;
constructor(private dataSource: DataSource) {
this.router = Router();
this.mercadoPagoService = new MercadoPagoService(dataSource);
this.initializeRoutes();
}
private initializeRoutes(): void {
// Webhook endpoint (público, sin auth)
this.router.post('/:tenantId', this.handleWebhook.bind(this));
}
/**
* POST /webhooks/mercadopago/:tenantId
* Recibir notificaciones IPN de MercadoPago
*/
private async handleWebhook(req: Request, res: Response, next: NextFunction): Promise<void> {
try {
const tenantId = req.params.tenantId;
const eventType = req.body.type || req.body.action;
const data = req.body;
// Extraer headers relevantes
const headers: Record<string, string> = {
'x-signature': req.headers['x-signature'] as string || '',
'x-request-id': req.headers['x-request-id'] as string || '',
};
// Responder inmediatamente (MercadoPago espera 200 rápido)
res.status(200).json({ received: true });
// Procesar webhook de forma asíncrona
await this.mercadoPagoService.handleWebhook(tenantId, eventType, data, headers);
} catch (error) {
// Log error pero no fallar el webhook
console.error('MercadoPago webhook error:', error);
// Si aún no enviamos respuesta
if (!res.headersSent) {
res.status(200).json({ received: true });
}
}
}
}