Chaindoc вебхуктары
Вебхуктар Chaindoc-та бір нәрсе болған сәтте деректерді серверіңізге жібереді. Сұраныс жоқ, кідіріс жоқ. Бұл бетте баптау, оқиға түрлері, HMAC растауы, қайталау логикасы және тестілеу көрсетілген.
Шолу
API-ны сұраудың орнына, вебхуктар не болғанын серверіңізге дереу айтады. Құжат күйін синхрондау, қолтаңбалар кейін жұмыс процестерін іске қосу, хабарландырулар жіберу және дерекқорыңызды синхрондау үшін қолданасыз.
- 3 автоматты қайталаумен (экспоненциалды кідіріс) лезде жеткізу
- Әр payload-та HMAC SHA256 қолтаңбасын растау
- Тек қызықтыратын оқиға түрлеріне сүзгі
- Басқару тақтасындағы жеткізу күйін бақылау
Орнату
1-қадам: API кілтін жасау
Chaindoc басқару тақтасында Параметрлер → API Access бөліміне өтіп, вебхук баптауы қосылған API кілтін жасаңыз.
2-қадам: Вебхук URL-ын баптау
Вебхук endpoint-іңізді баптау үшін API қолданыңыз:
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"
}'3-қадам: Endpoint іске асыру
Вебхук оқиғаларын қабылдау үшін серверіңізде endpoint жасаңыз. Міне түрлі тілдердегі мысалдар:
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);Оқиға түрлері
Chaindoc келесі оқиғалар үшін вебхуктар жібереді:
document.created
Жаңа құжат API арқылы жасалғанда іске қосылады.
{
"event": "document.created",
"documentId": "86840ee4-8bf2-4a91-a289-e99d8307ec25",
"name": "Service Agreement",
"timestamp": "2024-12-04T10:30:00.000Z"
}document.verified
Құжат blockchain-де сәтті расталғанда іске қосылады.
{
"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
Барлық қажетті қолтаңбалар жиналғанда іске қосылады.
{
"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
Жаңа қолтаңба сұранысы жасалғанда іске қосылады.
{
"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
Барлық қол қоюшылар қолтаңбаларын аяқтағанда іске қосылады.
{
"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
Қол қоюшы қолтаңба сұранысын бас тартқанда іске қосылады.
{
"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"
}Қауіпсіздік
Қолтаңбаны растау
Chaindoc барлық вебхук payload-тарын HMAC SHA256 арқылы қол қояды. Аутентификацияны қамтамасыз ету және қайталау шабуылдарын болдырмау үшін әрдайым қолтаңбаларды растаңыз.
Растау қалай жұмыс істейді
1Chaindoc қолтаңба жасайдыChaindoc вебхук құпиясыңызды қолданып HMAC қолтаңбасын жасайды
2Қолтаңба header-де жіберіледіҚолтаңба X-Webhook-Signature header-інде жіберіледі
3Серверіңіз растайдыСерверіңіз қолтаңбаны қайта есептейді және уақыт-безопас функциямен салыстырады
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');
}Қайталау логикасы
Chaindoc сәтсіз вебхук жеткізілімдерін экспоненциалды кідіріспен автоматты түрде қайталайды.
- 1-ші қайталау: 1 минуттан кейін
- 2-ші қайталау: 5 минуттан кейін (барлығы: 6 минут)
- 3-ші қайталау: 15 минуттан кейін (барлығы: 21 минут)
Вебхуктарды тестілеу
Жергілікті әзірлеу
ngrok сияқты құралдарды жергілікті серверіңізді вебхук тестілеуі үшін ашуға қолданыңыз:
# 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/chaindocҚолмен тестілеу
Вебхук endpoint-іңізді үлгі payload-пен тестілеңіз:
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"
}'Үздік тәжірибелер
- Өңдеуден бұрын әрдайым вебхук қолтаңбаларын растаңыз
- Ұзаққа созылмау үшін тез жауап беріңіз (30 секундтан аз)
- Вебхуктарды кезекте асинхронды түрде өңдеңіз
- Қайталанған оқиғаларды өңдеу үшін идемпотенттілікті іске асырыңыз
- Жөндеу және аудит үшін барлық вебхук оқиғаларын журналдаңыз
- Басқару тақтасында вебхук жеткізілімінің сәтсіздігін бақылаңыз
- Қауіпсіздік үшін HTTPS endpoint-терін қолданыңыз
- Барлық оқиға түрлерін дұрыс өңдеңіз (белгісіз оқиғаларды елемеу)
Өндірістік мысал
Міне, дерекқор интеграциясы бар өндіріске дайын вебхук өңдеушісі:
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,
verifiedAt: new Date(),
},
});
}
async function handleSignatureCompleted(payload: any) {
await prisma.signatureRequest.update({
where: { id: payload.signatureRequestId },
data: {
status: 'completed',
completedAt: new Date(),
},
});
}
function verifySignature(payload: any, signature: string, secret: string): boolean {
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(JSON.stringify(payload)).digest('hex');
try {
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(digest)
);
} catch {
return false;
}
}Келесі қадамдар
- API интеграциясы — жиі қолданылатын әдістер мен жұмыс процестері мысалдары
- API құжаттамасы — толық endpoint анықтамасы
- SDK — Server SDK және Embed SDK нұсқаулары
- Қауіпсіздік — HMAC растауы және кілт басқаруы
- Орнату — барлық фреймворктер үшін SDK орнату