Crear pedido de cobro

Crea una orden de pago compartido de cantidad fija. La respuesta incluye el número de pedido, la dirección de recepción, el pago URL y el pago status.

Se requiere notifyUrl. Las devoluciones de llamada posteriores para este pedido se entregan directamente a este URL.

POST/openapi/payin/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 de token, por ejemplo USDT.
merchantOrderNostringSíNúmero de pedido del comerciante. Máximo 128 caracteres.
amountstringSíImporte del ingreso, hasta 6 decimales.
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",
  "merchantOrderNo": "M202604150001",
  "amount": "100.00",
  "notifyUrl": "https://merchant.example.com/api/uugate/payin-notify"
}

Campos de respuesta

CampoTipoObligatorioDescripción
orderNostringSíNúmero de pedido de la plataforma.
merchantOrderNostring | nullSíNúmero de pedido del comerciante.
bindKeystring | nullSíBinding key for exclusive-wallet orders; empty for shared pay-in orders.
chainCodestring | nullSíRed del pedido.
tokenSymbolstring | nullSíMoneda del pedido.
txHashstring | nullSíHash de la transacción asociada; null antes de detectarla.
amountstring | nullSíImporte del pedido.
paidAmountstring | nullSíMonto pagado. Vaciar antes del pago.
addressstring | nullSíDirección de recepción real.
cashierUrlstring | nullSíURL completa de caja con token aleatorio. Conserva el fragmento #ct= completo.
paymentUristring | nullSíPago de billetera URI.
expireAtstring | nullSíHora de vencimiento del pedido.
createdAtstring | nullSíTiempo creado.
detectedAtstring | nullSíPayment detection time; empty before detection.
confirmedAtstring | nullSíOn-chain confirmation time; empty before confirmation.
completedAtstring | nullSíOrder completion time; empty before completion.
statusstringSíOrden status.

Ejemplo de respuesta

{
  "orderNo": "PI1776193200123ABCD1234",
  "merchantOrderNo": "M202604150001",
  "bindKey": null,
  "amount": "100.000000",
  "paidAmount": null,
  "address": "TXYZ3x9nJ5J4xP2gh6mQW7rT31jB8Y2pA9",
  "cashierUrl": "https://open.uugate.com/SK/PI1776193200123ABCD1234#ct=aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
  "paymentUri": "TRON:TXYZ3x9nJ5J4xP2gh6mQW7rT31jB8Y2pA9?token=USDT&amount=100.000000",
  "expireAt": "2026-04-18T06:30:00.000Z",
  "createdAt": "2026-04-18T06:00:00.000Z",
  "detectedAt": null,
  "confirmedAt": null,
  "completedAt": null,
  "status": "waiting_payment",
  "chainCode": "TRON",
  "tokenSymbol": "USDT",
  "txHash": null
}

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/payin/orders';
const canonicalQuery = '', canonicalBody = "{\"amount\":\"100.00\",\"chainCode\":\"TRON\",\"merchantOrderNo\":\"M202604150001\",\"notifyUrl\":\"https://merchant.example.com/api/uugate/payin-notify\",\"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

  • Una orden de pago compartida puede activar 40105 cuando el mismo comerciante, cadena, token y cantidad todavía están reservados por otra orden válida.
  • 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.