Saltar al contenido principal

Webhook de confirmación

POST /webhooks/crezcamos/pse-payments

El nombre es histórico (nació para PSE liquidado por Crezcamos); hoy lo usan Cuenta Crezcamos y Bre-B. Un alias con un nombre neutro es una mejora opcional.

Estado de cada afirmación: Implementado (lo hace el motor y tiene pruebas), Decisión local (elegido por el equipo, modificable) o Por confirmar (depende de Crezcamos).

Autenticación y duplicados​

  • Cabecera X-Crezcamos-Webhook-Secret con el secreto compartido (CREZCAMOS__WEBHOOKSECRET); comparación en tiempo constante. Implementado. Sin firma del cuerpo ni timestamp. Por confirmar: firma HMAC y timestamp.
  • Identificador del evento: event_id o id del cuerpo, o la cabecera X-Crezcamos-Event-Id; si no hay ninguno, el hash SHA-256 del cuerpo. Un identificador repetido se responde duplicate sin reprocesar. Implementado.

Respuestas​

HTTPCuerpoCuándo
200{"ok":true,"event_id":…,"payment_id":…,"payment_link_id":…}Procesado
200{"ok":true,"duplicate":true}Evento ya recibido
401{"ok":false,"error":"invalid signature"}Secreto incorrecto o ausente
422{"ok":false,"error":"payment not found"}No se resolvió ni el pago, ni el link, ni el comercio
422{"ok":false,"error":"amount mismatch"} / "currency mismatch"El monto o la moneda no coinciden con el total del link

Un 422 por monto no registra el evento: si lo reintentas con el mismo event_id vuelves a recibir 422, no duplicate. Implementado.

Cuerpo (JSON)​

CampoObligatorioUso
payment_link_token (o link.token)Sí, en el primer evento de un pagoLlave para resolver el link; el enlace que abrió el pagador ya lo lleva como token
status (o status_detail, transaction.status)SíVer estados
rail o payment_methodRecomendadocuentas_crezcamos, breb o pse. Sin él (o desconocido) se asume pse, como antes
provider_payment_id / payment_idRecomendadoIdentifica el pago en eventos posteriores
provider_transaction_id / transaction_idOpcionalAlternativa de búsqueda
reference / provider_referenceRecomendado en el primer eventoSe guarda como referencia del pago
amount, currencyRecomendadoSi vienen, deben coincidir con el total del link (COP; mayúsculas y escala decimal no importan). Si faltan, se usa el del link
event_idRecomendadoDeduplicación
status_detail, reason, approval_code, response_code, failure_reasonOpcionalesSe guardan; los vacíos no borran lo anterior
metadataOpcionalObjeto libre; uno vacío no borra el anterior
merchant_idNo usarSe ignora si el link ya resolvió el comercio (anti-suplantación)

Ejemplos​

Primer evento (el pago nace aquí):

curl -s -X POST "$API/webhooks/crezcamos/pse-payments" \
-H "Content-Type: application/json" \
-H "X-Crezcamos-Webhook-Secret: $CREZCAMOS_WEBHOOK_SECRET" \
-H "X-Crezcamos-Event-Id: evt-0001" \
-d '{
"status": "PENDING",
"rail": "breb",
"payment_link_token": "D8bwL5EqTqOMOtO-IhIXm5NAEwTDMElp",
"provider_payment_id": "brb-9981",
"reference": "pedido-1042",
"amount": 50000,
"currency": "COP"
}'

Evento terminal mínimo (solo identifica el pago y trae el estado; no borra la referencia ni el metadata):

curl -s -X POST "$API/webhooks/crezcamos/pse-payments" \
-H "Content-Type: application/json" \
-H "X-Crezcamos-Webhook-Secret: $CREZCAMOS_WEBHOOK_SECRET" \
-H "X-Crezcamos-Event-Id: evt-0002" \
-d '{"status": "APPROVED", "provider_payment_id": "brb-9981"}'
  1. El link del pago ya existente (por provider_payment_id o provider_transaction_id).
  2. payment_link_id / link.id.
  3. payment_link_token / link.token.
  4. reference tratada como token (limitación heredada: reference no es el token del link, así que solo sirve si reenvías el token en reference).

Por eso el primer evento debe llevar payment_link_token.

Qué hace la pasarela con el evento​

  • Un pago nuevo nace con el rail del evento y proveedor crezcamos (Cuenta Crezcamos y Bre-B) o akua (PSE). Implementado.
  • Un valor nuevo no vacío reemplaza al guardado; uno vacío lo conserva. Implementado.
  • Un pending tardío no degrada un pago ni un link ya paid; un contracargo sí. Implementado.
  • Tras procesarlo, dispara el webhook de pago al comercio. Implementado.
  • Se asume entrega al menos una vez y posible desorden. Decisión local.