Crear orden de pago saliente

Crea una orden de pago. Después del éxito, la plataforma congela el monto del pago y la tarifa de la red y luego devuelve los detalles del pedido.

Si no se proporciona fromAddress, el sistema selecciona automáticamente una dirección con saldo suficiente. Si no hay ninguno disponible, devuelve un saldo de dirección insuficiente.

POST/openapi/payout/orders

Encabezados

CampoTipoObligatorioDescripción
x-api-keystringSíComerciante API Key. Utilice el valor que comienza con mch_ de la página de configuración del comerciante API.
x-merchant-uidstringSíMerchant UID.
x-timestampstringSíMilisegundo de 13 dígitos timestamp. La desviación del reloj permitida por defecto es de 5 minutos.
x-noncestringSíCadena aleatoria única para cada solicitud, hasta 128 caracteres. Se rechaza la reutilización.
x-signaturestringSíFirma hexadecimal generada con HMAC-SHA256. La carga útil contiene Merchant UID, timestamp, nonce, método, ruta, query canónico y body canónico.

Parámetros

CampoTipoObligatorioDescripción
chainCodestringSíCódigo de cadena. Valores admitidos: TRON / BSC / SOL.
tokenSymbolstringSíSímbolo simbólico.
fromAddressstringNoDirección del remitente especificada. Si se omite, el sistema asigna uno automáticamente. Máximo 128 caracteres.
toAddressstringSíDirección de recepción. Máximo 128 caracteres.
amountstringSíImporte del pago, hasta 6 decimales.
deleteSourceAfterSuccessbooleanNoBooleano JSON opcional, false por defecto. Si es true, elimina lógicamente el origen solo tras confirmar este pago en cadena; un fallo o cancelación no lo elimina. Los pagos no exigen reserva de saldo.
merchantOrderNostringSíNúmero de pedido del lado comerciante. Máximo 128 caracteres.
notifyUrlstringSíDevolución de llamada específica del pedido URL. Se recomienda un HTTPS URL público propiedad del comerciante. Máximo 500 caracteres; destinos privados, loopback o inseguros están prohibidos.

Ejemplo de solicitud

{
  "chainCode": "TRON",
  "tokenSymbol": "USDT",
  "fromAddress": "TNjBrNq2a9FK2vwu4W9C1QdLKSZ42Yx5YY",
  "toAddress": "TS7b7iD8G2PaPqK1TqSmLJ9nrrYH4oKX1S",
  "amount": "35.50",
  "deleteSourceAfterSuccess": false,
  "merchantOrderNo": "PO202604150001",
  "notifyUrl": "https://merchant.example.com/api/uugate/payout-notify"
}

Campos de respuesta

CampoTipoObligatorioDescripción
orderNostringSíNúmero de orden de pago de la plataforma.
merchantOrderNostring | nullSíNúmero de pedido del comerciante.
fromAddressstring | nullSíDirección real del remitente.
toAddressstringSíDirección de recepción.
amountstringSíMonto del pago.
txHashstring | nullSíEl hash en cadena se devolvió después de la transmisión.
statusstringSíenviado / transmitido / confirmed / failed.
submittedAtstring | nullSíHora de envío.
broadcastedAtstring | nullSíHora de transmisión.
confirmedAtstring | nullSíHora de confirmación.
failedAtstring | nullSíTiempo fallido.
createdAtstring | nullSíTiempo creado.

Ejemplo de respuesta

{
  "orderNo": "PO1776193200A1B2C3D4",
  "merchantOrderNo": "PO202604150001",
  "fromAddress": "TNjBrNq2a9FK2vwu4W9C1QdLKSZ42Yx5YY",
  "toAddress": "TS7b7iD8G2PaPqK1TqSmLJ9nrrYH4oKX1S",
  "amount": "35.500000",
  "txHash": "b3d4fb0cb11eb86bb906d1e0ee3b84e17f40d5441d1e4c651ea46920a48a9a01",
  "status": "broadcasted",
  "submittedAt": "2026-04-15T03:00:00Z",
  "broadcastedAt": "2026-04-15T03:00:08Z",
  "confirmedAt": null,
  "failedAt": null,
  "createdAt": "2026-04-15T03:00:00Z"
}

Ejemplos de código

Ejecución: guarda Java como UUGateExample.java (UUGateCallback.java para callbacks) y usa java nombre de archivo; PHP: php example.php; Go: go run example.go; Node.js: node example.mjs. La verificación de callbacks lee el cuerpo original desde la entrada estándar.

import { createHmac, randomBytes } from 'node:crypto';

function required(name) {
  const value = process.env[name]?.trim();
  if (!value) throw new Error(name + ' is required');
  return value;
}
const uid = required("UUGATE_MERCHANT_UID"), key = required("UUGATE_API_KEY");
const timestamp = String(Date.now()), nonce = randomBytes(16).toString("hex");
const method = 'POST', path = '/openapi/payout/orders';
const canonicalQuery = '', canonicalBody = "{\"amount\":\"35.50\",\"chainCode\":\"TRON\",\"deleteSourceAfterSuccess\":false,\"fromAddress\":\"TNjBrNq2a9FK2vwu4W9C1QdLKSZ42Yx5YY\",\"merchantOrderNo\":\"PO202604150001\",\"notifyUrl\":\"https://merchant.example.com/api/uugate/payout-notify\",\"toAddress\":\"TS7b7iD8G2PaPqK1TqSmLJ9nrrYH4oKX1S\",\"tokenSymbol\":\"USDT\"}";
const payload = [uid, timestamp, nonce, method, path, canonicalQuery, canonicalBody].join('\n');
const signature = createHmac('sha256', key).update(payload, 'utf8').digest('hex');
const base = (process.env.UUGATE_BASE_URL || 'https://api.uugate.com').replace(/\/+$/, '');
const response = await fetch(base + path, {
  method, redirect: 'error', signal: AbortSignal.timeout(30000),
  headers: { 'Content-Type': 'application/json', 'x-api-key': key, 'x-merchant-uid': uid,
    'x-timestamp': timestamp, 'x-nonce': nonce, 'x-signature': signature },
  ...(canonicalBody ? { body: canonicalBody } : {}),
});
const raw = await response.text();
if (!response.ok) throw new Error('HTTP ' + response.status + ': ' + (raw || 'empty response body'));
JSON.parse(raw);
console.log(raw);

Notas

  • La API publica solo admite pagos individuales. Los pagos por lote estan disponibles solo en el panel del comercio.
  • Un pago de 10 requiere al menos 10 de saldo disponible en el origen, sin reserva adicional, independientemente de deleteSourceAfterSuccess. El importe no se reduce; la cuenta de tarifas debe cubrir la tarifa de red.
  • Envia true / false, no cadenas. Los reintentos con el mismo merchantOrderNo deben conservar el parametro. No se puede borrar el origen si hay otras transferencias sin finalizar.
  • Crear o transmitir con exito no equivale a confirmacion en cadena. La eliminacion logica conserva historial, registros y referencias de claves. Un fallo o cancelacion conserva el origen.
  • The create API automatically attempts submission. Use status from the response or a later query; an HTTP 2xx alone is not on-chain success.
  • Los cuatro lenguajes comparten rutas, parámetros y respuestas. Las credenciales se leen de UUGATE_MERCHANT_UID y UUGATE_API_KEY; UUGATE_BASE_URL usa https://api.uugate.com por defecto.
  • canonicalBody es JSON compacto con claves ordenadas. Al modificar parámetros, ordena objetos recursivamente, conserva el orden de arrays y usa UTF-8 sin escapes adicionales de barras ni Unicode. Los importes son cadenas y los booleanos true / false.
  • El éxito devuelve directamente el objeto de negocio, sin envoltorio code / data. Comprueba primero el estado HTTP. Los errores devuelven code, message, data y requestId; un rechazo de seguridad puede ser solo HTTP 401 / 403 sin cuerpo.
  • Tras un timeout o HTTP 5xx, consulta el pedido antes de repetir su creación o envío. Genera un timestamp, nonce y firma nuevos en cada solicitud.