代码之家  ›  专栏  ›  技术社区  ›  TinyTiger

设置Stripe Webhook签名时,是否应该拒绝未签名的事件?

  •  0
  • TinyTiger  · 技术社区  · 5 年前

    我通过以下方式设置条带订阅付款 this guide .

    在第4步(提供和监视订阅)中,Stripe告诉我们设置一个Webhook来处理订阅事件。

    当收到webhook事件时,可以对其签名进行身份验证,以确保它是由Stripe发送的,而不是恶意的第三方。

    但是在他们的代码示例中,在验证签名之后,他们立即包含一个 else 块直接从未签名事件的请求正文中检索事件数据。

    我搞不懂他们为什么会把这个包括进去。这不应该是一个或另一个,而不是两个都允许吗?

    我的理解是,两者都有否定了webhook身份验证的意义,因为现在允许有签名和无签名的事件。

    如果我设置了webhook签名,我应该删除它吗 其他的 块

    您可以在下面第28-33行看到示例代码。

    // Set your secret key. Remember to switch to your live secret key in production.
    // See your keys here: https://dashboard.stripe.com/apikeys
    const stripe = require('stripe')('API_KEY_GOES_HERE');
    
    app.post("/webhook", async (req, res) => {
      let data;
      let eventType;
      // Check if webhook signing is configured.
      const webhookSecret = {{'STRIPE_WEBHOOK_SECRET'}}
      if (webhookSecret) {
        // Retrieve the event by verifying the signature using the raw body and secret.
        let event;
        let signature = req.headers["stripe-signature"];
    
        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;
      }
    
      switch (eventType) {
          case 'checkout.session.completed':
            // Payment is successful and the subscription is created.
            // You should provision the subscription and save the customer ID to your database.
            break;
          case 'invoice.paid':
            // Continue to provision the subscription as payments continue to be made.
            // Store the status in your database and check when a user accesses your service.
            // This approach helps you avoid hitting rate limits.
            break;
          case 'invoice.payment_failed':
            // The payment failed or the customer does not have a valid payment method.
            // The subscription becomes past_due. Notify your customer and send them to the
            // customer portal to update their payment information.
            break;
          default:
          // Unhandled event type
        }
    
      res.sendStatus(200);
    });
    
    0 回复  |  直到 5 年前
        1
  •  0
  •   TinyTiger    5 年前

    我直接联系了Stripe,他们建议“应该是一个或另一个,而不是两个。”

    因此,如果您有Webhook签名设置,那么您应该将签名身份验证从 if/else 阻塞,从而使 如果/否则 没用,所以也把它去掉。

    以下是更新版本:

    // Set your secret key. Remember to switch to your live secret key in production.
    // See your keys here: https://dashboard.stripe.com/apikeys
    const stripe = require('stripe')('API_KEY_GOES_HERE');
    
    app.post("/webhook", async (req, res) => {
    
      // Check if webhook signing is configured.
      const webhookSecret = {{'STRIPE_WEBHOOK_SECRET'}}
    
      // Retrieve the event by verifying the signature using the raw body and secret.
      let event;
      let signature = req.headers["stripe-signature"];
    
      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.
      let data = event.data;
      let eventType = event.type;
    
      switch (eventType) {
          case 'checkout.session.completed':
            // Payment is successful and the subscription is created.
            // You should provision the subscription and save the customer ID to your database.
            break;
          case 'invoice.paid':
            // Continue to provision the subscription as payments continue to be made.
            // Store the status in your database and check when a user accesses your service.
            // This approach helps you avoid hitting rate limits.
            break;
          case 'invoice.payment_failed':
            // The payment failed or the customer does not have a valid payment method.
            // The subscription becomes past_due. Notify your customer and send them to the
            // customer portal to update their payment information.
            break;
          default:
          // Unhandled event type
        }
    
      res.sendStatus(200);
    });
    
    推荐文章