Таким образом, в LemonSqueezy API веб-перехватчики после успешной оплаты отправят полезную нагрузку. Но проблема, с которой я столкнулся, заключается в том, что подпись не будет проверена. Это ссылка, которую я использовал. https://docs.lemonsqueezy.com/help/webhooks#signing-requests
Это мой запрос на публикацию в машинописном тексте
import express, { Request, Response } from 'express';
import * as crypto from 'crypto';
import bodyParser from 'body-parser';
const webhook = express.Router();
let secret = "secretkey"
webhook.use(bodyParser.json())
webhook.post('/webhooks', async (req: Request, res: Response) => {
try {
if (!req.body) {
throw new Error('Missing request body');
}
// Create HMAC signature
const hmac = crypto.createHmac('sha256', secret);
const digest = Buffer.from(hmac.update(JSON.stringify(req.body)).digest('hex'), 'utf8');
// Retrieve and validate X-Signature header
const signature = Buffer.from(req.get('X-Signature') || '', 'utf8');
if (!crypto.timingSafeEqual(digest, signature)) {
throw new Error('Invalid signature');
}
const payload = req.body;
console.info('Received valid webhook:', payload);
return res.status(200).send({'Webhook received': payload});
} catch (err) {
console.error(err);
return res.status(400).send(err);
}
});
export default webhook






Потратил на это слишком много часов. Но проблема заключалась в том, что запрос был вызван тем, что это была строка, а не необработанное тело.
Итак, решение: скачайте npm i raw-body.
interface Request extends ExpressRequest {
rawBody?: string;
}
const webhook = express.Router();
let secret = ""
webhook.use((req: Request, _res: Response, next: NextFunction) => {
rawBody(req, {
length: req.headers['content-length'],
limit: '1mb', // Set your desired limit here
encoding: 'utf8' // or any encoding you prefer
}, (err, string) => {
if (err) return next(err);
(req as any).rawBody = string; // Define rawBody property on Request type
next();
});
});
webhook.post('/webhooks', async (req: Request, res: Response) => {
try {
if (!req.rawBody) {
throw new Error('Missing request body');
}
// Create HMAC signature
const hmac = crypto.createHmac('sha256', secret);
const digest = Buffer.from(hmac.update(req.rawBody).digest('hex'), 'utf8');
const signature = Buffer.from(req.get('X-Signature') || '', 'utf8');
if (!crypto.timingSafeEqual(digest, signature)) {
throw new Error('Invalid signature.');
}
const data = JSON.parse(req.rawBody)
console.info(data)
return res.status(200).send('Webhook received');
} catch (err) {
console.error(err);
return res.status(400).send(err);
}
});