关于 chargebee-webhooks
chargebee-webhooks 面向实现和排查 Chargebee Webhook 处理程序的开发者,介绍 Basic Auth 验证、事件负载和订阅计费事件,并提供 Express.js、Next.js 与 FastAPI 示例。
主要功能
- 01Basic Auth 验证指南
- 02Chargebee 事件类型参考
- 03订阅计费事件处理
- 04Express.js、Next.js 和 FastAPI 示例
- 05使用 Hookdeck CLI 本地测试
适用场景
- 01实现 Chargebee Webhook 端点
- 02排查 Basic Auth 验证失败
- 03处理订阅和付款事件
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ hookdeck/ webhook-skills --skill chargebee-webhooks安装后在 Claude Code 中输入/chargebee-webhooks确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
TODO.mdexamples/express/.env.examplejest.config.jspackage.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/chargebee/route.tsexamples/nextjs/test/webhook.test.tsreferences/overview.mdsetup.mdverification.md详细介绍
Chargebee Webhook
何时使用此技能
- 设置 Chargebee webhook 处理程序
- 调试 Basic Auth 验证失败问题
- 了解 Chargebee 事件类型和负载
- 处理订阅账单事件
核心代码
Chargebee 使用 Basic Authentication 验证 webhook。以下是实现方法:
Express.js
// Verify Chargebee webhook with Basic Auth
// NOTE: Chargebee uses Basic Auth (not HMAC signatures), so raw body access
// is not required. Use express.json() for automatic JSON parsing:
app.post('/webhooks/chargebee', express.json(), (req, res) => {
// Extract Basic Auth credentials
const auth = req.headers.authorization;
if (!auth || !auth.startsWith('Basic ')) {
return res.status(401).send('Unauthorized');
}
// Decode and verify credentials
const encoded = auth.substring(6);
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
const [username, password] = decoded.split(':');
const expectedUsername = process.env.CHARGEBEE_WEBHOOK_USERNAME;
const expectedPassword = process.env.CHARGEBEE_WEBHOOK_PASSWORD;
if (username !== expectedUsername || password !== expectedPassword) {
return res.status(401).send('Invalid credentials');
}
// Access the parsed JSON directly
const event = req.body;
console.log(`Received ${event.event_type} event:`, event.id);
// Handle specific event types
switch (event.event_type) {
case 'subscription_created':
case 'subscription_changed':
case 'subscription_cancelled':
// Process subscription events
break;
case 'payment_succeeded':
case 'payment_failed':
// Process payment events
break;
}
res.status(200).send('OK');
});
// Note: If you later need raw body access (e.g., for HMAC signature
// verification with other providers), use express.raw():
// app.post('/webhooks/other', express.raw({ type: 'application/json' }), (req, res) => {
// const rawBody = req.body.toString();
// // ... verify signature using rawBody ...
// });
Next.js (App Router)
// app/webhooks/chargebee/route.ts
import { NextRequest } from 'next/server';
export async function POST(req: NextRequest) {
// Extract Basic Auth credentials
const auth = req.headers.get('authorization');
if (!auth || !auth.startsWith('Basic ')) {
return new Response('Unauthorized', { status: 401 });
}
// Decode and verify credentials
const encoded = auth.substring(6);
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
const [username, password] = decoded.split(':');
const expectedUsername = process.env.CHARGEBEE_WEBHOOK_USERNAME;
const expectedPassword = process.env.CHARGEBEE_WEBHOOK_PASSWORD;
if (username !== expectedUsername || password !== expectedPassword) {
return new Response('Invalid credentials', { status: 401 });
}
// Process the webhook
const event = await req.json();
console.log(`Received ${event.event_type} event:`, event.id);
return new Response('OK', { status: 200 });
}
FastAPI
# main.py
from fastapi import FastAPI, Header, HTTPException, Depends
from typing import Optional
import base64
import os
app = FastAPI()
def verify_chargebee_auth(authorization: Optional[str] = Header(None)):
"""Verify Chargebee webhook Basic Auth"""
if not authorization or not authorization.startswith("Basic "):
raise HTTPException(status_code=401, detail="Unauthorized")
# Decode credentials
encoded = authorization[6:]
decoded = base64.b64decode(encoded).decode('utf-8')
# Split username:password (handle colons in password)
if ':' not in decoded:
raise HTTPException(status_code=401, detail="Invalid authorization format")
colon_index = decoded.index(':')
username = decoded[:colon_index]
password = decoded[colon_index + 1:]
expected_username = os.getenv("CHARGEBEE_WEBHOOK_USERNAME")
expected_password = os.getenv("CHARGEBEE_WEBHOOK_PASSWORD")
if username != expected_username or password != expected_password:
raise HTTPException(status_code=401, detail="Invalid credentials")
return True
@app.post("/webhooks/chargebee")
async def handle_chargebee_webhook(
event: dict,
auth_valid: bool = Depends(verify_chargebee_auth)
):
"""Handle Chargebee webhook events"""
event_type = event.get("event_type")
print(f"Received {event_type} event: {event.get('id')}")
# Process event based on type
if event_type in ["subscription_created", "subscription_changed", "subscription_cancelled"]:
# Handle subscription events
pass
elif event_type in ["payment_succeeded", "payment_failed"]:
# Handle payment events
pass
return {"status": "OK"}
常见事件类型
⚠️ 警告:请核实事件名称!
以下事件类型名称仅为示例,必须根据你的 Chargebee 配置,参照 Chargebee API 文档进行核实。事件名称可能因 API 版本和配置而有显著差异。
请特别注意:
- 支付事件(下方示例为
payment_succeeded和payment_failed)- 发票事件(下方示例为
invoice_generated)- 任何针对你的 Chargebee 设置的自定义事件
请务必检查 Chargebee Webhook 设置,确认账户使用的准确事件名称。
| 事件 | 触发时机 | 常见用例 |
|---|---|---|
subscription_created | 创建新订阅时 | 开通访问权限,发送欢迎邮件 |
subscription_changed | 修改订阅时 | 更新用户权限,同步变更 |
subscription_cancelled | 取消订阅时 | 撤销访问权限,触发留存流程 |
subscription_reactivated | 重新激活已取消的订阅时 | 恢复访问权限,发送通知 |
payment_succeeded | 成功处理付款时 | 更新付款状态,发送收据 |
payment_failed | 付款尝试失败时 | 重试付款,通知客户 |
invoice_generated | 创建发票时 | 向客户发送发票 |
customer_created | 创建新客户时 | 创建用户账户,同步数据 |
环境变量
# Chargebee webhook Basic Auth credentials
CHARGEBEE_WEBHOOK_USERNAME=your_webhook_username
CHARGEBEE_WEBHOOK_PASSWORD=your_webhook_password
本地开发
如需在本地测试 webhook,请使用 Hookdeck CLI:
npx hookdeck-cli listen 3000 chargebee --path /webhooks/chargebee
无需账户。提供本地隧道和 Web UI,可用于检查请求。
参考资料
示例
- Express 示例 - 带测试的完整 Express.js 实现
- Next.js 示例 - 带测试的 Next.js App Router 实现
- FastAPI 示例 - 带测试的 Python FastAPI 实现
推荐:webhook-handler-patterns
我们建议同时安装 webhook-handler-patterns 技能,以了解处理程序顺序、幂等性、错误处理和重试逻辑。主要参考资料(在 GitHub 上查看):
相关技能
- stripe-webhooks - Stripe 支付 Webhook 处理
- shopify-webhooks - Shopify 电商 Webhook 处理
- github-webhooks - GitHub 仓库 Webhook 处理
- resend-webhooks - Resend 邮件 Webhook 处理
- clerk-webhooks - Clerk 身份验证 Webhook 处理
- elevenlabs-webhooks - ElevenLabs Webhook 处理
- openai-webhooks - OpenAI Webhook 处理
- paddle-webhooks - Paddle 计费 Webhook 处理
- webhook-handler-patterns - 处理程序顺序、幂等性、错误处理、重试逻辑
- hookdeck-event-gateway - 可替代队列的 Webhook 基础设施,提供可靠投递、自动重试、重放、速率限制,以及 Webhook 处理程序的可观测性
评论
支持 Markdown