/** * Clip Controller * * Endpoints para pagos con Clip */ import { Router, Request, Response, NextFunction } from 'express'; import { DataSource } from 'typeorm'; import { ClipService } from '../services/clip.service'; export class ClipController { public router: Router; private clipService: ClipService; constructor(private dataSource: DataSource) { this.router = Router(); this.clipService = new ClipService(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 /clip/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.clipService.createPayment( tenantId, { amount: req.body.amount, currency: req.body.currency, description: req.body.description, customerEmail: req.body.customerEmail, customerName: req.body.customerName, customerPhone: req.body.customerPhone, 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 /clip/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.clipService.getPayment(tenantId, paymentId); res.json({ success: true, data: this.sanitizePayment(payment), }); } catch (error) { next(error); } } /** * POST /clip/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.clipService.refundPayment(tenantId, { paymentId, amount: req.body.amount, reason: req.body.reason, }); res.json({ success: true, data: this.sanitizePayment(payment), }); } catch (error) { next(error); } } /** * POST /clip/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.clipService.createPaymentLink( tenantId, { amount: req.body.amount, description: req.body.description, expiresInMinutes: req.body.expiresInMinutes, 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 */ private sanitizePayment(payment: any): any { const { providerResponse, ...safe } = payment; return safe; } }