Webhook 签名验证因 Express Stripe 失败

meh*_*ibe 3 node.js express stripe-payments

我正在尝试测试本地 webhook stripe 事件,但它说:

\n

Webhook 签名验证失败。

\n

这是我的 webhook 端点:

\n
exports.stripeListenWebhook = (req, res) => {\n    let data\n    let eventType\n    const webhookSecret = 'whsec_VjORamXpVZs1j6mCV0eTyE7B2GI92'\n\n    if (webhookSecret) {\n        // Retrieve the event by verifying the signature using the raw body and secret.\n        let event\n        let signature = req.headers['stripe-signature']\n\n        console.log(req.headers)\n\n        try {\n            event = stripe.webhooks.constructEvent(req.body, signature, webhookSecret)\n        } catch (err) {\n            console.log(`\xe2\x9a\xa0\xef\xb8\x8f  Webhook signature verification failed.`)\n            return res.sendStatus(400)\n        }\n        // Extract the object from the event.\n        data = event.data\n        eventType = event.type\n    } else {\n        // Webhook signing is recommended, but if the secret is not configured in `config.js`,\n        // retrieve the event data directly from the request body.\n        data = req.body.data\n        eventType = req.body.type\n    }\n\n    // Handle the event\n    switch (eventType) {\n        case 'checkout.session.completed':\n            const session = data.object\n            console.log(session)\n            // Then define and call a function to handle the event checkout.session.completed\n            break\n        default:\n            console.log(`Unhandled event type ${eventType}`)\n    }\n\n    res.json({ received: true })\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我的console.log(req.headers)执行此命令后

\n

条带触发器 checkout.session.completed

\n
{\n  host: 'localhost:8000',\n  'user-agent': 'Stripe/1.0 (+https://stripe.com/docs/webhooks)',\n  'content-length': '1923',\n  accept: '*/*; q=0.5, application/xml',\n  'cache-control': 'no-cache',\n  'content-type': 'application/json; charset=utf-8',\n  'stripe-signature': 't=1638211722,v1=08ed8a55af610fdb97d928c4ec068d19badfb82fe0a521aee7d8f8cfbe378d63,v0=aeebf964e3da2a19f9a533743d420804c168395bb25bf4789e04cfcd9f573d52',\n  'accept-encoding': 'gzip'\n}\n
Run Code Online (Sandbox Code Playgroud)\n

我遵循文档中的规则,并在 app.js 中使用此配置:

\n
const corsOptions = {\n    origin: [URLConfig.URL_CLIENT],\n    credentials: true,\n    methods: 'POST, PUT, OPTIONS, DELETE, GET, PATCH',\n    allowedHeaders: 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization',\n}\napp.use(cors(corsOptions))\napp.use(cookieParser())\napp.use(express.json())\napp.use(\n    express.urlencoded({\n        extended: true,\n    })\n)\n
Run Code Online (Sandbox Code Playgroud)\n

有人对我的问题有疑问吗?我发现 body-parser 已被废弃,所以我使用了express.json()代替

\n

meh*_*ibe 10

我用express.raw({ type: 'application/json' })替换它,基本上如果express.json()像这样放在它前面是行不通的:

app.use(express.json())
app.use(
    express.urlencoded({
        extended: true,
    })
)
app.use(URLConfig.URL_API + '/webhooks-stripe', express.raw({ type: 'application/json' }), WebHooksRoutes) / this need to be placed before
Run Code Online (Sandbox Code Playgroud)

所以解决方案是:

app.use(URLConfig.URL_API + '/webhooks-stripe', express.raw({ type: 'application/json' }), WebHooksRoutes)
app.use(express.json())
app.use(
    express.urlencoded({
        extended: true,
    })
)
Run Code Online (Sandbox Code Playgroud)