Crypto por API
Con Crypto, creás y confirmás una intención de pago desde tu servidor y redirigís al comprador a un formulario alojado por ONVO. El comprador elige el activo y la red disponibles, y envía el pago desde su billetera. ONVO actualiza la intención de forma asincrónica, aunque el comprador cierre la página.
Antes de empezar
- Crypto por API debe estar habilitado para tu cuenta y para el modo que vas a usar. Solicitá la habilitación al equipo de ONVO; la disponibilidad en Checkout no implica que esté habilitado por API.
- Está disponible para cuentas de Costa Rica y para intenciones en
USDoCRC. - El monto se expresa en la menor denominación de la moneda, no en unidades de crypto:
1000enUSDrepresenta USD 10,00. - Usá tu Secret API Key en el servidor y configurá webhooks.
- Este flujo corresponde a pagos únicos con captura automática. No admite captura manual, suscripciones ni reembolsos a través de la API de reembolsos.
1. Crear la intención de pago
Creá una intención por orden y guardá su id en tu servidor como PAYMENT_INTENT_ID.
curl https://api.onvopay.com/v1/payment-intents \
-X POST \
-H "Authorization: Bearer $ONVO_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"amount": 1000,
"currency": "USD",
"description": "Orden #1001"
}'
2. Crear el método de pago
Enviá type: "crypto" y el objeto crypto con fullName y email. El nombre completo debe ser texto no vacío y el correo debe ser válido; ONVO elimina los espacios al inicio y al final de ambos valores.
Enviá el nombre completo real del comprador y un correo electrónico válido al que tenga acceso. Ese correo se utiliza para comunicaciones relacionadas con su pago Crypto, incluidos avisos sobre cualquier reembolso automático que corresponda. Usar datos ficticios, el correo del comercio o una dirección a la que el comprador no tenga acceso puede impedir que reciba información importante sobre su pago.
Los datos del ejemplo son ilustrativos: reemplazalos por los datos reales del comprador al procesar un pago real.
curl https://api.onvopay.com/v1/payment-methods \
-X POST \
-H "Authorization: Bearer $ONVO_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"type": "crypto",
"crypto": {
"fullName": "María Rodríguez",
"email": "maria@example.com"
}
}'
Guardá el id devuelto para confirmar la intención. Podés asociar un cliente con customerId o customer, pero eso no reemplaza los campos requeridos de crypto. Estos datos se usan para completar la información del comprador en el formulario; el comprador todavía puede tener que aceptar términos o completar verificaciones.
No enviés cryptoPaymentId ni los objetos de otros tipos de método de pago. La sesión de pago se inicia al confirmar la intención. Cada método Crypto queda vinculado a una sola intención y no se puede reutilizar para otra orden.
3. Confirmar y redirigir
Reemplazá PAYMENT_METHOD_ID por el id del método creado. Para Crypto, returnUrl es obligatorio y debe ser una URL absoluta https:// o http:// de tu aplicación.
curl "https://api.onvopay.com/v1/payment-intents/$PAYMENT_INTENT_ID/confirm" \
-X POST \
-H "Authorization: Bearer $ONVO_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{
"paymentMethodId": "PAYMENT_METHOD_ID",
"returnUrl": "https://shop.example.com/orders/1001/return"
}'
Una sesión nueva devuelve requires_action y nextAction. Ejemplo abreviado de respuesta; los identificadores son ilustrativos:
{
"id": "PAYMENT_INTENT_ID",
"status": "requires_action",
"amount": 1000,
"receivedAmount": 0,
"currency": "USD",
"nextAction": {
"type": "redirect_to_url",
"redirectToUrl": {
"url": "https://checkout.onvopay.com/crypto/CRYPTO_SESSION_ID",
"returnUrl": "https://shop.example.com/orders/1001/return"
}
}
}
Redirigí al navegador a nextAction.redirectToUrl.url exactamente como lo devuelve la API. No construyás esa URL ni uses paymentMethod.crypto.hostedUrl para sustituirla. El formulario de ONVO incluye selección de idioma inglés/español e inicia en inglés.
La confirmación también crea un cargo pending para registrar el intento. Crear ese cargo o recibir una URL no significa que el pago esté completado.
4. Confirmar el resultado en tu servidor
Escuchá payment-intent.succeeded mediante el mecanismo de autenticación descrito en Webhooks. También podés consultar la intención desde tu servidor:
curl "https://api.onvopay.com/v1/payment-intents/$PAYMENT_INTENT_ID" \
-H "Authorization: Bearer $ONVO_SECRET_KEY"
Usá el ID guardado para tu orden y verificá su monto, moneda y status: "succeeded" antes de entregar el producto. Procesá la confirmación de cada orden una sola vez, aunque consultes la API y recibas un webhook para el mismo pago.
| Estado de la intención | Qué significa y cómo actuar |
|---|---|
requires_action | El comprador debe completar el formulario. Usá nextAction cuando esté presente. |
processing | El pago sigue pendiente, por ejemplo mientras se confirma una transferencia o falta completar el monto. No entregués el producto. |
succeeded | ONVO confirmó el pago completo. Podés completar la orden. |
requires_payment_method | El intento falló o se canceló antes de recibir fondos. Revisá lastPaymentError y permití un nuevo intento. |
canceled | La intención fue cancelada por el comercio. No la reutilicés para cobrar otra vez. |
Pagos parciales y pendientes
Si el comprador envía menos del monto requerido, la intención puede permanecer en processing. Mientras la sesión admita completar el pago, el formulario permite enviar el faltante. No cierres el flujo ni marques la orden como pagada porque hubo una transferencia.
receivedAmount representa el monto que ONVO ya registró para la intención, en la misma unidad que amount; no equivale necesariamente al monto que la billetera acaba de enviar. Una sesión en hold todavía está pendiente de confirmación y puede tener receivedAmount: 0.
El estado de la sesión, un mensaje de agradecimiento del formulario o nextAction: null no reemplazan el estado de la intención. Incluso si el formulario ya no está disponible o venció, processing sigue sin ser un pago exitoso. Consultá el estado y esperá la confirmación del servidor; no dependás de un evento payment-intent.processing.
Retorno al comercio
Cuando ONVO confirma succeeded, el formulario muestra el resultado y redirige automáticamente a returnUrl después de unos segundos. El retorno agrega estos parámetros:
| Parámetro | Descripción |
|---|---|
payment_intent_id | ID de la intención. |
status | Estado de la intención observado al regresar. |
outcome | success o cancel, según el resultado del flujo de retorno. |
Estos parámetros son informativos y pueden ser modificados en el navegador. Un retorno con outcome=success no prueba que se haya pagado. Recuperá la intención desde tu servidor o procesá el webhook autenticado. La actualización del pago no depende de que el comprador regrese a tu sitio.
Cancelación, vencimiento y reintentos
- Si el comprador cierra el formulario con la X antes de enviar fondos, ONVO falla el cargo con
crypto_payment_canceled, registra el error enlastPaymentErrory devuelve la intención arequires_payment_method. El retorno indicaoutcome=cancely se emitepayment-intent.failed. - Si ya hay fondos recibidos o una transferencia pendiente, cerrar el formulario no equivale a cancelar el pago ni revierte la transferencia. Seguí consultando la intención y atendiendo sus webhooks.
- Para cancelar la intención desde tu servidor, usá Cancelar una intención de pago. Esta operación deja la intención en
canceledy emitepayment-intent.canceled; no es un reembolso. - La sesión tiene su propia expiración, disponible en
paymentMethod.crypto.expiryDate. Una sesión vencida no se puede reutilizar. Para un nuevo intento sin fondos pendientes, creá un método Crypto nuevo y confirmá una intención que permita volver a intentar. - Reconfirmar la misma intención con su método y una sesión vigente permite recuperar la acción existente. No creés otra orden o intención solo porque el comprador vuelve del formulario.
Errores frecuentes
La API puede responder 400 con un error de validación (statusCode, message, error) si falta crypto, el nombre está vacío o el correo es inválido. Esos errores no garantizan un campo code. Para errores de negocio, usá el code de la respuesta:
| Código | Qué revisar |
|---|---|
payment_methods.invalid_payment_method_payload | El payload mezcla detalles de distintos tipos de método o no cumple el contrato del método. |
payment_methods.crypto_not_enabled | La cuenta, el país o el modo no tienen Crypto por API habilitado. |
payment_methods.crypto_currency_not_supported | La moneda de la intención debe ser USD o CRC. |
payment_intents.return_url_required | Falta returnUrl en la confirmación. Una URL mal formada también puede producir un error de validación. |
payment_methods.crypto_already_used | El método ya está vinculado a otra intención o no se puede reutilizar. |
payment_methods.crypto_session_expired | Necesitás una sesión nueva para un nuevo intento. |
payment_intents.crypto_session_unavailable | No se pudo iniciar el formulario. Consultá la intención antes de volver a intentar. |
payment_intents.crypto_settlement_in_progress | Una actualización del pago está en curso. Esperá y consultá el estado antes de reintentar la cancelación. |
Pruebas
Usá una llave onvo_test_ con Crypto por API habilitado en modo de prueba. Seguí las instrucciones del formulario para el activo y la red de prueba que muestra; por ejemplo, si muestra testBTC, usá fondos de prueba de esa red. No enviés fondos reales al flujo de prueba.
Validá el pago completo, el pago parcial seguido del faltante, el estado pendiente, el cierre sin fondos, el vencimiento y los datos de comprador inválidos. En cada caso verificá la intención desde el servidor y comprobá que tu aplicación solo entrega la orden en succeeded, incluso si el comprador cierra el navegador.