首页 > 解决方案 > Stripe webhook 失败 - Webhook 错误:504

问题描述

Stripe webhook 失败,我认为这是因为 Stripe 没有从我的 webhook api 端点收到“成功”响应。

错误是:

Test webhook error: 504

An error occurred with your deployment

FUNCTION_INVOCATION_TIMEOUT

我使用 Nextjs 及其在 pages/api/createOrder 文件夹结构中构建来创建 api。这就是我的 createOrder webhook 的样子:

import { buffer } from "micro"
const AWS = require("aws-sdk")

AWS.config.update({
  accessKeyId: process.env.MY_AWS_ACCESS_KEY_ID,
  secretAccessKey: process.env.MY_AWS_SECRET_ACCESS_KEY,
  region: process.env.MY_AWS_REGION,
  endpoint: process.env.MY_AWS_ENDPOINT,
})

// Establish Stripe connection
const stripe = require("stripe")(process.env.STRIPE_SECRET_KEY)
const endpointSecret = process.env.STRIPE_CREATE_ORDER_SIGNING_SECRET

const createOrder = async session => {
  console.log("create order - session.id: ", session.id)
  console.log(
    "create order - session.metadata.userID: ",
    session.metadata.userID
  )
  console.log(
    "create order - session.amount_total / 100: ",
    session.amount_total / 100
  )

  const docClient = new AWS.DynamoDB.DocumentClient()
  let date = new Date()

  // create Order
  let orderParams = {
    TableName: process.env.ORDER_TABLE_NAME,
    Item: {
      id: session.id,
      userID: session.metadata.userID,
      amount: session.amount_total / 100,
      adID: session.metadata.adID,

      createdAt: date.toISOString(),
      updatedAt: date.toISOString(),
    },
  }
  docClient.put(orderParams, function (err, data) {
    if (err) {
      console.log("Order put err - " + JSON.stringify(err, null, 2))
    } else {
      console.log("Order put Success - " + JSON.stringify(data, null, 2))
    }
  })

  // create - TTL
  const ninetyDays = 1000 * 60 * 60 * 24 * 90
  const currTime = Date.now()
  const ttlSeconds = Math.ceil((ninetyDays + currTime) / 1000)

  // update Ad
  let adParams = {
    TableName: process.env.AD_TABLE_NAME,
    Key: { id: session.metadata.adID },
    UpdateExpression: "set paid = :paid, expdate = :expdate",
    ExpressionAttributeValues: {
      ":paid": true,
      ":expdate": ttlSeconds,
    },
    ReturnValues: "UPDATED_NEW",
  }
  docClient.update(adParams, function (err, data) {
    if (err) {
      console.log("UPDATE Ad err - " + JSON.stringify(err, null, 2))
    } else {
      console.log("UPDATE Ad Success - " + JSON.stringify(data, null, 2))
    }
  })
}

export default async (req, res) => {
  if (req.method === "POST") {
    const requestBuffer = await buffer(req)
    const payload = requestBuffer.toString()
    const sig = req.headers["stripe-signature"]

    let event

    // Verify that the EVENT posted came from stripe
    try {
      event = stripe.webhooks.constructEvent(payload, sig, endpointSecret)
    } catch (err) {
      console.log("ERROR", err.message)
      return res.status(400).send(`Webhook create Order error: ${err.message}`)
    }

    // Handle the checkout.session.completed event
    if (event.type === "checkout.session.completed") {
      const session = event.data.object

      // Fulfill update Ad -> paid = true and ttl - expdate
      return createOrder(session)
        .then(() => res.status(200))
        .catch(err =>
          res.status(400).send(`Create Order Error - ${err.message}`)
        )
    }
  }

  // Notify Stripe that req reached api
  res.status(200).json({ received: true })
}

export const config = {
  api: {
    bodyParser: false,
    externalResolver: true,
  },
}

我找到了一些解决方案来告诉 Stripe 已收到 webhook 调用,但它们都不起作用。现在我正在使用:

res.status(200).json({ received: true })

也许问题出在其他地方?我想指出 Order 已创建并且 Ad 已更新 - 因此 webhook 可以按预期工作,只是它失败了。

标签: error-handlingnext.jstimeoutstripe-payments

解决方案


经过2个月的调试,我找到了解决方案。

我认为问题在于 AWS 似乎很慢。我添加了 setTimeout 来通知 Stripe 连接成功并且它现在可以工作了!

setTimeout(() => {
    // 3. Notify Stripe that event recieved.
    res.json({ received: true })
}, 2000)

如果 some1 有更好的解决方案请告诉我们:)


推荐阅读