8.6 KiB
8.6 KiB
RF-MGN-016-001: Integración MercadoPago
Módulo: MGN-016 - Integraciones de Pagos y POS Prioridad: P1 Story Points: 13 Estado: Definido Fecha: 2025-12-05
Descripción
El sistema debe permitir a los tenants conectar su cuenta de MercadoPago para procesar pagos de sus clientes finales. Esto incluye pagos con tarjeta (presencial y online), pagos en efectivo (OXXO), transferencias SPEI, y el uso de terminales Point de MercadoPago.
Actores
- Actor Principal: Tenant Admin (configura integración)
- Actores Secundarios:
- Vendedor/Cajero (procesa pagos)
- Cliente final (realiza pago)
- MercadoPago API (procesa transacción)
Precondiciones
- Tenant debe tener suscripción activa con feature
mercadopago_enabled - Tenant Admin debe tener credenciales de MercadoPago (o crearlas vía OAuth)
- Cuenta MercadoPago debe estar verificada
Flujo Principal - Configurar Integración
- Tenant Admin accede a "Configuración > Integraciones > Pagos"
- Sistema muestra proveedores disponibles
- Admin selecciona "Conectar MercadoPago"
- Sistema redirige a MercadoPago OAuth
- Admin autoriza acceso a la aplicación
- MercadoPago retorna
access_tokenyrefresh_token - Sistema almacena tokens encriptados
- Sistema verifica conexión exitosa
- Admin configura opciones adicionales (terminales, notificaciones)
Flujo Alternativo - Procesar Pago con Terminal Point
- Vendedor crea venta en sistema (o selecciona orden existente)
- Vendedor selecciona "Cobrar con MercadoPago"
- Sistema crea Payment Intent via API
- Sistema envía intent a terminal Point vinculada
- Cliente presenta tarjeta/NFC en terminal
- Terminal procesa y envía resultado a MercadoPago
- MercadoPago envía webhook con confirmación
- Sistema actualiza estado de pago
- Sistema genera recibo
Flujo Alternativo - Pago con OXXO
- Vendedor crea cobro con método "OXXO"
- Sistema genera referencia de pago via API
- Sistema muestra/imprime ficha de pago con:
- Referencia OXXO
- Monto
- Fecha de vencimiento
- Cliente paga en tienda OXXO
- MercadoPago envía webhook de confirmación (24-48h)
- Sistema actualiza estado de pago
Métodos de Pago Soportados
| Método | Tipo | Comisión | Tiempo de Acreditación |
|---|---|---|---|
| Tarjeta Crédito (presencial) | card_present | 3.49% + IVA | Inmediato |
| Tarjeta Débito (presencial) | card_present | 2.49% + IVA | Inmediato |
| Tarjeta Online | card_not_present | 3.49% + IVA | Inmediato |
| OXXO | ticket | $10 MXN + IVA | 24-48h |
| SPEI | bank_transfer | $7 MXN + IVA | Inmediato |
| Mercado Crédito | credit | 4.99% + IVA | Inmediato |
Reglas de Negocio
- RN-1: Tokens OAuth se refrescan automáticamente antes de expirar
- RN-2: Pagos fallidos se reintentan hasta 3 veces
- RN-3: Webhooks deben validar firma HMAC
- RN-4: Montos se expresan en centavos (int) para la API
- RN-5: IPN URL debe ser HTTPS con certificado válido
- RN-6: Reembolsos solo hasta 180 días después del pago
- RN-7: Un tenant puede tener múltiples terminales Point
Criterios de Aceptación
- Tenant Admin puede conectar cuenta MercadoPago vía OAuth
- Sistema almacena tokens de forma segura (encriptados)
- Sistema refresca tokens automáticamente
- Vendedor puede procesar pago con tarjeta presencial
- Vendedor puede generar ficha de pago OXXO
- Sistema recibe y procesa webhooks correctamente
- Dashboard muestra transacciones de MercadoPago
- Admin puede desconectar integración
- Logs de todas las transacciones disponibles
Entidades Involucradas
integrations.payment_providers
CREATE TABLE integrations.payment_providers (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES core_tenants.tenants(id),
provider_code VARCHAR(50) NOT NULL, -- 'mercadopago', 'clip', 'stripe'
display_name VARCHAR(100),
is_active BOOLEAN DEFAULT true,
is_default BOOLEAN DEFAULT false,
config JSONB DEFAULT '{}', -- Configuración específica
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
CONSTRAINT uq_provider_tenant UNIQUE (tenant_id, provider_code)
);
integrations.payment_credentials
CREATE TABLE integrations.payment_credentials (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
provider_id UUID NOT NULL REFERENCES integrations.payment_providers(id),
credential_type VARCHAR(50) NOT NULL, -- 'oauth', 'api_key'
-- Todos los campos sensibles encriptados con AES-256
access_token_encrypted BYTEA,
refresh_token_encrypted BYTEA,
expires_at TIMESTAMPTZ,
merchant_id VARCHAR(100), -- ID de cuenta en MercadoPago
environment VARCHAR(20) DEFAULT 'sandbox', -- 'sandbox', 'production'
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP
);
integrations.payment_transactions
CREATE TABLE integrations.payment_transactions (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL,
provider_id UUID NOT NULL REFERENCES integrations.payment_providers(id),
-- Referencias internas
order_id UUID, -- Orden de venta relacionada
invoice_id UUID, -- Factura relacionada
-- Datos de MercadoPago
external_id VARCHAR(100), -- ID en MercadoPago
external_reference VARCHAR(100), -- Nuestra referencia enviada
payment_type VARCHAR(50), -- card, ticket, bank_transfer
payment_method VARCHAR(50), -- visa, mastercard, oxxo, spei
-- Montos
amount DECIMAL(15,2) NOT NULL,
currency VARCHAR(3) DEFAULT 'MXN',
fee_amount DECIMAL(15,2), -- Comisión cobrada
net_amount DECIMAL(15,2), -- Monto neto recibido
-- Estado
status VARCHAR(50) NOT NULL, -- pending, approved, rejected, refunded
status_detail VARCHAR(100),
-- Tarjeta (si aplica)
card_last_four VARCHAR(4),
card_brand VARCHAR(20),
-- Terminal (si aplica)
terminal_id UUID REFERENCES integrations.payment_terminals(id),
-- Timestamps
created_at TIMESTAMPTZ DEFAULT CURRENT_TIMESTAMP,
approved_at TIMESTAMPTZ,
-- Metadata
raw_response JSONB, -- Respuesta completa de la API
CONSTRAINT chk_status CHECK (status IN ('pending', 'approved', 'rejected', 'cancelled', 'refunded', 'in_process'))
);
API de MercadoPago
Crear Payment Intent
// POST https://api.mercadopago.com/v1/payments
const paymentData = {
transaction_amount: 1500.00,
description: "Venta #ORD-2025-001",
payment_method_id: "visa",
payer: {
email: "cliente@email.com"
},
external_reference: "ORD-2025-001",
notification_url: "https://erp.example.com/webhooks/mercadopago",
metadata: {
tenant_id: "uuid-tenant",
order_id: "uuid-order"
}
};
Procesar Webhook
// POST /webhooks/mercadopago
interface MercadoPagoWebhook {
id: string;
type: 'payment' | 'merchant_order';
action: 'payment.created' | 'payment.updated';
data: {
id: string; // Payment ID
};
}
// Validar firma
const isValid = validateMercadoPagoSignature(
request.headers['x-signature'],
request.body,
webhookSecret
);
Terminales Point
Modelos Soportados
| Modelo | Conectividad | Características |
|---|---|---|
| Point Smart | WiFi, 4G | Pantalla táctil, impresora |
| Point Pro 2 | Bluetooth | Portable, NFC |
| Point Mini | Bluetooth | Básico, económico |
Vincular Terminal
// POST /api/v1/integrations/mercadopago/terminals
{
serialNumber: "MP-123456789",
displayName: "Caja 1",
locationId: "uuid-sucursal"
}
Seguridad
- OAuth Tokens: Encriptados con AES-256-GCM
- Webhook Signature: HMAC-SHA256 validation
- HTTPS: Obligatorio para todos los endpoints
- Rate Limiting: Respeto de límites de API
- Audit Log: Todas las transacciones logueadas
Manejo de Errores
| Código | Descripción | Acción |
|---|---|---|
cc_rejected_insufficient_amount |
Fondos insuficientes | Notificar, solicitar otro método |
cc_rejected_bad_filled_card_number |
Número inválido | Solicitar re-ingreso |
cc_rejected_call_for_authorize |
Llamar al banco | Contactar emisor |
pending_contingency |
En revisión | Esperar webhook |
Referencias
Dependencias
- RF Requeridos: Ninguno (módulo base)
- Bloqueante para: RF-MGN-016-004 (Gestión de Terminales), RF-MGN-016-005 (Conciliación)