Documentación de Integración Andino Pay
Aprende a integrar la pasarela de pagos líder en Colombia. Conecta tu tienda en minutos con nuestro plugin oficial para WooCommerce o implementa una solución a medida utilizando nuestra API REST v1.
1. Introducción y Selección de Integración
Andino Pay ofrece dos caminos principales para procesar pagos digitales (PSE, tarjetas de crédito/débito y más) en tu negocio:
Plugin Oficial para WordPress / WooCommerce
Ideal si tu tienda está construida sobre WooCommerce. Sin escribir código: descargas el ZIP, ingresas tus llaves de API y comienzas a recibir pagos en modo Redirect (WebCheckout) o Direct PSE.
Integración Directa mediante API REST
Para aplicaciones móviles, plataformas SaaS, e-commerce personalizados (Next.js, Laravel, Django, Node.js) o tiendas con requerimientos a la medida que requieren control total de la experiencia de pago.
2. Llaves y Credenciales de API
Para autenticar tus peticiones con Andino Pay necesitas dos credenciales generadas desde el Portal de tu Comercio → Integraciones:
| Credencial | Formato / Prefijo | Uso y Seguridad |
|---|---|---|
| API Key (Pública) | pk_test_... / pk_live_... |
Identifica tu comercio. Se envía en el header Authorization: Bearer <API_KEY>. |
| API Secret (Privado) | Cadena secreta alfanumérica |
Utilizado para generar la firma criptográfica HMAC-SHA256 (X-Signature) y validar los webhooks recibidos. Se muestra una sola vez al generarse.
|
API Secret nunca debe exponerse en clientes frontend (HTML, JavaScript público, apps móviles sin backend proxy) ni subirse a repositorios públicos. Trátalo con el mismo nivel de confidencialidad que una contraseña bancaria.
3. Ambientes (Sandbox vs Producción)
Andino Pay utiliza una URL base unificada. El ambiente operativo lo determina automáticamente el tipo de API Key que envíes:
| Ambiente | Prefijo API Key | Base URL | Efecto de las Transacciones |
|---|---|---|---|
| Sandbox (Pruebas) | pk_test_... |
https://api.andinopay.com/api |
Simulador bancario. Ningún cobro o débito es real. Permite probar flujos completos de aprobación, rechazo y reintentos. |
| Producción (Live) | pk_live_... |
https://api.andinopay.com/api |
Procesamiento financiero real a través de PSE y redes bancarias autorizadas. |
4. Autenticación y Firma HMAC (X-Signature)
Todas las peticiones a la API REST requieren el encabezado estándar:
Firma Digital HMAC-SHA256 (X-Signature)
Para garantizar la integridad y no repudio del payload, cada petición POST en producción (y recomendada en sandbox) debe firmarse con tu API Secret:
X-Signature: sha256={HMAC-SHA256(raw_json_body, api_secret)}. En peticiones GET sin cuerpo, se calcula sobre una cadena vacía ("").
// Ejemplo en PHP (cURL / Guzzle / Laravel Http)
$apiKey = 'pk_live_xxxxxxxxxxxxxxxxxxxxxxxx';
$apiSecret = 'sec_live_yyyyyyyyyyyyyyyyyyyyyyyy';
$rawBody = json_encode($payload);
$firma = 'sha256=' . hash_hmac('sha256', $rawBody, $apiSecret);
$response = Http::withHeaders([
'Authorization' => 'Bearer ' . $apiKey,
'X-Signature' => $firma,
'Content-Type' => 'application/json',
])->post('https://api.andinopay.com/api/v1/transactions', $payload);
5. Integración con WordPress / WooCommerce
El plugin oficial AndinoPay para WooCommerce (v1.0) permite habilitar cobros en tu tienda en pocos minutos, con soporte nativo para HPOS y Block Checkout.
Requisitos Previos del Sistema
| Componente | Requisito Mínimo | Detalle |
|---|---|---|
| WordPress | 6.0 o superior | Compatible con Classic Editor y Block Themes (FSE). |
| WooCommerce | 8.0 o superior | Soporta almacenamiento de pedidos de alto rendimiento (HPOS). |
| PHP | 8.0 o superior (8.1 / 8.2 recomendado) | Requiere extensiones curl, json y openssl. |
| Credenciales | API Key y API Secret | Disponibles desde el portal de tu comercio en Andino Pay. |
Instalación Paso a Paso
Descargar el archivo del Plugin
Descarga el archivo empaquetado andinopay-for-woocommerce.zip provisto por el equipo de Andino Pay.
Subir a WordPress
En el panel de administración de tu WordPress, ingresa a Plugins → Agregar nuevo → Subir plugin.
Instalar y Activar
Selecciona el archivo ZIP, presiona Instalar ahora y luego haz clic en Activar plugin.
6. Configuración de la Pasarela en WooCommerce
Ve a WooCommerce → Ajustes → pestaña Pagos, busca AndinoPay en la lista de métodos de pago y haz clic en Gestionar.
Campos de Configuración
| Campo | Descripción |
|---|---|
| Habilitar / Deshabilitar | Activa o desactiva la pasarela en el checkout de tu tienda. |
| Título | Texto que verá el cliente (ej: AndinoPay - PSE y Pagos Digitales). |
| Descripción | Texto explicativo que se muestra debajo del título durante la selección del método de pago. |
| API Key — Producción | Clave pública de producción (pk_live_...). |
| API Secret — Producción | Secreto de producción para firma y webhooks. |
| API Key — Sandbox | Clave pública de pruebas (pk_test_...). |
| API Secret — Sandbox | Secreto de pruebas para el simulador bancario. |
| Ambiente Activo | Conmutador entre Sandbox (Pruebas) y Producción. Puedes cargar ambas llaves al mismo tiempo y alternar con un solo clic. |
Modalidades de Integración en WooCommerce
| Modalidad | Funcionamiento | Recomendación de Uso |
|---|---|---|
| Redirect (Recomendado) | El cliente es redirigido al WebCheckout seguro de AndinoPay, donde puede pagar con PSE, tarjetas y cualquier nuevo canal activado en tu cuenta de manera automática. | Ideal para la gran mayoría de tiendas. Cero mantenimiento y máxima compatibilidad. |
| Direct PSE | El formulario y selector de bancos PSE aparece embebido directamente en el checkout de tu WooCommerce sin redirigir a una página externa. | Para tiendas que desean mantener al comprador dentro de su propio dominio durante la selección de banco. |
Notificaciones Webhook en WooCommerce
AndinoPay notifica automáticamente los cambios de estado (aprobado, rechazado) al endpoint interno de tu tienda:
Puedes seleccionar el modo de procesamiento del Webhook:
-
Asíncrono (Recomendado): Responde inmediatamente
HTTP 200 OKa AndinoPay y procesa la actualización del pedido en segundo plano mediante Action Scheduler. Incluye el panel WooCommerce → Webhooks pendientes para auditoría y reproceso manual. - Síncrono: Procesa el pedido de inmediato antes de responder.
Verificación en Sandbox y Compatibilidad HPOS
- Selecciona el Ambiente Sandbox.
- Agrega un producto al carrito y realiza una compra de prueba.
- Verifica que el pedido pase de Pendiente de pago a Procesando / Completado tras la simulación.
- Revisa WooCommerce → Estado → Registros con el filtro
andinopaypara inspeccionar logs.
Preguntas Frecuentes (FAQ WooCommerce)
| Pregunta | Respuesta |
|---|---|
| ¿Es compatible con Block Checkout? | Sí, el plugin soporta tanto el checkout clásico de shortcode como el nuevo sistema de bloques de WooCommerce. |
| ¿Es compatible con HPOS? | Sí, declara compatibilidad nativa con High-Performance Order Storage (HPOS). |
| ¿Qué ocurre con los pedidos de prueba al pasar a producción? | Cada pedido registra el ambiente en el que se originó; las órdenes de sandbox no interfieren con la contabilidad real. |
7. Especificación Técnica de la API REST v1
Para integraciones directas desde el backend de tu sistema, la API REST expone endpoints seguros bajo formato JSON.
Encabezados Requeridos
| Header | Valor | Requerido |
|---|---|---|
Authorization |
Bearer pk_test_... / Bearer pk_live_... |
Obligatorio |
Content-Type |
application/json |
Obligatorio |
X-Signature |
sha256={HMAC-SHA256(body, secret)} |
Obligatorio en Live / Opcional en Sandbox |
8. Crear Sesión de Checkout (WebCheckout)
Permite delegar la pantalla de pago a Andino Pay. Envías el monto y recibes una URL segura (checkout_url) a la cual redirigir al comprador.
Parámetros del Request (Body JSON)
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
monto |
number | Obligatorio | Valor a cobrar en pesos colombianos (COP). Mínimo 0.01. |
moneda |
string | Opcional | Código de moneda ISO. Default: "COP". Enviar otra moneda retorna error currency_not_supported. |
order_id |
string | Obligatorio | Identificador único del pedido en tu sistema (ej: "ORDER-001"). |
descripcion |
string | Opcional | Detalle visible en la pantalla de pago. Máximo 500 caracteres. |
redirect_url |
string | Obligatorio | URL de tu tienda a la que regresa el cliente al completar el flujo. |
webhook_url |
string | Opcional | URL para recibir la notificación HTTP asíncrona. |
metadata |
object | Opcional | Objeto clave-valor para almacenar metadatos personalizados (ej: {"customer_id": "USR-789"}). |
payer |
object | Opcional | Datos opcionales para prellenar la pantalla del pagador (nombre, apellido, email, documento, etc.). |
curl -X POST https://api.andinopay.com/api/v1/checkout/sessions \
-H "Authorization: Bearer pk_test_qyNu58wqSrIFeGYr0EiLwJBKFI8fZjwJ" \
-H "Content-Type: application/json" \
-d '{
"monto": 250000,
"moneda": "COP",
"order_id": "ORDER-001",
"descripcion": "Pago del pedido #ORDER-001",
"redirect_url": "https://tu-tienda.com/orden/ORDER-001/resultado",
"webhook_url": "https://tu-tienda.com/webhooks/pago",
"metadata": {
"customer_id": "USR-789"
},
"payer": {
"nombre": "María",
"apellido": "López",
"email": "maria@ejemplo.com",
"tipo_documento": "CC",
"documento": "9876543210",
"telefono": "3001234567"
}
}'
{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"checkout_url": "https://checkout.andinopay.com/cs/550e8400-e29b-41d4-a716-446655440000?ct=eyJhbGciOiJIUzI1NiIsInR...",
"estado": "pendiente",
"monto": 250000.0,
"moneda": "COP",
"expires_at": "2026-08-20T15:00:00-05:00"
}
9. Consultar Sesión de Checkout
Permite a tu backend consultar el estado de una sesión creada previamente por su UUID (session_id) y comprobar si fue pagada, expiró o está en proceso.
Estados Posibles de una Sesión
| Estado de Sesión | Descripción |
|---|---|
| pendiente | Sesión activa en espera de que el pagador ingrese y complete el checkout. |
| en_proceso | El comprador fue redirigido al banco y la transacción está en confirmación. |
| completada | Pago acreditado exitosamente. Contiene una transacción aprobada en el array transacciones. |
| expirada | Expiró el tiempo límite de 1 hora sin completarse la compra. |
curl -X GET https://api.andinopay.com/api/v1/checkout/sessions/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer pk_test_qyNu58wqSrIFeGYr0EiLwJBKFI8fZjwJ"
{
"session_id": "550e8400-e29b-41d4-a716-446655440000",
"estado": "completada",
"monto": 250000.0,
"moneda": "COP",
"checkout_url": "https://checkout.andinopay.com/cs/550e8400-e29b-41d4-a716-446655440000",
"redirect_url": "https://tu-tienda.com/orden/ORDER-001/resultado",
"expires_at": "2026-08-20T15:00:00-05:00",
"created_at": "2026-08-20T14:00:00-05:00",
"transacciones": [
{
"uuid": "660e8400-e29b-41d4-a716-446655440001",
"estado": "aprobada",
"monto": 250000.0,
"neto": 242500.0,
"origen": "webcheckout",
"created_at": "2026-08-20T14:02:00-05:00"
}
]
}
10. Crear Transacción Directa (PSE / Direct API)
Crea una transacción directamente desde tu backend cuando recolectas los datos del pagador y el banco seleccionado en tu propio formulario embebido.
Parámetros Principales de la Petición
| Campo | Tipo | Requerido | Descripción |
|---|---|---|---|
monto |
number | Obligatorio | Monto en COP (mínimo 0.01). |
moneda |
string | Opcional | Por defecto "COP". Enviar otra moneda devuelve error 422 currency_not_supported. |
referencia_externa |
string | Obligatorio | Tu referencia interna (orden, factura, etc.) — actúa como clave de idempotencia estricta. |
descripcion |
string | Opcional | Descripción libre del pago. Máximo 500 caracteres. |
canal_pago_id |
integer | Opcional |
ID del canal de pago. Es opcional: si se omite, Andino Pay resuelve automáticamente el canal PSE activo asignado a tu comercio según el ambiente de tu API Key. Solo se envía si tu comercio tiene múltiples canales y deseas forzar uno específico (ver GET /v1/channels). Si no hay canal PSE activo, responde 422 canal_not_found.
|
redirect_url |
string | Obligatorio para PSE | URL del banco a la que se redirige al cliente tras autorizar o cancelar. Sin este campo retorna 422 redirect_url_required. |
webhook_url |
string | Opcional | URL donde recibirás la notificación HTTP asíncrona. |
payer |
object | Obligatorio | Objeto con los datos del pagador (ver tabla a continuación). |
Objeto Payer (Datos del Pagador)
Campo en payer |
Tipo | Requerido (PSE) | Valores / Descripción |
|---|---|---|---|
nombre |
string | Obligatorio | Nombre del titular de la cuenta bancaria. |
apellido |
string | Obligatorio | Apellido del titular. |
email |
string | Obligatorio | Correo electrónico registrado en PSE. |
tipo_documento |
string | Obligatorio | CC, CE, NIT, PP, TI, TE. |
documento |
string | Obligatorio | Número de documento de identidad. |
telefono |
string | Obligatorio | Número de contacto (ej: "3001234567"). |
tipo_persona |
string | Obligatorio | natural o juridica. |
banco_pse |
string | Obligatorio | Código del banco obtenido mediante GET /v1/pse/banks. |
direccion |
string | Opcional | Dirección del comprador. |
curl -X POST https://api.andinopay.com/api/v1/transactions \
-H "Authorization: Bearer pk_test_qyNu58wqSrIFeGYr0EiLwJBKFI8fZjwJ" \
-H "Content-Type: application/json" \
-d '{
"monto": 150000,
"moneda": "COP",
"referencia_externa": "ORDER-2026-001",
"descripcion": "Pago del pedido #ORDER-2026-001",
"redirect_url": "https://tucomercio.com/gracias",
"webhook_url": "https://tucomercio.com/webhooks/andinopay",
"payer": {
"nombre": "Juan",
"apellido": "Pérez",
"email": "juan@ejemplo.com",
"tipo_documento": "CC",
"documento": "1234567890",
"telefono": "3001234567",
"tipo_persona": "natural",
"banco_pse": "1007"
}
}'
{
"transaction_id": 123,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"estado": "pendiente",
"ambiente": "sandbox",
"monto": 150000.00,
"comision": 5250.00,
"porcentaje_aplicado": 2.50,
"fija_aplicada": 1500.00,
"neto": 144750.00,
"canal_pago": "PSE Sandbox",
"referencia_externa": "ORDER-2026-001",
"redirect_url": "https://api.andinopay.com/sandbox/pse/550e8400-e29b-41d4-a716-446655440000",
"created_at": "2026-08-20T14:00:00-05:00"
}
11. Consultar Bancos PSE y Canales
Obtiene la lista oficial de entidades bancarias habilitadas para PSE según el ambiente de tu API Key.
Parámetro opcional: GET /api/v1/pse/banks?canal_pago_id=X permite forzar la consulta de bancos para un canal específico si tu comercio cuenta con múltiples canales PSE asignados. Si tu comercio no tiene ningún canal PSE disponible en ese ambiente, la respuesta es 404 no_channels_available.
[
{ "bankCode": "1007", "bankName": "Bancolombia" },
{ "bankCode": "1051", "bankName": "Davivienda" },
{ "bankCode": "1023", "bankName": "Banco de Occidente" },
{ "bankCode": "1001", "bankName": "Banco de Bogotá" }
]
Consultar Canales Asignados
[
{ "id": 3, "nombre": "PSE", "metodo": "pse", "ambiente": "produccion" }
]
12. Consultar Estado de Transacción
Permite verificar el estado actual de un pago utilizando su identificador numérico (transaction_id).
Ciclo de Vida y Estados de Transacción
| Estado | Significado | Acción en tu Sistema |
|---|---|---|
| pendiente | Esperando que el pagador complete la autenticación en el banco. | Mantener la orden en espera. |
| en_proceso | Confirmación bancaria en curso. | Esperar webhook o re-consultar en unos minutos. |
| aprobada | Pago acreditado exitosamente en tu balance. | Liberar producto, servicio o pedido. |
| rechazada | Fondos insuficientes o rechazo de la entidad financiera. | Permitir reintento al cliente. |
| fallida | Fallo técnico de comunicación o timeout del banco. | Permitir reintento con la misma referencia. |
13. Idempotencia con referencia_externa
El campo referencia_externa actúa como clave de idempotencia estricta para prevenir cobros duplicados accidentales:
| Estado de la TX Previa | Comportamiento de la API ante un nuevo POST | Respuesta HTTP |
|---|---|---|
| aprobada | La orden ya fue pagada. No se crea otra transacción. | 422 already_paid |
| pendiente / en_proceso | Existe una transacción en curso. Se retorna la TX existente sin duplicar el cobro. | 200 duplicate_reference con "idempotent": true |
| rechazada / fallida | Permite que el cliente intente nuevamente con la misma referencia_externa generando una TX limpia. |
201 Created (nueva TX) |
Ejemplo de Respuesta Idempotente (200 OK)
{
"message": "Ya existe una transacción activa para esta referencia",
"code": "duplicate_reference",
"idempotent": true,
"transaction_id": 123,
"uuid": "550e8400-e29b-41d4-a716-446655440000",
"redirect_url": "https://api.andinopay.com/sandbox/pse/550e8400-e29b-41d4-a716-446655440000"
}
14. Webhooks y Validación de Firma
Cuando una transacción cambia de estado, Andino Pay envía una notificación HTTP POST en formato JSON a tu webhook_url.
Campos del Payload del Webhook
| Campo | Tipo | Descripción |
|---|---|---|
event | string | Nombre del evento ("transaction.updated"). |
ambiente | string | "sandbox" o "produccion". |
transaction_id | string | UUID de la transacción en Andino Pay. |
estado | string | Nuevo estado: aprobada, rechazada, fallida. |
monto | number | Monto total pagado en COP. |
neto | number | Monto acreditado a tu balance tras comisiones. |
processor | string | Adaptador/procesador utilizado (ej: "pse", "sandbox"). |
processor_reference | string | Código de autorización/referencia entregado por la red bancaria. |
referencia_externa | string | Tu identificador de orden o pedido. |
descripcion | string | Descripción de la compra. |
created_at / updated_at | string | Estampas de tiempo ISO 8601. |
Validación Obligatoria de X-Webhook-Signature
Cada notificación incluye el encabezado X-Webhook-Signature: sha256=.... Debes verificar que coincida con el hash HMAC-SHA256 del cuerpo recibido en crudo (raw body) antes de procesar la orden:
// Validación en PHP puro o Laravel
$rawBody = file_get_contents('php://input');
$recibida = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$apiSecret = 'TU_API_SECRET';
$esperada = 'sha256=' . hash_hmac('sha256', $rawBody, $apiSecret);
if (! hash_equals($esperada, $recibida)) {
http_response_code(401);
exit('Firma del webhook inválida');
}
$payload = json_decode($rawBody, true);
// Procesar $payload['estado'] y actualizar tu base de datos
http_response_code(200);
echo 'OK';
Política de 5 Reintentos Automáticos
Tu servidor debe responder HTTP 2xx en menos de 10 segundos. Si no responde o devuelve error, Andino Pay ejecuta la siguiente política de reintentos:
| Intento | Intervalo de Espera |
|---|---|
| 1° Intento | Inmediato tras el cambio de estado |
| 2° Intento | 1 minuto |
| 3° Intento | 5 minutos |
| 4° Intento | 15 minutos |
| 5° Intento (Último) | 1 hora |
| Sin respuesta tras 5 intentos | Estado interno marcado como webhook_status = failed |
15. Catálogo de Errores y Códigos HTTP
| HTTP | Código Interno | Causa | Solución |
|---|---|---|---|
| 401 | missing_api_key |
Falta el encabezado Authorization |
Incluir Authorization: Bearer pk_... en los headers. |
| 401 | invalid_api_key |
API Key incorrecta o revocada | Verificar y re-generar la llave en el portal de comercio. |
| 401 | invalid_signature |
Firma X-Signature inválida |
Validar que se calcule sobre el raw body y con el API Secret correspondiente. |
| 404 | no_channels_available |
Comercio sin canal PSE disponible en ese ambiente | Contactar a soporte Andino Pay para habilitar canal PSE en tu cuenta. |
| 422 | already_paid |
La orden ya fue pagada con esa referencia | No reintentar cobro; el pedido ya está saldado. |
| 200 | duplicate_reference |
Ya existe una transacción activa (idempotente) | Utilizar la redirect_url retornada sin duplicar la orden. |
| 422 | canal_not_found |
Canal PSE no asignado al comercio o ID inválido | Contactar soporte Andino Pay o verificar GET /v1/channels. |
| 422 | redirect_url_required |
Falta el campo redirect_url para PSE |
Enviar una URL de retorno válida en el cuerpo de la petición. |
| 422 | currency_not_supported |
Moneda enviada no es soportada | Enviar moneda: "COP" (única moneda aceptada por ahora). |
| 503 | comercio_unavailable |
Comercio inactivo o en revisión de cumplimiento | Verificar el estado de la cuenta con tu ejecutivo Andino Pay. |
16. Colección Oficial de Postman
Prueba todos los endpoints de Andino Pay v1 directamente en Postman con scripts de auto-firma y variables de ambiente preconfiguradas: