Webhookok
Automatikus HTTP-értesítéseket kap a szerverén, amikor fontos események történnek a WAzionban.
1. Bevezetés
A webhookok lehetővé teszik, hogy a szervered automatikus értesítéseket kapjon, amikor bizonyos események történnek a WAzionban. Ahelyett, hogy rendszeresen lekérdeznéd, történt-e valami újdonság, a WAzion HTTP POST kérést küld a szerverednek, amikor valami fontos történik.
Hogyan működik?
- 1 Beállítasz egy URL-t a szerveredhez a WAzion irányítópultján.
- 2 Kiválasztod, mely eseményeket szeretnéd megkapni
- 3 Amikor esemény történik, a WAzion POST kérést küld az URL-címedre
- 4 A szerver feldolgozza az eseményt, és HTTP 200-as válasszal reagál.
Felhasználási esetek
- • Új kapcsolatok szinkronizálása a CRM rendszereddel
- • Leadeket automatikusan generálni
- • Automatizálások indítása Zapierben/Make-ben
- • Értesítés belső rendszereknek
2. Elérhető események
phone.detected
FőAz aktiválódik, amikor egy új telefonszámot észlelnek egy beszélgetésben. Hasznos az érdeklődők automatikus rögzítéséhez.
Példa hasznos teher
{
"event_type": "phone.detected",
"phone": "+34612345678",
"detected_at": "2025-01-15T14:30:00Z",
"shop_id": 123,
"conversation_hash": "a1b2c3d4e5f6..."
}
A terhelési mezők
| event_type | Eseménytípus |
| phone | Észlelt szám (E.164) |
| detected_at | ISO 8601 dátum/idő |
| shop_id | Az Ön WAzion áruházának azonosítója |
| conversation_hash | A beszélgetés egyedi hash-e |
test
Teszt esemény, amelyet kézzel indíthatsz el az irányítópultból, hogy ellenőrizd, helyesen működik-e a végpontod.
{
"event_type": "test",
"message": "Este es un webhook de prueba desde WAzion",
"timestamp": "2025-01-15T14:30:00+01:00",
"shop_id": 123,
"test": true
}
3. HTTP fejlécsorok
WAzion minden webhook kérésben a következő fejléceket küldi:
| Header | Leírás | Példa |
|---|---|---|
| Content-Type | Tartalomtípus | application/json |
| User-Agent | WAzion azonosító | WAzion-Webhooks/1.0 |
| X-Webhook-ID | A webhook egyedi azonosítója (wh_XXXXXXXX formátum) | wh_00012345 |
| X-Webhook-Event | Eseménytípus | phone.detected |
| X-Webhook-Attempt | Próbálkozás száma (1-6) | 1 |
| X-Webhook-Timestamp | Unix időbélyeg küldése | 1705329000 |
| X-Webhook-Signature | HMAC-SHA256 hex aláírás (ha van titok) | a1b2c3d4e5f6... |
4. HMAC-SHA256 aláírás
Ha beállítasz egy webhook titkot, a WAzion minden kérelmet HMAC-SHA256-tal fog aláírni. Ez lehetővé teszi számodra, hogy ellenőrizd, hogy a kérés valóban a WAzion-tól érkezik.
Hogyan keletkezik az aláírás
// 1. Concatenar timestamp + "." + payload JSON
signature_payload = timestamp + "." + payload_json
// 2. Calcular HMAC-SHA256 y convertir a hexadecimal
signature = HMAC-SHA256(signature_payload, webhook_secret).toHex()
// 3. El header X-Webhook-Signature contiene la firma directamente:
"a1b2c3d4e5f6789..." // Sin prefijo, solo el hash hex
Ellenőrzés PHP-ben
<?php
function verificarFirmaWebhook($payload, $signatureRecibida, $secret, $timestamp) {
// Verificar que el timestamp no sea muy antiguo (5 min)
if (abs(time() - intval($timestamp)) > 300) {
return false;
}
// Construir payload firmado
$signedPayload = $timestamp . '.' . $payload;
// Calcular firma esperada
$expectedSignature = hash_hmac('sha256', $signedPayload, $secret);
// Comparar de forma segura (timing-safe)
return hash_equals($expectedSignature, $signatureRecibida);
}
// Uso:
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$secret = 'tu-webhook-secret';
if (!verificarFirmaWebhook($payload, $signature, $secret, $timestamp)) {
http_response_code(401);
exit('Firma inválida');
}
Ellenőrzés Node.js-ben
const crypto = require('crypto');
function verificarFirmaWebhook(payload, signatureRecibida, secret, timestamp) {
// Verificar que el timestamp no sea muy antiguo (5 min)
const currentTime = Math.floor(Date.now() / 1000);
if (Math.abs(currentTime - parseInt(timestamp)) > 300) {
return false;
}
// Construir payload firmado
const signedPayload = `${timestamp}.${payload}`;
// Calcular firma esperada
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(signedPayload)
.digest('hex');
// Comparar de forma segura (timing-safe)
return crypto.timingSafeEqual(
Buffer.from(signatureRecibida),
Buffer.from(expectedSignature)
);
}
Fontos: Ellenőrizned kell azt is, hogy az időbélyeg ne legyen túl régi (pl.: legfeljebb 5 perc), hogy megelőzd a visszajátszásos támadásokat.
5. Műszaki specifikációk
Időtúllépések
| Időtúllépés kérésre | 10 másodpercek |
| Maximális a sorban | 100 webhooks |
Újrapróbálkozások
| Maximális kísérletek száma | 6 |
| Stratégia | Eksponenciális visszalépés |
Újrapróbálkozási naptár
A 6. próbálkozás után a webhook végleges hibaként van jelölve.
Elfogadott válaszok
Bármely 2xx kód sikernek számít.
Újrapróbálkozást aktiváló kódok
Újrapróbálkozás nélküli kódok (végleges hiba)
Automatikus duplikációeltávolítás
A WAzion elkerüli, hogy ugyanazt a telefonszámot kétszer küldje el. Minden elküldött telefonszám SHA256 hash-ét tárolja. Ha a telefonszámot korábban már értesítették, akkor azt újra nem küldi el.
Korlátozás sebessége
Boltanként maximum 100 webhook lehet várakozó állapotban. Ha a korlátot túllépik, az új webhookokat elvetik. A feldolgozó futásonként maximum 50 webhookot küld, egy másodperces késleltetéssel mindegyik között.
Kapcsolat beállítása
A webhokkok NEM követik az átirányításokat. A te végpontodnak közvetlenül kell válaszolnia átirányítás nélkül.
6. Teljes Példa Kód
<?php
// webhook-handler.php
header('Content-Type: application/json');
// Configuración
$webhookSecret = 'tu-webhook-secret'; // Deja vacío si no usas firma
// Obtener datos
$payload = file_get_contents('php://input');
$signature = $_SERVER['HTTP_X_WEBHOOK_SIGNATURE'] ?? '';
$timestamp = $_SERVER['HTTP_X_WEBHOOK_TIMESTAMP'] ?? '';
$eventType = $_SERVER['HTTP_X_WEBHOOK_EVENT'] ?? '';
// Verificar firma (si hay secret configurado)
if ($webhookSecret) {
$expectedSignature = hash_hmac(
'sha256',
$timestamp . '.' . $payload,
$webhookSecret
);
if (!hash_equals($expectedSignature, $signature)) {
http_response_code(401);
echo json_encode(['error' => 'Invalid signature']);
exit;
}
// Verificar timestamp (máximo 5 minutos de antigüedad)
if (abs(time() - intval($timestamp)) > 300) {
http_response_code(401);
echo json_encode(['error' => 'Timestamp too old']);
exit;
}
}
// Decodificar payload
$data = json_decode($payload, true);
// Procesar según tipo de evento
switch ($eventType) {
case 'phone.detected':
$phone = $data['phone'];
$shopId = $data['shop_id'];
// Guardar en tu base de datos, CRM, etc.
guardarNuevoLead($phone, $shopId);
echo json_encode(['status' => 'ok', 'message' => 'Lead saved']);
break;
case 'test':
// Evento de prueba
echo json_encode(['status' => 'ok', 'message' => 'Test received']);
break;
default:
echo json_encode(['status' => 'ok', 'message' => 'Event not handled']);
}
function guardarNuevoLead($phone, $shopId) {
// Tu lógica aquí: guardar en BD, enviar a CRM, etc.
error_log("Nuevo lead: $phone de shop $shopId");
}
const express = require('express');
const crypto = require('crypto');
const app = express();
const WEBHOOK_SECRET = 'tu-webhook-secret'; // Deja vacío si no usas firma
// Middleware para raw body
app.use('/webhook', express.raw({ type: 'application/json' }));
app.post('/webhook', (req, res) => {
const payload = req.body.toString();
const signature = req.headers['x-webhook-signature'] || '';
const timestamp = req.headers['x-webhook-timestamp'] || '';
const eventType = req.headers['x-webhook-event'] || '';
// Verificar firma (si hay secret)
if (WEBHOOK_SECRET) {
const expectedSignature = crypto
.createHmac('sha256', WEBHOOK_SECRET)
.update(`${timestamp}.${payload}`)
.digest('hex');
const sigBuffer = Buffer.from(signature);
const expectedBuffer = Buffer.from(expectedSignature);
if (sigBuffer.length !== expectedBuffer.length ||
!crypto.timingSafeEqual(sigBuffer, expectedBuffer)) {
return res.status(401).json({ error: 'Invalid signature' });
}
// Verificar timestamp
if (Math.abs(Date.now() / 1000 - parseInt(timestamp)) > 300) {
return res.status(401).json({ error: 'Timestamp too old' });
}
}
const data = JSON.parse(payload);
// Procesar evento
switch (eventType) {
case 'phone.detected':
console.log(`Nuevo lead: ${data.phone} de shop ${data.shop_id}`);
// Tu lógica aquí
break;
case 'test':
console.log('Test webhook received');
break;
}
res.json({ status: 'ok' });
});
app.listen(3000, () => console.log('Webhook server running on port 3000'));
Változási előzmények
Nincs a közelmúltban történt változás ebben a dokumentációban.