Saltar al contenido principal

Órdenes

Una Order es el pago en sí — referencia una cotización, lleva el emisor y el receptor, y atraviesa los estados descritos en estados de una order hasta que se completa o falla (ver detalles de falla). OrdersClient cubre crear, leer y listar órdenes.

Accede a estos métodos directamente en RetornaClient o a través de client.orders() — las dos formas ejecutan el mismo código.

createOrder(request, idempotencyKey)​

Crea una orden contra una cotización. El backend requiere un header X-Idempotency-Key en cada llamada; el SDK lo envía por ti a partir del argumento idempotencyKey.

Firma​

public Order createOrder(CreateOrderRequest request)

public Order createOrder(CreateOrderRequest request, String idempotencyKey)

La sobrecarga de un solo argumento genera un UUID al azar como clave de idempotencia. Prefiere la forma de dos argumentos con tu propia referencia (un número de factura, por ejemplo) — ese valor vuelve como order.idempotencyKey(), así que puedes buscar la orden después por ese valor, y un reintento que reutiliza la misma clave contra el mismo cuerpo repite la orden original en lugar de crear un duplicado.

Parámetros​

NombreTipoRequeridoDescripción
requestCreateOrderRequestSíLa orden a crear. Ver los componentes abajo.
idempotencyKeyStringNoTu propia referencia. Si es null o está vacía, se genera un UUID al azar. Reutilizar la misma clave con un cuerpo distinto es un 409; reutilizarla con el cuerpo idéntico repite la orden original.

Componentes de CreateOrderRequest — ármalo con el constructor canónico o withPurpose(...):

// Canonical (5-arg) constructor
public CreateOrderRequest(
String quotationId,
Map<String, Object> metadata,
String purpose,
OrderSender sender,
OrderDestination destination
)

// Typed entry point for the purpose catalog
public static CreateOrderRequest withPurpose(
String quotationId,
Map<String, Object> metadata,
OrderPurpose purpose,
OrderSender sender,
OrderDestination destination
)
ComponenteTipoRequeridoDescripción
quotationIdStringSíUUID de una cotización creada previamente. De un solo uso: respalda exactamente una orden, para siempre.
metadataMap<String, Object>NoEtiquetas definidas por el cliente, devueltas sin cambios. Se omite del wire cuando es null.
purposeString (o OrderPurpose vía withPurpose)SíPropósito declarado de la remesa. Tiene que ser un valor de OrderPurpose — null o cualquier valor fuera del catálogo lanza una excepción del lado del cliente. No hay un campo idempotencyKey aquí; es solo de respuesta.
senderOrderSenderSínames, lastNames, document (PersonDocument), country (ISO alpha-2 de 2 caracteres), phone (nullable, E.164), email (nullable).
destinationOrderDestinationSíVer abajo.

OrderSender es un record: OrderSender(names, lastNames, document, country, phone, email). El constructor anterior de 4 argumentos (names, lastNames, document, country) sigue funcionando — phone y email quedan en null por defecto — así que el código existente compila sin cambios. Usa la forma de 6 argumentos para definir phone y/o email; el cliente valida phone como E.164 y email como dirección cuando no son null. Los dos vuelven en sender() en las lecturas solo si los enviaste al crear.

OrderDestination — para construir un request, usa el constructor de 2 argumentos (receiver, paymentInstructions); targetAmount/targetCurrency son solo de respuesta y quedan afuera del wire de creación.

ComponenteTipoRequeridoDescripción
receiverOrderReceiverSínames, lastNames, document (PersonDocument), email (nullable), country (ISO alpha-2 de 2 caracteres).
paymentInstructionsPaymentInstructionsSíExactamente uno de bankAccount o bankPhoneAccount tiene que estar definido — constrúyelo con PaymentInstructions.ofBankAccount(...) o PaymentInstructions.ofBankPhoneAccount(...).

PersonDocument(type, id, country) — type (por ejemplo "CC", "V"), id (número de documento), country (ISO alpha-2 de 2 caracteres del país emisor).

Para un pago por transferencia bancaria, construye la cuenta con BankAccount.of(FinancialEntity, number, BankAccountType):

public static BankAccount of(FinancialEntity bank, String number, BankAccountType type)
ComponenteTipoRequeridoDescripción
bankFinancialEntitySíCódigo de plataforma del catálogo cerrado de bancos, por ejemplo BANCO_BANESCO_VE — nunca el nombre comercial. Consulta entidades bancarias para la lista completa.
numberStringSíNúmero de cuenta, guardado como string para preservar ceros a la izquierda.
typeBankAccountTypeSíCHECKING, SAVINGS, CORRIENTE, o AHORRO — el backend acepta tanto la forma en inglés como en español.

Retorno​

Order:

AccesorTipoSignificado
id()StringId de la orden.
type()StringTipo de orden (por ejemplo "REMITTANCE").
status()StringVer estados de una order para los valores observados y cómo evolucionan.
quotationId()StringLa cotización con la que se creó esta orden.
idempotencyKey()StringTu clave de idempotencia, devuelta sin cambios; nullable.
amount() / currency()StringMonto y código de moneda de origen.
metadata()Map<String, Object>Metadata devuelta sin cambios; nullable.
sender() / destination()OrderSender / OrderDestinationNullable en algunos estados. destination().targetAmount()/targetCurrency() llevan el monto del lado del pago en las lecturas.
execution()OrderExecutionsource() y destination(), cada uno un ExecutionLeg con status() y referenceId() (nullable).
purposeEnum()OrderPurposeParseado del string crudo purpose(); null si está ausente o no lo reconoce esta versión del SDK.
events()List<OrderEvent>Línea de tiempo de cambios de estado; nullable. Cada OrderEvent tiene fromStatus() (nullable), toStatus(), trigger(), reason() (nullable), message() (nullable), createdAt().
failureCode() / failureReason()StringDetalle de falla legible por máquina / por humanos; ambos nullable. Ver detalles de falla. Ramifica según failureCode(), nunca según failureReason().
createdAt() / updatedAt()OffsetDateTimeTimestamps.

El JSON en el wire es snake_case (quotation_id, idempotency_key, failure_code, ...); los accesores de Java de arriba son camelCase.

Ejemplo​

import app.retorna.sdk.RetornaClient;
import app.retorna.sdk.RetornaClientBuilder;
import app.retorna.sdk.core.environment.RetornaEnvironment;
import app.retorna.sdk.models.order.BankPhoneAccount;
import app.retorna.sdk.models.order.CreateOrderRequest;
import app.retorna.sdk.models.order.FinancialEntity;
import app.retorna.sdk.models.order.Order;
import app.retorna.sdk.models.order.OrderDestination;
import app.retorna.sdk.models.order.OrderPurpose;
import app.retorna.sdk.models.order.OrderReceiver;
import app.retorna.sdk.models.order.OrderSender;
import app.retorna.sdk.models.order.PaymentInstructions;
import app.retorna.sdk.models.order.PersonDocument;

RetornaClient client = new RetornaClientBuilder()
.environment(RetornaEnvironment.SANDBOX)
.clientId(System.getenv("RETORNA_CLIENT_ID"))
.clientSecret(System.getenv("RETORNA_CLIENT_SECRET"))
.privateKey(System.getenv("RETORNA_PRIVATE_KEY"))
.buildClient();

String quotationId = "0190f9b2-0000-7000-8000-000000000000"; // from createQuotation
String idempotencyKey = "invoice-2026-0042"; // your own reference

Order order = client.createOrder(
CreateOrderRequest.withPurpose(
quotationId,
null,
OrderPurpose.FAMILY_SUPPORT,
new OrderSender("Ana María", "Pérez Gómez",
new PersonDocument("CC", "1020304050", "CO"), "CO"),
new OrderDestination(
new OrderReceiver("Carlos Andrés", "Rodríguez López",
new PersonDocument("V", "12345678", "VE"),
PaymentInstructions.ofBankPhoneAccount(
BankPhoneAccount.of(FinancialEntity.BNC_VE,
"+584121234567", "12345678")))),
idempotencyKey);

System.out.printf("Order %s status=%s idempotencyKey=%s%n",
order.id(), order.status(), order.idempotencyKey());

Errores​

Notas​

  • Pasa siempre tu propio idempotencyKey en código de producción; la sobrecarga de un solo argumento es cómoda para scripts, no para algo que necesites reintentar de forma segura.
  • No hay un campo idempotencyKey en el request — solo en la respuesta. No intentes mandar uno; siempre sale de la clave de idempotencia.

Referencia de API​

POST /orders

getOrder(id)​

Lee una única orden por id.

Firma​

public Order getOrder(String id)

Parámetros​

NombreTipoRequeridoDescripción
idStringSíEl id de la orden tal como lo emitió el backend — se valida solo por longitud (1 a 100 caracteres), no como forma de UUID.

Retorno​

La misma forma de Order devuelta por createOrder arriba.

Ejemplo​

import app.retorna.sdk.RetornaClient;
import app.retorna.sdk.RetornaClientBuilder;
import app.retorna.sdk.core.environment.RetornaEnvironment;
import app.retorna.sdk.models.order.Order;

RetornaClient client = new RetornaClientBuilder()
.environment(RetornaEnvironment.SANDBOX)
.clientId(System.getenv("RETORNA_CLIENT_ID"))
.clientSecret(System.getenv("RETORNA_CLIENT_SECRET"))
.privateKey(System.getenv("RETORNA_PRIVATE_KEY"))
.buildClient();

Order order = client.getOrder("0190f9b2-0000-7000-8000-000000000001");
System.out.printf("status=%s failureCode=%s%n", order.status(), order.failureCode());

Errores​

  • IllegalArgumentException — id es null, vacío, o más largo que 100 caracteres.
  • RetornaB2BException con codeEnum() uno de: B2B_ORDER_NOT_FOUND, B2B_UNAUTHORIZED, B2B_RATE_LIMITED — reintentable, B2B_UNKNOWN.
  • RetornaAuthException — falla del intercambio de token.
  • RetornaSdkException — falla de red o falla de deserialización.

Notas​

  • El id es opaco; no asumas una forma fija.

Referencia de API​

GET /orders/:id

listOrders(params)​

Lista órdenes, paginadas por cursor, con filtros opcionales.

Firma​

public OrdersListResponse listOrders(ListOrdersParams params)

Parámetros​

NombreTipoRequeridoDescripción
paramsListOrdersParamsNo (pasa null o ListOrdersParams.firstPage())Filtros de la consulta. Ver los componentes abajo.

Componentes de ListOrdersParams:

ComponenteTipoRequeridoDescripción
cursorStringNoCursor opaco de next_cursor de la página anterior. Null para la primera página.
limitIntegerNoTamaño de página, 1 a 100; el default del backend es 20. Mantenlo fijo durante todo el recorrido.
statusStringNoFiltra por estado de la orden. Libre — no está restringido a un enum.
idempotencyKeyStringNoFiltra por tu clave de idempotencia. Coincidencia exacta, no parcial.
createdFrom / createdToOffsetDateTimeNoLímites inclusivos sobre created_at.
typeStringNoFiltra por tipo de transacción, ej. "WALLET_TO_POG". Libre, un solo valor — a diferencia de status, no acepta una lista separada por comas. Se agregó como último componente de ListOrdersParams; el constructor anterior de 6 argumentos sigue funcionando y deja type en null.

Factories de conveniencia: ListOrdersParams.firstPage(), firstPage(int limit), byIdempotencyKey(String idempotencyKey), y byType(String type).

Retorno​

OrdersListResponse:

AccesorTipoSignificado
data()List<Order>Órdenes de esta página — ver la forma de Order de createOrder arriba.
pagination()CursorPaginationnextCursor() (String, nullable cuando termina), hasMore() (boolean), limit() (int), total() (Integer, nullable — cuenta de coincidencias, no tamaño de página).

Ejemplo​

import app.retorna.sdk.RetornaClient;
import app.retorna.sdk.RetornaClientBuilder;
import app.retorna.sdk.core.environment.RetornaEnvironment;
import app.retorna.sdk.models.order.ListOrdersParams;
import app.retorna.sdk.models.order.Order;
import app.retorna.sdk.models.order.OrdersListResponse;

RetornaClient client = new RetornaClientBuilder()
.environment(RetornaEnvironment.SANDBOX)
.clientId(System.getenv("RETORNA_CLIENT_ID"))
.clientSecret(System.getenv("RETORNA_CLIENT_SECRET"))
.privateKey(System.getenv("RETORNA_PRIVATE_KEY"))
.buildClient();

String cursor = null;
do {
OrdersListResponse page = client.listOrders(
cursor == null ? ListOrdersParams.firstPage(20)
: new ListOrdersParams(cursor, 20, null, null, null, null));

for (Order order : page.data()) {
System.out.printf("%s %s %s%n", order.id(), order.status(), order.amount());
}
cursor = page.pagination().nextCursor();
} while (cursor != null);

Errores​

  • IllegalArgumentException — un cursor o idempotencyKey vacío (pero no null), o un limit fuera de 1 a 100.
  • RetornaB2BException con codeEnum() uno de: B2B_INVALID_PAGINATION_CURSOR — reinicia el recorrido sin cursor, B2B_UNAUTHORIZED, B2B_RATE_LIMITED — reintentable, B2B_UNKNOWN.
  • RetornaAuthException — falla del intercambio de token.
  • RetornaSdkException — falla de red o falla de deserialización.

Notas​

  • Consulta paginación para el contrato completo del cursor: mantén limit y los filtros fijos durante todo el recorrido, y trata el cursor como opaco.
  • idempotencyKey es una coincidencia exacta sobre tu clave de idempotencia — muchas veces más rápido que paginar cuando ya sabes qué orden estás buscando.

Referencia de API​

GET /orders