我需要从Nest.js应用程序中的Stripe访问webhook请求的原始正文。
在this示例之后,我将以下内容添加到模块中,该模块具有需要原始主体的 Controller 方法。
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');
}
}
在 Controller 中,我正在使用
@Req() req
,然后使用req.rawBody
来获取原始主体。我需要原始主体,因为Stripe api的constructEvent正在使用它来验证请求。问题是请求被卡住了。似乎没有为数据或结束事件调用req.on。因此,在中间件中未调用
next()
。我也尝试过使用像here这样的
raw-body
,但是得到的结果几乎相同。在那种情况下,req.read总是错误的,所以我也被困在那里。我想这是Nest.js的问题,但我不确定...
最佳答案
昨晚我尝试验证Slack token 时遇到了类似的问题。
我们使用的解决方案确实需要从核心Nest App禁用bodyParser,然后在向带有原始请求正文的请求中添加新的rawBody
key 后重新启用它。
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 }));
然后在我的中间件中,我可以像这样访问它:
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();
}
发光!
关于node.js - 在Nest.js中访问Stripe Webhook的原始正文,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/54346465/