コンテンツにスキップ

Stripe webhook

ここでは、Hono を使用して Stripe Webhook イベントを受信する API を作成する方法を説明します。

準備

最初に、Stripe の公式 SDK をインストールしてください

bash
npm install stripe

.dev.vars ファイルに次の値を挿入して Stripe API キーを入力します

STRIPE_API_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxx

Stripe API キーについて詳しくは、次のドキュメントを参照してください

Stripe Webhook イベントに対する API 保護方法

Webhook イベントを処理する API はパブリックにアクセスできます。そのため、悪意のある第三者が Stripe の Webhook イベントオブジェクトをスプーフィングしてリクエストを送信するなどの攻撃から保護するためのメカニズムが必要です。Stripe の場合、Webhook の秘密を発行して各リクエストを検証することで API を保護できます。

詳細: https://docs.stripe.com/webhooks?lang=node#verify-official-libraries

ホスティング環境またはフレームワークで Webhook API を実装

Stripe で署名検証を実行するには、生のリクエストボディが必要です。フレームワークを使用する場合、元のボディが変更されていないことを確認する必要があります。生のリクエストボディに変更を加えると、検証は失敗します。

Hono の場合、context.req.text() メソッドを使用して生のリクエストボディを取得できます。そのため、Webhook API を次のような例のように作成できます

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

関連項目

MIT ライセンスに基づきリリースされています。