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.
total:100 y el servidor guardó la suma real de los ítems
1 · Merge de feat/carrito-checkout → dev y producción
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.
| Commit | Contenido | Verificación |
|---|---|---|
| 7e67295 | Merge del flujo Carrito → Datos → Pago (4 archivos nuevos + amrstore/config/portal modificados) | E2E local Playwright OK |
| 6a22176 | Hardening de api-checkout.php (ver sección 2) + fix de ruta de DB en pedido.php | 5 pruebas OK |
| 1535cfe | Datos de pago reales + UI de QR y botón de pago en línea (checkout + pedido) | Verificado en prod |
| 43f7841 | Secció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)
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.
| Área | Antes | Después |
|---|---|---|
| Total | Confiable al cliente (fraude directo) | Recalculado en servidor desde los ítems saneados |
| Método de pago | Cualquier string aceptado | Whitelist contra config.json → 422 si no existe |
| Ítems | Campos extra y cantidades libres | Saneo campo a campo, qty 1–99, máx 100 ítems, payload cap 100 KB |
| Base de datos | Tocaba database.sqlite (CRM) | DB propia data/checkout.sqlite (gitignorada, directorio writable verificado en prod) |
pedido.php | 404 por ruta incorrecta de DB | Lee data/checkout.sqlite con guard is_file |
3 · Datos de pago reales + QR y link de pago
| Método | Dato | Estado en vivo |
|---|---|---|
| Nequi | 3186855106 · Anderson Mares | VERIFICADO EN PROD |
| Daviplata | 3168265737 · Anderson Mares | EN CONFIG |
| Bancolombia | 10312669607 · Ahorros · Anderson Mares | EN CONFIG |
| USDT BEP-20 | Sin wallet disponible | ELIMINADO |
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.
| Endpoint | Función | Validaciones |
|---|---|---|
| api=get_payments | Lee los métodos de config.json | Sesión admin requerida (401 si no) |
| api=save_payments | Valida 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_qr | Sube 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 |
| Prueba | Entrada | Resultado |
|---|---|---|
Sin sesión → save_payments | POST sin cookie | 401 ✓ |
| Roundtrip de guardado | Los 3 métodos actuales | config.json semánticamente idéntico ✓ |
| Payload malicioso | <script> en id · javascript: en link · path traversal en QR | Todo saneado/rechazado ✓ |
| Upload PNG válido (x2) | Imagen real | Guarda y reemplaza (1 archivo) ✓ |
| Upload .txt y PHP renombrado a .png | Archivos no-imagen | 422 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 vivo | Resultado |
|---|---|---|
| 1 | checkout.php, carrito.php, amrstore.php responden | 200 / 200 / 200 ✓ |
| 2 | Etiqueta duplicada «Streaming · Streaming» en amrstore | 0 ocurrencias en vivo ✓ |
| 3 | POST create con total:100 fraudulento (ítems = 2 × $18.000) | Pedido #1001 guardó $36.000 ✓ |
| 4 | Método de pago inexistente (bitcoin) | HTTP 422 ✓ |
| 5 | pedido.php?id=… del pedido de prueba | 200 · #1001 · Nequi 3186855106 · total 36.000 · titular ✓ |
| 6 | Limpieza: DELETE del pedido de prueba vía SSH | 0 órdenes restantes · 404 al reconsultar ✓ |
| 7 | Seguridad perimetral (HSTS, nosniff, frame-options, TTFB) | Cabeceras intactas · TTFB ~0.4 s ✓ |
6 · Evaluación: conexión de la API de Wompi
payment_link + botón renderizado).
| Vía | Cómo funciona | Encaje con el flujo actual | Esfuerzo |
|---|---|---|---|
| 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 |
- Métodos soportados: tarjeta, Nequi, PSE, Bancolombia Transfer y Collect (COP únicamente).
- Requisitos: cuenta de comercio Wompi · llaves
pub_prod_/prv_prod_(la privada solo en servidor) · token de aceptación · firma de integridad (HMAC) · webhook público. - Validación de pagos: Wompi exige validar por webhook + consulta API, nunca por la redirección del navegador.
- Impacto en seguridad: Fase 1/2 requieren guardar la llave privada en
env.phpy firmar solicitudes — patrón ya compatible con la arquitectura actual.
7 · Evaluación: conexión de la API de Dropi
docs/dropi_products_*.json) o ingesta POST → MySQL dropshipping_products
(api-dropshipping.php, 918 líneas, 0 referencias a api.dropi.co).
| Servicio Dropi | Endpoint / uso | Estado en nuestro sistema |
|---|---|---|
| Login (token) | POST login → Bearer TOKEN | FALTA CREDENCIAL — código interno ya prevé «migrar a token en Fase 1» |
| Crear orden | POST con products{id,price,quantity}, payment_method_id=1 | GAP: requiere dir, phone, dni del cliente — el checkout solo pide nombre/email |
| Consultar/listar órdenes | GET por ID, guía o filtros | Mapeable: la tabla ya guarda dropi_id por producto |
| Guía PDF / estado | PUT genera guía · GET estados | Desbloquea tracking de entrega en pedido.php |
| Cotizador de flete | POST con códigos DANE | Posible mostrar costo de envío en checkout |
- Camino recomendado: (1) pedir credenciales/token Dropi → (2) ampliar el paso «Datos» del checkout con ficha de envío (dirección, ciudad, teléfono, cédula) → (3) endpoint
api-checkoutque disparecrear ordenen Dropi tras confirmar el pago → (4) sincronizar estados/guía al pedido. - Beneficio: pedidos automáticos con guía y opción contraentrega (recaudo), eliminando el paso manual en el panel Dropi.
- Esfuerzo estimado: ≈ 2–3 días (ficha de envío + endpoint + token + reintentos), una vez se reciban las credenciales.
- Riesgo: sin token de Dropi no hay forma de probar; los campos obligatorios amplían el alcance del checkout.
8 · Recomendaciones priorizadas (roadmap de venta)
| Prioridad | Acción | Depende de |
|---|---|---|
| P0 | Subir 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 |
| P0 | Cron/panel para revisar pedidos pendientes (hoy solo se ven en la BD del servidor) | Definir canal de notificación (email/WhatsApp) |
| P1 | Wompi Fase 1/2: links dinámicos o widget + webhook para pagos automáticos | Llaves de comercio Wompi |
| P1 | Ficha de envío en checkout + creación automática de órdenes en Dropi | Token/cuenta de API Dropi |
| P2 | Bloque de testimonios/confianza (pendiente del plan REPLICAR fase 3) | Contenido real de clientes |
| P2 | Limpieza de legacy en prod (.old.-install.php, error_log, demos 14-*.html, amr/, crm/) — protegidos en el deploy, pendiente aprobación | Aprobación explícita de borrado |