在Nest.js中访问Stripe Webhook的原始正文 [英] Access raw body of Stripe webhook in Nest.js

查看:70
本文介绍了在Nest.js中访问Stripe Webhook的原始正文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在我的Nest.js应用程序中从Stripe访问webhook请求的原始正文.

I need to access the raw body of the webhook request from Stripe in my Nest.js application.

以下示例,我将以下内容添加到具有需要原始主体的控制器方法的模块中.

Following this example, I added the below to the module which has a controller method that is needing the raw body.

function addRawBody(req, res, next) {
  req.setEncoding('utf8');

  let data = '';

  req.on('data', (chunk) => {
    data += chunk;
  });

  req.on('end', () => {
    req.rawBody = data;

    next();
  });
}

export class SubscriptionModule {
  configure(consumer: MiddlewareConsumer) {
    consumer
      .apply(addRawBody)
      .forRoutes('subscriptions/stripe');
  }
}

在控制器中,我正在使用@Req() req,然后使用req.rawBody来获取原始主体.我需要原始主体,因为Stripe api的ConstructEvent正在使用它来验证请求.

In the controller I am using @Req() reqand then req.rawBody to get the raw body. I need the raw body because the constructEvent of the Stripe api is using it to verify the request.

问题是请求被卡住了.似乎没有为数据或结束事件调用req.on.因此next()在中间件中不会被调用.

The problem is that the request is stuck. It seems that the req.on is not called either for data nor for the end event. So next() is not called in the middleware.

我也确实尝试过使用raw-body,例如此处,但得到的结果几乎相同.在这种情况下,req.可读性总是为假,所以我也被困在那里.

I did also try to use raw-body like here but I got pretty much the same result. In that case the req.readable is always false, so I am stuck there as well.

我想这是Nest.js的问题,但我不确定...

I guess this is an issue with Nest.js but I am not sure...

推荐答案

昨晚我在尝试验证Slack令牌时遇到了类似的问题.

I ran into a similar problem last night trying to authenticate a Slack token.

我们最终使用的解决方案确实需要从核心Nest App禁用bodyParser,然后在向带有原始请求正文的请求中添加新的rawBody键之后重新启用它.

The solution we wound up using did require disabling the bodyParser from the core Nest App then re-enabling it after adding a new rawBody key to the request with the raw request body.

    const app = await NestFactory.create(AppModule, {
        bodyParser: false
    });

    const rawBodyBuffer = (req, res, buf, encoding) => {
        if (buf && buf.length) {
            req.rawBody = buf.toString(encoding || 'utf8');
        }
    };

    app.use(bodyParser.urlencoded({verify: rawBodyBuffer, extended: true }));
    app.use(bodyParser.json({ verify: rawBodyBuffer }));

然后在我的中间件中,我可以像这样访问它:

Then in my middleware I could access it like so:

const isVerified = (req) => {
    const signature = req.headers['x-slack-signature'];
    const timestamp = req.headers['x-slack-request-timestamp'];
    const hmac = crypto.createHmac('sha256', 'somekey');
    const [version, hash] = signature.split('=');

    // Check if the timestamp is too old
    // tslint:disable-next-line:no-bitwise
    const fiveMinutesAgo = ~~(Date.now() / 1000) - (60 * 5);
    if (timestamp < fiveMinutesAgo) { return false; }

    hmac.update(`${version}:${timestamp}:${req.rawBody}`);

    // check that the request signature matches expected value
    return timingSafeCompare(hmac.digest('hex'), hash);
};

export async function slackTokenAuthentication(req, res, next) {
    if (!isVerified(req)) {
        next(new HttpException('Not Authorized Slack', HttpStatus.FORBIDDEN));
    }
    next();
}

发光!

这篇关于在Nest.js中访问Stripe Webhook的原始正文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆