encore-webhook
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseEncore Webhook Endpoints
Encore Webhook 端点
Instructions
说明
Use to receive inbound webhooks from third-party services. Raw endpoints give you direct access to the Node.js-style request and response objects, which you need for signature verification (the verification typically requires the unparsed raw body).
api.raw(...)使用 接收第三方服务发送的入站 Webhook。Raw endpoint 可直接访问 Node.js 风格的请求和响应对象,这对于签名验证是必需的,因为验证过程通常需要使用未经解析的原始正文。
api.raw(...)1. Import
1. 导入
typescript
import { api } from "encore.dev/api";typescript
import { api } from "encore.dev/api";2. Define the endpoint with api.raw
api.raw2. 使用 api.raw
定义端点
api.rawtypescript
export const stripeWebhook = api.raw(
{ expose: true, path: "/webhooks/stripe", method: "POST" },
async (req, res) => {
const sig = req.headers["stripe-signature"];
// Read raw body
const chunks: Buffer[] = [];
for await (const chunk of req) chunks.push(chunk);
const rawBody = Buffer.concat(chunks).toString("utf8");
// Verify signature, parse event...
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ received: true }));
}
);typescript
export const stripeWebhook = api.raw(
{ expose: true, path: "/webhooks/stripe", method: "POST" },
async (req, res) => {
const sig = req.headers["stripe-signature"];
// 读取原始正文
const chunks: Buffer[] = [];
for await (const chunk of req) chunks.push(chunk);
const rawBody = Buffer.concat(chunks).toString("utf8");
// 验证签名、解析事件……
res.writeHead(200, { "Content-Type": "application/json" });
res.end(JSON.stringify({ received: true }));
}
);3. Verify the signature
3. 验证签名
Most providers sign webhooks. Read the secret with from (see the skill) and verify before trusting the payload:
secret(...)encore.dev/configencore-secrettypescript
import { secret } from "encore.dev/config";
const stripeWebhookSecret = secret("StripeWebhookSecret");
// inside handler:
import Stripe from "stripe";
const stripe = new Stripe(stripeApiKey());
const event = stripe.webhooks.constructEvent(rawBody, sig, stripeWebhookSecret());For GitHub, verify the HMAC-SHA256 in the header against the raw body using your webhook secret.
X-Hub-Signature-256大多数提供商会为 Webhook 签名。使用 中的 读取密钥(参见 skill),并在信任载荷前完成验证:
encore.dev/configsecret(...)encore-secrettypescript
import { secret } from "encore.dev/config";
const stripeWebhookSecret = secret("StripeWebhookSecret");
// 在 handler 内:
import Stripe from "stripe";
const stripe = new Stripe(stripeApiKey());
const event = stripe.webhooks.constructEvent(rawBody, sig, stripeWebhookSecret());对于 GitHub,应使用 Webhook 密钥对原始正文验证 请求头中的 HMAC-SHA256 签名。
X-Hub-Signature-256Common providers
常见提供商
| Provider | Signature header | Verification |
|---|---|---|
| Stripe | | |
| GitHub | | HMAC-SHA256 over the raw body |
| Slack | | HMAC-SHA256 over |
| Shopify | | HMAC-SHA256 (base64) over the raw body |
| Twilio | | HMAC-SHA1 over URL + sorted form fields |
| 提供商 | 签名请求头 | 验证方式 |
|---|---|---|
| Stripe | | |
| GitHub | | 对原始正文执行 HMAC-SHA256 |
| Slack | | 对 |
| Shopify | | 对原始正文执行 HMAC-SHA256(base64) |
| Twilio | | 对 URL 和排序后的表单字段执行 HMAC-SHA1 |
Always respond quickly
始终快速响应
Webhook senders retry on non-2xx or slow responses. Acknowledge with a 2xx as soon as the payload is verified, then enqueue the actual work via Pub/Sub (see ) instead of doing it in the request handler.
encore-pubsubtypescript
import { Topic } from "encore.dev/pubsub";
interface StripeEvent { id: string; type: string; data: unknown; }
const stripeEvents = new Topic<StripeEvent>("stripe-events", {
deliveryGuarantee: "at-least-once",
});
// inside the raw handler, after verification:
await stripeEvents.publish({ id: event.id, type: event.type, data: event.data });
res.writeHead(200); res.end();当响应不是 2xx 或响应过慢时,Webhook 发送方会进行重试。验证载荷后应立即返回 2xx 以确认接收,然后通过 Pub/Sub(参见 )将实际工作加入队列,而不要在请求处理器中执行。
encore-pubsubtypescript
import { Topic } from "encore.dev/pubsub";
interface StripeEvent { id: string; type: string; data: unknown; }
const stripeEvents = new Topic<StripeEvent>("stripe-events", {
deliveryGuarantee: "at-least-once",
});
// 在 raw handler 内,完成验证后:
await stripeEvents.publish({ id: event.id, type: event.type, data: event.data });
res.writeHead(200); res.end();Guidelines
指南
- Use only for webhooks and other low-level HTTP integrations.
api.raw - Always verify the provider's signature before trusting the payload.
- Always respond 2xx fast — push slow work onto Pub/Sub.
- Store the signing secret with ; never inline it.
secret(...) - For typed JSON endpoints in your own service, use plain from the
api(...)skill.encore-api
- 仅将 用于 Webhook 和其他底层 HTTP 集成。
api.raw - 信任提供商载荷前,始终验证其签名。
- 始终快速返回 2xx,并将耗时工作推送到 Pub/Sub。
- 使用 存储签名密钥;切勿将其内联到代码中。
secret(...) - 对于服务内部需要类型安全的 JSON 端点,请使用 skill 中的普通
encore-api。api(...)