Integración para bots de terceros — cómo un bot cobra con QuickPay
¿Tienes un bot de WhatsApp, Telegram o tu propia app? Integra QuickPay en 3 pasos y cobra a tus clientes sin construir infraestructura bancaria.
El flujo es simple: tu bot crea un link de pago, lo envía en un mensaje con botón, QuickPay cobra, y te avisa por webhook.
Flujo de pago del usuario final
1. Cliente abre WhatsApp → ve mensaje de tu bot con botón "Pagar"
2. Toca el botón → abre en WhatsApp el checkout hosteado de QuickPay
3. Selecciona su banco, autoriza con la clave de 8 dígitos que le envía su banco (SMS, notificación o correo)
4. QuickPay cobra y, si enviaste `success_url`, lo devuelve a tu web
5. Tu bot se entera por webhook → entrega el servicioPaso 1: Obtén tu llave
- Abre tu cuenta de comercio en el portal (con tu cédula o el RIF de tu empresa).
- En Integraciones › Llaves de API, crea una llave de prueba. Tiene la forma
tu-comercio:sk_test_…y se muestra una sola vez. - Guárdala en una variable de entorno de tu servidor (nunca en el código del bot que corre en el teléfono del cliente).
Cuando todo funcione en prueba, crea la de producción: → Pasar a producción
Paso 2: Crea un link de pago desde tu bot
Cuando un cliente quiera pagar, crea un link:
Ejemplo: bot de Node.js
const axios = require('axios');
async function crearLinkDePago(monto, concepto, metaDatos) {
const response = await axios.post(
'https://pay.pagaconquickpay.com/switch/v1/links',
{
monto,
concepto,
expira_horas: 24,
metadata: metaDatos, // tus datos; vuelven al crear, no en el webhook
idempotency_key: metaDatos.orden, // reintentar no duplica el cobro
},
{
headers: {
'x-switch-key': process.env.QUICKPAY_KEY,
'content-type': 'application/json'
}
}
);
return response.data;
}
// Uso
const link = await crearLinkDePago(
450.00,
'Crédito bot de consultoría',
{ cliente_id: 'CLI-001', orden: 'ORD-2026-100' }
);
console.log('Link de pago:', link.url);
// Guarda link.id junto a la orden: el webhook te dirá ese id cuando la paguen.Ejemplo: bot de Python
import requests
import os
def crear_link_de_pago(monto, concepto, metadatos):
response = requests.post(
'https://pay.pagaconquickpay.com/switch/v1/links',
json={
'monto': monto,
'concepto': concepto,
'expira_horas': 24,
'metadata': metadatos,
'idempotency_key': metadatos['orden'],
},
headers={
'x-switch-key': os.environ['QUICKPAY_KEY'],
'content-type': 'application/json'
}
)
return response.json()
# Uso
link = crear_link_de_pago(
450.00,
'Crédito bot de consultoría',
{'cliente_id': 'CLI-001', 'orden': 'ORD-2026-100'}
)
print(f"Link: {link['url']}")Ejemplo: bot de Make/n8n (sin código)
Make.com:
- HTTP Request a
POST https://pay.pagaconquickpay.com/switch/v1/links - Headers:
x-switch-key: {{QUICKPAY_KEY}} - Body (JSON): ``
json { "monto": {{monto}}, "concepto": "{{concepto}}", "expira_horas": 24, "metadata": { "cliente_id": "{{cliente_id}}" } }``
- Extrae
data.urlde la respuesta.
- Continúa con el resto de tu flow (enviar a WhatsApp, etc.).
Paso 3: Envía el link por WhatsApp con botón
Una vez tienes la URL, envía un mensaje interactivo con botón al cliente.
3.1 Si usas WhatsApp Cloud API
const axios = require('axios');
async function enviarPagoWhatsApp(numeroCliente, urlPago, monto) {
await axios.post(
`https://graph.facebook.com/v18.0/${process.env.WA_PHONE_ID}/messages`,
{
messaging_product: 'whatsapp',
to: numeroCliente,
type: 'interactive',
interactive: {
type: 'cta_url',
body: {
text: `Hola, tienes un pago de Bs ${monto.toFixed(2)} pendiente. Puedes pagarlo desde cualquier banco.`
},
footer: {
text: 'Powered by QuickPay'
},
action: {
name: 'cta_url',
parameters: { display_text: 'Pagar ahora', url: urlPago }
}
}
},
{
headers: {
'Authorization': `Bearer ${process.env.WA_TOKEN}`
}
}
);
}3.2 Si usas Make/n8n/Zapier
- Module: WhatsApp / Send Interactive Message
- Text: "Tienes un pago de Bs XXX pendiente"
- Button type: URL
- Button text: "Pagar ahora"
- Button URL:
{{link.url}}
Paso 4: Recibe la confirmación de pago (webhook)
Registra la URL de tu bot en Integraciones › Webhooks (o con POST /switch/v1/webhooks). Cuando tu cliente paga, te llega link.pagado con el link_id: búscalo en tu base, verifica la firma v2 y confírmale al cliente por WhatsApp. → Webhooks
Paso 5: Entrega el servicio/producto
El aviso trae el link_id, no tus metadata: busca la orden que guardaste con ese id.
// En tu handler del webhook (después de verificar la firma)
if (event.type === 'link.pagado') {
const orden = await BD.buscarOrden({ link_id: event.data.link_id });
if (!orden || orden.estado === 'pagado') return; // ya entregada: el aviso puede llegar dos veces
await BD.actualizar({ link_id: event.data.link_id }, { estado: 'pagado', pagado_en: new Date() });
await entregarServicio(orden.cliente_id, orden.id);
await enviarConfirmacion(orden.cliente_id);
}Flujo completo (ejemplo real)
Bot de créditos educativos:
const express = require('express');
const axios = require('axios');
const app = express();
app.use(express.json());
// Cliente envía: "/pagar 450 Matricula"
app.post('/api/iniciar-pago', async (req, res) => {
const { cliente_id, monto, concepto } = req.body;
// 1. Crear link de pago
const link = await axios.post(
'https://pay.pagaconquickpay.com/switch/v1/links',
{
monto,
concepto,
metadata: { cliente_id }
},
{ headers: { 'x-switch-key': process.env.QUICKPAY_KEY } }
);
// 2. Guardar orden pendiente
await BD.insertOne({
cliente_id,
link_id: link.data.id,
monto,
concepto,
estado: 'pendiente'
});
// 3. Enviar botón a WhatsApp
await axios.post(`https://graph.facebook.com/v18.0/${process.env.WA_PHONE_ID}/messages`, {
messaging_product: 'whatsapp',
to: cliente_id,
type: 'interactive',
interactive: {
type: 'cta_url',
body: { text: `Hola, tienes un pago de Bs ${monto} por ${concepto}.` },
action: {
name: 'cta_url',
parameters: { display_text: 'Pagar ahora', url: link.data.url }
}
}
}, {
headers: { 'Authorization': `Bearer ${process.env.WA_TOKEN}` }
});
res.json({ link: link.data.url });
});
// 4. Webhook de confirmación (verifica la firma v2 antes: ver Webhooks)
app.post('/webhooks/quickpay', async (req, res) => {
const event = req.body;
if (event.type === 'link.pagado') {
// El aviso trae link_id: con él encuentras la orden que guardaste en el paso 2
const orden = await BD.findOne({ link_id: event.data.link_id, estado: 'pendiente' });
if (!orden) return res.status(200).send('OK'); // repetido o desconocido
const cliente_id = orden.cliente_id;
await BD.updateOne({ link_id: event.data.link_id }, { estado: 'pagado', pagado_en: new Date() });
// Envía confirmación a WhatsApp
axios.post(`https://graph.facebook.com/v18.0/${process.env.WA_PHONE_ID}/messages`, {
messaging_product: 'whatsapp',
to: cliente_id,
type: 'text',
text: { body: '✓ Pago confirmado. Tu matrícula está activa.' }
}, {
headers: { 'Authorization': `Bearer ${process.env.WA_TOKEN}` }
});
}
res.status(200).send('OK');
});
app.listen(3000);Checklist de implementación
- ✅ Tengo
x-switch-keyyQUICKPAY_WEBHOOK_SECRETen.env. - ✅ Mi bot crea links con
POST /switch/v1/links. - ✅ Envío el link en un botón de WhatsApp (o mi plataforma).
- ✅ Registré el webhook en
/switch/v1/webhooks. - ✅ Mi endpoint verifica firmas HMAC-SHA256.
- ✅ Respondo
200en menos de 8 segundos desde el webhook. - ✅ Deduplico eventos por
(type, data.link_id). - ✅ Entrego el servicio cuando recibo
link.pagado. - ✅ Probé con la llave de prueba (
sk_test_…) antes de producción.
Troubleshooting
| Problema | Solución |
|---|---|
| "unauthorized" (401) | Verifica que x-switch-key está en formato comercio:sk_test_xxx |
| Link devuelve estado "pendiente" | Normal, espera el webhook. Cliente aún no pagó. |
| No recibo webhook | Verifica que tu URL es HTTPS, responde 200 y tu firewall no bloquea. |
| "Invalid signature" | Asegúrate de capturar el raw body antes de parsear JSON. |
| Cliente se sale del checkout | Normal, espera a que intente de nuevo o el link expire (24h default). |
Seguridad
- Guarda
sk_live_…en variables de entorno, nunca en código. - Verifica siempre el webhook — no confíes en un
link.pagadosin firma. - Sé idempotente — un webhook puede llegar dos veces.
- No des acceso a
QUICKPAY_WEBHOOK_SECRETa código cliente. - Usa HTTPS en tu endpoint de webhook.
Próximos pasos
- Prueba el ciclo completo con tu llave de prueba → Modo prueba
- Cuando funcione, cambia a la llave de producción → Pasar a producción
Soporte
Escríbenos por WhatsApp desde el enlace Soporte al pie de esta página.