getryt-demo / src /services /whatsappWebhookSupport.js
KaboKableMolefe's picture
Sync from GitHub via hub-sync
4ed88f9 verified
Raw
History Blame Contribute Delete
1.64 kB
const crypto = require('crypto');
function constantTimeEquals(left, right) {
const leftBuffer = Buffer.from(left || '', 'utf8');
const rightBuffer = Buffer.from(right || '', 'utf8');
if (leftBuffer.length !== rightBuffer.length) {
return false;
}
return crypto.timingSafeEqual(leftBuffer, rightBuffer);
}
function isValidWebhookVerification({ mode, verifyToken, expectedVerifyToken }) {
return (
mode === 'subscribe' &&
Boolean(expectedVerifyToken) &&
constantTimeEquals(verifyToken, expectedVerifyToken)
);
}
function isValidMetaSignature({ rawBody, signature, appSecret }) {
if (!rawBody || !signature || !appSecret) {
return false;
}
const expectedSignature = `sha256=${crypto
.createHmac('sha256', appSecret)
.update(rawBody)
.digest('hex')}`;
return constantTimeEquals(signature, expectedSignature);
}
function extractIncomingWhatsAppMessages(payload) {
if (payload?.object !== 'whatsapp_business_account') {
return [];
}
const messages = [];
for (const entry of payload.entry || []) {
for (const change of entry.changes || []) {
const value = change.value || {};
for (const message of value.messages || []) {
messages.push({
id: message.id || null,
from: message.from || null,
type: message.type || 'unknown',
text: message.type === 'text' ? message.text?.body?.trim() || '' : '',
});
}
}
}
return messages.filter((message) => Boolean(message.from));
}
module.exports = {
extractIncomingWhatsAppMessages,
isValidMetaSignature,
isValidWebhookVerification,
};