首页 > 解决方案 > 在 Nest.js 中访问 Stripe webhook 的原始主体

问题描述

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

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

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 正在使用它来验证请求。

问题是请求被卡住了。似乎 req.on 既不是为数据调用,也不是为结束事件调用。所以next()在中间件中没有调用。

我也尝试过在这里使用raw-body我得到了几乎相同的结果。在那种情况下, req.readable 总是错误的,所以我也被困在那里。

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

标签: node.jstypescriptexpressstripe-paymentsnestjs

解决方案


对于任何寻求更优雅解决方案的人,请关闭bodyParserin main.ts。创建两个中间件函数,一个rawbody用于json-parsed-body.

json-body.middleware.ts

import { Request, Response } from 'express';
import * as bodyParser from 'body-parser';
import { Injectable, NestMiddleware } from '@nestjs/common';

@Injectable()
export class JsonBodyMiddleware implements NestMiddleware {
    use(req: Request, res: Response, next: () => any) {
        bodyParser.json()(req, res, next);
    }
}

原始body.middleware.ts

import { Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from 'express';
import * as bodyParser from 'body-parser';

@Injectable()
export class RawBodyMiddleware implements NestMiddleware {
    use(req: Request, res: Response, next: () => any) {
        bodyParser.raw({type: '*/*'})(req, res, next);
    }
}

将中间件功能应用于app.module.ts.

app.module.ts

[...]

export class AppModule implements NestModule {
    public configure(consumer: MiddlewareConsumer): void {
        consumer
            .apply(RawBodyMiddleware)
            .forRoutes({
                path: '/stripe-webhooks',
                method: RequestMethod.POST,
            })
            .apply(JsonBodyMiddleware)
            .forRoutes('*');
    }
}

[...]

并调整 Nest 的初始化以关闭 bodyParser:

主要的.ts

[...]

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

[...]

BTWreq.rawbodyexpress很久以前就被删除了。

https://github.com/expressjs/express/issues/897


推荐阅读