Skip to content

Stripe Webhook

本指南介绍如何使用 Hono 创建 API 以接收 Stripe Webhook 事件。

¥This introduces how to create an API with Hono to receive Stripe Webhook events.

准备工作

¥Preparation

请先安装官方 Stripe SDK:

¥Please install the official Stripe SDK at first:

bash
npm install stripe

并在 .dev.vars 文件中放入以下值以插入 Stripe API 密钥:

¥And put the following values on the .dev.vars file to insert the Stripe API keys:

STRIPE_API_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx

你可以通过以下文档了解有关 Stripe API 密钥的信息:

¥You can learn about the Stripe API keys by the following documents:

如何保护 Stripe Webhook 事件的 API

¥How to protect the API for Stripe Webhook events

处理 Webhook 事件的 API 已公开访问。因此,需要一种机制来保护它免受攻击,例如恶意第三方伪造 Stripe 的 webhook 事件对象并发送请求。以 Stripe 为例,你可以通过颁发 webhook 密钥并验证每个请求来保护 API。

¥The API that processes webhook events is publicly accessible. Therefore, a mechanism is needed to protect it from attacks such as malicious third parties spoofing Stripe's webhook event objects and sending requests. In Stripe's case, you can protect the API by issuing a webhook secret and verifying each request.

了解更多:https://docs.stripe.com/webhooks?lang=node#verify-official-libraries

¥Learn more: https://docs.stripe.com/webhooks?lang=node#verify-official-libraries

通过托管环境或框架实现 Webhook API

¥Implementing the Webhook API by hosting environment or framework

要使用 Stripe 进行签名验证,需要原始请求体。使用框架时,你需要确保原始请求体未被修改。如果对原始请求体进行任何更改,验证将失败。

¥To perform signature verification with Stripe, the raw request body is needed. When using a framework, you need to ensure that the original body is not modified. If any changes are made to the raw request body, the verification will fail.

对于 Hono,我们可以通过 context.req.text() 方法获取原始请求体。因此,我们可以创建如下示例所示的 Webhook API:

¥In the case of Hono, we can get the raw request body by the context.req.text() method. So we can create the webhook API like the following example:

ts
import Stripe from 'stripe'
import { Hono } from 'hono'
import { env } from 'hono/adapter'

const app = new Hono()

app.post('/webhook', async (context) => {
  const { STRIPE_SECRET_API_KEY, STRIPE_WEBHOOK_SECRET } =
    env(context)
  const stripe = new Stripe(STRIPE_SECRET_API_KEY)
  const signature = context.req.header('stripe-signature')
  try {
    if (!signature) {
      return context.text('', 400)
    }
    const body = await context.req.text()
    const event = await stripe.webhooks.constructEventAsync(
      body,
      signature,
      STRIPE_WEBHOOK_SECRET
    )
    switch (event.type) {
      case 'payment_intent.created': {
        console.log(event.data.object)
        break
      }
      default:
        break
    }
    return context.text('', 200)
  } catch (err) {
    const errorMessage = `⚠️  Webhook signature verification failed. ${
      err instanceof Error ? err.message : 'Internal server error'
    }`
    console.log(errorMessage)
    return context.text(errorMessage, 400)
  }
})

export default app

另请参阅

¥See also

Hono v4.11 中文网 - 粤ICP备13048890号