Chaindoc Webhooks
Chaindoc hesabınızda olaylar meydana geldiğinde gerçek zamanlı bildirimler alın. Webhooks, olay verilerini anında sunucunuza aktarır ve böylece yoklama ihtiyacını ortadan kaldırır.
Genel Bakış
Chaindoc Webhooks, hesabınızda bir olay meydana geldiğinde uygulamanızın gerçek zamanlı bildirimler almasını sağlar. API'yi sorgulamak yerine, webhooks bir eylem gerçekleştiğinde olay verilerini sunucunuza aktarır.
Temel Özellikler
- Gerçek Zamanlı Bildirimler - Sunucunuza anında olay teslimi
- Otomatik Yeniden Denemeler - Üstel geri çekilme ile en fazla 3 yeniden deneme
- İmza Doğrulama - Yükün gerçekliği için HMAC SHA256
- Etkinlik Filtreleme - Yalnızca ilgilendiğiniz etkinlikleri alın
- Hata Takibi - Webhook teslimat durumunu ve hatalarını izleyin
Kullanım Örnekleri
- Belgeler imzalandığında e-posta bildirimleri gönderin
- Belgeler blok zincirinde doğrulandığında iş akışlarını tetikleyin
- İmza talepleri oluşturulduğunda veritabanınızı güncelleyin
- Belge durumunu harici sistemlerle senkronize edin
- Denetim izi ve uyumluluk günlüğü
Kurulum
Adım 1: API Anahtarı Oluşturun
Chaindoc kontrol panelinizde Ayarlar → API Erişimi'ne gidin ve webhook yapılandırması etkinleştirilmiş bir API anahtarı oluşturun.
Adım 2: Webhook URL'sini yapılandırın
API'yi kullanarak webhook uç noktanızı yapılandırın:
curl -X PATCH https://api.chaindoc.io/user/api-access/1/config \
-H "Authorization: Bearer your_auth_token" \
-H "Content-Type: application/json" \
-d '{
"webhookUrl": "https://yourapp.com/webhooks/chaindoc",
"webhookEnabled": true,
"webhookSecret": "your_secure_random_string"
}'Adım 3: Webhook Uç Noktasını Uygulayın
Webhook olaylarını almak için sunucunuzda bir uç nokta oluşturun. İşte farklı dillerde örnekler:
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json());
app.post('/webhooks/chaindoc', (req, res) => {
const signature = req.headers['x-webhook-signature'];
const eventType = req.headers['x-webhook-event'];
// Verify signature
if (!verifySignature(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process event
console.log('Received event:', eventType, req.body);
// Handle different event types
switch (eventType) {
case 'document.created':
handleDocumentCreated(req.body);
break;
case 'document.verified':
handleDocumentVerified(req.body);
break;
case 'signature.request.completed':
handleSignatureCompleted(req.body);
break;
}
// Always respond with 200 OK
res.status(200).send('Webhook received');
});
function verifySignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(JSON.stringify(payload)).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(digest)
);
}
app.listen(3000);Etkinlik Türleri
Chaindoc, aşağıdaki olaylar için webhook'lar gönderir:
document.created
API aracılığıyla yeni bir belge oluşturulduğunda tetiklenir.
{
"event": "document.created",
"documentId": "86840ee4-8bf2-4a91-a289-e99d8307ec25",
"name": "Service Agreement",
"timestamp": "2024-12-04T10:30:00.000Z"
}document.verified
Bir belge blok zincirinde başarıyla doğrulandığında tetiklenir.
{
"event": "document.verified",
"documentId": "86840ee4-8bf2-4a91-a289-e99d8307ec25",
"versionId": "f0b7721f-0399-4035-9b69-7b95d3a367f0",
"txHash": "0x789ghi...",
"chainId": 137,
"timestamp": "2024-12-04T10:35:00.000Z"
}belge.imzalı
Gerekli tüm imzalar toplandığında tetiklenir.
{
"event": "document.signed",
"documentId": "86840ee4-8bf2-4a91-a289-e99d8307ec25",
"signatureRequestId": "req_21096b94498f4a2d9795e810edc2c9a9",
"signers": [
{
"email": "signer1@example.com",
"signedAt": "2024-12-04T10:30:00.000Z"
},
{
"email": "signer2@example.com",
"signedAt": "2024-12-04T10:32:00.000Z"
}
],
"timestamp": "2024-12-04T10:32:00.000Z"
}signature.request.created
Yeni imza isteği oluşturulduğunda tetiklenir.
{
"event": "signature.request.created",
"signatureRequestId": "req_21096b94498f4a2d9795e810edc2c9a9",
"documentId": "86840ee4-8bf2-4a91-a289-e99d8307ec25",
"recipients": [
{"email": "signer1@example.com"},
{"email": "signer2@example.com"}
],
"deadline": "2024-12-31T23:59:59.000Z",
"timestamp": "2024-12-04T10:30:00.000Z"
}signature.request.completed
Tüm imzalayanlar imzalarını tamamladığında tetiklenir.
{
"event": "signature.request.completed",
"signatureRequestId": "req_21096b94498f4a2d9795e810edc2c9a9",
"documentId": "86840ee4-8bf2-4a91-a289-e99d8307ec25",
"completedAt": "2024-12-04T10:32:00.000Z",
"timestamp": "2024-12-04T10:32:00.000Z"
}signature.request.rejected
İmzalayan kişi imza talebini reddettiğinde tetiklenir.
{
"event": "signature.request.rejected",
"signatureRequestId": "req_21096b94498f4a2d9795e810edc2c9a9",
"documentId": "86840ee4-8bf2-4a91-a289-e99d8307ec25",
"rejectedBy": "signer1@example.com",
"reason": "Terms not acceptable",
"timestamp": "2024-12-04T10:30:00.000Z"
}Güvenlik
İmza Doğrulama
Chaindoc, HMAC SHA256 kullanarak tüm webhook yüklerini imzalar. Orijinalliği sağlamak ve tekrar saldırılarını önlemek için imzaları her zaman doğrulayın.
İmza Doğrulama Nasıl Çalışır?
1Chaindoc İmza OluştururChaindoc, webhook gizli anahtarınızı kullanarak HMAC imzası oluşturur.
2Başlıkta Gönderilen İmzaİmza, X-Webhook-Signature başlığında gönderilir.
3Sunucunuz DoğrularSunucunuz imzayı yeniden hesaplar ve zamanlama güvenli işlev kullanarak karşılaştırır.
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(JSON.stringify(payload)).digest('hex');
// Use timing-safe comparison to prevent timing attacks
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(digest)
);
}
// Usage
const isValid = verifyWebhookSignature(
req.body,
req.headers['x-webhook-signature'],
process.env.WEBHOOK_SECRET
);
if (!isValid) {
return res.status(401).send('Invalid signature');
}Yeniden Deneme Mantığı
Chaindoc, başarısız webhook teslimatlarını üstel geri çekilme ile otomatik olarak yeniden dener.
- 1. yeniden deneme: 1 dakika sonra
- 2. deneme: 5 dakika sonra (toplam: 6 dakika)
- 3. deneme: 15 dakika sonra (toplam: 21 dakika)
Webhook'ları Test Etme
Yerel Geliştirme
Webhook testi için yerel sunucunuzu açığa çıkarmak için ngrok gibi araçlar kullanın:
# Install ngrok
npm install -g ngrok
# Start your local server
node server.js
# Expose port 3000
ngrok http 3000
# Use the ngrok URL as your webhook endpoint
# Example: https://abc123.ngrok.io/webhooks/chaindocManuel Test
Webhook uç noktanızı örnek bir yük ile test edin:
curl -X POST https://yourapp.com/webhooks/chaindoc \
-H "Content-Type: application/json" \
-H "X-Webhook-Event: document.created" \
-H "X-Webhook-Signature: test_signature" \
-d '{
"event": "document.created",
"documentId": "test-123",
"name": "Test Document",
"timestamp": "2024-12-04T10:30:00.000Z"
}'En İyi Uygulamalar
- İşleme başlamadan önce her zaman webhook imzalarını doğrulayın.
- Zaman aşımını önlemek için hızlı yanıt verin (30 saniye içinde).
- Webhook'ları bir kuyrukta eşzamansız olarak işleyin
- Yinelenen olayları işlemek için idempotensi uygulayın
- Hata ayıklama ve denetim için tüm webhook olaylarını kaydedin
- Kontrol panelinizde webhook teslimat hatalarını izleyin
- Güvenlik için HTTPS uç noktaları kullanın
- Tüm olay türlerini nazikçe işleyin (bilinmeyen olayları yok sayın)
Tam Örnek
İşte veritabanı entegrasyonuna sahip, üretime hazır bir webhook işleyicisi:
import express from 'express';
import crypto from 'crypto';
import { PrismaClient } from '@prisma/client';
const app = express();
const prisma = new PrismaClient();
app.use(express.json());
app.post('/webhooks/chaindoc', async (req, res) => {
const signature = req.headers['x-webhook-signature'] as string;
const eventType = req.headers['x-webhook-event'] as string;
const payload = req.body;
// 1. Verify signature
if (!verifySignature(payload, signature, process.env.WEBHOOK_SECRET!)) {
console.error('Invalid webhook signature');
return res.status(401).json({ error: 'Invalid signature' });
}
// 2. Check for duplicate events (idempotency)
const eventId = `${eventType}-${payload.timestamp}`;
const existing = await prisma.webhookEvent.findUnique({
where: { eventId },
});
if (existing) {
console.log('Duplicate event, skipping:', eventId);
return res.status(200).json({ status: 'duplicate' });
}
// 3. Store event
await prisma.webhookEvent.create({
data: {
eventId,
eventType,
payload,
processedAt: new Date(),
},
});
// 4. Process event asynchronously
processWebhookAsync(eventType, payload).catch((error) => {
console.error('Error processing webhook:', error);
});
// 5. Respond immediately
res.status(200).json({ status: 'received' });
});
async function processWebhookAsync(eventType: string, payload: any) {
switch (eventType) {
case 'document.verified':
await handleDocumentVerified(payload);
break;
case 'signature.request.completed':
await handleSignatureCompleted(payload);
await sendNotificationEmail(payload);
break;
case 'signature.request.rejected':
await handleSignatureRejected(payload);
break;
}
}
async function handleDocumentVerified(payload: any) {
await prisma.document.update({
where: { id: payload.documentId },
data: {
status: 'verified',
blockchainTxHash: payload.txHash,
verifiedAt: new Date(payload.timestamp),
},
});
}
async function handleSignatureCompleted(payload: any) {
await prisma.signatureRequest.update({
where: { id: payload.signatureRequestId },
data: {
status: 'completed',
completedAt: new Date(payload.completedAt),
},
});
}
function verifySignature(payload: any, signature: string, secret: string): boolean {
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(JSON.stringify(payload)).digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}
app.listen(3000);