使用 LemonSqueezy Webhooks 时签名无效

问题描述 投票:0回答:1

因此在 LemonSqueezy API 中,一旦支付成功,webhooks 就会发送一个有效负载。但我遇到的问题是签名无法得到验证。这是我使用的参考。 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.log('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
typescript express cryptography body-parser
1个回答
0
投票

为此花费了太多时间。但问题是请求是由于它是字符串而不是原始主体。

解决方案,下载 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.log(data)

        return res.status(200).send('Webhook received');
    } catch (err) {
        console.error(err);
        return res.status(400).send(err);
    }
});
© www.soinside.com 2019 - 2024. All rights reserved.