Webhook 签名验证失败并出现快速条带

Posted

技术标签:

【中文标题】Webhook 签名验证失败并出现快速条带【英文标题】:Webhook signature verification failed with express stripe 【发布时间】:2022-01-06 14:42:28 【问题描述】:

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

Webhook 签名验证失败。

所以这是我的 webhook 端点:

exports.stripeListenWebhook = (req, res) => 
    let data
    let eventType
    const webhookSecret = 'whsec_VjORamXpVZs1j6mCV0eTyE7B2GI92'

    if (webhookSecret) 
        // Retrieve the event by verifying the signature using the raw body and secret.
        let event
        let signature = req.headers['stripe-signature']

        console.log(req.headers)

        try 
            event = stripe.webhooks.constructEvent(req.body, signature, webhookSecret)
         catch (err) 
            console.log(`⚠️  Webhook signature verification failed.`)
            return res.sendStatus(400)
        
        // Extract the object from the event.
        data = event.data
        eventType = event.type
     else 
        // Webhook signing is recommended, but if the secret is not configured in `config.js`,
        // retrieve the event data directly from the request body.
        data = req.body.data
        eventType = req.body.type
    

    // Handle the event
    switch (eventType) 
        case 'checkout.session.completed':
            const session = data.object
            console.log(session)
            // Then define and call a function to handle the event checkout.session.completed
            break
        default:
            console.log(`Unhandled event type $eventType`)
    

    res.json( received: true )

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

条带触发 checkout.session.completed


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

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

const corsOptions = 
    origin: [URLConfig.URL_CLIENT],
    credentials: true,
    methods: 'POST, PUT, OPTIONS, DELETE, GET, PATCH',
    allowedHeaders: 'Origin, X-Requested-With, Content, Accept, Content-Type, Authorization',

app.use(cors(corsOptions))
app.use(cookieParser())
app.use(express.json())
app.use(
    express.urlencoded(
        extended: true,
    )
)

有人对我的问题有意见吗?我看到 body-parser 已被弃用,所以我使用 express.json() 代替

【问题讨论】:

作为诊断步骤,您可以尝试使用 body-parser 并将其配置为检索原始请求正文 [1] 吗? Stripe 的签名验证要求您将原始请求正文传递给它,但许多库默认修改正文,这是导致此错误的常见原因。如果您的代码与 body-parser 和原始请求正文一起使用,我将检查如何使用 express.json() 获取原始请求正文。 [1]***.com/questions/9920208/expressjs-raw-body 你说得对!我在我的端点中使用了 bodyParser : router.post('/', bodyParser.raw( type: 'application/json' ), WebHooksController.stripeListenWebhook) 并且它有效。现在我需要使用 express.json() 找到一个解决方案,以免破坏其他应用程序端点。有什么解决办法吗?谢谢大哥! 【参考方案1】:

我用 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

所以解决办法是:

app.use(URLConfig.URL_API + '/webhooks-stripe', express.raw( type: 'application/json' ), WebHooksRoutes)
app.use(express.json())
app.use(
    express.urlencoded(
        extended: true,
    )
)

【讨论】:

以上是关于Webhook 签名验证失败并出现快速条带的主要内容,如果未能解决你的问题,请参考以下文章

相互证书身份验证失败并出现错误 403.16

IOS 验证/提交到 iTunes Connect 失败

如何在 PHP 中验证 Paypal webhook 签名?

签名验证失败。没有提供安全密钥来验证签名

UseJwtBearerAuthentication 失败并显示 IDX10504:无法验证签名,令牌没有签名

签名验证失败。无法匹配“孩子”