Procesar pago alternativo
Inicia el flujo de pago alternativo con un procesador específico seleccionado de la lista retornada en el momento de creación. La forma de la respuesta depende del procesador — Migo la normaliza mediante un discriminador data.type para que el frontend del comercio pueda renderizar la UI correcta.
POST https://mw.migopayments.com/api/v1/integrations/transactions/{transactionId}/payments
Consulta la entrada en el spec en vivo: POST /api/v1/integrations/transactions/{transactionId}/payments.
Recordatorio de auth. Toda llamada envía
Authorization: Bearer <token>. Ve Autenticación para más detalles.
Petición — body unificado
El body es la misma forma para cada procesador. El integrador siempre puede enviar todos los campos documentados; el runtime solo lee las llaves que aplican al processor elegido. Los campos que no aplican son ignorados.
{
"processor": "bamPaymentButton",
"data": {
"user": "",
"phoneNumber": "",
"installments": 1
}
}
| Campo | Tipo | Requerido | Notas |
|---|---|---|---|
processor | string | sí | Debe estar presente en el array paymentMethods retornado al crear la transacción. |
data | object | sí (puede ser {}) | Envoltorio unificado — ve el mapeo campo-a-procesador abajo. El runtime solo lee las llaves que aplican al processor elegido; todo lo demás es ignorado. |
Mapeo campo-a-procesador
El integrador puede mantener una sola forma de body y solo llenar lo que aplica. Envía strings vacíos, {}, u omite campos — Migo ignora todo lo que esté fuera del payload documentado del procesador activo.
Campo en data | Usado por |
|---|---|
user o phoneNumber (al menos uno) | fri |
installments | bamPaymentButton |
Procesadores sin requerimiento de data (envía data: {} u omite las llaves no usadas): bancoIndustrial, quickPayQR, akisiQR, pronet, zigi.
La forma unificada completa está documentada en el spec como AlternativePaymentDataDto.
cURL — BAM Payment Button (Guatemala)
curl -X POST https://mw.migopayments.com/api/v1/integrations/transactions/trx_8f3c2b1d9e7a/payments \
-H 'Authorization: Bearer <token>' \
-H 'Content-Type: application/json' \
-d '{
"processor": "bamPaymentButton",
"data": { "installments": 1 }
}'
Node.js
const res = await fetch(
`https://mw.migopayments.com/api/v1/integrations/transactions/${transactionId}/payments`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MIGO_JWT}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
processor: 'bamPaymentButton',
data: { installments: 1 },
}),
}
);
const { data } = await res.json();
// data.type drives the rendering branch
if (data.type === 'url') window.location.href = data.data; // Zigi, BAM Payment Button
if (data.type === 'base64') renderImage(data.data); // Akisi QR, Banco Industrial
if (data.type === 'json') renderStructuredPayload(data.data); // Pronet, QuickPay QR, FRI
Ejemplos de petición por procesador
Cada ejemplo usa la misma forma de body unificada. El integrador puede mantener el mismo tipo del lado del cliente y solo poblar los campos que aplican — Migo ignora las llaves fuera del payload del procesador activo.
FRI (push payment)
fri requiere al menos uno de user o phoneNumber.
{
"processor": "fri",
"data": {
"user": "fri-user-001"
}
}
BAM Payment Button (Guatemala, redirect hosteado)
{
"processor": "bamPaymentButton",
"data": {
"installments": 1
}
}
Procesadores sin data (envía {})
bancoIndustrial, quickPayQR, akisiQR, pronet, zigi — el cliente paga vía su app después de que Migo emite el QR / push notification.
{
"processor": "bancoIndustrial",
"data": {}
}
Forma de respuesta por data.type
data.type | Estrategia de render | Campo de payload | Procesadores de ejemplo |
|---|---|---|---|
url | Redireccionar al cliente a la URL | data.data es el string de URL | Zigi, BAM Payment Button |
qr | Renderizar imagen QR a partir de un string EMVCo crudo | data.data es el string del QR | (ninguno actualmente) |
base64 | Insertar el valor directo en <img src=...> | data.data es un URI data:image/png;base64,… | Akisi QR, Banco Industrial |
json | Payload estructurado (referencias) | data.data es el payload estructurado | Pronet, QuickPay QR, FRI |
data.data, no data.valueEl runtime emite el payload bajo data.data. Recetas anteriores (especialmente recipes/guatemala.md) usaban data.value — esa variante está desactualizada. Al parsear la respuesta, siempre lee data.data.
Ejemplo para type: "url":
{
"success": true,
"message": "success",
"data": {
"uid": "trx_8f3c2b1d9e7a",
"type": "url",
"data": "https://gateway.example.com/redirect/abc",
"cancelAt": 600
}
}
Ejemplo para type: "base64" (Akisi QR — verificado contra sb-mw.migopayments.com):
{
"success": true,
"message": "Success",
"data": {
"transaction_id": "12740927961946781727",
"type": "base64",
"data": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAJQAAA…"
}
}
El identificador de la transacción en la respuesta vuelve como uid para algunos rieles (p. ej. Zigi, BAM Payment Button) y como transaction_id para otros (p. ej. Akisi QR, QuickPay QR). Los dos campos que siempre debes leer para renderizar son type y data.
Polling vs webhooks
Migo confirma el estado final mediante el webhook del procesador (APPROVED, DENIED, EXPIRED). Para UX puedes hacer polling al estado de la transacción cada 3–5 segundos mientras el cliente completa el rail; no dependas del polling como fuente de verdad — el webhook es autoritativo.
Errores
| HTTP | Causa |
|---|---|
| 400 | Parámetros faltantes, procesador no permitido para este cliente, o llaves de data requeridas faltantes (la respuesta incluye data.missingValues) |
| 401 | Falló la autenticación del lado del usuario (Ridivi) |
| 405 | Procesador temporalmente no disponible (por ejemplo, Banco Industrial retorna un unavailabilityReason) |
| 500 | El request al procesador no pudo ser procesado |