Webhook dengan Claude Code
Pelajari tentang webhook menggunakan Claude Code. Dilengkapi tips praktis dan contoh kode.
Webhook
Webhook event発生時 HTTPrequest 外部sistem notifikasi mekanisme.決済selesainotifikasi、Git pushevent、formpengiriman dll.多く 場面 使われ.Claude Code 使えば、robustなWebhookimplementasi efisien pembangunan bisa dilakukan.
implementasi Webhookpenerimaan側
import express from "express";
import crypto from "crypto";
const app = express();
// rawBody 保持middleware
app.use("/webhooks", express.raw({ type: "application/json" }));
// 署名verifikasi
function verifyWebhookSignature(
payload: Buffer,
signature: string,
secret: string
): boolean {
const expected = crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(`sha256=${expected}`)
);
}
app.post("/webhooks/stripe", async (req, res) => {
const signature = req.headers["stripe-signature"] as string;
const secret = process.env.STRIPE_WEBHOOK_SECRET!;
// 署名verifikasi
if (!verifyWebhookSignature(req.body, signature, secret)) {
return res.status(401).json({ error: "Invalid signature" });
}
const event = JSON.parse(req.body.toString());
// 冪等性チェック
const processed = await redis.get(`webhook:${event.id}`);
if (processed) {
return res.json({ status: "already_processed" });
}
try {
await processWebhookEvent(event);
// pemrosesan済み dan マーク(24時間保持)
await redis.set(`webhook:${event.id}`, "1", "EX", 86400);
res.json({ status: "processed" });
} catch (error) {
console.error("Webhook processing failed:", error);
res.status(500).json({ error: "Processing failed" });
}
});
async function processWebhookEvent(event: any) {
switch (event.type) {
case "payment_intent.succeeded":
await handlePaymentSuccess(event.data.object);
break;
case "customer.subscription.updated":
await handleSubscriptionUpdate(event.data.object);
break;
case "invoice.payment_failed":
await handlePaymentFailed(event.data.object);
break;
default:
console.log(`Unhandled event type: ${event.type}`);
}
}
implementasi Webhookpengiriman側
interface WebhookConfig {
id: string;
url: string;
secret: string;
events: string[];
active: boolean;
}
class WebhookSender {
private maxRetries = 3;
private retryDelays = [1000, 5000, 30000]; // ms
async send(
config: WebhookConfig,
event: string,
payload: Record<string, unknown>
): Promise<void> {
const body = JSON.stringify({
id: crypto.randomUUID(),
event,
timestamp: new Date().toISOString(),
data: payload,
});
const signature = this.sign(body, config.secret);
for (let attempt = 0; attempt <= this.maxRetries; attempt++) {
try {
const response = await fetch(config.url, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-Webhook-Signature": `sha256=${signature}`,
"X-Webhook-Event": event,
"X-Webhook-Delivery": crypto.randomUUID(),
},
body,
signal: AbortSignal.timeout(10000),
});
if (response.ok) {
await this.logDelivery(config.id, event, "success", attempt);
return;
}
if (response.status >= 400 && response.status < 500) {
// clienterror リトライし tidak
await this.logDelivery(config.id, event, "client_error", attempt);
return;
}
throw new Error(`HTTP ${response.status}`);
} catch (error) {
if (attempt < this.maxRetries) {
await new Promise((r) => setTimeout(r, this.retryDelays[attempt]));
} else {
await this.logDelivery(config.id, event, "failed", attempt);
throw error;
}
}
}
}
private sign(payload: string, secret: string): string {
return crypto
.createHmac("sha256", secret)
.update(payload)
.digest("hex");
}
private async logDelivery(
configId: string,
event: string,
status: string,
attempts: number
) {
await prisma.webhookDelivery.create({
data: { configId, event, status, attempts },
});
}
}
WebhookregistrasiAPI
const router = express.Router();
router.post("/api/webhooks", async (req, res) => {
const { url, events } = req.body;
// URL verifikasi
try {
const parsed = new URL(url);
if (parsed.protocol !== "https:") {
return res.status(400).json({ error: "HTTPS required" });
}
} catch {
return res.status(400).json({ error: "Invalid URL" });
}
// シークレット generate
const secret = crypto.randomBytes(32).toString("hex");
const webhook = await prisma.webhookConfig.create({
data: {
url,
events,
secret,
active: true,
userId: req.user!.id,
},
});
// シークレット pembuatan時 み返す
res.status(201).json({
id: webhook.id,
url: webhook.url,
events: webhook.events,
secret,
});
});
ディスパッチ event
class EventDispatcher {
private sender = new WebhookSender();
async dispatch(event: string, payload: Record<string, unknown>) {
// 該当event 購読 Webhook pengambilan
const configs = await prisma.webhookConfig.findMany({
where: {
active: true,
events: { has: event },
},
});
// 並列 pengiriman(キュー 入れる場合 BullMQ penggunaan)
const results = await Promise.allSettled(
configs.map((config) => this.sender.send(config, event, payload))
);
const failed = results.filter((r) => r.status === "rejected");
if (failed.length > 0) {
console.error(`${failed.length}/${configs.length} webhooks failed`);
}
}
}
// Usage example
const dispatcher = new EventDispatcher();
// 注文selesai時
async function completeOrder(orderId: string) {
const order = await prisma.order.update({
where: { id: orderId },
data: { status: "completed" },
});
await dispatcher.dispatch("order.completed", {
orderId: order.id,
total: order.total,
customerId: order.customerId,
});
}
Pemanfaatan dengan Claude Code
Webhookimplementasi Claude Code 依頼 例.非同期pemrosesan mengenai ジョブキュー・非同期pemrosesan、event設計 event駆動arsitektur juga bisa dijadikan referensi.
Webhooksistem implementasikan.
- penerimaan: Stripe/GitHub Webhook 署名verifikasi
- pengiriman: HMAC署名付き、リトライ機能付き
- 冪等性 保証
- distribusiログ dan monitoring
- registrasi・manajemen用 REST API
Mengenai Webhookのセキュリティ, konfirmasiできます。 di OWASP Webhook Securityを参照してください。Claude Codeの活用法は公式ドキュメント.
Summary
Webhook sistem間integrasi pentingなpola.Claude Code 使えば、署名verifikasi、リトライ、冪等性保証 含むrobustなWebhookfondasi efisien pembangunan bisa dilakukan.
Related Posts
Setup MCP Server Claude Code dan Use Case Praktis
Panduan lengkap tentang kemampuan MCP server Claude Code. Pelajari cara menghubungkan tool eksternal, mengonfigurasi server, dan contoh integrasi dunia nyata.
Menguasai Claude Code Hooks: Auto-Format, Auto-Test, dan Lainnya
Pelajari cara menyiapkan auto-formatting dan auto-testing dengan Claude Code hooks. Dilengkapi contoh konfigurasi praktis dan use case dunia nyata.
Panduan Lengkap Menulis CLAUDE.md: Best Practice untuk Konfigurasi Project
Panduan menyeluruh untuk menulis file CLAUDE.md yang efektif. Pelajari cara mengkomunikasikan tech stack, konvensi, dan struktur project untuk memaksimalkan kualitas output Claude Code.