/** * MercadoPago Controller * * Endpoints para pagos con MercadoPago */ import { Router, Request, Response, NextFunction } from 'express'; import { DataSource } from 'typeorm'; import { MercadoPagoService } from '../services/mercadopago.service'; export class MercadoPagoController { public router: Router; private mercadoPagoService: MercadoPagoService; constructor(private dataSource: DataSource) { this.router = Router(); this.mercadoPagoService = new MercadoPagoService(dataSource); this.initializeRoutes(); } private initializeRoutes(): void { // Pagos this.router.post('/payments', this.createPayment.bind(this)); this.router.get('/payments/:id', this.getPayment.bind(this)); this.router.post('/payments/:id/refund', this.refundPayment.bind(this)); // Links de pago this.router.post('/links', this.createPaymentLink.bind(this)); } /** * POST /mercadopago/payments * Crear un nuevo pago */ private async createPayment(req: Request, res: Response, next: NextFunction): Promise { try { const tenantId = this.getTenantId(req); const userId = this.getUserId(req); const payment = await this.mercadoPagoService.createPayment( tenantId, { amount: req.body.amount, currency: req.body.currency, description: req.body.description, paymentMethod: req.body.paymentMethod, customerEmail: req.body.customerEmail, customerName: req.body.customerName, referenceType: req.body.referenceType, referenceId: req.body.referenceId, metadata: req.body.metadata, }, userId ); res.status(201).json({ success: true, data: this.sanitizePayment(payment), }); } catch (error) { next(error); } } /** * GET /mercadopago/payments/:id * Obtener estado de un pago */ private async getPayment(req: Request, res: Response, next: NextFunction): Promise { try { const tenantId = this.getTenantId(req); const paymentId = req.params.id; const payment = await this.mercadoPagoService.getPayment(tenantId, paymentId); res.json({ success: true, data: this.sanitizePayment(payment), }); } catch (error) { next(error); } } /** * POST /mercadopago/payments/:id/refund * Reembolsar un pago */ private async refundPayment(req: Request, res: Response, next: NextFunction): Promise { try { const tenantId = this.getTenantId(req); const paymentId = req.params.id; const payment = await this.mercadoPagoService.refundPayment(tenantId, { paymentId, amount: req.body.amount, reason: req.body.reason, }); res.json({ success: true, data: this.sanitizePayment(payment), }); } catch (error) { next(error); } } /** * POST /mercadopago/links * Crear un link de pago */ private async createPaymentLink(req: Request, res: Response, next: NextFunction): Promise { try { const tenantId = this.getTenantId(req); const userId = this.getUserId(req); const link = await this.mercadoPagoService.createPaymentLink( tenantId, { amount: req.body.amount, title: req.body.title, description: req.body.description, expiresAt: req.body.expiresAt ? new Date(req.body.expiresAt) : undefined, referenceType: req.body.referenceType, referenceId: req.body.referenceId, }, userId ); res.status(201).json({ success: true, data: link, }); } catch (error) { next(error); } } /** * Obtener tenant ID del request */ private getTenantId(req: Request): string { const tenantId = (req as any).tenantId || (req as any).user?.tenantId; if (!tenantId) { throw new Error('Tenant ID not found in request'); } return tenantId; } /** * Obtener user ID del request */ private getUserId(req: Request): string | undefined { return (req as any).userId || (req as any).user?.id; } /** * Sanitizar pago para respuesta (ocultar datos sensibles) */ private sanitizePayment(payment: any): any { const { providerResponse, ...safe } = payment; return safe; } }