Iniciando una transacción

¿Qué es un intento de pago?

Para procesar un pago, primero se debe crear un intento de pago (payment intent).

Este intento representa la intención de cobrar al cliente y contiene toda la información necesaria para iniciar el flujo de pago seguro.

El intento de pago no garantiza que la transacción se concrete exitosamente: el cliente debe completar todos los pasos en la interfaz (ingreso de datos de tarjeta, autenticación 3D Secure si aplica, etc.). Al finalizar:

  • Puede resultar en una transacción exitosa (autorizada y capturada).
  • Puede resultar en una transacción fallida (rechazada por fondos insuficientes, tarjeta inválida, cancelación por el usuario, problemas de conexión, etc.).

Solo las transacciones exitosas generan un pago real en tu cuenta bancaria.

Cómo crear un intento de pago

Para iniciar el proceso, debes enviar una solicitud (vía POST) desde tu integración al sistema de pago online, incluyendo los siguientes campos:

📘

URL ambientes

Integración: https://frontend-api.payment.haulmer.dev/v1/payment
Producción: https://core.payment.haulmer.com/api/v1/payment

Campos de cabecera

CampoValor
X-REDIRECTfalse
Content-Typeapplication/json

Campos requeridos en cuerpo de la petición

CampoTipoDescripciónEjemplo / Notas
x_account_idStringID de cuenta con el cual se identificará el origen de la transacción.62224230 o similar – proporcionado por TUU.
x_amountNumberMonto total a cobrar en la transacción.19990 – usar punto como separador decimal, sin formato de miles
x_currencyStringMoneda de la transacciónCLP (única soportada actualmente)
x_customer_emailStringEmail del cliente[email protected] – recomendable validarlo en frontend
x_customer_first_nameStringNombre del clienteJuan
x_customer_last_nameStringApellido del clientePérez
x_customer_phoneStringTeléfono del cliente (formato recomendado: +56912345678)+56987654321 – útil para notificaciones y recuperación de carrito
x_descriptionStringDescripción breve de la compraCompra de zapatillas ON – Orden #12345campo opcional.
x_referenceStringIdentificador único de tu sistema (order ID o similar)ORD-20260316-ABC123debe ser único para evitar duplicados
x_shop_nameStringNombre de tu comercioMi Tienda Online AB
x_url_callbackURLURL donde se notificará el resultado (callback / server-to-server)https://tutienda.cl/api/webpay/callbackdebe ser HTTPS
x_url_cancelURLURL a la que redirige el cliente si cancela el pagohttps://tutienda.cl/checkout/cancelado
x_url_completeURLURL a la que redirige el cliente tras finalizar el flujo de pago.`https://tutienda.cl/checkout/gracias?order=12345

Ejemplo de payload (JSON)

{
  "x_account_id": "62224230",
  "x_amount": 19990,
  "x_currency": "CLP",
  "x_customer_email": "[email protected]",
  "x_customer_first_name": "Mia",
  "x_customer_last_name": "Piamonte",
  "x_customer_phone": "+56912345678",
  "x_description": "Pack 3 botellas vino Pinot Reserva 2023",
  "x_reference": "VENTA-20260316-000478",
  "x_shop_name": "Viña Ejemplo Online",
  "x_url_callback": "https://api.tu-dominio.cl/webpay/notificacion",
  "x_url_cancel": "https://tu-dominio.cl/pago/cancelado",
  "x_url_complete": "https://tu-dominio.cl/pago/exito?ref=VENTA-20260316-000478"
}

Manejo de callback y notificaciones

El sistema de pago online informa tanto al integrador (tu backend) como al cliente final (el comprador) sobre el resultado de cada intento de pago. Esto se logra mediante dos mecanismos principales:

  • Notificación asíncrona (callback/server-to-server) → hacia tu backend, para actualizar el estado real de la transacción de forma segura y confiable.
  • Redirección síncrona (browser redirect) → hacia las páginas de tu sitio (éxito o cancelación), para mostrar al usuario un mensaje amigable.

Estos mecanismos utilizan las URLs que proporcionaste al crear el intento de pago:

  • x_url_callback → notificación POST asíncrona (obligatoria para producción).
  • x_url_complete → redirección GET al finalizar (éxito o fracaso).
  • x_url_cancel → redirección GET si el usuario cancela explícitamente.

Diferencias clave entre los mecanismos

MecanismoMétodo HTTPFormato de parámetrosPropósito principalFiabilidad / Uso recomendado
x_url_callbackPOSTx-www-form-urlencoded (body)Notificar resultado real y seguro al backendPrincipal y obligatorio para confirmar pagos
x_url_completeGETQuery string (?param=valor&...)Mostrar resultado al cliente (éxito/fallo)Experiencia de usuario – no para lógica crítica
x_url_cancelGETQuery string (?param=valor&...)Indicar cancelación explícita por el usuarioExperiencia de usuario – no para lógica crítica

Importante:

  • Nunca confíes exclusivamente en las redirecciones GET (complete o cancel) para actualizar el estado de una orden en tu base de datos. Estas pueden fallar (usuario cierra ventana, bloqueador de pop-ups, red lenta, etc.).
  • La notificación POST (callback) es la fuente de verdad. Debe ser procesada de forma idempotente y segura.

Parámetros enviados en las notificaciones y redirecciones

Se envía un conjunto estándar de parámetros con información clave de la transacción. Los nombres mantienen el prefijo x_ tanto en la respuesta por POST como GET.

Parámetros más comunes recibidos (en callback POST y redirecciones GET)

ParámetroTipoDescripciónEjemploNotas / Uso recomendado
x_account_idStringCódigo de comercio62224230Identifica tu cuenta
x_referenceStringReferencia única enviada por ti (order ID)ORD-20260316-ABC123Clave para idempotencia – úsala para buscar orden
x_amountNumberMonto original de la transacción19990Verificar que coincida con tu orden
x_currencyStringMonedaCLPSiempre CLP
x_resultStringResultado de la transaccióncompleted, failed, pendingIndica estado de transacción.
x_timestampStringFecha/hora de la transacción2026-03-16T20:45:12Formato ISO
x_messageStringMensaje de error o éxito.Saldo insuficienteDetalle del error de una transacción
x_signatureStringFirma digital para validar autenticidada1b2c3...Verificar siempre que coincida. Ver generación de firma.

Detalles técnicos del callback (x_url_callback)

  • Método: POST
  • Content-Type: application/x-www-form-urlencoded
  • Cuerpo: parámetros en formato clave=valor&clave=valor...
  • Reintentos automáticos:
    • Si tu servidor responde con código HTTP 200 OK → El sistema detiene los reintentos (éxito).
    • Si responde 4xx (cliente error) o 5xx (servidor error) → El sistema reintenta hasta 10 veces (con backoff exponencial).
    • Después de 10 fallos → la notificación se marca como fallida internamente (no se reintentará más).
  • Recomendaciones para tu endpoint:
    1. Responder rápido (ideal < 5 segundos) → evita timeouts y reintentos innecesarios.
    2. Procesar de forma idempotente: si recibes la misma notificación varias veces (por reintentos o duplicados), actualiza solo si es necesario.
    3. Validar parámetros: compara x_amount, x_reference con tu base de datos.
    4. Registrar siempre: guarda el payload completo, IP origen, timestamp y código de respuesta.
    5. Responder solo 200 OK cuando hayas procesado exitosamente (incluso si la transacción fue rechazada).

Generación y Verificación de Firma (x_signature)

Para garantizar la integridad y autenticidad de las peticiones y respuestas entre tu sistema y la pasarela de pago, se utiliza una firma digital llamada x_signature.

Esta firma se genera mediante HMAC-SHA256 sobre un subconjunto específico de los parámetros enviados/recibidos, usando tu Llave Secreta (secret key) como clave privada.

La firma protege contra:

  • Modificaciones maliciosas en los parámetros (ej: cambiar monto, referencia).
  • Replay attacks (reutilización de peticiones antiguas).
  • Suplantación de identidad.

Importante: La firma siempre debe calcularse en el backend (nunca exponer la llave secreta en frontend o JavaScript del cliente).

Proceso de generación de la firma

  1. Filtrar parámetros:
    Solo se incluyen los campos cuyo nombre comienza con x_ (ej: x_amount, x_reference, x_url_callback, etc.).
    Se excluye explícitamente x_signature (no se firma a sí misma).

  2. Ordenar alfabéticamente:
    Ordena las claves (nombres de campos) de forma alfabética estricta (case-sensitive, ASCII order).
    Ejemplo: x_account_id → antes que x_amount → antes que x_currency.

  3. Concatenar sin separadores:
    Une cada clave con su valor directamente, sin =, &, espacios ni otros caracteres.
    Formato: clave1valor1clave2valor2clave3valor3...
    → Campos vacíos se concatenan como clave (sin valor).
    → Valores se toman tal cual (strings, números como string sin formato adicional).

  4. Aplicar HMAC-SHA256:
    Usa el algoritmo HMAC con SHA-256, clave = tu Llave Secreta.
    La salida debe ser en hexadecimal (cadena de 64 caracteres en minúsculas).

  5. Encoding: UTF-8 en todo momento (especialmente importante para emails, descripciones con acentos o caracteres especiales).

Ejemplo en PHP (creación de firma para request)

function generarFirma(array $datos, string $llaveSecreta): string
{
    // 1. Filtrar solo campos que empiecen con 'x_'
    $datosParaFirmar = array_filter($datos, function($key) {
        return str_starts_with($key, 'x_');
    }, ARRAY_FILTER_USE_KEY);

    // 2. Ordenar claves alfabéticamente
    ksort($datosParaFirmar);

    // 3. Concatenar clave + valor sin separadores
    $cadena = '';
    foreach ($datosParaFirmar as $clave => $valor) {
        $cadena .= $clave . $valor;
    }

    // 4. Generar HMAC-SHA256 en hexadecimal (minúsculas)
    return hash_hmac('sha256', $cadena, $llaveSecreta);
}

// Uso ejemplo
$datos = [
    'x_account_id' => '82121521',
    'x_amount' => '16580',
    'x_currency' => 'CLP',
    'x_customer_email' => '[email protected]',
    'x_customer_first_name' => 'Test',
    'x_customer_last_name' => 'Api',
    'x_customer_phone' => '+56987654321',
    'x_description' => 'polera#222',
    'x_reference' => '2231',
    'x_shop_name' => 'Integración 1',
    'x_url_callback' => 'https://transaction-handler.haulmer.xyz/callbackExample',
    'x_url_cancel' => 'https://transaction-handler.haulmer.xyz/payment/cancel',
    'x_url_complete' => 'https://transaction-handler.haulmer.xyz/payment/complete',
    // ... otros campos x_*
];

$llaveSecreta = 'KsHcnuUXF5ehiqbuzPJ8Vq2yw267xc48fuBZM5EnxMyIYfiIlLju3Lw0jF1RTDuibsHp3RQBhP8nuY9FvND2WBwsaKU1sId2VkVp5LmNFOikTInoSnFLhyijQXhGUDua';

$firma = generarFirma($datos, $llaveSecreta);
// Resultado esperado: 56ef2554442d536c1df9128a41901a8e4335a711f25de9f53282009edf0cd152

Credenciales de prueba

Account ID (account_id): 62224230

Secret Key (secret_key): yAk0dXTJLQzkeEWODsQWVpPX0bn7ND50qwoQrXgqqNiUyEpgxIPxPtoCgKeLNeh1upTw72JZx5O9x5IaAtPIGUAVcMNcsUSg3M0M8tgWdUb4F8qkS8I7rHpOUmZqzvfS

URL Integración: https://frontend-api.payment.haulmer.dev/v1/payment

Tarjetas de Prueba

Para probar tu integración de pago online de manera segura y sin generar cargos reales, utiliza tarjetas de prueba en el ambiente de integración.

Estas tarjetas simulan diferentes escenarios (aprobadas, rechazadas, errores específicos) sin afectar cuentas reales ni requerir fondos.

Importante:

  • Solo funcionan en ambiente de integración (no en producción).
  • Usa el código de comercio de pruebas proporcionado por tu proveedor (ej: 62224230).
  • CVV y fecha de expiración: cualquier valor válido (ej: CVV 123 o 1234; expiración futura como 12/28).

Tarjetas recomendadas para tu integración

Estas son las tarjetas explícitamente compatibles con tu flujo (basadas en la información proporcionada):

Tipo de tarjetaNúmero de tarjetaCVVFecha expiraciónResultado esperadoNotas / Escenarios recomendados
VISA4051 8856 0044 6623123Cualquiera futuraAprobada (éxito)Usa para probar flujo completo: éxito, callback OK, redirección a x_url_complete.
AMEX3700 0000 0002 0321234Cualquiera futuraAprobada (éxito)Prueba con AMEX (menos común). Verifica si tu sistema maneja bien tarjetas american express (a veces con CVV de 4 dígitos).
MASTERCARD5186 0595 5959 0568123Cualquiera futuraRechazada (fallida)Simula rechazo (fondos insuficientes o tarjeta inválida). Verifica callback con x_result=failed, actualización de estado a fallido y mensaje al usuario.

Resultado esperado:

  • Aprobadas → Transacción exitosa → Callback POST con resultado OK → Redirección GET a x_url_complete.
  • Rechazada → Transacción fallida → Callback POST con resultado failed → Redirección GET a x_url_complete o x_url_cancel (dependiendo del flujo).