如何用emulate在本地完整测试Webhook:GitHub App签名、Slack事件与Stripe验签全覆盖
【免费下载链接】emulateLocal API emulation for CI and no-network sandboxes项目地址https://gitcode.com/gh_mirrors/emul/emulate点击查看免费下载emulate是一个运行在本地的 API 模拟服务API emulation专为 CI 和无网络沙箱设计一条命令即可启动 GitHub、Slack、Stripe 等 14 个服务的本地仿真副本。它的 Webhook 能力不是简单 mock而是按生产协议真实签名——GitHub App 的X-Hub-Signature-256、Slack 事件的X-Slack-Signature、Stripe 的Stripe-Signature全部由模拟服务计算并投递到你的本地端点让你可以完整验证验签逻辑。为什么本地测试 Webhook 很难Webhook 调试是典型的本地难复现问题CI 和沙箱环境没有外网打不开真实服务事件发不出来签名依赖密钥手工构造一个合法的X-Hub-Signature-256或Stripe-Signature容易在时间戳、消息格式上出错事件 payload 复杂比如 Slack 的event_callback外层包着team_id、event_id、event_time手写测试数据既繁琐又失真。emulate 的思路是在本地把发送方整个仿真出来。它是有状态的生产级 API 仿真fully stateful, production-fidelity你调用它提供的 REST 接口触发事件它就按照真实服务的签名算法把 Webhook POST 到你配置的本地地址。一条命令启动本地 Webhook 模拟无需配置文件直接运行需要 Node 环境npx emulate各服务自动分配端口GitHub 在http://localhost:4001、Slack 在http://localhost:4003、Stripe 在http://localhost:4009。也可以只启动需要的服务npx emulate --service github,slack,stripe要指定 Webhook 地址、密钥等就准备一份 seed 配置支持 YAML/JSON仓库里有一份完整示例可以参考emulate.config.example.yaml。配置会自动探测也可以用npx emulate --seed config.yaml显式指定npx emulate list可查看所有可用服务。 每个服务还自带一个Inspector 本地检视页访问服务根路径可以看到事件订阅、Webhook 投递记录状态码、耗时、成功与否和当前数据状态还能一键重置回初始种子——排障时非常有用。GitHub App 签名测试X-Hub-Signature-256 验签全覆盖配置 App 与投递地址在 seed 配置里声明一个 GitHub App重点是webhook_url和webhook_secretgithub: apps: - app_id: 12345 slug: my-github-app name: My GitHub App events: [push, pull_request] webhook_url: http://localhost:3000/webhooks/github webhook_secret: my-secret installations: - installation_id: 100 account: my-org当被安装 App 的仓库上发生事件时emulate 会模仿真实 GitHub 的行为payload 中携带installation字段含id和node_id并向webhook_url投递事件。若配置了webhook_secret请求头会带上用该密钥计算的X-Hub-Signature-256格式为sha256HMAC-SHA256 十六进制值。签名逻辑见核心分发器webhooks.ts。你的端点如何验签# 1. 计算 body 的 HMAC-SHA256与请求头比对 expected sha256 HMAC_SHA256(webhook_secret, raw_body) if (expected ! req.headers[X-Hub-Signature-256]) return 401注意两点必须用原始请求体unparsed body计算签名不能先 JSON 解析再序列化否则结果对不上App 的private_key可以省略emulate 会自动生成 RSA-2048 密钥程序化启动时通过generatedSecrets读取方便测试 JWTRS256鉴权链路。仓库内的测试 webhook-installation.test.ts 演示了完整的 App JWT 签发与投递流程可直接对照阅读。Slack 事件订阅测试X-Slack-Signature 签名回调配置 signing_secretslack: signing_secret: my_signing_secret这个密钥会应用到所有出站的事件订阅回调上。配置后每次回调都会带上两个请求头请求头含义X-Slack-Request-Timestamp投递时间Unix 秒X-Slack-Signaturev0HMAC-SHA256 十六进制值签名算法是v0:timestamp:raw-body的 HMAC-SHA256实现见 index.ts。如果密钥缺失或为空回调保持不签名——这也方便你分别测试有签名和无签名两种分支。触发事件与 payload 结构Slack 模拟器是有状态的渠道、消息、线程、文件、用户资料都能真实读写。任何受支持的写操作例如发消息都会产生一条标准的event_callback事件包外层包含team_id、event_id、event_time内层是具体event封装逻辑在 events.ts。你的验签端点应这样校验const ts req.headers[X-Slack-Request-Timestamp]; const sig req.headers[X-Slack-Signature]; const expected v0 hmacSha256(secret, v0:${ts}:${rawBody}); // 用 timingSafeEqual 比较同时检查 ts 是否过旧防重放官方测试 slack-events.test.ts 覆盖了密钥更新、空密钥不签名、特殊字符Unicode/引号/反斜杠下签名仍然正确等边界场景是验签实现的绝佳参照。Stripe 验签测试Stripe-Signature 时间戳 v1 签名在 seed 配置中注册 Webhookstripe: webhooks: - url: http://localhost:3000/webhooks/stripe events: [checkout.session.completed, customer.created] secret: whsec_test配置了secret后每次投递都会带上真实的Stripe-Signature请求头格式与生产完全一致tunix时间戳,v1HMAC-SHA256(secret, ${timestamp}.${rawBody})实现位于 index.ts时间戳与请求体用英文句点拼接后做 HMAC-SHA256。单测 stripe.test.ts 逐字节校验了签名格式并断言不会误带 GitHub 的请求头。本地跑一个端到端例子仓库自带一个 Stripe Checkout 完整示例examples/stripe-checkout商品目录 → 加购物车 → 创建 Checkout Session → 模拟支付 → 模拟器自动发出checkout.session.completedWebhook → 你的处理器落单。运行方式在仓库根目录pnpm install pnpm --filter stripe-checkout dev打开本地页面完成一次结账就能在自己的Stripe-Signature验证器里看到真实事件被成功接收。示例中的产品T-Shirt $25、Mug $15、Sticker Pack $8、Hoodie $50在启动时自动注入。三种签名机制速查表服务签名请求头算法参与签名的内容GitHub AppX-Hub-Signature-256sha256HMAC-SHA256原始请求体Slack 事件X-Slack-Signaturev0HMAC-SHA256v0:timestamp:raw-bodyStripeStripe-Signaturetts,v1HMAC-SHA256timestamp.raw-body共同要点都用 HMAC-SHA256都基于原始请求体——所以你的处理器一定要在解析 JSON 之前拿到 raw body。投递状态怎么排查emulate 的WebhookDispatcher会记录每一条投递事件、payload、状态码、耗时、是否成功见 webhooks.ts。排查步骤打开对应服务的 Inspector 页面查看 deliveries 标签页确认目标端点返回 2xx否则记为投递失败点重置恢复初始种子数据重新触发事件验证你的验签代码对不同时间戳/密钥的行为。常见问题Q没有配置密钥时事件还会投递吗会。GitHub 仓库级 Hook、Slack 事件订阅在没有密钥时正常投递但不带签名头Stripe 同理。你可以先用默认行为跑通链路再叠加签名测试。QCI 里能这样用吗能这正是 emulate 的核心场景。程序化 API 支持createEmulator指定port: 0或listen: false每个测试用例前后调用reset()/close()完全离线运行无需任何真实网络调用。Q和写死 mock 响应有什么区别emulate 是全状态仿真数据可以被读写、分页、鉴权拦截事件 payload 由真实的状态变更派生签名由分发器实时计算——你测的是真实协议而不是固定的假数据。小结用 emulate 做 Webhook 本地测试的核心路径只有四步npx emulate启动 → seed 配置里填webhook_url和密钥 → 调用本地 API 触发事件 → 在自己的端点用官方算法验签。GitHub App、Slack 事件、Stripe 验签三条链路都能在断网的 CI 和沙箱里端到端跑通配合 Inspector 检视页和reset()重置Webhook 调试从玄学变成了可以反复验证的常规测试。更多服务与配置细节可参考 README.md 与 packages/emulate 下的 CLI 实现。赞分享【免费下载链接】emulateLocal API emulation for CI and no-network sandboxes项目地址https://gitcode.com/gh_mirrors/emul/emulate点击查看免费下载相关推荐Supabase Edge Functions 集成 Stripe Webhooks签名校验与本地联调的完整实战指南Supabase Edge Functions 集成 Stripe Webhooks签名校验与本地联调的完整实战指南 本篇指南围绕 stripe webhoo后端前端数据库open-saas 如何用 Stripe CLI 在本地跑通测试支付流程并验证 webhook 事件入库open saas 如何用 Stripe CLI 在本地跑通测试支付流程并验证 webhook 事件入库 在 open saas 里接入 Stripe 之后本后端前端示例工程Atom 开源仓库全解析Electron 文本编辑器的安装、构建与架构指南Atom 开源仓库全解析Electron 文本编辑器的安装、构建与架构指南 Atom 是一个基于 Electron 构建、以“深度可定制但仍保持默认配置即可上开发工具创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考