ROKIConnect

Trampas verificadas

12.1 Los campos desconocidos se ignoran en silencio

Un cuerpo con un nombre de campo mal escrito devuelve 201 Created sin ninguna advertencia, y el pago se crea sin esa funcionalidad.

{ "amount": 100, "service_fee": true }     <- wrong name
-> 201 Created, service_fee_amount: 0       <- the fee pass-through was NOT applied

Este es el modo de falla más peligroso de la API, porque el resultado parece exitoso. Es especialmente peligroso para código generado por IA, que tiende a escribir con total confianza los nombres de campo de otras pasarelas (card_token, payment_method, customer_id, amount_cents).

Defensa obligatoria: después de crear un pago, verificá en la respuesta que los campos calculados (sales_tax_amount, service_fee_amount, total, reusable) coincidan con lo que esperabas. Y validá el cuerpo de tu petición contra el esquema de openapi.yaml, que declara additionalProperties: false justamente para atrapar lo que la API deja pasar.

12.2 amount no tiene tope y hace coerción de tipos

La API acepta montos absurdos (11 dígitos) y strings numéricos ("150.00"). Imponé un máximo razonable antes de enviar.

12.3 Dos tipos distintos de 404

Respuesta Significado
{"message":"Pago no encontrado."} La ruta existe; el pago no. Id equivocado, o un id del otro entorno.
{"message":"The route ... could not be found."} La ruta no existe. URL mal formada o un endpoint inexistente.

Distinguirlos ahorra horas: el segundo nunca se arregla cambiando el id.

12.4 Los timestamps vienen en hora local de Honduras sin offset

expires_at, created_at y paid_at vuelven como YYYY-MM-DD HH:MM:SS en hora de Honduras (UTC-6), sin marca de zona horaria en el string. Parsearlos como UTC corre cada valor seis horas - suficiente para que un vencimiento futuro parezca vencido, o para que una orden parezca pagada antes de haber sido creada. Agregá el offset explícitamente al parsear.

12.5 Una propina elegida por el cliente no está en el total que te dieron

Con tip_customer_selectable, el total que se devuelve al crear excluye la propina porque el cliente todavía no la eligió. Por eso el monto realmente cobrado puede ser mayor que el total que guardaste. Conciliá contra el payload del webhook o contra una consulta nueva, nunca contra la respuesta de creación.

12.6 metadata puede volver como un arreglo vacío

Cuando no se envió metadata, la API puede devolver "metadata": [] en vez de {}. Los deserializadores estrictos que esperan un objeto van a fallar. Tratá ambas formas como "sin metadata".

12.7 No hardcodees el dominio del checkout que aparece en la documentación oficial

La documentación oficial de ROKI muestra checkout_url en pay.roki.app; la API en realidad devuelve aura.roki.systems/pay/link/{slug}. Nunca hardcodees ni pongas en lista blanca un dominio de checkout - siempre redirigí al checkout_url exacto que devolvió la API.

12.8 success_url acepta http://

Aunque la documentación oficial exige HTTPS, la API acepta URLs sin cifrar. Usá HTTPS de todas formas - es una URL de retorno en un flujo de pago.