Express 4.17 获取一个端点的原始正文

Ker*_*mit 8 javascript parsing express stripe-payments

我正在尝试在我的 Web API 中实现 Stripe,并且需要读取请求的原始正文。我的应用程序中已经有不需要原始主体的现有 API 路径。

\n

我实现的代码基于 Stripe 文档示例,请参见下文。

\n
const stripe = require('stripe')('apikey...');\nconst endpointSecret = 'whsec_...';\n\nconst express = require('express');\nconst app = express();\napp.post('/webhook', express.raw({type: 'application/json'}), (request, response) => {\n  let event = request.body;\n  console.log('body', event);\n  const headers = JSON.stringify(request.headers);\n  console.log('Headers', headers);\n  // Only verify the event if you have an endpoint secret defined.\n  // Otherwise use the basic event deserialized with JSON.parse\n  if (endpointSecret) {\n    // Get the signature sent by Stripe\n    const signature = request.headers['stripe-signature'];\n    try {\n      event = stripe.webhooks.constructEvent(request.body, signature, endpointSecret);\n    } catch (err) {\n      console.log(`\xe2\x9a\xa0\xef\xb8\x8f  Webhook signature verification failed.`, err.message);\n      return response.sendStatus(400);\n    }\n  }\n\n  // Handle the event\n  ...\n  // Return a 200 response to acknowledge receipt of the event\n  response.send();\n});\n\napp.listen(443, () => console.log('Running on port 443'));\n
Run Code Online (Sandbox Code Playgroud)\n

此代码记录以下消息 - 因为原始主体是空的。

\n
body\nHeaders {"host":".....}\n\xe2\x9a\xa0\xef\xb8\x8f Webhook signature verification failed. No signatures found matching the expected signature for payload. Are you passing the raw request body you received from Stripe? https://github.com/stripe/stripe-node#webhook-signing\n
Run Code Online (Sandbox Code Playgroud)\n

我尝试通过添加中间件来读取原始主体来解决此问题。

\n
// Custom middleware that keeps the raw request body. This is needed for Stripe\napp.use((req, res, next)=>{\n  req.rawBody = '';\n  req.on('data', (chunk) => { req.rawBody += chunk; });\n  req.on('end', () => {\n    try {\n      req.body = JSON.parse(req.rawBody);\n      next();\n    } catch (err) {\n      console.log('Error parsing body')\n      next();\n    }\n   });\n });\n\napp.post('/webhook', (request, response) => {\n  let event = request.body;\n  console.log('rawBody', request.rawBody)\n  if (endpointSecret) {\n    // Get the signature sent by Stripe\n    const signature = request.headers['stripe-signature'];\n    try {\n      event = stripe.webhooks.constructEvent(request.rawBody, signature, endpointSecret);\n    } catch (err) {\n      console.log(`\xe2\x9a\xa0\xef\xb8\x8f  Webhook signature verification failed.`, err.message);\n      return resp.sendStatus(400);\n    }\n
Run Code Online (Sandbox Code Playgroud)\n

根据记录,原始尸体仍然是空的。我仍然在控制台中收到相同的错误消息。

\n

如何将原始正文添加到请求中?最好使用中间件。\n亲切的问候 /K

\n

更新:(感谢 Bravo!)\n下面的代码似乎可以通过暴露原始主体来工作

\n
app.post('/webhook', express.raw(), (request, response) => {\n      let event = request.rawBody;\n
Run Code Online (Sandbox Code Playgroud)\n

Dan*_*itu 1

我能够通过将该verify方法添加到中间件配置(在幕后express.json使用)来解决这个问题。body-parser

例子:

const RAW_BODY_WHITELIST = ['/webhooks/stripe'];

app.use(express.json({
  verify: (req: Request, _res: Response, buf: Buffer, _encoding: string) => {
    if (RAW_BODY_WHITELIST.includes(req.path)) {
      req.rawBody = buf.toString();
    }
  },
}));
Run Code Online (Sandbox Code Playgroud)

这样,您就可以很好地组织所有中间件,并且不必在其他中间件之前或之间声明 Webhook 路由。