Webhooks
Recibe callbacks que notifican cuando ocurren eventos en tu cuenta
Los webhooks son callbacks que notifican cuando ocurren eventos en tu cuenta. Un webhook hará una petición HTTP a tu aplicación (usualmente mediante el método POST
), cuyo cuerpo contendrá un objeto que describe el evento asociado. Son increíblemente útiles y una forma sencilla para implementar reacciones a eventos.
Por ejemplo: Cuando se genera un cobro recurrente de una suscripción, un Webhook te permite recibir una notificación para que puedas tomar una acción, como enviar un email de agradecimiento al usuario.
Los webhooks son útiles en dos situaciones:
- Cuando se genera un evento que no es un resultado directo de una llamada a la API. Como por ejemplo, el cobro de una suscripción.
- Cuando existen servicios o funcionalidades que necesitan saber la respuesta a una llamada, pero estos no la realizan directamente. Como por ejemplo, un servicio de contabilidad que necesita actualizar el registro cuando se genera una transacción.
Algunos casos de uso son:
- Actualizar la membresía de un cliente en tu base de datos cuando el pago de una suscripción es exitoso.
- Enviar un email a un cliente cuando el pago de su suscripción falla.
- Registrar una entrada en contabilidad cuando se realiza una transacción.
Consumir un webhook
El primer paso para consumir un webhook es crear un endpoint para recibirlos. No es diferente a crear cualquier otra página en tu sitio. Basta con crear una nueva ruta con la URL deseada.
Los datos del webhook son enviados en formato JSON en el body o cuerpo de la llamada POST. Todos los detalles del evento están incluidos y pueden ser usados directamente (luego de parsear el JSON).
¿Cómo configurar un webhook?
Para configurar un webhook se tienen dos opciones:
- Llenar el formulario de solicitudes: en este debes envíar los detalles de tu ID de comercio, URL de webhook y las notificaciones que deseas recibir. De esta manera recibirás las notificaciones de tus transacciones.
- Vía API: para envíar y recibir notificaciones de webhooks vía API deberás agregar el objeto webhook para los siguientes endpoints:
- Card: Make a charge or deferred charge, Void a transaction y Refund a transaction.
- Transfer in: Init Transaction.
- Transfer out: Init Transaction.
- Cash in: Init Transaction.
- Cash out: Init Transaction.
- Card async: Init Transaction.
- JSON
{"webhooks": [{"events": ["approvedTransaction","declinedTransaction"],"headers": [{"label": "json","value": "12"}],"urls": ["https://eof2hhkrta4ooo1.m.pipedream.net"]}]}
En caso de que tengas un Webhook creado por consola y decidas envíar la petición de webhook vía API, se realizará la notificación a los dos webhooks. Esto significa que no serán excluyentes.
Las notificaciones se verán en el dashboard de Notificaciones de Webhooks y tendrán un nuevo campo llamado Configuración que diferenciará el origen de la notificación.
Seguridad
Cifrado
Puedes usar un HTTP o una url HTTPS para los webhooks. En la mayoría de los casos, HTTP es suficiente, pero HTTPS puede ser útil si tus datos son sensibles o si deseas protegerte contra ataques de repetición, por ejemplo.
Autenticación
Dado que cualquiera podría en principio enviar una solicitud a tu endpoint, es importante verificar que estos webhooks son originados por Kushki. Por lo tanto, los Webhooks válidos contendrán estos encabezados que permiten verificar su autenticidad:
X-Kushki-Key
: ID del comercio.X-Kushki-Signature:
Corresponde a la firma HMAC SHA256 del cuerpo de la petición más el timestamp, utilizando tu ID de firma de Webhooks.X-Kushki-SimpleSignature:
Corresponde a la firma HMAC SHA256 delX-Kushki-Id
, utilizando tu ID de firma de webhooks.X-Kushki-Id:
Fecha en formato timestamp (UNIX Time
).
Utilizando estos encabezados, deberás comparar con la firma generada desde tu lado, empleando el ID de firma de webhooks de tu comercio que puedes encontrar en la consola. Puedes usar tanto X-Kushki-Signature
como X-Kushki-SimpleSignature
para la comprobación.
¿Cómo obtener el webhook signature?
Puedes ver y copiar el webhook signature desde la Consola. Para ello, dirígete a Desarrolladores > Webhooks. En la parte superior podrás copiar fácilmente el webhook signature.
Ejemplos
A continuación te mostramos ejemplos de cómo realizar la comprobación de la firma en los encabezados.
X-Kushki-Signature
- Javascript
- Python
- PHP
var crypto = require('crypto')/*** webhook_signature: Backoffice > Desarrolladores > Webhooks* x_kushki_id: Request Header* $x_kushki_signature: Request header* body : Request body*/var x_kushki_signature = request.headers["x-kushki-signature"];var webhook_signature = process.env.WEBHOOK_SIGNATURE;var x_kushki_id = request.headers["x-kushki-id"];var body = request.body;var payload = `${JSON.stringify(body)}.${x_kushki_id}`;var generated_signature = crypto.createHmac('sha256', webhook_signature).update(payload).digest("hex");if(x_kushki_signature === generated_signature){response.status("200")} else{response.status("401")}
import hmacimport hashlibimport os###### webhook_signature: Backoffice > Desarrolladores > Webhooks## x_kushki_id: Request Header## $x_kushki_signature: Request header## body : Request body####x_kushki_signature = request.headers["x-kushki-signature"]x_kushki_id = request.headers["x-kushki-id"]webhook_signature = os.getenv('WEBHOOK_SIGNATURE')body = request.bodypayload = json.dumps(body)+.+x_kushki_idgenerated_signature = hmac.new(bytes(webhook_signature , 'utf-8'), msg = bytes(payload , 'utf-8'), digestmod = hashlib.sha256).hexdigest()if x_kushki_signature == generated_signature:response.status(200)else:response.status(401)
<?php/*** webhook_signature: Backoffice > Desarrolladores > Webhooks* x_kushki_id: Request Header* $x_kushki_signature: Request header* body: Request body*/$webhook_signature = getenv('WEBHOOK_SIGNATURE');$x_kushki_id = $_SERVER['HTTP_X_KUSHKI_ID'];$x_kushki_signature = $_SERVER['HTTP_X_KUSHKI_SIGNATURE'];$body = file_get_contents('php://input');$payload = $body.'.'.$x_kushki_id;$signature_generated = hash_hmac("sha256", $payload, $webhook_signature);if ($signature_generated === $x_kushki_signature) {header("Status: 200 OK");} else {aheader("Status: 401 Not authenticated");}?>
X-Kushki-SimpleSignature
- Javascript
- Python
- PHP
var crypto = require('crypto')/*** webhook_signature: Backoffice > Desarrolladores > Webhooks* x_kushki_id: Request Header* $x_kushki_simple_signature: Request header*/var x_kushki_simple_signature = request.headers["x-kushki-simplesignature"];var webhook_signature = process.env.WEBHOOK_SIGNATURE;var x_kushki_id = request.headers["x-kushki-id"];var generated_signature = crypto.createHmac('sha256', webhook_signature).update(kushki_id).digest("hex");if(x_kushki_simple_signature === generated_signature){response.status("200")} else{response.status("401")}
import hmacimport hashlibimport os###### webhook_signature: Backoffice > Desarrolladores > Webhooks## x_kushki_id: Request Header## $x_kushki_simple_signature: Request header####x_kushki_simplesignature = request.headers["x-kushki-simplesignature"]x_kushki_id = request.headers["x-kushki-id"]webhook_signature = os.getenv('WEBHOOK_SIGNATURE')generated_signature = hmac.new(bytes(webhook_signature , 'utf-8'), msg = bytes(x_kushki_id , 'utf-8'), digestmod = hashlib.sha256).hexdigest()if x_kushki_simplesignature == generated_signature:response.status(200)else:response.status(401)
<?php/*** webhook_signature: Backoffice > Desarrolladores > Webhooks* x_kushki_id: Request Header* $x_kushki_simple_signature: Request header*/$webhook_signature = getenv('WEBHOOK_SIGNATURE');$x_kushki_id = $_SERVER['HTTP_X_KUSHKI_ID'];$x_kushki_simple_signature = $_SERVER['HTTP_X_KUSHKI_SIMPLESIGNATURE'];$signature_generated = hash_hmac("sha256", $x_kushki_id, $webhook_signature);if ($signature_generated === $x_kushki_simple_signature) {header("Status: 200 OK");} else {header("Status: 401 Not authenticated");}?>
De acuerdo a lo que hayas integrado, existirán distintos tipos de cuerpo para las peticiones:
- Pagos únicos con Tarjetas de crédito y débito
- Pagos únicos con transferencia bancaria
- Pagos únicos con efectivo
- Pagos recurrentes con tarjeta
- Links de pago
- Contracargos
Política de reintentos de Webhooks
En Kushki nos aseguramos que recibas correctamente una devolución de llamada de Webhook. Por esta razón, el proceso de la política de reintentos de Webhooks se realiza de la siguiente manera:
- Primer intento inmediato: este pasa a través de mensajería instantánea (conocida como Notify Now).
- El sistema espera un código de estado o status code de 200/201.
- Si recibimos un estado diferente, se realizan 3 reintentos en la siguiente hora y después se hacen 4 reintentos en las siguientes 2 horas.
Lo anterior, teniendo en cuenta que nuestra lógica de reintentos de envío de notificaciones funciona con un máximo de 7 reintentos en un transcurso de 3 horas una vez falla el Notify Now.
- Una vez finalizados los 7 reintentos, si no recibes una respuesta exitosa, el Webhook se marca como fallido y dejamos de reintentar.
Si al finalizar este ciclo de envíos no hemos recibido un estado exitoso y deseas recibir el webhook, por favor comunícate con nuestro Equipo de soporte.
¿Cómo funcionan los reintentos a través del tiempo transcurrido?
Si falla el Notify Now, debes esperar 20 minutos a que se envíe el primer reintento y de la misma manera el mismo periodo de tiempo hasta completar la hora, tal y como se muestra a continuación:
- Primer reintento: se envía al minuto 20.
- Segundo reintento: se envía al minuto 40.
- Tercer reintento: se envía al minuto 60 (1 hora).
Transcurridos los 60 minutos (1 hora) y si el tercer reintento falla, debes esperar 30 minutos a que se envíe el cuarto reintento hasta completar las 2 horas siguientes de la siguiente forma:
- Cuarto reintento: se envía al minuto 30.
- Quinto reintento: se envía al minuto 60.
- Sexto reintento: se envía al minuto 90.
- Séptimo reintento: se envía al minuto 120.
Buenas prácticas
Revisa consideraciones importantes a la hora de consumir un Webhook.