POST /VerificacionPago
curl --request POST \
--url https://api.example.com/VerificacionPago \
--header 'Content-Type: application/json' \
--data '
{
"int_id_comercio": 123,
"str_usr_comercio": "<string>",
"str_pwd_Comercio": "<string>",
"str_id_pago": "<string>",
"int_no_pago": 123
}
'import requests
url = "https://api.example.com/VerificacionPago"
payload = {
"int_id_comercio": 123,
"str_usr_comercio": "<string>",
"str_pwd_Comercio": "<string>",
"str_id_pago": "<string>",
"int_no_pago": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
int_id_comercio: 123,
str_usr_comercio: '<string>',
str_pwd_Comercio: '<string>',
str_id_pago: '<string>',
int_no_pago: 123
})
};
fetch('https://api.example.com/VerificacionPago', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/VerificacionPago",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'int_id_comercio' => 123,
'str_usr_comercio' => '<string>',
'str_pwd_Comercio' => '<string>',
'str_id_pago' => '<string>',
'int_no_pago' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/VerificacionPago"
payload := strings.NewReader("{\n \"int_id_comercio\": 123,\n \"str_usr_comercio\": \"<string>\",\n \"str_pwd_Comercio\": \"<string>\",\n \"str_id_pago\": \"<string>\",\n \"int_no_pago\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/VerificacionPago")
.header("Content-Type", "application/json")
.body("{\n \"int_id_comercio\": 123,\n \"str_usr_comercio\": \"<string>\",\n \"str_pwd_Comercio\": \"<string>\",\n \"str_id_pago\": \"<string>\",\n \"int_no_pago\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/VerificacionPago")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"int_id_comercio\": 123,\n \"str_usr_comercio\": \"<string>\",\n \"str_pwd_Comercio\": \"<string>\",\n \"str_id_pago\": \"<string>\",\n \"int_no_pago\": 123\n}"
response = http.request(request)
puts response.read_body{
"int_estado": 123,
"int_error": 123,
"str_detalle": {},
"int_cantidad_pagos": 123,
"str_res_pago": "<string>"
}Endpoints
POST /VerificacionPago
Consulta el estado de una o más transacciones.
POST
/
VerificacionPago
POST /VerificacionPago
curl --request POST \
--url https://api.example.com/VerificacionPago \
--header 'Content-Type: application/json' \
--data '
{
"int_id_comercio": 123,
"str_usr_comercio": "<string>",
"str_pwd_Comercio": "<string>",
"str_id_pago": "<string>",
"int_no_pago": 123
}
'import requests
url = "https://api.example.com/VerificacionPago"
payload = {
"int_id_comercio": 123,
"str_usr_comercio": "<string>",
"str_pwd_Comercio": "<string>",
"str_id_pago": "<string>",
"int_no_pago": 123
}
headers = {"Content-Type": "application/json"}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({
int_id_comercio: 123,
str_usr_comercio: '<string>',
str_pwd_Comercio: '<string>',
str_id_pago: '<string>',
int_no_pago: 123
})
};
fetch('https://api.example.com/VerificacionPago', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.example.com/VerificacionPago",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'int_id_comercio' => 123,
'str_usr_comercio' => '<string>',
'str_pwd_Comercio' => '<string>',
'str_id_pago' => '<string>',
'int_no_pago' => 123
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.example.com/VerificacionPago"
payload := strings.NewReader("{\n \"int_id_comercio\": 123,\n \"str_usr_comercio\": \"<string>\",\n \"str_pwd_Comercio\": \"<string>\",\n \"str_id_pago\": \"<string>\",\n \"int_no_pago\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.example.com/VerificacionPago")
.header("Content-Type", "application/json")
.body("{\n \"int_id_comercio\": 123,\n \"str_usr_comercio\": \"<string>\",\n \"str_pwd_Comercio\": \"<string>\",\n \"str_id_pago\": \"<string>\",\n \"int_no_pago\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/VerificacionPago")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Content-Type"] = 'application/json'
request.body = "{\n \"int_id_comercio\": 123,\n \"str_usr_comercio\": \"<string>\",\n \"str_pwd_Comercio\": \"<string>\",\n \"str_id_pago\": \"<string>\",\n \"int_no_pago\": 123\n}"
response = http.request(request)
puts response.read_body{
"int_estado": 123,
"int_error": 123,
"str_detalle": {},
"int_cantidad_pagos": 123,
"str_res_pago": "<string>"
}URL de producción:
https://www.zonapagos.com/Apis_CicloPago/api/VerificacionPagoVisión general
Este endpoint consulta el estado actual de una transacción previamente iniciada con/InicioPago. Se usa en dos momentos:
- Al recibir el callback del usuario — antes de entregar el producto.
- Desde la sonda — cada 10-15 minutos para transacciones en estado pendiente.
Headers
Content-Type: application/json
Cuerpo del request
A diferencia de/InicioPago, este endpoint recibe un objeto plano (sin anidar):
integer
required
Tu
int_id_comercio. Ej. 678.string
required
Tu usuario técnico (mismo valor que
str_usuario en /InicioPago). Máximo 40 caracteres.string
required
Tu clave (mismo valor que
str_clave en /InicioPago). Máximo 50 caracteres.Nota la C mayúscula en
str_pwd_Comercio. Sí, rompe con la convención snake_case del resto del API.string
required
El
str_id_pago que enviaste al crear la transacción en /InicioPago. Máximo 30 caracteres.integer
required
Número de intento de pago. Usar
-1 para consultar todos los intentos asociados al str_id_pago.Si pagos mixtos están habilitados, un str_id_pago puede tener varios int_no_pago. Con -1 recibes todos; con un valor específico, solo ese.Cuerpo del response
integer
1 si el API ejecutó correctamente (incluso si no hay pagos). 2 si hubo error de autenticación o validación.integer
0 si se encontraron pagos. -1 si hubo error (el detalle va en str_detalle).string | null
Texto del error cuando
int_error: -1. null en caso de éxito.integer
Cantidad de intentos de pago encontrados para el
str_id_pago consultado.string
Detalle de las transacciones en formato de texto plano con separadores
| y |;|. Ver cómo parsearlo.Cuando
int_cantidad_pagos: 0, este campo viene vacío o nulo.Ejemplo completo
{
"int_id_comercio": 678,
"str_usr_comercio": "Usuario",
"str_pwd_Comercio": "ClaveSecreta",
"str_id_pago": "180921",
"int_no_pago": -1
}
{
"int_estado": 1,
"int_error": 0,
"str_detalle": null,
"int_cantidad_pagos": 2,
"str_res_pago": "31|3772|1|1|1|12500|12500|0|Compra de camisa|123456789|Juan|Perez|3001234567|cliente@ejemplo.com|canal-web|campaña-abril|||||21/04/2026 12:58:41|29|18092100031|2701|1022|BANCO UNION COLOMBIANO|1468228|3|;|"
}
{
"int_estado": 1,
"int_error": 0,
"str_detalle": null,
"int_cantidad_pagos": 0,
"str_res_pago": ""
}
{
"int_estado": 2,
"int_error": -1,
"str_detalle": "Credenciales inválidas",
"int_cantidad_pagos": 0,
"str_res_pago": null
}
Parsear str_res_pago
El formato es:
campo1|campo2|...|campoN|;|campo1|campo2|...|campoN|;|
int_id_forma_pago).
function parseStrResPago(str) {
if (!str || str.trim() === "") return [];
// Campos base (comunes a todos los medios)
const CAMPOS_BASE = [
"int_ped_numero",
"int_n_pago",
"int_pago_parcial",
"int_pago_terminado",
"int_estado_pago",
"dbl_valor_pagado",
"dbl_total_pago",
"dbl_valor_iva_pagado",
"str_descripcion",
"str_id_cliente",
"str_nombre",
"str_apellido",
"str_telefono",
"str_email",
"str_campo1",
"str_campo2",
"str_campo3",
"str_campo4",
"str_campo5",
"dat_fecha",
"int_id_forma_pago"
];
// Separar pagos
return str
.split("|;|")
.map(s => s.trim())
.filter(s => s.length > 0)
.map(pago => {
const partes = pago.split("|");
const obj = {};
CAMPOS_BASE.forEach((campo, i) => {
obj[campo] = partes[i] !== undefined ? partes[i].trim() : "";
});
// Campos extra dependen del medio de pago
const extras = partes.slice(CAMPOS_BASE.length);
obj._campos_adicionales = extras;
return obj;
});
}
// Uso
const pagos = parseStrResPago(response.data.str_res_pago);
console.log(`Encontrados ${pagos.length} intento(s) de pago`);
pagos.forEach(p => console.log(`${p.str_descripcion}: estado ${p.int_estado_pago}`));
def parse_str_res_pago(raw: str) -> list[dict]:
if not raw or not raw.strip():
return []
CAMPOS_BASE = [
"int_ped_numero", "int_n_pago", "int_pago_parcial",
"int_pago_terminado", "int_estado_pago",
"dbl_valor_pagado", "dbl_total_pago", "dbl_valor_iva_pagado",
"str_descripcion", "str_id_cliente",
"str_nombre", "str_apellido", "str_telefono", "str_email",
"str_campo1", "str_campo2", "str_campo3", "str_campo4", "str_campo5",
"dat_fecha", "int_id_forma_pago"
]
pagos = []
for pago_raw in [p.strip() for p in raw.split("|;|") if p.strip()]:
partes = [x.strip() for x in pago_raw.split("|")]
obj = {campo: partes[i] if i < len(partes) else ""
for i, campo in enumerate(CAMPOS_BASE)}
obj["_campos_adicionales"] = partes[len(CAMPOS_BASE):]
pagos.append(obj)
return pagos
public static List<Dictionary<string, string>> ParseStrResPago(string raw)
{
var result = new List<Dictionary<string, string>>();
if (string.IsNullOrWhiteSpace(raw)) return result;
var CAMPOS_BASE = new[]
{
"int_ped_numero", "int_n_pago", "int_pago_parcial",
"int_pago_terminado", "int_estado_pago",
"dbl_valor_pagado", "dbl_total_pago", "dbl_valor_iva_pagado",
"str_descripcion", "str_id_cliente",
"str_nombre", "str_apellido", "str_telefono", "str_email",
"str_campo1", "str_campo2", "str_campo3", "str_campo4", "str_campo5",
"dat_fecha", "int_id_forma_pago"
};
var pagosRaw = raw.Split(new[] { "|;|" }, StringSplitOptions.None)
.Select(p => p.Trim())
.Where(p => p.Length > 0);
foreach (var pagoRaw in pagosRaw)
{
var partes = pagoRaw.Split('|').Select(x => x.Trim()).ToArray();
var obj = new Dictionary<string, string>();
for (int i = 0; i < CAMPOS_BASE.Length; i++)
obj[CAMPOS_BASE[i]] = i < partes.Length ? partes[i] : "";
result.Add(obj);
}
return result;
}
¿Cuándo consultar?
1
Al recibir el callback del usuario
ZonaPagos redirige al usuario a tu URL de retorno con
id_comercio e id_pago. Al recibirlo, tu backend debe consultar VerificacionPago antes de mostrarle el estado al usuario.2
Desde la sonda (obligatorio para PSE)
Para pagos en estado
999, 4001, 4000, 4003, tu backend debe consultar periódicamente hasta recibir un estado definitivo.3
Al reprocesar manualmente
Si un pago quedó en estado dudoso, tu equipo de soporte puede consultar desde un panel admin.
Ver también
Estados de pago
Todos los valores de
int_estado_pago y qué hacer con cada uno.Implementar sonda
Guía paso a paso del job programado que consulta pagos pendientes.