chargebee-webhooks について
chargebee-webhooksは、ChargebeeのWebhookハンドラーを実装・デバッグする開発者向けのスキルです。Basic Authによる検証、イベントペイロード、サブスクリプション課金イベントを扱い、Express.js、Next.js、FastAPIの例を紹介します。
主な機能
- 01Basic Auth検証のガイダンス
- 02Chargebeeイベント種別の参照
- 03サブスクリプション課金イベントの処理
- 04Express.js、Next.js、FastAPIの例
- 05Hookdeck CLIによるローカルテスト
活用シーン
- 01Chargebee Webhookエンドポイントの実装
- 02Basic 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 Webhooks
このスキルを使う場面
- Chargebee の Webhook ハンドラーを設定するとき
- Basic Auth の検証失敗をデバッグするとき
- Chargebee のイベントタイプとペイロードを理解するとき
- サブスクリプションの請求イベントを処理するとき
基本的なコード
Chargebee は Webhook の検証に Basic Authentication を使用します。実装方法は次のとおりです。
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 を利用できます。
参考資料
- 概要 - Chargebee Webhook の説明とよくあるイベントタイプ
- セットアップ - Chargebee ダッシュボードで Webhook を設定する方法
- 検証 - Basic Auth の検証に関する詳細と注意点
例
- 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 の E コマース 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 対応