FOLIO: AUD-20261001-003 Secuencia: Informe #003 del día 2026-10-01
📅 2026-10-01 23:15:00 COT 👤 Auditor: Anderson Mares (AMR TECH) ● VIGENTE
ENTREGADO: CHECKOUT EN PROD + PAGOS PARAMETRIZABLES 4 commits (7e67295 · 6a22176 · 1535cfe · 43f7841) Suite 26/26 · E2E prod ✓ · Deploy 0 borrados

Merge del carrito/checkout a producción, blindaje del API de pedidos, pagos reales con QR/link parametrizables desde el admin y evaluación de integración con Wompi y Dropi

Continuación directa de los informes AUD-20261001-001 (archivo 45 · implementación del flujo) y AUD-20261001-002 (archivo 46 · ítems REPLICAR + CSP). Este documento certifica el merge, endurecimiento, despliegue y verificación en vivo del flujo Carrito → Checkout → Pedido con métodos de pago reales (Nequi, Daviplata, Bancolombia), la nueva sección «Métodos de Pago» del panel admin para editar números, subir QR y pegar links de pago desde la web, más la evaluación técnica de factibilidad para conectar las APIs de Wompi (pagos en línea) y Dropi (órdenes automáticas de dropshipping). Todo verificado con suite PHP, requests HTTP y navegador real contra streamingapps.online.

7 / 7
Archivos del merge desplegados a producción (carrito, checkout, pedido, api-checkout, amrstore, config.json, .gitignore)
$100 → $36.000
Intento de fraude de total bloqueado en producción: el cliente envió total:100 y el servidor guardó la suma real de los ítems
3 / 3
Métodos de pago con datos reales en vivo: Nequi 3186855106 · Daviplata 3168265737 · Bancolombia 10312669607 (Ahorros)
5 / 5
Pruebas del nuevo API admin aprobadas (401 sin sesión · roundtrip idéntico · sanitización maliciosa · PNG válido · .txt/.php rechazados)
26/26
Suite PHP en host (100%) tras cada bloque antes de commit y deploy
0
Órdenes de prueba residuales y 0 archivos borrados en prod (limpieza vía SSH verificada con 404 posterior)

1 · Merge de feat/carrito-checkout → dev y producción

La rama feat/carrito-checkout (commit 396c93e) se fusionó en dev (7e67295) resolviendo 4 conflictos: en amrstore.php ganaron los fixes de la sesión anterior (bloque .price-from y .product-tag oculto en móvil, ambos verificados visualmente) y en auditorias/index.html se conservaron ambas filas de informes. El carrito nunca había sido desplegado: el dry-run rsync confirmó 4 archivos nuevos (f+++++++) en producción.
CommitContenidoVerificación
7e67295Merge del flujo Carrito → Datos → Pago (4 archivos nuevos + amrstore/config/portal modificados)E2E local Playwright OK
6a22176Hardening de api-checkout.php (ver sección 2) + fix de ruta de DB en pedido.php5 pruebas OK
1535cfeDatos de pago reales + UI de QR y botón de pago en línea (checkout + pedido)Verificado en prod
43f7841Sección «Métodos de Pago» en el panel admin (ver sección 4)5 pruebas OK

E2E local (Playwright): agregar al carrito → badge «1» → carrito $36.000 → checkout con los métodos → submit → Pedido #1003 renderizado con referencia de comprobante → 0 errores de consola.

2 · Hardening del API de pedidos (api-checkout.php)

Vulnerabilidad confirmada y corregida: el total del pedido venía del cliente y se guardaba tal cual (ataque real: total:100 → se persistía $100 mientras los ítems sumaban $50.000). Hoy el servidor siempre recalcula total = Σ(price × qty) e ignora el total externo.
ÁreaAntesDespués
TotalConfiable al cliente (fraude directo)Recalculado en servidor desde los ítems saneados
Método de pagoCualquier string aceptadoWhitelist contra config.json → 422 si no existe
ÍtemsCampos extra y cantidades libresSaneo campo a campo, qty 1–99, máx 100 ítems, payload cap 100 KB
Base de datosTocaba database.sqlite (CRM)DB propia data/checkout.sqlite (gitignorada, directorio writable verificado en prod)
pedido.php404 por ruta incorrecta de DBLee data/checkout.sqlite con guard is_file

3 · Datos de pago reales + QR y link de pago

MétodoDatoEstado en vivo
Nequi3186855106 · Anderson MaresVERIFICADO EN PROD
Daviplata3168265737 · Anderson MaresEN CONFIG
Bancolombia10312669607 · Ahorros · Anderson MaresEN CONFIG
USDT BEP-20Sin wallet disponibleELIMINADO

Se agregaron dos campos por método en config.json: qr_image (ruta /data/pagos/…) y payment_link (URL https). La UI los consume de forma condicional: el checkout muestra chips «QR disponible» / «Pago en línea», y la página del pedido renderiza el bloque QR con imagen y el botón «Pagar en línea (tarjeta o link de pago)» (target _blank + rel=noopener) solo cuando los campos tienen valor. Mientras estén vacíos, el flujo manual tradicional sigue intacto — verificado en prod (pedido #1001: número y titular reales correctos; QR/botón ocultos por diseño al ir vacíos).

4 · Sección «Métodos de Pago» en el panel admin

Nueva pestaña en admin-amrtech.php para parametrizar los pagos desde la web sin tocar archivos: editar números/titulares, subir el QR del comercio y pegar el link de pago de Wompi. Todo persiste en config.json y aplica de inmediato al checkout y al pedido.

EndpointFunciónValidaciones
api=get_paymentsLee los métodos de config.jsonSesión admin requerida (401 si no)
api=save_paymentsValida y escribe config.json (LOCK_EX)IDs saneados [a-z0-9_-], sin duplicados, máx 20 métodos, campos con límite de longitud, qr_image restringido a /data/pagos/…, payment_link solo http(s), claves desconocidas descartadas
api=upload_payment_qrSube el QR a data/pagos/ (crea el dir si no existe)Mime real vía getimagesize (PNG/JPG/WEBP), máx 2 MB, nombre aleatorio, reemplaza QRs anteriores del mismo método, chmod 0644
PruebaEntradaResultado
Sin sesión → save_paymentsPOST sin cookie401 ✓
Roundtrip de guardadoLos 3 métodos actualesconfig.json semánticamente idéntico ✓
Payload malicioso<script> en id · javascript: en link · path traversal en QRTodo saneado/rechazado ✓
Upload PNG válido (x2)Imagen realGuarda y reemplaza (1 archivo) ✓
Upload .txt y PHP renombrado a .pngArchivos no-imagen422 rechazado ✓

Nota de despliegue: la carpeta data/pagos/ quedó gitignorada (los QRs viven solo en el servidor) y el directorio data/ ya fue verificado writable en producción.

5 · Verificación end-to-end en producción

#Prueba en vivoResultado
1checkout.php, carrito.php, amrstore.php responden200 / 200 / 200 ✓
2Etiqueta duplicada «Streaming · Streaming» en amrstore0 ocurrencias en vivo ✓
3POST create con total:100 fraudulento (ítems = 2 × $18.000)Pedido #1001 guardó $36.000 ✓
4Método de pago inexistente (bitcoin)HTTP 422 ✓
5pedido.php?id=… del pedido de prueba200 · #1001 · Nequi 3186855106 · total 36.000 · titular ✓
6Limpieza: DELETE del pedido de prueba vía SSH0 órdenes restantes · 404 al reconsultar ✓
7Seguridad perimetral (HSTS, nosniff, frame-options, TTFB)Cabeceras intactas · TTFB ~0.4 s ✓

6 · Evaluación: conexión de la API de Wompi

Veredicto: FACTIBLE y de bajo riesgo. Wompi (pasarela de Grupo Bancolombia, solo COP) ofrece tres vías de integración y el checkout actual ya está preparado para recibirlas (campo payment_link + botón renderizado).
VíaCómo funcionaEncaje con el flujo actualEsfuerzo
Fase 0 · Link estático
(dashboard, sin API)
Se genera https://checkout.wompi.co/l/:id desde el panel de Wompi y se pega en el admin SIN CÓDIGO — listo hoy
El campo payment_link + botón ya están desplegados
0 (solo tener cuenta Wompi)
Fase 1 · Link dinámico por pedido POST /v1/payment_links con Bearer prv_…, monto fijo (amount_in_cents), redirect_url a pedido.php Link con el total exacto del carrito, creado al confirmar el pedido ≈ 0.5–1 día + llave privada en servidor
Fase 2 · Widget/Web Checkout + Webhook Formulario a checkout.wompi.co/p/ o widget JS con firma de integridad; webhook (evento) marca payment_status Pago con tarjeta/Nequi/PSE/Bancolombia Transfer inline y estado de pago automático en el pedido ≈ 1–2 días + URL webhook pública

7 · Evaluación: conexión de la API de Dropi

Veredicto: FACTIBLE con 1 gap de datos. La API de Dropi permite crear órdenes y rastrear guías con token Bearer. El repositorio hoy no llama a la API: el catálogo entra por scraper (docs/dropi_products_*.json) o ingesta POST → MySQL dropshipping_products (api-dropshipping.php, 918 líneas, 0 referencias a api.dropi.co).
Servicio DropiEndpoint / usoEstado en nuestro sistema
Login (token)POST login → Bearer TOKENFALTA CREDENCIAL — código interno ya prevé «migrar a token en Fase 1»
Crear ordenPOST con products{id,price,quantity}, payment_method_id=1GAP: requiere dir, phone, dni del cliente — el checkout solo pide nombre/email
Consultar/listar órdenesGET por ID, guía o filtrosMapeable: la tabla ya guarda dropi_id por producto
Guía PDF / estadoPUT genera guía · GET estadosDesbloquea tracking de entrega en pedido.php
Cotizador de fletePOST con códigos DANEPosible mostrar costo de envío en checkout

8 · Recomendaciones priorizadas (roadmap de venta)

PrioridadAcciónDepende de
P0Subir el QR de Nequi/Daviplata y el link de Wompi desde la nueva pestaña del admin (Fase 0)Tener la cuenta/comercio Wompi y el QR del banco
P0Cron/panel para revisar pedidos pendientes (hoy solo se ven en la BD del servidor)Definir canal de notificación (email/WhatsApp)
P1Wompi Fase 1/2: links dinámicos o widget + webhook para pagos automáticosLlaves de comercio Wompi
P1Ficha de envío en checkout + creación automática de órdenes en DropiToken/cuenta de API Dropi
P2Bloque de testimonios/confianza (pendiente del plan REPLICAR fase 3)Contenido real de clientes
P2Limpieza de legacy en prod (.old.-install.php, error_log, demos 14-*.html, amr/, crm/) — protegidos en el deploy, pendiente aprobaciónAprobación explícita de borrado