En ninguna de las dos etapas trabajas contra un guion nuestro. La etapa 1 no te pide preparar nada: OnePay la hace sobre el tráfico que ya generaste en sandbox, revisando tus llamadas reales.La etapa 2 la corres por tu cuenta, con tu llave de producción, cuando estés listo. Al terminar nos entregas los
id y nosotros analizamos el flujo de peticiones y el del pago del lado de OnePay. No hace falta agendar nada ni esperar a que estemos conectados.- Requisito — sin esto no se homologa.
- Recomendación — no bloquea la homologación, pero es lo que hace que la integración aguante en producción.
Prerrequisitos
Tu llave
sk_live_ la generas tú desde el panel de administración. La homologación no te la retiene: la necesitas para correr la etapa 2.Lo que sí depende de este proceso es la salida a producción de la compañía: OnePay la habilita cuando la homologación queda aprobada, así que conviene cerrarla antes de planear la fecha de salida.Etapa 1 · Validación por endpoint
Crear factura — POST /v1/invoices
Por qué el reintento va con el mismo cuerpo: si repites el
POST con un cuerpo idéntico, la deduplicación te devuelve el mismo id y no se duplica el cobro. Un reintento con datos cambiados no es un reintento — crea un cobro nuevo.Actualizar factura — PUT /v1/invoices/{id}
El contacto se hereda. Si el
PUT no trae phone ni email, el cobro de reemplazo conserva los del cobro anterior. Enviarlos sirve para actualizarlos; no es obligatorio para que el cobro llegue.Cancelar factura — DELETE /v1/invoices/{id}
Los dos motivos de cancelación no son intercambiables: cada uno corresponde a una situación real distinta.
Para qué sirve
payment_method: es el medio con el que el cliente pagó por fuera de OnePay. Texto libre de hasta 60 caracteres — Efectivo, Nequi, Consignación Bancolombia. Sin él, OnePay sabe que la factura se pagó afuera pero no sabe cómo.El
404 de desajuste de ambiente aparece cuando consultas una factura de sandbox con la llave de producción o al revés. Es terminal: reintentarlo no cambia nada, hay que revisar qué llave está usando el proceso.Webhooks
Por qué
invoice.paid es el mínimo: es el evento que cierra el ciclo de cobro. Sin él no te enteras de que una factura se pagó en OnePay y tu sistema queda desincronizado.La firma se calcula sobre el cuerpo crudo.
Signature es un HMAC-SHA256 sobre los bytes tal como llegaron. Deserializar el JSON y volver a serializarlo antes de calcular el HMAC cambia el cuerpo y rompe la firma, aunque el contenido sea equivalente. Ver Verificar la firma.Por qué la idempotencia importa: los reintentos pueden entregarte el mismo evento dos veces. Sin idempotencia por
invoice.id + tipo de evento, un reintento se convierte en un pago registrado dos veces en tu sistema.Etapa 2 · Corrida integral
Es la misma secuencia de la etapa 1, pero ejecutada de punta a punta con tu llavesk_live_ y sobre facturas nuevas. Al correr en producción son facturas reales de tus clientes: el dinero se mueve y los mensajes salen normalmente. Al terminar nos entregas el id de OnePay de cada paso, y nosotros revisamos el flujo de peticiones y el del pago para confirmar que cada resultado esperado se dio.
1
Crear la factura, dos veces con el mismo cuerpo
POST /v1/invoices con el payload completo, enviado dos veces con el mismo cuerpo. Usa un monto bajo: esta factura se paga de verdad en el paso 2.Esperado: ambas respuestas 201 y con el mismo id. Si el segundo 201 trae un id distinto, hay un cobro duplicado.2
Pagar la factura
Paga el
payment.payment_link. Es un pago real: el dinero se mueve y se liquida como cualquier otro cobro, con su comisión.Esperado: llega invoice.paid con el pago aprobado, la factura queda en CONCILIATED, y en tu sistema queda marcada como pagada. Este último punto se verifica con evidencia de tu lado: es el paso que demuestra que el webhook no solo llega, sino que cierra el ciclo.3
Actualizar otra factura
PUT /v1/invoices/{id} cambiando el monto de otra factura.Esperado: 200 con un payment_id nuevo. El cobro conserva el teléfono de la factura original y llega por WhatsApp.4
Cancelar por pago externo
DELETE /v1/invoices/{id} con reason: PAID_FROM_PROVIDER, provider_payment_id y payment_method.Esperado: 204. La factura sobrevive en estado PAID_FROM_PROVIDER con el método registrado — no se borra. Si la factura tiene teléfono, el cliente recibe el recibo en PDF por WhatsApp.5
Cancelar por anulación
DELETE /v1/invoices/{id} con reason: DELETE_FROM_PROVIDER sobre otra factura.Esperado: 204. La factura se elimina.6
Intentar cancelar la factura ya pagada
DELETE /v1/invoices/{id} sobre la factura que pagaste en el paso 2.Esperado: 409, registrado en tu sistema como “ya pagada en OnePay” y sin reintentos.Los pasos 4 y 5 son los que más seguido revelan un problema: son el mismo endpoint con dos comportamientos distintos, y una integración que trata los dos motivos por igual falla ahí.
Salida a producción
Con las etapas 1 y 2 cerradas:- Salida a producción habilitada por OnePay, y tu webhook de producción configurado con
secrety los mismos eventos que homologaste. - Primera factura real acompañada de punta a punta: creación, envío, pago y conciliación, con OnePay presente.
- Retiro de las facturas de prueba que hayan quedado en sandbox.
- Monitoreo de las primeras 72 horas: entregas de webhook, tasa de
422y cobros duplicados.