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 rawuniquement 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:apisimple de la skillencore-go-api.