Qué vas a tener
Un canal de Discord con un embed rojo cuando un cobro de factura falla: cliente, email, importe y tipo de evento.
No hace falta bot de Discord: basta un Incoming Webhook, una dirección secreta que Discord te da para publicar en un canal sin más permisos. Primero compruebas que el aviso se ve bien; conectar Stripe de verdad viene después.
- Evento payment_failed
- Tu código lo traduce
- Discord muestra el embed
Para el JSON del evento: Webhooks de Stripe.
Requisitos
- Un canal de Discord donde seas administrador, que es quien puede crear webhooks
- Para la primera mitad, nada más
- Para la segunda: cuenta de Stripe en modo test y un sitio donde alojar el receptor — ver el aviso de más abajo
Crea el webhook en Discord
- Abre el canal (mejor uno dedicado, p. ej.
#billing-fallos). - Engranaje del canal → Integraciones → Webhooks → Nuevo webhook.
- Nombre claro, por ejemplo
Stripe fallos. - Copiar URL del webhook.
Esa URL es un secreto. No la pegues en issues, chats públicos ni en el repo.
Prueba el destino
Sustituye todo el valor entre comillas por la URL que te dio Discord (empieza por https://discord.com/api/webhooks/ — no la pegues encima del prefijo).
WEBHOOK_URL="pega-aqui-tu-url-completa"
curl -sS -o /dev/null -w "%{http_code}\
" -X POST "$WEBHOOK_URL" \
-H "Content-Type: application/json" \
-d "{\"embeds\":[{\"title\":\"Pago fallido (prueba)\",\"description\":\"Cliente demo · 19.00 EUR\
Evento: invoice.payment_failed\",\"color\":15158332,\"fields\":[{\"name\":\"Cliente\",\"value\":\"cus_demo\",\"inline\":true},{\"name\":\"Email\",\"value\":\"demo@example.com\",\"inline\":true},{\"name\":\"Importe\",\"value\":\"19.00 EUR\",\"inline\":true}]}]}"Resultado esperado: Discord responde 204 y en el canal aparece el embed de prueba.
Eso demuestra el formato del aviso y que el Incoming Webhook funciona. No demuestra que Stripe te haya entregado un evento firmado.
Qué mapearás desde Stripe
Cuando llegue un invoice.payment_failed real, los campos útiles de la factura suelen ser:
| Campo Stripe | En el embed |
|---|---|
customer | Cliente |
customer_email | |
amount_due / currency | Importe (céntimos → unidades; 1900 + eur = 19,00 EUR) |
id de factura | Factura |
type del evento | Evento |
hosted_invoice_url | Enlace del título (si existe) |
Detalle del evento: Webhooks de Stripe.
Engancha Stripe
Ya tienes el aviso pintado en Discord. Pero Stripe no puede hablar directamente con Discord: alguien tiene que recibir el evento, comprobar que viene de Stripe y traducirlo al formato del mensaje.
Para la otra mitad tienes tres caminos:
- No-code (Zapier, Make, etc.)
- Más rápido si no quieres escribir ni hospedar código; misma idea evento → mensaje.
- Endpoint HTTPS propio
- Stripe Dashboard → Developers → Webhooks → URL pública que verifique `Stripe-Signature` y luego haga POST a Discord.
- Stripe CLI en local
- Solo desarrollo: reenvía eventos a un proceso **tuyo** en un puerto; sin ese proceso, `listen` no completa el aviso a Discord.
Si tiras por el camino propio, el receptor hace esto — en el orden en que se enumera. No es código para copiar, es el guion:
- Recibir
POSTdel body raw. - Verificar firma con el signing secret (docs Stripe (se abre en una pestaña nueva)).
- Si
type === "invoice.payment_failed", mapear factura → embed (céntimos → unidades). POSTa tu Incoming Webhook de Discord.- Responder
2xxa Stripe pronto. - Deduplicar por
evt_…o porinvoice.idsi no quieres un mensaje por cada reintento.
Ejemplo de CLI cuando ya tengas algo escuchando en un puerto local (p. ej. 4242):
stripe listen --forward-to localhost:4242/webhook
# en otra terminal:
stripe trigger invoice.payment_failedPuedes parar tras la prueba del destino Discord y dejar el pegamento Stripe para cuando tengas dónde hospedar el receptor. Ver el evento en bruto: Webhooks de Stripe.
Seguridad
- Regenera el Incoming Webhook si la URL se filtra.
- Separa endpoints test y live en Stripe.
- No loguees la URL de Discord ni el signing secret.
- Piensa en reintentos: Stripe puede emitir varios
payment_failedpor la misma factura.
Errores habituales
| Qué ves | Causa habitual | Qué hacer |
|---|---|---|
| Discord 404 | Webhook borrado o URL vieja | Crea otro y actualiza la variable |
| Discord 401 / cuerpo raro | URL incompleta o mal pegada | Copia de nuevo sin espacios |
curl OK y silencio en el canal | Miras otro servidor/canal | Confirma el canal del webhook |
| Stripe “entrega fallida” | Tu endpoint no responde 2xx o firma mala | Logs del receptor; secret del endpoint concreto |
| Muchos embeds por un cliente | Reintentos sin dedupe | Filtra por factura o espacia avisos |
Alternativas
- Email de Stripe
- Cero código; menos visible en el equipo.
- Slack Incoming Webhook
- Mismo evento, otro destino.
- Bot de Telegram
- Mismo evento hacia un chat o grupo, con token y chat_id.