关于 encore-go-webhook
面向 Encore Go 开发者的 Webhook 端点技能,指导接收原始 HTTP 请求并在信任载荷前验证签名。它还建议快速确认请求,并将耗时工作交给 Pub/Sub。
主要功能
- 01定义原始 HTTP 端点
- 02验证提供方签名
- 03快速返回 2xx 响应
- 04通过 Pub/Sub 处理耗时任务
适用场景
- 01接收 Stripe 或 GitHub Webhook
- 02验证 Slack 或 Shopify 请求
- 03将已验证事件排入异步处理
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ encoredev/ skills --skill encore-go-webhook安装后在 Claude Code 中输入/encore-go-webhook确认已加载。
详细介绍
Encore Go Webhook 端点
说明
使用 //encore:api raw 接收来自第三方服务的入站 Webhook。Raw 端点可让你直接访问 http.ResponseWriter 和 *http.Request,这是验证签名所必需的(验证通常需要未经解析的原始请求正文)。
1. 使用 //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")
// Read the raw body — needed for signature verification.
body, err := io.ReadAll(req.Body)
if err != nil {
http.Error(w, "could not read body", http.StatusBadRequest)
return
}
// Verify signature, parse event, handle, then respond...
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(http.StatusOK)
w.Write([]byte(`{"received":true}`))
}
2. 验证签名
大多数提供商都会为 Webhook 签名。使用 secrets 读取密钥(参见 encore-go-secret 技能),并在信任负载前进行验证。
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 is now trusted — handle it.
_ = event
w.WriteHeader(http.StatusOK)
}
对于 GitHub,使用 Webhook 密钥,根据原始请求正文验证 X-Hub-Signature-256 标头中的 HMAC-SHA256。
常见提供商
| 提供商 | 签名标头 | 验证方式 |
|---|---|---|
| Stripe | Stripe-Signature | stripe.webhook.ConstructEvent(rawBody, sig, secret) |
| GitHub | X-Hub-Signature-256 | 对原始请求正文计算 HMAC-SHA256 |
| Slack | X-Slack-Signature | 对 v0:{timestamp}:{rawBody} 计算 HMAC-SHA256 |
| Shopify | X-Shopify-Hmac-Sha256 | 对原始请求正文计算 HMAC-SHA256(base64) |
| Twilio | X-Twilio-Signature | 对 URL 和排序后的表单字段计算 HMAC-SHA1 |
始终快速响应
Webhook 发送方会在收到非 2xx 响应或响应缓慢时重试。验证负载后,应立即以 2xx 确认接收,然后通过 Pub/Sub 将实际工作加入队列(参见 encore-go-pubsub),而不是在请求处理程序中执行。
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) {
// ... verify signature, parse event ...
_, _ = StripeEvents.Publish(req.Context(), &StripeEvent{
ID: event.ID, Type: string(event.Type), Data: event.Data,
})
w.WriteHeader(http.StatusOK)
}
指南
- 仅将
//encore:api raw用于 Webhook 和其他底层 HTTP 集成。 - 在信任负载前,始终验证提供商的签名。
- 始终快速返回 2xx 响应——将耗时工作交给 Pub/Sub。
- 将签名密钥存储在
secrets struct{...}中;切勿直接写入代码。 - 对于你自己服务中的带类型 JSON 端点,请使用
encore-go-api技能中的普通//encore:api。
评论
支持 Markdown