Webhook Example
The SDK provides utilities for handling webhooks sent from the Compliance API.
import express from 'express';
import {
WebhookEvent,
WebhookEventType,
WebhookSignatureHeader,
verifyWebhookSignature
} from '@paytweed/compliance-sdk';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
app.use('/webhook', express.raw({ type: 'application/json' }));
const WEBHOOK_SECRET = process.env.COMPLIANCE_SDK_WEBHOOK_SECRET; // Get your secret from env vars
/**
* Example Curl:
* curl -X 'POST' 'http://localhost:3000/webhook' \
* -H 'host: webhook.site' \
* -H 'tracestate: dd=t.tid:680cb60000000000;t.dm:-3;s:2;p:35554b4d8ec726f5' \
* -H 'traceparent: 00-680cb600000000003cb0e3a7ccbde59d-35554b4d8ec726f5-01' \
* -H 'x-datadog-tags: _dd.p.tid=680cb60000000000,_dd.p.dm=-3' \
* -H 'x-datadog-sampling-priority: 2' \
* -H 'x-datadog-parent-id: 3843060653510567669' \
* -H 'x-datadog-trace-id: 4373245548010792349' \
* -H 'accept-encoding: gzip, compress, deflate, br' \
* -H 'content-length: 223' \
* -H 'user-agent: axios/1.7.7' \
* -H 'x-hub-signature-256: sha256=e1cb6899bca87bfde07f4d77cb2b942414a6e4dc0b48acf574bd4983e1472ca4' \
* -H 'x-tweed-delivery: 4222e6bf-7e88-4dc2-8f38-dbe861dc2f9c' \
* -H 'x-tweed-event: individual_client.updated' \
* -H 'x-tweed-hook-id: 6bc02889-1720-4da2-9ebd-b168d57b6b53' \
* -H 'content-type: application/json' \
* -H 'accept: application/json, text/plain, *\/' \
* -d $'{"data":{"id":"ba4a02ff-9eb2-4f4e-8b29-f3880d65ee21","referenceId":"d043bea8-809a-41b3-9edf-b39e0c18a964","updated":{"activityStatus":"NOT_ACTIVE"}},"type":"individual_client.updated","timestamp":"2025-04-26T10:31:28.489Z"}'
*/
app.post('/webhook', (req: any, res: any) => {
const signature = req.headers[WebhookSignatureHeader] as string;
const rawBody = req.body; // req.body is a Buffer due to express.raw()
if (!WEBHOOK_SECRET) {
console.error('Webhook secret is not configured.');
return res.status(500).send('Webhook secret not configured.');
}
if (!signature) {
console.warn('Missing signature header');
return res.status(400).send('Missing signature header.');
}
try {
console.log('WEBHOOK_SECRET', WEBHOOK_SECRET);
console.log('rawBody', rawBody.toString('utf-8'));
console.log('signature', signature);
const isValid = verifyWebhookSignature(WEBHOOK_SECRET, rawBody.toString('utf-8'), signature);
console.log('isValid', isValid);
if (!isValid) {
return res.status(403).send('Invalid signature.');
}
} catch (error) {
console.error('Invalid signature:', error);
return res.status(403).send('Invalid signature.');
}
let event: WebhookEvent<any, any>;
try {
event = JSON.parse(rawBody.toString('utf-8'));
} catch (error) {
console.error('Error parsing webhook JSON:', error);
return res.status(400).send('Invalid JSON payload.');
}
console.log(`Received webhook event: ${event.type}`);
console.log(`Timestamp: ${event.timestamp}`);
console.log('Data:', JSON.stringify(event.data, null, 2));
switch (event.type) {
case WebhookEventType.INDIVIDUAL_CLIENT_CREATED:
console.log(`Handling ${event.type}...`);
// Add specific logic here...
break;
case WebhookEventType.INDIVIDUAL_CLIENT_UPDATED:
// Handle individual client updated event
console.log(`Handling ${event.type}...`);
break;
case WebhookEventType.CORPORATE_CLIENT_CREATED:
// Handle corporate client created event
console.log(`Handling ${event.type}...`);
break;
case WebhookEventType.CORPORATE_CLIENT_UPDATED:
// Handle corporate client updated event
console.log(`Handling ${event.type}...`);
break;
case WebhookEventType.ALERT_CREATED:
// Handle alert created event
console.log(`Handling ${event.type}...`);
break;
case WebhookEventType.ALERT_UPDATED:
// Handle alert updated event
console.log(`Handling ${event.type}...`);
break;
case WebhookEventType.CASE_CREATED:
// Handle case created event
console.log(`Handling ${event.type}...`);
break;
case WebhookEventType.CASE_UPDATED:
// Handle case updated event
console.log(`Handling ${event.type}...`);
break;
default:
console.warn(`Unhandled event type: ${event.type}`);
}
// Acknowledge receipt
res.status(200).send('Webhook received');
});
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Webhook handler listening on port ${PORT}`);
});
// Export the app for potential testing or use in other modules
export default app;
Updated 13 days ago