Skip to main content
Esta guía es SOLO para el programa de partners de Confío. Si solo necesitas consumir la API pública de Confío o recibir webhooks estándar, esta guía NO aplica para ti. Consulta “Cuándo usar esta guía”.

Cuándo usar esta guía

Integración estándar (NO requiere esta guía)

Usa la integración estándar si quieres:
  • Consumir la API de Confío para crear pagos desde tu aplicación.
  • Recibir webhooks de Confío sobre cambios de estado de pagos.
  • Usar una cuenta centralizada de Confío para procesar pagos de todos tus usuarios.
En ese caso:
  1. Contacta a tu gerente de cuenta de Confío para obtener tu CONFIO_ACCESS_TOKEN.
  2. Proporciona la URL de tu endpoint de webhooks y el token que Confío debe usar para autenticarse contra ese endpoint.
  3. Comienza con la guía de creación de pagos y la guía de webhooks.

Programa de partners (SÍ requiere esta guía)

Esta guía aplica si:
  • Eres un Partner (por ejemplo, Shopify, Dropi, WooCommerce u otra plataforma de e-commerce).
  • Cada comercio de tu plataforma conecta su propia tienda de Confío.
  • Confío debe validar un token emitido por tu plataforma antes de crear la integración.
  • Tu plataforma debe recibir un token emitido por Confío para llamar la API pública en nombre de esa integración.
Confío admite distintos flujos de Partner. Esta guía documenta el contrato público para Partners que exponen endpoints propios (/merchant y /notifications). Shopify y WooCommerce tienen flujos específicos gestionados por la interfaz de Confío.

Conceptos y tokens

Confío registrará una URL base de tu API (PARTNER_BASE_URL). A partir de esa URL, Confío llama rutas fijas:
PropósitoRuta llamada por Confío
Validar token y obtener comercioGET {PARTNER_BASE_URL}/merchant
Enviar handshake, teardown y webhooksPOST {PARTNER_BASE_URL}/notifications
Por ejemplo, si tu URL base es https://tu-api.com/confio, Confío llamará:
  • GET https://tu-api.com/confio/merchant
  • POST https://tu-api.com/confio/notifications
Tokens:
  • PARTNER_ACCESS_TOKEN: token que genera tu plataforma. El comercio lo copia en Confío al activar la integración. Confío lo usa como Authorization: Bearer <PARTNER_ACCESS_TOKEN> cuando llama a tus endpoints. Debe seguir siendo válido mientras la integración esté activa.
  • CONFIO_ACCESS_TOKEN: token que Confío genera al crear la integración. Confío lo envía en el webhook de handshake. Tu plataforma debe guardarlo y usarlo como Authorization: Bearer <CONFIO_ACCESS_TOKEN> al llamar la API pública de Confío.

Resumen del flujo

Requisitos previos

Antes de activar integraciones, coordina con Confío:
  1. Registro del Partner en Confío.
  2. Configuración de la URL base de tu API (PARTNER_BASE_URL).
  3. Los eventos de webhook soportados por este contrato:
    • payment.statusChanged
    • paymentAttempt.statusChanged
Tu plataforma debe implementar:
  1. GET {PARTNER_BASE_URL}/merchant
  2. POST {PARTNER_BASE_URL}/notifications
  3. Generación y validación de PARTNER_ACCESS_TOKEN.
  4. Almacenamiento seguro del CONFIO_ACCESS_TOKEN recibido en el handshake.

Paso 1: Generar el PARTNER_ACCESS_TOKEN

Tu plataforma debe permitir que el comercio genere un token para conectar su cuenta con Confío. Este token:
  • Debe identificar inequívocamente al comercio en tu plataforma.
  • Debe poder revocarse si la integración se desactiva.
  • Debe permanecer válido mientras la integración esté activa, porque Confío lo reutiliza en webhooks futuros.
Ejemplo:
function generatePartnerAccessToken(merchantId) {
  const token = generateSecureToken();

  storeTokenForMerchant(merchantId, token, {
    purpose: "confio_integration",
    active: true,
    createdAt: new Date(),
  });

  return token;
}

Paso 2: Implementar GET /merchant

Confío usa este endpoint para validar el PARTNER_ACCESS_TOKEN y obtener la información del comercio.

Solicitud

curl -X GET "https://tu-api.com/confio/merchant" \
  -H "Authorization: Bearer PARTNER_ACCESS_TOKEN"
Este ejemplo asume PARTNER_BASE_URL=https://tu-api.com/confio.

Respuesta 200

{
  "id": "platform_merchant_12345",
  "name": "Tienda Ejemplo"
}
Campos:
  • id: identificador del comercio en tu plataforma.
  • name: nombre visible del comercio.

Errores recomendados

  • 401 Unauthorized: falta el bearer token o el token es inválido.
  • 403 Forbidden: token revocado o no autorizado.
  • 404 Not Found: comercio no encontrado.
  • 429 Too Many Requests: rate limit.
  • 5xx: error interno o dependencia no disponible.

Ejemplo de implementación

app.get("/confio/merchant", (req, res) => {
  const authHeader = req.headers.authorization;

  if (!authHeader?.startsWith("Bearer ")) {
    return res.status(401).json({ error: "Bearer token required" });
  }

  const partnerAccessToken = authHeader.substring("Bearer ".length);
  const tokenData = verifyPartnerAccessToken(partnerAccessToken);

  if (!tokenData || tokenData.purpose !== "confio_integration") {
    return res.status(401).json({ error: "Invalid token" });
  }

  const merchant = getMerchantInfo(tokenData.merchantId);
  if (!merchant) {
    return res.status(404).json({ error: "Merchant not found" });
  }

  return res.json({
    id: merchant.id,
    name: merchant.name,
  });
});

Paso 3: Recibir el webhook handshake

Después de validar el comercio, Confío crea un CONFIO_ACCESS_TOKEN y lo entrega a tu plataforma con un webhook handshake.

Solicitud

curl -X POST "https://tu-api.com/confio/notifications" \
  -H "Authorization: Bearer PARTNER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Confio-Event: handshake" \
  -H "X-Confio-Checksum: 4F6A..." \
  -d '{
    "event": "handshake",
    "data": {
      "organization": "01JYPD4F81VSTY57TWM4WKDMSW",
      "store": "01JYPD4KMSGXW0B58YYSNMGC51",
      "token": "CONFIO_ACCESS_TOKEN"
    },
    "timestamp": 1710345600,
    "signature": {
      "properties": ["organization", "store", "token"],
      "checksum": "4F6A..."
    }
  }'
Campos importantes:
  • data.organization: identificador de la organización en Confío.
  • data.store: identificador de la tienda en Confío.
  • data.token: CONFIO_ACCESS_TOKEN que tu plataforma debe guardar.
  • X-Confio-Event: también contiene el evento (handshake).
  • X-Confio-Checksum: contiene el mismo valor de signature.checksum.

Firma/checksum de webhooks

Confío incluye un checksum SHA-256 en cada webhook. Para validarlo:
  1. Toma los valores de data en el orden indicado por signature.properties.
  2. Concatena esos valores como strings.
  3. Concatena timestamp.
  4. Concatena la clave de firma.
  5. Calcula SHA-256 y representa el resultado en hexadecimal mayúscula, sin prefijos como sha256=.
Para webhooks del programa de partners, la clave de firma es el CONFIO_ACCESS_TOKEN de la integración. En el handshake, esa clave es el mismo data.token que estás recibiendo. Ejemplo para handshake:
import { createHash, timingSafeEqual } from "node:crypto";

function checksum(data, properties, timestamp, key) {
  const input = [
    ...properties.map((property) => String(data[property] ?? "")),
    String(timestamp),
    key,
  ].join("");

  return createHash("sha256").update(input).digest("hex").toUpperCase();
}

function safeEqual(a, b) {
  const left = Buffer.from(a);
  const right = Buffer.from(b);
  return left.length === right.length && timingSafeEqual(left, right);
}

function verifyConfioChecksum(payload, signatureKey) {
  const expected = checksum(
    payload.data,
    payload.signature.properties,
    payload.timestamp,
    signatureKey,
  );

  return safeEqual(expected, payload.signature.checksum);
}

// Handshake: el token recibido es la clave de firma.
verifyConfioChecksum(handshakePayload, handshakePayload.data.token);

Ejemplo de endpoint POST /notifications

app.post("/confio/notifications", (req, res) => {
  const authHeader = req.headers.authorization;
  if (!authHeader?.startsWith("Bearer ")) {
    return res.status(401).json({ error: "Bearer token required" });
  }

  const partnerAccessToken = authHeader.substring("Bearer ".length);
  if (!verifyPartnerAccessToken(partnerAccessToken)) {
    return res.status(401).json({ error: "Invalid partner token" });
  }

  const event = req.headers["x-confio-event"];
  if (!event || event !== req.body.event) {
    return res.status(400).json({ error: "Invalid X-Confio-Event" });
  }

  switch (event) {
    case "handshake": {
      const { organization, store, token } = req.body.data;

      if (!verifyConfioChecksum(req.body, token)) {
        return res.status(400).json({ error: "Invalid checksum" });
      }

      storeConfioAccessToken({
        organization,
        store,
        token,
        partnerAccessToken,
      });
      return res.json({ success: true });
    }

    case "teardown": {
      const { organization, store } = req.body.data;
      const confioAccessToken =
        getConfioAccessTokenForPartnerToken(partnerAccessToken);

      if (!verifyConfioChecksum(req.body, confioAccessToken)) {
        return res.status(400).json({ error: "Invalid checksum" });
      }

      removeConfioIntegration({ organization, store });
      return res.json({ success: true });
    }

    case "payment.statusChanged":
    case "paymentAttempt.statusChanged": {
      const confioAccessToken =
        getConfioAccessTokenForPartnerToken(partnerAccessToken);

      if (!verifyConfioChecksum(req.body, confioAccessToken)) {
        return res.status(400).json({ error: "Invalid checksum" });
      }

      processWebhook(req.body);
      return res.json({ success: true });
    }

    default:
      return res.status(400).json({ error: `Unsupported event: ${event}` });
  }
});

Paso 4: Llamar la API pública de Confío

Usa el CONFIO_ACCESS_TOKEN recibido en el handshake para autenticar llamadas a Confío. Ejemplo:
curl -X GET "https://api.confiopagos.com/v1/stores/{store}/payments/{payment}" \
  -H "Authorization: Bearer CONFIO_ACCESS_TOKEN" \
  -H "Content-Type: application/json"
Consulta la referencia de API para los endpoints disponibles.

Webhooks posteriores

Para Partners que usan este contrato, Confío crea automáticamente un webhook hacia:
{PARTNER_BASE_URL}/notifications
Los eventos enviados son:
  • payment.statusChanged
  • paymentAttempt.statusChanged
Confío solo envía estos webhooks a la integración que creó el pago con su CONFIO_ACCESS_TOKEN. Estos webhooks usan el mismo formato de envoltura (event, data, timestamp, signature) y se autentican con:
Authorization: Bearer PARTNER_ACCESS_TOKEN
X-Confio-Event: <event>
X-Confio-Checksum: <checksum>
Para ejemplos de payload de pagos, consulta la guía de webhooks.

Eliminar integración (teardown)

Cuando la integración se inactiva en Confío, Confío envía un webhook teardown a tu endpoint.
curl -X POST "https://tu-api.com/confio/notifications" \
  -H "Authorization: Bearer PARTNER_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "X-Confio-Event: teardown" \
  -H "X-Confio-Checksum: 9C1B..." \
  -d '{
    "event": "teardown",
    "data": {
      "organization": "01JYPD4F81VSTY57TWM4WKDMSW",
      "store": "01JYPD4KMSGXW0B58YYSNMGC51"
    },
    "timestamp": 1710345600,
    "signature": {
      "properties": ["organization", "store"],
      "checksum": "9C1B..."
    }
  }'
Para validar este checksum, usa el CONFIO_ACCESS_TOKEN que guardaste durante el handshake.

Seguridad y buenas prácticas

  1. Usa HTTPS siempre.
  2. Valida Authorization: Bearer PARTNER_ACCESS_TOKEN en cada solicitud recibida desde Confío.
  3. Valida X-Confio-Event y signature.checksum antes de procesar el payload.
  4. Guarda CONFIO_ACCESS_TOKEN de forma segura.
  5. Diseña /notifications de forma idempotente: Confío puede reintentar webhooks si no recibe una respuesta 2xx.
  6. Registra solicitudes y respuestas para auditoría y soporte.

Pruebas de integración

Flujo recomendado:
  1. Genera un PARTNER_ACCESS_TOKEN en tu entorno de pruebas.
  2. Activa la integración en el sandbox de Confío.
  3. Verifica que Confío llama GET {PARTNER_BASE_URL}/merchant.
  4. Verifica que recibes el webhook handshake y guardas el CONFIO_ACCESS_TOKEN.
  5. Crea un pago usando la API pública con CONFIO_ACCESS_TOKEN.
  6. Confirma que recibes webhooks de estado en {PARTNER_BASE_URL}/notifications.

Soporte y recursos adicionales