chargebee-webhooks
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseChargebee Webhooks
Chargebee Webhooks
When to Use This Skill
何时使用该技能
- Setting up Chargebee webhook handlers
- Debugging Basic Auth verification failures
- Understanding Chargebee event types and payloads
- Processing subscription billing events
- 设置Chargebee webhook处理器
- 调试Basic Auth验证失败问题
- 了解Chargebee事件类型和负载结构
- 处理订阅计费事件
Essential Code
核心代码示例
Chargebee uses Basic Authentication for webhook verification. Here's how to implement it:
Chargebee 使用Basic Authentication进行webhook验证,以下是具体实现方式:
Express.js
Express.js
javascript
// 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 ...
// });javascript
// 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)
Next.js (App Router)
typescript
// 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 });
}typescript
// 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
FastAPI
python
undefinedpython
undefinedmain.py
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"}undefinedfrom 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"}undefinedCommon Event Types
常见事件类型
⚠️ WARNING: Verify Event Names!The event type names below are examples and MUST be verified against the Chargebee API documentation for your specific Chargebee configuration. Event names can vary significantly between API versions and configurations.Special attention required for:
- Payment events (shown as
andpayment_succeededbelow)payment_failed- Invoice events (shown as
below)invoice_generated- Any custom events specific to your Chargebee setup
Always check your Chargebee Webhook settings for the exact event names your account uses.
| Event | Triggered When | Common Use Cases |
|---|---|---|
| New subscription is created | Provision access, send welcome email |
| Subscription is modified | Update user permissions, sync changes |
| Subscription is cancelled | Revoke access, trigger retention flow |
| Cancelled subscription is reactivated | Restore access, send notification |
| Payment is successfully processed | Update payment status, send receipt |
| Payment attempt fails | Retry payment, notify customer |
| Invoice is created | Send invoice to customer |
| New customer is created | Create user account, sync data |
⚠️ 警告:请验证事件名称!以下事件类型仅为示例,**必须对照你的Chargebee配置查看Chargebee API文档**进行验证。不同API版本和配置下的事件名称可能存在显著差异。需要特别注意以下类型:
- 支付事件(如下方的
和payment_succeeded)payment_failed- 发票事件(如下方的
)invoice_generated- 你的Chargebee账户中配置的任何自定义事件
请务必在Chargebee Webhook设置中确认你的账户使用的具体事件名称。
| 事件 | 触发时机 | 常见应用场景 |
|---|---|---|
| 创建新订阅时 | 开通用户权限、发送欢迎邮件 |
| 修改订阅时 | 更新用户权限、同步变更信息 |
| 取消订阅时 | 收回用户权限、触发客户留存流程 |
| 重新激活已取消的订阅时 | 恢复用户权限、发送通知邮件 |
| 支付成功时 | 更新支付状态、发送收据 |
| 支付尝试失败时 | 重试支付、通知客户 |
| 创建发票时 | 向客户发送发票 |
| 创建新客户时 | 创建用户账号、同步客户数据 |
Environment Variables
环境变量
bash
undefinedbash
undefinedChargebee webhook Basic Auth credentials
Chargebee webhook Basic Auth credentials
CHARGEBEE_WEBHOOK_USERNAME=your_webhook_username
CHARGEBEE_WEBHOOK_PASSWORD=your_webhook_password
undefinedCHARGEBEE_WEBHOOK_USERNAME=your_webhook_username
CHARGEBEE_WEBHOOK_PASSWORD=your_webhook_password
undefinedLocal Development
本地开发测试
For local webhook testing, use Hookdeck CLI:
bash
brew install hookdeck/hookdeck/hookdeck
hookdeck listen 3000 --path /webhooks/chargebeeNo account required. Provides local tunnel + web UI for inspecting requests.
本地测试webhook可使用Hookdeck CLI:
bash
brew install hookdeck/hookdeck/hookdeck
hookdeck listen 3000 --path /webhooks/chargebee无需注册账户,提供本地隧道和Web界面用于检查请求。
Reference Materials
参考资料
- Overview - What Chargebee webhooks are, common event types
- Setup - Configure webhooks in Chargebee dashboard
- Verification - Basic Auth verification details and gotchas
- 概述 - Chargebee webhook是什么,常见事件类型
- 设置指南 - 在Chargebee控制台配置webhook
- 验证细节 - Basic Auth验证的详细说明和注意事项
Examples
示例项目
- Express Example - Complete Express.js implementation with tests
- Next.js Example - Next.js App Router implementation with tests
- FastAPI Example - Python FastAPI implementation with tests
- Express示例 - 完整的Express.js实现及测试用例
- Next.js示例 - Next.js App Router实现及测试用例
- FastAPI示例 - Python FastAPI实现及测试用例
Recommended: webhook-handler-patterns
推荐搭配:webhook-handler-patterns
We recommend installing the webhook-handler-patterns skill alongside this one for handler sequence, idempotency, error handling, and retry logic. Key references (open on GitHub):
- Handler sequence — Verify first, parse second, handle idempotently third
- Idempotency — Prevent duplicate processing
- Error handling — Return codes, logging, dead letter queues
- Retry logic — Provider retry schedules, backoff patterns
我们建议同时安装webhook-handler-patterns技能,以获取处理器流程设计、幂等性处理、错误处理和重试逻辑的最佳实践。关键参考内容(可在GitHub查看):
Related Skills
相关技能
- stripe-webhooks - Stripe payment webhook handling
- shopify-webhooks - Shopify e-commerce webhook handling
- github-webhooks - GitHub repository webhook handling
- resend-webhooks - Resend email webhook handling
- clerk-webhooks - Clerk auth webhook handling
- elevenlabs-webhooks - ElevenLabs webhook handling
- openai-webhooks - OpenAI webhook handling
- paddle-webhooks - Paddle billing webhook handling
- webhook-handler-patterns - Handler sequence, idempotency, error handling, retry logic
- hookdeck-event-gateway - Webhook infrastructure that replaces your queue — guaranteed delivery, automatic retries, replay, rate limiting, and observability for your webhook handlers
- 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处理器提供可靠投递、自动重试、事件重放、速率限制和可观测性