关于 gocardless-webhooks
面向 GoCardless Webhook 接收端开发者的技能,涵盖批量事件、原始请求体 HMAC-SHA256 验证、事件处理及多种框架示例。
主要功能
- 01验证原始请求体的 HMAC-SHA256 签名
- 02处理批量事件及事件类型
- 03按 event ID 去重投递
- 04参考 Express、Next.js 和 FastAPI 示例
- 05通过 Hookdeck 隧道进行本地测试
适用场景
- 01处理已确认或失败的付款
- 02处理 mandate、payout 和 refund 事件
- 03排查 Webhook-Signature 验证失败
- 04构建幂等的 Webhook 接收端
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ hookdeck/ webhook-skills --skill gocardless-webhooks安装后在 Claude Code 中输入/gocardless-webhooks确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
TODO.mdexamples/express/.env.examplepackage.jsonREADME.mdexamples/express/src/index.jsexamples/express/test/webhook.test.jsexamples/fastapi/.env.examplemain.pyREADME.mdrequirements.txttest_webhook.pyexamples/nextjs/.env.examplenext.config.jspackage.jsonREADME.mdtsconfig.jsonvitest.config.tsexamples/nextjs/app/layout.tsxpage.tsxexamples/nextjs/app/webhooks/gocardless/route.tsexamples/nextjs/test/webhook.test.tsreferences/overview.mdsetup.mdverification.md详细介绍
GoCardless Webhooks
GoCardless 是一个银行借记/周期性付款平台。它以批次形式发送 Webhook,每个请求最多包含 250 个事件,存放在 events 数组中,并在 Webhook-Signature 标头中使用 HMAC-SHA256 签名。
何时使用此技能
- 如何接收 GoCardless Webhook?
- 如何验证 GoCardless 的
Webhook-Signature标头? - 为什么我的 GoCardless Webhook 签名验证失败?
- 如何处理
paymentsconfirmed/failed、mandatescancelled或payoutspaid事件? - 如何以幂等方式处理 GoCardless 的
events数组?
GoCardless 如何对 Webhook 签名
- 标头:
Webhook-Signature—— 纯 64 位小写十六进制摘要(无X-前缀,也无sha256=方案前缀) - 算法: 对原始请求正文执行 HMAC-SHA256,使用 Webhook 端点密钥作为密钥(可在 GoCardless Dashboard 中获取)
- 密钥: 将密钥原样作为 UTF-8 字符串使用——即使它看起来像 base64url,也不要对其进行 base64 解码;解码后会得到错误的签名
- 编码: 小写十六进制字符串
- 比较: 使用时序安全比较
- 响应: 接受整个批次后返回
204 No Content;非 2xx 响应(例如498)会将此次投递标记为失败。GoCardless 不会自动重试——重新投递需手动触发(POST /webhooks/{id}/actions/retry)。投递采用至少一次语义,因此处理程序应根据event.id实现幂等性。
(已于 2026-08 根据实时沙盒投递和官方 gocardless-nodejs SDK 验证该方案;GoCardless 的说明仍未指出所用算法。)
务必使用原始正文进行验证——先解析 JSON 再重新序列化会改变字节内容,导致签名验证失败。
验证(核心)
在适用环境(Node.js)中使用官方 gocardless-nodejs SDK。parse() 会验证签名(时序安全),并返回 events 数组;如果签名不匹配,则会抛出 InvalidSignatureError。
// Node.js — official SDK (gocardless-nodejs), req.body is the RAW Buffer
const { parse, InvalidSignatureError } = require('gocardless-nodejs/webhooks');
try {
const events = parse(
req.body, // raw body (Buffer/string), NOT parsed JSON
process.env.GOCARDLESS_WEBHOOK_SECRET, // webhook endpoint secret
req.headers['webhook-signature'] // Webhook-Signature header
);
// signature valid — process each event, then respond 204
} catch (err) {
if (err instanceof InvalidSignatureError) {
// signature mismatch — respond 498 (do not process)
}
}
对于没有 GoCardless SDK 的语言(例如 Python/FastAPI),请手动验证——使用相同算法和时序安全比较:
import hmac, hashlib
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
valid = hmac.compare_digest(expected, signature_header) # timing-safe
如需查看包含测试的完整处理程序,请参阅 examples/express/、examples/nextjs/ 和 examples/fastapi/。
常见事件类型
GoCardless 事件由 resource_type 和 action 组合而成。最常见的类型如下:
| resource_type | action | 触发时机 |
|---|---|---|
payments | confirmed | 已确认从客户处收取款项 |
payments | paid_out | 付款已包含在转入你银行账户的付款中 |
payments | failed | 付款失败(例如,资金不足) |
payments | cancelled | 付款提交前已取消 |
payments | charged_back | 客户已拒付该笔付款 |
mandates | active | 扣款授权已设置完毕,可以收款 |
mandates | customer_approval_granted | 客户已授权扣款(已确认适用于正式环境) |
mandates | cancelled | 扣款授权已取消(例如,银行账户已关闭) |
mandates | failed | 扣款授权设置失败 |
mandates | expired | 扣款授权因长期未使用而过期 |
payouts | paid | 款项已转入你的银行账户 |
refunds | paid | 已向客户提交退款 |
refunds | failed | 退款失败 |
subscriptions | created | 已创建订阅 |
subscriptions | cancelled | 订阅已取消 |
如需查看每种资源类型的完整操作列表,请参阅 overview.md。
环境变量
# Webhook endpoint secret from the GoCardless Dashboard (Developers → Webhook endpoints)
GOCARDLESS_WEBHOOK_SECRET=your_webhook_endpoint_secret
本地开发
如需在本地测试 Webhook,可通过 npx 运行 Hookdeck CLI,无需安装:
npx hookdeck-cli listen 3000 gocardless --path /webhooks/gocardless
无需账户。CLI 首次运行时会创建访客账户,并提供本地隧道和 Web UI,用于检查请求。FastAPI 示例请使用端口 8000。
参考资料
示例
- Express 示例 - 使用 GoCardless SDK 的 Express 5 处理程序,包含测试
- Next.js 示例 - 使用 GoCardless SDK 的 Next.js App Router 路由,包含测试
- FastAPI 示例 - 使用手动 HMAC 验证的 Python FastAPI 处理程序,包含测试
推荐:webhook-handler-patterns
我们建议同时安装 webhook-handler-patterns 技能。GoCardless 不会自动重试(需要手动重新投递),但投递至少会进行一次,因此幂等性很重要。关键参考资料(在 GitHub 上查看):
相关技能
- stripe-webhooks - Stripe 支付 Webhook 处理
- paddle-webhooks - Paddle 账单 Webhook 处理
- chargebee-webhooks - Chargebee 订阅账单 Webhook 处理
- paypal-webhooks - PayPal 支付 Webhook 处理
- shopify-webhooks - Shopify 电商 Webhook 处理
- github-webhooks - GitHub 仓库 Webhook 处理
- webhook-handler-patterns - 处理程序顺序、幂等性、错误处理、重试逻辑
- hookdeck-event-gateway - 替代队列的 Webhook 基础设施 — 为 Webhook 处理程序提供可靠投递、自动重试、重放、速率限制和可观测性