Saltar al contenido principal

Salir a producción

Lo que separa una integración que funciona en tu portátil de una que aguanta el lunes por la mañana. Ninguno de estos puntos es teórico: todos son formas de perder dinero o clientes que hemos visto de cerca.


Antes del primer cobro real​

Credenciales​

  • Una credencial por sistema, con los alcances mínimos. Si un solo secreto está repartido entre tu tienda, tu ERP y tres terminales, no puedes revocar ninguno sin tumbar los cinco.
  • El secreto vive en tu gestor de secretos o en variables de entorno. Nunca en el repositorio, nunca en el navegador, nunca en un .env commiteado.
  • Restringe por IP si tu integración sale siempre desde las mismas.
  • Tienes escrito cómo rotar. El día que haga falta no es el día de averiguarlo.

Idempotencia​

  • Toda llamada que crea o modifica manda Idempotency-Key. Es obligatoria, así que si no lo haces ya lo sabes — pero asegúrate de que la clave sea tu identificador de negocio (el número de pedido, el de ticket), no un aleatorio nuevo en cada intento. Un aleatorio no protege de nada: el reintento genera otra clave y otro cobro.
  • Tus reintentos de 5xx reusan la misma clave.

Webhooks​

  • Verificas la firma antes de procesar nada. → Cómo
  • Firmas el cuerpo crudo, no el objeto re-serializado. Es el error número uno y el síntoma no apunta a la causa.
  • Respondes 2xx rápido y haces el trabajo pesado aparte. Cada intento tiene 10 segundos.
  • Guardas los id de evento y descartas los repetidos. La entrega es «al menos una vez».
  • Tu servidor no sigue redirecciones: un 3xx cuenta como fallo y no lo seguimos.

Conciliación​

  • No dependes sólo de los webhooks. Para cuadrar contabilidad, GET /v1/transactions y GET /v1/payment_links son el estado real.
  • Comparas contra el amount del enlace, no contra lo que mandó el pagador. En un pago cruzado son cifras distintas y sólo la primera es predecible. → Pagos cruzados
  • Registras el request_id de cada llamada en tus propios logs.

Interfaz​

  • El importe a pagar se enseña con todos sus decimales y no se puede editar. Una transferencia por otro importe no se acredita.
  • processing se lee como «estamos confirmando tu pago», no como error. En cadena hay confirmaciones y en un pago cruzado hay una conversión.
  • Si construyes tu propia pantalla de cobro, escuchas payment_link:quotes_updated: la CLABE puede cambiar mientras el pagador la mira.
  • Enseñas sólo los métodos disponibles para ese importe, no la lista completa.

Los cinco errores que más caro salen​

1 · Firmar el cuerpo re-serializado. Todas las firmas fallan y el mensaje no dice por qué. Guarda los bytes tal cual llegan, antes de parsear el JSON.

2 · Usar un aleatorio como clave de idempotencia. Parece que cumples y no proteges nada: cada reintento lleva una clave distinta y crea un cobro nuevo. La clave tiene que ser tu identificador de pedido.

3 · Mandar amount como número. JSON.parse pierde precisión antes de que lo veamos. Devolvemos 400 a propósito, pero si tu capa intermedia lo convierte en cadena por su cuenta, cobrarás una cifra que no es la tuya.

4 · Dar por bueno un webhook sin verificar. Es un POST a una URL pública. Cualquiera que la adivine puede inventarte un cobro pagado.

5 · Tratar processing como fallo. El cliente pagó, tú le dices que falló, y paga otra vez. El doble cobro se lo comes tú.


Qué vigilar una vez en marcha​

SeñalDóndeQué significa
429 en aumentoTus logsTe estás acercando al tope. Mira RateLimit-Remaining
Destino de webhooks apagadoGET /v1/webhook_endpoints → disabled_atCinco entregas fallidas seguidas. Arregla tu servidor antes de reactivarlo
Enlaces atascados en processingGET /v1/payment_links?status=processingSi pasan horas, escríbenos con el code
Cobros de QR generados ≫ pagadosGET /v1/qr/statsSuele ser problema de mostrador, no de la API

Cuando algo se rompe​

En este orden, porque cada paso descarta la mitad de los casos:

  1. GET /v1/ping — ¿tu credencial sigue viva y con los alcances que crees?
  2. GET /v1/request_logs — ¿nos llegó tu llamada? Si no aparece ahí, el problema está entre tu servidor y nosotros.
  3. El code del error — busca en el catálogo qué lo provoca.
  4. Escríbenos con el request_id. Con él localizamos la llamada exacta en segundos; sin él, empezamos preguntando.

Lo que todavía no hay​

Por transparencia, para que no lo descubras a mitad de la integración:

  • No hay entorno de pruebas separado. Las credenciales pertenecen al entorno donde se emiten. Prueba con importes pequeños.
  • Las devoluciones no están en la API. Se hacen desde el panel.
  • Dar de alta un destino bancario de retiro se hace desde el panel. Ordenar el retiro sí está en la API, y sólo a destinos ya dados de alta — es lo que impide que un fallo mande tu saldo a una cuenta que nadie aprobó. → Retiros
  • El QR de mostrador se puede dar de alta por API desde POST /v1/qr, pero su ciclo de vida completo —revocarlo, por ejemplo— sigue en el panel.

Si algo de esto te bloquea, dínoslo: saber quién lo necesita es lo que decide qué se construye antes.