Stripe-Webhook
Hier erfährst du, wie du mit Hono eine API zum Empfang von Stripe-Webhook-Ereignissen erstellst.
Vorbereitung
Installiere zunächst das offizielle Stripe SDK:
npm install stripeTrage dann die folgenden Werte in die Datei .dev.vars ein, um die Stripe-API-Schlüssel zu hinterlegen:
STRIPE_API_KEY=sk_test_xxx
STRIPE_WEBHOOK_SECRET=whsec_xxxWeitere Informationen zu Stripe-API-Schlüsseln findest du in diesen Dokumenten:
- Geheimer Schlüssel: https://docs.stripe.com/keys
- Webhook-Geheimnis: https://docs.stripe.com/webhooks
Die API für Stripe-Webhook-Ereignisse schützen
Die API, die Webhook-Ereignisse verarbeitet, ist öffentlich erreichbar. Deshalb ist ein Schutzmechanismus gegen Angriffe erforderlich, etwa wenn böswillige Dritte Stripe-Webhook-Ereignisobjekte fälschen und Anfragen senden. Bei Stripe kannst du die API schützen, indem du ein Webhook-Geheimnis erzeugst und jede Anfrage überprüfst.
Weitere Informationen: https://docs.stripe.com/webhooks?lang=node#verify-official-libraries
Die Webhook-API je nach Hostingumgebung oder Framework implementieren
Für die Signaturprüfung mit Stripe wird der unveränderte Anfrage-Body benötigt. Wenn du ein Framework verwendest, musst du sicherstellen, dass der ursprüngliche Body nicht verändert wird. Jede Änderung am unveränderten Anfrage-Body führt dazu, dass die Prüfung fehlschlägt.
In Hono können wir den unveränderten Anfrage-Body mit der Methode context.req.text() abrufen. Deshalb lässt sich die Webhook-API wie im folgenden Beispiel erstellen:
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 appSiehe auch
- Details zu Stripe-Webhooks: https://docs.stripe.com/webhooks
- Implementierung für die Zahlungsabwicklung: https://docs.stripe.com/payments/handling-payment-events
- Implementierung für Abonnements: https://docs.stripe.com/billing/subscriptions/webhooks
- Liste der von Stripe gesendeten Webhook-Ereignisse: https://docs.stripe.com/api/events
- Beispielvorlage für Cloudflare: https://github.com/stripe-samples/stripe-node-cloudflare-worker-template/