/** * 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 { try { const tenantId = req.params.tenantId; const eventType = req.body.type || req.body.action; const data = req.body; // Extraer headers relevantes const headers: Record = { '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 }); } } } }