slogan3

Help me een aangepaste webhook-implementatie opzetten voor gebeurtenisgestuurde architectuur.

description

Door deze prompt te gebruiken, kun je een meer responsieve applicatie creëren die reageert op specifieke gebeurtenissen, wat de gebruikerservaring en systeem efficiëntie verbetert.

prompt

try_prompt

Ik wil een webhook-implementatie maken die specifieke acties triggert op basis van aangepaste gebeurtenissen in mijn applicatie. Mijn webhook-URL is: {{webhook_url}}. Beschrijf hoe je aangepaste gebeurtenistypen definieert, paylo ... more
generate_helper
disclaimerOnPageApi image_legal_disclaimer...

ai_answers

provider: openai
model: gpt-4.1-nano
Het opzetten van een webhook-implementatie voor aangepaste gebeurtenissen vereist een gestructureerde aanpak. Hier is een stapsgewijze gids met best practices: 1. Definieer Aangepaste Gebeurtenistypen - Gebeurtenisnaam: Kies duidelijke, beschrijvende namen, bijvoorbeeld `nieuw_bericht`, `gebruikers_actie`, `betaling_voltooid`. - Eventuele subtypes: Als nodig, voeg subcategorieën toe, zoals `betaling_voltooid/visa`. - Documentatie: Documenteer alle eventtypen en hun betekenis. 2. Configureer Payload-structuren - Consistentie: Gebruik een vaste structuur voor alle payloads, bijvoorbeeld: ```json { "event_type": "nieuw_bericht", "timestamp": "2024-04-27T12:34:56Z", "data": { ... } } ``` - Data-inhoud: Plaats relevante gegevens onder `data`, zoals bericht-id, gebruiker-id, etc. - Versiebeheer: Voeg een versieveld toe om structuurwijzigingen te beheren: ```json { "version": "1.0", ... } ``` - Validatie: Gebruik JSON-schema’s om payloads te valideren. 3. Routing en Eventhandlers Opzetten - Endpoint: Gebruik je webhook-URL: `https://mijnapp.com/webhooks`. - Event-dispatching: Implementeer een router op je server die binnenkomende POST-verzoeken leest en het `event_type` gebruikt om de juiste handler aan te roepen. - Handlerfuncties: Definieer aparte functies voor elke gebeurtenistype, bv. `handleNieuwBericht()`, `handleGebruikersActie()`. - Asynchroon: Verwerk gebeurtenissen indien mogelijk asynchroon om latency te minimaliseren. 4. Best Practices voor Betrouwbaarheid en Conflicthantering - Bevestiging: Stuur een 200 OK terug zodra de webhook is ontvangen en geaccepteerd. - Retry-mechanismen: Bij niet-geslaagde verwerking, implementeer retries met exponential backoff. - Idempotentie: Zorg dat dezelfde gebeurtenis meerdere keren verwerken geen problemen veroorzaakt, bijvoorbeeld door een uniek gebeurtenis-ID te gebruiken en bij te houden. - Verificatie: Controleer de authenticiteit van verzoeken, bijvoorbeeld via geheime tokens of HMAC-siganturen. - Loggen: Log alle ontvangen gebeurtenissen en verwerkingstatus voor audit en debugging. - Conflictbeheer: Bij conflicten (bijvoorbeeld dubbele gebeurtenissen) gebruik idempotentie om consistentie te bewaren. Door deze stappen te volgen, creëer je een robuuste, schaalbare webhook-implementatie die nauwkeurig reageert op je aangepaste gebeurtenissen en mogelijke problemen correct afhandelt.
provider: deepseek
model: deepseek-chat
Hier is een uitgebreide beschrijving voor het implementeren van uw webhook-systeem: ## 1. Aangepaste Gebeurtenistypen Definiëren ```json { "event_types": { "user_registered": { "description": "Nieuwe gebruiker geregistreerd", "version": "1.0" }, "order_created": { "description": "Nieuwe bestelling geplaatst", "version": "1.0" }, "payment_processed": { "description": "Betaling verwerkt", "version": "1.0" }, "subscription_cancelled": { "description": "Abonnement geannuleerd", "version": "1.0" } } } ``` ## 2. Payload-structuur Configureren **Basis payload-structuur:** ```json { "event_id": "evt_123456789", "event_type": "order_created", "event_version": "1.0", "timestamp": "2024-01-15T10:30:00Z", "source": "https://uwapp.com/api", "data": { "order_id": "ord_987654321", "customer_email": "klant@voorbeeld.nl", "amount": 99.99, "currency": "EUR" }, "metadata": { "attempt": 1, "webhook_id": "wh_123456" } } ``` ## 3. Routing voor Gebeurtenisafhandelaars **Express.js voorbeeld:** ```javascript const webhookRouter = express.Router(); // Event handler mapping const eventHandlers = { 'user_registered': require('./handlers/userHandler'), 'order_created': require('./handlers/orderHandler'), 'payment_processed': require('./handlers/paymentHandler'), 'subscription_cancelled': require('./handlers/subscriptionHandler') }; webhookRouter.post('/webhooks', async (req, res) => { const { event_type, event_id } = req.body; // Controleer dubbele events if (await isDuplicateEvent(event_id)) { return res.status(200).json({ status: 'duplicate_ignored' }); } const handler = eventHandlers[event_type]; if (handler) { try { await handler.process(req.body); res.status(200).json({ status: 'success' }); } catch (error) { await logFailedEvent(event_id, error); res.status(500).json({ status: 'error' }); } } else { res.status(400).json({ error: 'unknown_event_type' }); } }); ``` ## 4. Best Practices voor Nauwkeurige Levering ### **Idempotentie Garanderen** ```javascript class EventProcessor { constructor() { this.processedEvents = new Set(); } async processEvent(event) { // Controleer op duplicaten if (this.processedEvents.has(event.event_id)) { return { status: 'already_processed' }; } // Idempotente verwerking const result = await this.handleEventSafely(event); // Markeer als verwerkt this.processedEvents.add(event.event_id); return result; } async handleEventSafely(event) { // Implementeer idempotente logica switch (event.event_type) { case 'order_created': return await this.createOrderIfNotExists(event.data); case 'payment_processed': return await this.updatePaymentStatus(event.data); } } } ``` ### **Retry Mechanisme** ```javascript class WebhookDelivery { async deliverWithRetry(webhookUrl, payload, maxAttempts = 3) { for (let attempt = 1; attempt <= maxAttempts; attempt++) { try { const response = await fetch(webhookUrl, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-Webhook-Signature': this.generateSignature(payload) }, body: JSON.stringify(payload) }); if (response.ok) return true; // Exponential backoff await this.sleep(Math.pow(2, attempt) * 1000); } catch (error) { console.error(`Attempt ${attempt} failed:`, error); } } return false; } } ``` ## 5. Conflictbeheer tussen Gebeurtenissen ### **Event Sourcing Pattern** ```javascript class EventStore { constructor() { this.eventLog = []; this.entityVersions = new Map(); } async appendEvent(event) { const entityId = event.data.entity_id; const currentVersion = this.entityVersions.get(entityId) || 0; // Optimistische locking if (event.expected_version && event.expected_version !== currentVersion) { throw new Error('Concurrent modification detected'); } event.version = currentVersion + 1; this.eventLog.push(event); this.entityVersions.set(entityId, event.version); return event; } async getEntityState(entityId) { const events = this.eventLog.filter(e => e.data.entity_id === entityId); return events.reduce((state, event) => this.applyEvent(state, event), {}); } } ``` ### **Event Sortering en Volgorde** ```javascript class EventSequencer { constructor() { this.sequenceNumbers = new Map(); } ensureOrderedProcessing(events) { return events.sort((a, b) => { // Sorteer op timestamp en sequence number const timeDiff = new Date(a.timestamp) - new Date(b.timestamp); if (timeDiff !== 0) return timeDiff; return (a.sequence_number || 0) - (b.sequence_number || 0); }); } async processInOrder(entityId, events) { const sortedEvents = this.ensureOrderedProcessing(events); for (const event of sortedEvents) { await this.processEventWithLock(entityId, event); } } } ``` ## 6. Beveiliging en Validatie ### **Webhook Signature** ```javascript const crypto = require('crypto'); class WebhookSecurity { generateSignature(payload, secret) { return crypto .createHmac('sha256', secret) .update(JSON.stringify(payload)) .digest('hex'); } verifySignature(signature, payload, secret) { const expectedSignature = this.generateSignature(payload, secret); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(expectedSignature) ); } } ``` ### **Rate Limiting** ```javascript const rateLimit = require('express-rate-limit'); const webhookLimiter = rateLimit({ windowMs: 1 * 60 * 1000, // 1 minuut max: 100, // maximaal 100 requests per minuut message: { error: 'Te veel webhook requests', retry_after: 60 } }); ``` ## 7. Monitoring en Logging ```javascript class WebhookMonitor { async logWebhookDelivery(event) { await db.webhook_logs.insert({ event_id: event.event_id, event_type: event.event_type, delivery_status: 'pending', attempt_count: 0, last_attempt: null, created_at: new Date() }); } async updateDeliveryStatus(eventId, status, error = null) { await db.webhook_logs.update({ delivery_status: status, last_attempt: new Date(), error_message: error?.message, attempt_count: db.raw('attempt_count + 1') }).where({ event_id: eventId }); } } ``` Deze implementatie biedt een robuuste basis voor uw webhook-systeem met aandacht voor betrouwbaarheid, beveiliging en schaalbaarheid.