Pocapay mas técnico
Apartado técnico de POCAPAY
🎵 POCAPAY GO — Mega Resumen de Funcionalidades
Todo lo que se pensó, diseñó y construyó
🛍️ MODELO DE NEGOCIO DUAL
POCAPAY no es una tienda online común. Tiene DOS modelos de venta integrados:
1. PRODUCTOS (E-commerce tradicional)
- Catálogo de productos K-pop con variantes (versiones de álbumes, tamaños, etc.)
- Inventario en tiempo real con stock por variante
- Preventas con fecha de estreno y fin de preventa
- Productos importados con aviso de EMS/aduanales
- Backorder (pedido sin stock, con límite de cantidad)
2. CLAIMS (Compra grupal / Preventa especial)
- Sistema exclusivo para K-pop: compras grupales desde tiendas coreanas
- El cliente elige su MEMBER (miembro del grupo) específico
- Secciones por tipo: photocard, fansign, meet & call, etc.
- Tienda origen: Korea, Japón, China, etc.
- Deadline de pago configurable
- Tracking de EMS + costos de aduana integrados
🔒 ANTI-SOBREVENTA: 16 Mecanismos de Protección
Esto es lo que diferencia POCAPAY de una tienda básica:
Reserva con Lock (5 minutos)
- Cuando un cliente hace checkout, se CREA un ReservationLock con token único
- El stock se descuenta ATÓMICAMENTE (no puede haber sobreventa concurrente)
- Si no paga en 5 minutos → se libera automáticamente el stock
- Self-healing: antes de cada nueva reserva, se limpian todas las expiradas
Decremento Atómico de Stock
- UPDATE products SET inventoryQuantity = inventoryQuantity - X
- WHERE inventoryQuantity >= X ← CLAVE: si no hay stock suficiente, no se descuenta
- Esto previene que 2 clientes compren la última unidad al mismo tiempo
PendingOrder (Snapshot de Reserva)
- Se guarda TODO el pedido (productos, dirección, total) por 30 minutos
- Si la reserva expira pero el pago llega después → el webhook puede crear la orden desde el snapshot
- Upsert: si el cliente reintenta, actualiza el snapshot existente
Claim Member Stock Control
- Cada miembro de un claim tiene
claimedQtyytotalQty - UPDATE claim_members SET claimedQty = claimedQty + 1
- WHERE claimedQty < totalQty ← No se puede exceder el límite
Bloqueo Automático de Claims
- Los claims se bloquean cuando se alcanza el límite de stock
isLockedse activa → no acepta más reservas- Deadline de pago configurable por claim
Cancelación Automática de Órdenes Expiradas
- Cron job cada 10 minutos revisa órdenes pendientes
- Si pasó el deadline → libera stock, cancela la orden, notifica al usuario
- Cada orden se procesa en su propia transacción (un fallo no afecta las demás)
Liberación de Reservas Expiradas
- Cron job cada 5 minutos libera todos los ReservationLock expirados
- Stock se restaura automáticamente
Webhook HMAC-SHA256
- Verificación de firma del webhook de MercadoPago
crypto.timingSafeEqualpreviene ataques de timing- Deduplicación en memoria por x-request-id (max 10,000 entries)
- Idempotencia en DB: si la orden ya existe con status "payment_confirmed", no duplica
Verificación Server-Side del Pago
- NO confía en el payload del webhook
- Consulta directamente la API de MercadoPago para verificar el monto
- Compara monto pagado vs monto esperado (tolerancia ±$1 MXN)
- Alerta al admin si hay discrepancia
Cupones Anti-Abuso
- Límite de uso global (usageLimit)
- Límite por cliente (CouponRedemption por usuario)
- Restricción por producto y/o categoría
- Monto mínimo de orden
- Incremento atómico del contador de uso en SQL crudo
Rate Limiting
- 20 req/min en rutas de autenticación
- 60 req/min en otras APIs
- 3 req/min en newsletter y contacto
- Headers: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset
- 429 con Retry-After header
Protección IDOR
- En pay, preference, cancel → verifica que el userId del request coincida con el de la orden
- No puede pagar/cancelar órdenes de otro usuario
Tokens Criptográficos
crypto.randomBytespara tokens de pago y números de orden- Formato: "poc_" + 8 chars aleatorios, "POC-YYYYMMDD-XXXX"
💳 PAGOS: MercadoPago Integration
- Checkout Pro (redirect a MercadoPago)
- Preferencias expiran en 30 minutos (binary_mode=true)
- Manejo de todos los estados: approved, rejected, cancelled, refunded, charged_back
- Webhook con verificación HMAC
- Rechazo → libera reserva + elimina PendingOrder
- Pruebas: filtra notificaciones de test (data.id="123456", live_mode=false)
🚚 ENVÍOS: Sistema Dual
Envío Manual
- Opciones configurables por el admin (nombre, precio, rangos de peso)
- Filtrado por peso del pedido
DrEnvio API (Tiempo Real)
- Cotizaciones en tiempo real de FedEx, Estafeta, DHL, AM/PM
- Generación de etiquetas de envío
- Fallback: si DrEnvio falla, muestra solo opciones manuales
- Normalización de direcciones (múltiples formatos de input)
Tracking Internacional
- Estado de EMS (envío internacional desde Korea)
- Costos de aduana
- Pago de aduana inline con MercadoPago
- Gallery de fotos de prueba de compra
🎨 EXPERIENCIA DE USUARIO
Diseño
- Dark/Light mode con persistencia en localStorage
- Prevención de FOUC (flash de unstyled content)
- Glassmorphism en header con scroll
- Fonts custom: Cabinet Grotesk, Satoshi, Nunito
- Animaciones suaves, blobs decorativos, wave dividers
Navegación
- Sticky header con efecto blur
- Mega menú de categorías
- Breadcrumbs en productos
- Mobile: drawer deslizante desde la derecha (85vw)
- Scroll lock cuando el drawer está abierto
Productos
- Galería de imágenes múltiple
- Selector de variantes (versiones de álbum)
- Indicador de stock bajo (< 4 unidades)
- Estado de agotado / backorder / preventa
- Reviews con ratings
- Wishlist (corazón)
- Breadcrumbs
Claims
- Selector de MEMBER (tu bias del grupo)
- Badge con color por tipo (gradientes)
- Countdown timers en claims activos
- Agrupación por grupo de K-pop
Carrito y Checkout
- Zustand-based cart
- Badge con contador en header
- Multi-step: init → confirmed → paying → done
- Timer de reserva de 5 minutos con countdown
- Cupones (porcentaje + monto fijo)
- Guardar/seleccionar direcciones
- Selector de cotización de envío
Contacto
- Float buttons: WhatsApp + Email (bottom-right)
- Formulario de contacto
- Newsletter con popup de bienvenida (10% descuento, 3s delay)
Empty States
- Diseñados con iconos y CTAs
- "No hay eventos activos" → link a productos
- "No hay productos destacados" → link a claims
📱 RESPONSIVE / MOBILE
- Mobile-first design
- Grid: 1 col → 2 col → 3/4 col
- Hero carousel aspect ratio: 4/3 (mobile) → 16/9 (tablet) → 1240/500 (desktop)
- Touch targets mínimos 44x44px
active:scale-[0.97]en botones (feedback táctil)- Search bar colapsable en mobile
- Search dentro del drawer mobile
- Flechas del carousel siempre visibles en mobile
🔍 SEO PROFESIONAL
Metadata
- Title template: "%s — POCAPAY GO"
- OpenGraph por página (claims, productos)
- Twitter cards: summary_large_image @pocapaygo
- Canonical URLs en páginas clave
- Truncado: título 60 chars, descripción 155 chars
JSON-LD (Structured Data)
- Organization: nombre, URL, logo, redes sociales, contacto
- WebSite: SearchAction (caja de búsqueda en Google)
- Product: nombre, precio, MXN, disponibilidad, marca, SKU
- BreadcrumbList: navegación en productos
Sitemap Dinámico
- Generado desde la base de datos
- Prioridades: home (1.0), claims (0.9), products (0.9), groups (0.7)
- changeFrequency y priority por tipo de página
Robots.txt
- Allow all por defecto
- Disallow: /api/, /auth/, /claims/admin
OG Images Dinámicas
- Endpoint /api/og para generar imágenes de Open Graph
⚡ RENDIMIENTO
Next.js
- output: "standalone" (imagen Docker mínima)
- ISR: revalidate = 60 en homepage
- experimental.optimizePackageImports: lucide-react, framer-motion, @radix-ui
Imágenes
- AVIF + WebP formats
- deviceSizes: [640, 750, 828, 1080]
- Cache TTL mínimo: 30 días
- Priority loading en primeras 5 imágenes de grupos
- Hero carousel primer slide: fetchPriority="high"
Caching
- Assets estáticos: immutable, 1 año
- /uploads/*: immutable, 1 año
- /_next/image: 30 días, stale-while-revalidate=1 día
- ISR: 60 segundos en homepage
Data Fetching
- Promise.all para carga paralela (homepage, sitemap)
- React Query (TanStack Query) para datos del cliente
- Server Components para carga inicial
- Suspense boundaries para loading states
🛡️ SEGURIDAD
Autenticación
- better-auth con Prisma adapter
- Session cookies: httpOnly, sameSite="lax", secure
- Sesión: 7 días, refresh cada 24h
- Roles: user (default), admin
- Google OAuth
Headers de Seguridad
- X-Frame-Options: DENY
- X-Content-Type-Options: nosniff
- Referrer-Policy: strict-origin-when-cross-origin
- Permissions-Policy: camera=(), microphone=(), geolocation=()
- HSTS: max-age=63072000, includeSubDomains, preload
- CSP detallada (permite MercadoPago, analytics)
- COOP: same-origin-allow-popups
- CORP: same-origin
- X-DNS-Prefetch-Control: on
Protecciones Adicionales
- Brute-force protection en Admin Assistant API (5 intentos → 15 min lockout)
- Deploy webhook verification con timingSafeEqual
- Escape de HTML en emails (XSS prevention)
📧 COMUNICACIÓN
Emails Transaccionales (Resend)
- Confirmación de orden
- Actualización de estado
- Recordatorio de pago (urgencia)
- Producto de vuelta en stock (wishlist)
Broadcasts
- Segment-based targeting via Resend contacts/topics
- Admin-only
- Newsletter subscription con rate limit
Notificaciones In-App
- Bell icon en header
- Preferencias de notificación
- Tipos: info, success, warning, error
- notifyAdmin() para alertas internas
🎯 PANEL DE ADMINISTRACIÓN
15+ secciones en el admin:
- Dashboard: métricas y overview
- Productos: CRUD completo con editor de 8 secciones
- Claims: CRUD con editor de 5 secciones
- Pedidos: gestión de órdenes
- Usuarios: gestión de clientes, banning
- Categorías: CRUD jerárquico
- Envíos: opciones manuales + DrEnvio config
- Hero Banners: carrusel de homepage
- Broadcasts: campañas de email
- Audiencias/Segments: segmentación de clientes
- Descuentos/Cupones: creación y gestión
- Comebacks: tracking de comebacks de grupos
- Config: settings del sitio
- Tiendas (Stores): CRUD de tiendas
- Pricing Calculator: calculadora de costos KRW→MXN
Admin Assistant API
- Endpoint headless para crear entidades desde CLI/Telegram
- Acciones: createStore, createGroup, createComeback, createProduct, createClaim, createCategory, listGroups, listStores, listComebacks
- API key con brute-force protection
📄 PÁGINAS DEL SITIO (20+)
Públicas
- / — Homepage (hero carousel, groups, claims, products)
- /claims — Listado de claims
- /claims/[id] — Detalle de claim (member selector, claim button)
- /claims/grupo/[id] — Claims filtrados por grupo
- /claims/acerca-de — Acerca de claims
- /products — Catálogo con filtros, búsqueda, paginación
- /products/[slug] — Detalle (gallery, variantes, reviews, breadcrumbs)
- /groups — Listado de grupos
- /groups/[slug] — Feed del grupo
- /categories — Categorías
- /categories/[slug] — Productos por categoría
- /contacto — Formulario de contacto
- /preguntas-frecuentes — FAQ
- /terminos-y-condiciones — T&C
- /aviso-de-privacidad — Aviso de privacidad (LFPDPPP México)
Autenticación
- /auth/signin — Login
- /auth/register — Registro
Usuario
- /account — Perfil
- /account/notifications — Preferencias
- /orders — Mis Pedidos (con tracking EMS + aduana)
- /wishlist — Favoritos
- /cart — Carrito
- /checkout — Checkout completo
- /checkout/success — Post-pago
🧮 COST ACCOUNTING
- FIFO (First In, First Out) para costos de inventario
- InventoryCostLayer: tracking de costo por lote de compra
- CogsEntry: registro de costo de mercancía vendida
- Pricing calculator: conversión KRW → MXN con configuración de margen
🔔 CRON JOBS (Automatización)
- cancel-expired-orders (cada 10 min): cancela órdenes sin pago, libera stock
- release-reservations (cada 5 min): libera reservas expiradas
- check-stock (configurable): notifica a suscriptores de wishlist cuando hay stock
Todos autenticados con CRON_SECRET + timingSafeEqual.
📊 ANALYTICS
- Umami self-hosted (analytics.pocapay.com)
- Sin dependencia de Google Analytics
- Privacidad del usuario respetada
🏗️ STACK TECNOLÓGICO
- Frontend: Next.js 16, React 19, Tailwind CSS v4
- Backend: Next.js API Routes + Server Actions
- Database: PostgreSQL + Prisma 7
- Auth: better-auth
- Payments: MercadoPago (Checkout Pro)
- Shipping: DrEnvio API + manual
- Email: Resend
- Analytics: Umami (self-hosted)
- Hosting: Dokploy (Docker, auto-redeploy)
- DNS: A root + CNAME subs, Traefik compress middleware
💡 DECISIONES DE DISEÑO INTELIGENTES
- "Desde $X" + require variant selection → Fans quieren versiones específicas, no auto-select
- Claims con member selector → El fan elige su bias, no recibe aleatorio
- Reserva de 5 minutos → Suficiente para pagar, no suficiente para acaparar
- Snapshot de PendingOrder → Si el pago llega tarde, no se pierde la orden
- Dual shipping → DrEnvio para cotización real + manual como fallback
- Admin Assistant API → Gestión headless desde CLI/Telegram sin navegador
- JSON-LD completo → Google muestra rich snippets de productos
- OG images dinámicas → Cada producto/claim tiene su imagen de compartición
- FIFO cost accounting → Margen real por producto, no estimado
- Newsletter popup con 10% → Captura de leads con incentivo inmediato
- Floating WhatsApp → Contacto directo sin fricción (K-pop fans usan WhatsApp)
- Dark mode con anti-FOUC → Sin flash blanco al cargar en dark mode
- Cron jobs self-healing → Reservas expiradas se limpian automáticamente
- Webhook server-side verification → No confía en el payload, verifica con MP directamente
- 30+ modelos en Prisma → Arquitectura escalable para crecer
Documento generado el 22 de mayo 2026 POCAPAY GO — K-pop e-commerce para México
