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
| Campo | Valor |
|---|---|
X-REDIRECT | false |
Content-Type | application/json |
Campos requeridos en cuerpo de la petición
| Campo | Tipo | Descripción | Ejemplo / Notas |
|---|---|---|---|
x_account_id | String | ID de cuenta con el cual se identificará el origen de la transacción. | 62224230 o similar – proporcionado por TUU. |
x_amount | Number | Monto total a cobrar en la transacción. | 19990 – usar punto como separador decimal, sin formato de miles |
x_currency | String | Moneda de la transacción | CLP (única soportada actualmente) |
x_customer_email | String | Email del cliente | [email protected] – recomendable validarlo en frontend |
x_customer_first_name | String | Nombre del cliente | Juan |
x_customer_last_name | String | Apellido del cliente | Pérez |
x_customer_phone | String | Teléfono del cliente (formato recomendado: +56912345678) | +56987654321 – útil para notificaciones y recuperación de carrito |
x_description | String | Descripción breve de la compra | Compra de zapatillas ON – Orden #12345 – campo opcional. |
x_reference | String | Identificador único de tu sistema (order ID o similar) | ORD-20260316-ABC123 – debe ser único para evitar duplicados |
x_shop_name | String | Nombre de tu comercio | Mi Tienda Online AB |
x_url_callback | URL | URL donde se notificará el resultado (callback / server-to-server) | https://tutienda.cl/api/webpay/callback – debe ser HTTPS |
x_url_cancel | URL | URL a la que redirige el cliente si cancela el pago | https://tutienda.cl/checkout/cancelado |
x_url_complete | URL | URL 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
| Mecanismo | Método HTTP | Formato de parámetros | Propósito principal | Fiabilidad / Uso recomendado |
|---|---|---|---|---|
x_url_callback | POST | x-www-form-urlencoded (body) | Notificar resultado real y seguro al backend | Principal y obligatorio para confirmar pagos |
x_url_complete | GET | Query string (?param=valor&...) | Mostrar resultado al cliente (éxito/fallo) | Experiencia de usuario – no para lógica crítica |
x_url_cancel | GET | Query string (?param=valor&...) | Indicar cancelación explícita por el usuario | Experiencia de usuario – no para lógica crítica |
Importante:
- Nunca confíes exclusivamente en las redirecciones GET (
completeocancel) 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ámetro | Tipo | Descripción | Ejemplo | Notas / Uso recomendado |
|---|---|---|---|---|
x_account_id | String | Código de comercio | 62224230 | Identifica tu cuenta |
x_reference | String | Referencia única enviada por ti (order ID) | ORD-20260316-ABC123 | Clave para idempotencia – úsala para buscar orden |
x_amount | Number | Monto original de la transacción | 19990 | Verificar que coincida con tu orden |
x_currency | String | Moneda | CLP | Siempre CLP |
x_result | String | Resultado de la transacción | completed, failed, pending | Indica estado de transacción. |
x_timestamp | String | Fecha/hora de la transacción | 2026-03-16T20:45:12 | Formato ISO |
x_message | String | Mensaje de error o éxito. | Saldo insuficiente | Detalle del error de una transacción |
x_signature | String | Firma digital para validar autenticidad | a1b2c3... | Verificar siempre que coincida. Ver generación de firma. |
Detalles técnicos del callback (x_url_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:
- Responder rápido (ideal < 5 segundos) → evita timeouts y reintentos innecesarios.
- Procesar de forma idempotente: si recibes la misma notificación varias veces (por reintentos o duplicados), actualiza solo si es necesario.
- Validar parámetros: compara
x_amount,x_referencecon tu base de datos. - Registrar siempre: guarda el payload completo, IP origen, timestamp y código de respuesta.
- 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
-
Filtrar parámetros:
Solo se incluyen los campos cuyo nombre comienza conx_(ej:x_amount,x_reference,x_url_callback, etc.).
Se excluye explícitamentex_signature(no se firma a sí misma). -
Ordenar alfabéticamente:
Ordena las claves (nombres de campos) de forma alfabética estricta (case-sensitive, ASCII order).
Ejemplo:x_account_id→ antes quex_amount→ antes quex_currency. -
Concatenar sin separadores:
Une cada clave con su valor directamente, sin=,&, espacios ni otros caracteres.
Formato:clave1valor1clave2valor2clave3valor3...
→ Campos vacíos se concatenan comoclave(sin valor).
→ Valores se toman tal cual (strings, números como string sin formato adicional). -
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). -
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: 56ef2554442d536c1df9128a41901a8e4335a711f25de9f53282009edf0cd152Credenciales 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 tarjeta | Número de tarjeta | CVV | Fecha expiración | Resultado esperado | Notas / Escenarios recomendados |
|---|---|---|---|---|---|
| VISA | 4051 8856 0044 6623 | 123 | Cualquiera futura | Aprobada (éxito) | Usa para probar flujo completo: éxito, callback OK, redirección a x_url_complete. |
| AMEX | 3700 0000 0002 032 | 1234 | Cualquiera futura | Aprobada (éxito) | Prueba con AMEX (menos común). Verifica si tu sistema maneja bien tarjetas american express (a veces con CVV de 4 dígitos). |
| MASTERCARD | 5186 0595 5959 0568 | 123 | Cualquiera futura | Rechazada (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_completeox_url_cancel(dependiendo del flujo).
Updated about 1 month ago