Solicitar ejemplo y verificación de firma

Método de solicitud: las API usan principalmente `GET` / `POST`; las solicitudes JSON usan `application/json`.

Autenticación: las solicitudes OpenAPI se verifican con encabezados y firmas HMAC-SHA256.

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.

Reglas de firma

  • Las solicitudes utilizan application/json. Para GET APIs sin body, la parte body en la firma es una cadena vacía.
  • La ruta de la firma debe ser la ruta sin formato API, por ejemplo /openapi/payin/orders, sin el dominio.
  • Los parámetros de consulta están ordenados por clave; Las claves JSON body se ordenan antes de la serialización.
  • Los errores de firma comunes incluyen timestamp caducados, valores nonce repetidos, orden de campos inconsistente o espacios adicionales.

El timestamp, nonce y las credenciales fijos son valores de prueba de firma sin conexión. Para solicitudes reales, usa el timestamp actual en milisegundos y un nonce aleatorio nuevo. Las rutas API no tienen prefijo de versión; v1 solo identifica la firma de callbacks.

Ejemplo de payload de firma

880001
1776193200000
2f5c7b147c3748f0a8b3d9bb38aa91a4
POST
/openapi/payin/orders

{"amount":"100.00","chainCode":"TRON","merchantOrderNo":"M202604150001","notifyUrl":"https://merchant.example.com/api/uugate/payin-notify","tokenSymbol":"USDT"}

Ejemplo completo

POST /openapi/payin/orders HTTP/1.1
Host: api.uugate.com
Content-Type: application/json
x-api-key: mch_xxxxxxxxxxxxxxxxxxxx
x-merchant-uid: 880001
x-timestamp: 1776193200000
x-nonce: 2f5c7b147c3748f0a8b3d9bb38aa91a4
x-signature: 6d7e96fdbf3ec37c1ec515540f46c6c19b08754973c43293e54644c2da910838

{
  "chainCode": "TRON",
  "tokenSymbol": "USDT",
  "merchantOrderNo": "M202604150001",
  "amount": "100.00",
  "notifyUrl": "https://merchant.example.com/api/uugate/payin-notify"
}

Ejemplos de firma

  • 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.

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 = "880001", key = "mch_xxxxxxxxxxxxxxxxxxxx";
const timestamp = "1776193200000", nonce = "2f5c7b147c3748f0a8b3d9bb38aa91a4";
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');
console.log(signature);

Los errores de negocio devuelven JSON con code, message, data y requestId. Claves, firmas, timestamps, nonces inválidos o restricciones de seguridad pueden devolver HTTP 401 / 403 sin cuerpo ni código de negocio. Comprueba el estado HTTP y el cuerpo antes de analizar JSON. No tomes decisiones según el mensaje traducido.

Campos de error

CampoTipoObligatorioDescripción
codenumberSíCódigo de error empresarial.
messagestringSíMensaje de error.
dataobject | nullSíDatos de error adicionales.
requestIdstring | nullSíID de seguimiento de solicitud del servidor.

Ejemplo de error

HTTP/1.1 401 Unauthorized
Cache-Control: no-store
Content-Length: 0