Chaindoc webhookid
Webhookid saadavad sündmuste andmed sinu serverile hetkega, kui midagi Chaindocis juhtub. Pole vaja küsitlusi ega viivitusi. See leht hõlmab seadistust, sündmuste tüüpe, HMAC verifitseerimist, uuesti proovimise loogikat ja testimist.
Ülevaade
Selle asemel, et API pidevalt küsitleda, annavad webhookid sinu serverile teada, mis juhtus kohe, kui see juhtub. Sa kasutad neid dokumentide oleku sünkroonimiseks, töövoogude käivitamiseks pärast allkirju, teavituste saatmiseks ja andmebaasi sünkroonis hoidmiseks.
- Kohene kohaletoimetamine kuni 3 automaatse uuesti proovimisega (eksponentsiaalne taandareng)
- HMAC SHA256 allkirja verifitseerimine igal koormusel
- Filtreeri ainult need sündmuste tüübid, mis sind huvitavad
- Kohaletoimetamise oleku jälgimine sinu armatuurlaual
Seadistus
Samm 1: Loo API võti
Navigeeri oma Chaindoc armatuurlaual Seaded → API Ligipääs ja loo API võti, millel on webhookide seadistamine lubatud.
Samm 2: Seadista webhooki URL
Kasuta API-t oma webhooki lõpp-punkti seadistamiseks:
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"
}'Samm 3: Rakenda oma lõpp-punkt
Loo lõpp-punkt oma serveris webhooki sündmuste vastuvõtmiseks. Siin on näited erinevates keeltes:
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);Sündmuste tüübid
Chaindoc saadab webhook-e järgmiste sündmuste puhul:
document.created
Käivitub, kui uus dokument luuakse API kaudu.
{
"event": "document.created",
"documentId": "86840ee4-8bf2-4a91-a289-e99d8307ec25",
"name": "Service Agreement",
"timestamp": "2024-12-04T10:30:00.000Z"
}document.verified
Käivitub, kui dokument on edukalt plokiahelas verifitseeritud.
{
"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"
}document.signed
Käivitub, kui kõik nõutud allkirjad on kogutud.
{
"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
Käivitub, kui uus allkirjapäring luuakse.
{
"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
Käivitub, kui kõik allkirjastajad lõpetavad oma allkirjad.
{
"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
Käivitub, kui allkirjastaja lükkab allkirjapäringu tagasi.
{
"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"
}Turvalisus
Allkirja verifitseerimine
Chaindoc allkirjastab kõik webhooki koormused HMAC SHA256 abil. Verifitseeri alati allkirjad autentsuse tagamiseks ja kordusrünnakute vältimiseks.
Kuidas verifitseerimine töötab
1Chaindoc loob allkirjaChaindoc loob HMAC allkirja kasutades sinu webhooki saladust
2Allkiri saadetakse päisesAllkiri saadetakse X-Webhook-Signature päises
3Sinu server verifitseeribSinu server arvutab allkirja uuesti ja võrdleb ajakindel funktsiooni abil
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');
}Uuesti proovimise loogika
Chaindoc proovib automaatselt ebaõnnestunud webhooki kohaletoimetamisi uuesti eksponentsiaalse taandarenguga.
- 1. kord: Pärast 1 minutit
- 2. kord: Pärast 5 minutit (kokku: 6 minutit)
- 3. kord: Pärast 15 minutit (kokku: 21 minutit)
Webhookide testimine
Lokaalne arendus
Kasuta tööriistu nagu ngrok, et avalikustada oma lokaalne server webhookide testimiseks:
# 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/chaindocManuaalne testimine
Testi oma webhooki lõpp-punkti näidiskoormusega:
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"
}'Parimad tavad
- Verifitseeri alati webhooki allkirjad enne töötlemist
- Vasta kiiresti (alla 30 sekundi), et vältida aegumisi
- Töötle webhook-e asünkroonselt järjekorras
- Rakenda idempotentsus duplikaat-sündmuste käsitlemiseks
- Logi kõik webhooki sündmused silumiseks ja auditeerimiseks
- Jälgi webhooki kohaletoimetamise ebaõnnestumisi oma armatuurlaual
- Kasuta turvalisuse jaoks HTTPS lõpp-punkte
- Käitle kõiki sündmuste tüüpe viisakalt (ignoreeri tundmatuid sündmusi)
Tootmise näide
Siin on tootmisvalmis webhooki käitleja andmebaasi integratsiooniga:
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', txHash: payload.txHash },
});
}
function verifySignature(payload: any, signature: string, secret: string) {
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(JSON.stringify(payload)).digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(digest));
}Mida järgmiseks teha
- API integratsioon — levinud mustrid ja töövoo näited
- API dokumentatsioon — täielik lõpp-punktide viide
- SDK-d — Server SDK ja Embed SDK juhendid
- Turvalisus — HMAC verifitseerimine ja võtmehaldus
- Paigaldus — SDK seadistus kõigile raamistikele