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:
- Contacta a tu gerente de cuenta de Confío para obtener tu
CONFIO_ACCESS_TOKEN.
- Proporciona la URL de tu endpoint de webhooks y el token que Confío debe usar para autenticarse contra ese endpoint.
- 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ósito | Ruta llamada por Confío |
|---|
| Validar token y obtener comercio | GET {PARTNER_BASE_URL}/merchant |
| Enviar handshake, teardown y webhooks | POST {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:
- Registro del Partner en Confío.
- Configuración de la URL base de tu API (
PARTNER_BASE_URL).
- Los eventos de webhook soportados por este contrato:
payment.statusChanged
paymentAttempt.statusChanged
Tu plataforma debe implementar:
GET {PARTNER_BASE_URL}/merchant
POST {PARTNER_BASE_URL}/notifications
- Generación y validación de
PARTNER_ACCESS_TOKEN.
- 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:
- Toma los valores de
data en el orden indicado por signature.properties.
- Concatena esos valores como strings.
- Concatena
timestamp.
- Concatena la clave de firma.
- 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
- Usa HTTPS siempre.
- Valida
Authorization: Bearer PARTNER_ACCESS_TOKEN en cada solicitud recibida desde Confío.
- Valida
X-Confio-Event y signature.checksum antes de procesar el payload.
- Guarda
CONFIO_ACCESS_TOKEN de forma segura.
- Diseña
/notifications de forma idempotente: Confío puede reintentar webhooks si no recibe una respuesta 2xx.
- Registra solicitudes y respuestas para auditoría y soporte.
Pruebas de integración
Flujo recomendado:
- Genera un
PARTNER_ACCESS_TOKEN en tu entorno de pruebas.
- Activa la integración en el sandbox de Confío.
- Verifica que Confío llama
GET {PARTNER_BASE_URL}/merchant.
- Verifica que recibes el webhook
handshake y guardas el CONFIO_ACCESS_TOKEN.
- Crea un pago usando la API pública con
CONFIO_ACCESS_TOKEN.
- Confirma que recibes webhooks de estado en
{PARTNER_BASE_URL}/notifications.
Soporte y recursos adicionales