encore-go-webhook

Par encoredev · skills

Recevez des webhooks entrants de services externes (Stripe, GitHub, Slack, Twilio, etc.) dans Encore Go en utilisant `//encore:api raw`. La compétence idéale dès que l'utilisateur mentionne un fournisseur tiers qui envoie des événements en POST vers une URL que vous possédez.

npx skills add https://github.com/encoredev/skills --skill encore-go-webhook

Points de terminaison Webhook Encore Go

Instructions

Utilisez //encore:api raw pour recevoir les webhooks entrants de services tiers. Les endpoints raw vous donnent un accès direct à http.ResponseWriter et *http.Request, nécessaires pour la vérification de signature (la vérification nécessite généralement le corps brut non analysé).

1. Définissez le endpoint avec //encore:api raw

package webhooks

import (
    "io"
    "net/http"
)

//encore:api public raw path=/webhooks/stripe method=POST
func StripeWebhook(w http.ResponseWriter, req *http.Request) {
    sig := req.Header.Get("Stripe-Signature")

    // Lisez le corps brut — nécessaire pour la vérification de signature.
    body, err := io.ReadAll(req.Body)
    if err != nil {
        http.Error(w, "could not read body", http.StatusBadRequest)
        return
    }

    // Vérifiez la signature, analysez l'événement, traitez-le, puis répondez...

    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(http.StatusOK)
    w.Write([]byte(`{"received":true}`))
}

2. Vérifiez la signature

La plupart des fournisseurs signent les webhooks. Lisez le secret avec secrets (voir la skill encore-go-secret) et vérifiez avant de faire confiance à la charge.

package webhooks

import (
    "github.com/stripe/stripe-go/v76/webhook"
)

var secrets struct {
    StripeWebhookSecret string
}

//encore:api public raw path=/webhooks/stripe method=POST
func StripeWebhook(w http.ResponseWriter, req *http.Request) {
    body, _ := io.ReadAll(req.Body)
    sig := req.Header.Get("Stripe-Signature")

    event, err := webhook.ConstructEvent(body, sig, secrets.StripeWebhookSecret)
    if err != nil {
        http.Error(w, "signature verification failed", http.StatusBadRequest)
        return
    }

    // event est maintenant sûr — traitez-le.
    _ = event
    w.WriteHeader(http.StatusOK)
}

Pour GitHub, vérifiez le HMAC-SHA256 dans l'en-tête X-Hub-Signature-256 par rapport au corps brut en utilisant votre secret de webhook.

Fournisseurs courants

Fournisseur En-tête de signature Vérification
Stripe Stripe-Signature stripe.webhook.ConstructEvent(rawBody, sig, secret)
GitHub X-Hub-Signature-256 HMAC-SHA256 sur le corps brut
Slack X-Slack-Signature HMAC-SHA256 sur v0:{timestamp}:{rawBody}
Shopify X-Shopify-Hmac-Sha256 HMAC-SHA256 (base64) sur le corps brut
Twilio X-Twilio-Signature HMAC-SHA1 sur URL + champs de formulaire triés

Répondez toujours rapidement

Les émetteurs de webhooks réessaient sur des réponses non-2xx ou lentes. Accuser réception avec un 2xx dès que la charge est vérifiée, puis mettre en file d'attente le travail réel via Pub/Sub (voir encore-go-pubsub) au lieu de le faire dans le gestionnaire de requête.

package webhooks

import (
    "encore.dev/pubsub"
    "net/http"
)

type StripeEvent struct {
    ID   string `json:"id"`
    Type string `json:"type"`
    Data any    `json:"data"`
}

var StripeEvents = pubsub.NewTopic[*StripeEvent]("stripe-events", pubsub.TopicConfig{
    DeliveryGuarantee: pubsub.AtLeastOnce,
})

//encore:api public raw path=/webhooks/stripe method=POST
func StripeWebhook(w http.ResponseWriter, req *http.Request) {
    // ... vérifiez la signature, analysez l'événement ...

    _, _ = StripeEvents.Publish(req.Context(), &StripeEvent{
        ID: event.ID, Type: string(event.Type), Data: event.Data,
    })
    w.WriteHeader(http.StatusOK)
}

Recommandations

  • Utilisez //encore:api raw uniquement pour les webhooks et autres intégrations HTTP bas niveau.
  • Vérifiez toujours la signature du fournisseur avant de faire confiance à la charge.
  • Répondez toujours 2xx rapidement — déplacez le travail lent vers Pub/Sub.
  • Stockez le secret de signature dans secrets struct{...} ; ne l'insérez jamais en dur.
  • Pour les endpoints JSON typés dans votre propre service, utilisez //encore:api simple de la skill encore-go-api.

Skills similaires