mcpField
E
encore-go-webhook

encore-go-webhook

github.com/encoredev开发30317 次安装2 天前更新
代码仓库

关于 encore-go-webhook

面向 Encore Go 开发者的 Webhook 端点技能,指导接收原始 HTTP 请求并在信任载荷前验证签名。它还建议快速确认请求,并将耗时工作交给 Pub/Sub。

主要功能

  1. 01定义原始 HTTP 端点
  2. 02验证提供方签名
  3. 03快速返回 2xx 响应
  4. 04通过 Pub/Sub 处理耗时任务

适用场景

  1. 01接收 Stripe 或 GitHub Webhook
  2. 02验证 Slack 或 Shopify 请求
  3. 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。

常见提供商

提供商签名标头验证方式
StripeStripe-Signaturestripe.webhook.ConstructEvent(rawBody, sig, secret)
GitHubX-Hub-Signature-256对原始请求正文计算 HMAC-SHA256
SlackX-Slack-Signature对 v0:{timestamp}:{rawBody} 计算 HMAC-SHA256
ShopifyX-Shopify-Hmac-Sha256对原始请求正文计算 HMAC-SHA256(base64)
TwilioX-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