Chaindoc logoChaindoc

Chaindoc SDK

Chaindoc пропонує два TypeScript SDK: Server SDK для роботи на бекенді (Node.js) та Embed SDK для вбудовування інтерфейсу підписування у ваш веб-застосунок. Обидва мають повні типи, нуль залежностей під час виконання та працюють з будь-яким фреймворком.

Доступні SDK

Для налаштування npm та конфігурації під конкретний фреймворк (змінні середовища, провайдери тощо) дивіться посібник з встановлення.

  • Server SDK (@chaindoc_io/server-sdk) — інтеграція бекенду для Node.js 18+
  • Embed SDK (@chaindoc_io/embed-sdk) — інтерфейс підписування для веб-застосунків
  • Python SDK — з'явиться незабаром
  • PHP SDK — з'явиться незабаром

Server SDK

Server SDK обгортає REST API у типобезпечний інтерфейс Node.js. Використовуйте його для керування документами, створення запитів на підпис, обробки завантажень файлів та запуску блокчейн-верифікації.

Встановлення

npm install @chaindoc_io/server-sdk

Швидкий старт

server.ts
import { Chaindoc } from '@chaindoc_io/server-sdk';
import { readFile } from 'fs/promises';

// 1. Ініціалізуйте SDK
const chaindoc = new Chaindoc({
  secretKey: process.env.CHAINDOC_SECRET_KEY!,
});

// 2. Завантажте файл документа
const buffer = await readFile('./contract.pdf');
const file = new Blob([buffer], { type: 'application/pdf' });
const { media } = await chaindoc.media.upload([file]);

// 3. Створіть документ
const doc = await chaindoc.documents.create({
  name: 'Service Agreement',
  description: 'Contract for consulting services',
  media: media[0],
  status: 'published', // Запускає блокчейн-верифікацію
  hashtags: ['#contract', '#2024'],
  meta: [{ key: 'client', value: 'Acme Corp' }],
});

// 4. Створіть запит на підпис
const sigRequest = await chaindoc.signatures.createRequest({
  versionId: doc.document.versions[0].uuid,
  recipients: [{ email: 'signer@example.com' }],
  deadline: new Date('2024-12-31'),
  embeddedFlow: true,
});

// 5. Створіть сесію для фронтенд SDK
const session = await chaindoc.embedded.createSession({
  email: 'signer@example.com',
  metadata: {
    documentId: doc.documentId,
    signatureRequestId: sigRequest.signatureRequest.uuid,
  },
});

console.log('Session ID:', session.sessionId);

Інтеграція з Express.js

server.ts
import express from 'express';
import { Chaindoc, ChaindocError } from '@chaindoc_io/server-sdk';
import multer from 'multer';

const app = express();
const upload = multer({ storage: multer.memoryStorage() });

const chaindoc = new Chaindoc({
  secretKey: process.env.CHAINDOC_SECRET_KEY!,
});

// Завантаження та створення документа
app.post('/api/documents', upload.single('file'), async (req, res) => {
  try {
    const file = new Blob([req.file!.buffer], { type: req.file!.mimetype });
    const { media } = await chaindoc.media.upload([file]);

    const doc = await chaindoc.documents.create({
      name: req.body.name,
      description: req.body.description || '',
      media: media[0],
      status: 'published',
      hashtags: req.body.hashtags || [],
      meta: req.body.meta || [],
    });

    res.json({ documentId: doc.documentId });
  } catch (error) {
    if (error instanceof ChaindocError) {
      res.status(error.statusCode || 500).json({ error: error.message });
    } else {
      res.status(500).json({ error: 'Internal server error' });
    }
  }
});

// Створення вбудованої сесії для підписанта
app.post('/api/signing/session', async (req, res) => {
  try {
    const { email, documentId, signatureRequestId } = req.body;

    const session = await chaindoc.embedded.createSession({
      email,
      metadata: { documentId, signatureRequestId },
    });

    res.json({ sessionId: session.sessionId });
  } catch (error) {
    if (error instanceof ChaindocError) {
      res.status(error.statusCode || 500).json({ error: error.message });
    }
  }
});

app.listen(3000);

API маршрути Next.js

app/api/signing/create-session/route.ts
import { NextRequest, NextResponse } from 'next/server';
import { Chaindoc, ChaindocError } from '@chaindoc_io/server-sdk';

const chaindoc = new Chaindoc({
  secretKey: process.env.CHAINDOC_SECRET_KEY!,
});

export async function POST(request: NextRequest) {
  try {
    const { email, documentId, signatureRequestId } = await request.json();

    const session = await chaindoc.embedded.createSession({
      email,
      metadata: { documentId, signatureRequestId },
    });

    return NextResponse.json({
      sessionId: session.sessionId,
      expiresAt: session.expiresAt,
    });
  } catch (error) {
    if (error instanceof ChaindocError) {
      return NextResponse.json(
        { error: error.message },
        { status: error.statusCode || 500 }
      );
    }
    return NextResponse.json(
      { error: 'Internal server error' },
      { status: 500 }
    );
  }
}

Обробка помилок

Завжди обгортайте виклики API у try-catch блоки та обробляйте ChaindocError окремо:

terminal
import { ChaindocError } from '@chaindoc_io/server-sdk';

try {
  const doc = await chaindoc.documents.create({ /* ... */ });
} catch (error) {
  if (error instanceof ChaindocError) {
    console.error('API Error:', error.message);
    console.error('Status Code:', error.statusCode);
    
    switch (error.statusCode) {
      case 400:
        // Неправильний запит — перевірте параметри
        break;
      case 401:
        // Неавторизовано — перевірте API ключ
        break;
      case 404:
        // Не знайдено
        break;
      case 429:
        // Ліміт запитів — SDK автоматично повторить
        break;
    }
  }
}

Embed SDK

Embed SDK дозволяє показувати інтерфейс підписування Chaindoc прямо у вашому веб-застосунку. Він керує iframe, OTP-верифікацією та комунікацією між вашим застосунком і Chaindoc. Ваші користувачі підписують документи, не залишаючи ваш сайт.

Встановлення

npm install @chaindoc_io/embed-sdk

Базове використання

terminal
import { ChaindocEmbed } from '@chaindoc_io/embed-sdk';

// 1. Ініціалізуйте SDK (один раз на сторінку)
const chaindoc = new ChaindocEmbed({
  publicKey: 'pk_live_xxxxxxxxxxxxx',
  environment: 'production',
});

// 2. Отримайте сесію з вашого бекенду
const response = await fetch('/api/signing/create-session', {
  method: 'POST',
  body: JSON.stringify({ documentId, signerEmail }),
});
const { sessionId } = await response.json();

// 3. Відкрийте процес підписування
const instance = chaindoc.openSignatureFlow({
  sessionId,
  
  onReady: () => {
    console.log('Інтерфейс підписування завантажено');
  },
  
  onSuccess: (data) => {
    console.log('Документ підписано:', data.signatureId);
    instance.close();
  },
  
  onError: (error) => {
    console.error('Помилка підписання:', error.code, error.message);
  },
  
  onCancel: () => {
    console.log('Користувач скасував');
    instance.close();
  },
});

Інтеграція з React

components/SignButton.tsx
import { useCallback, useRef, useEffect } from 'react';
import { ChaindocEmbed, EmbedInstance } from '@chaindoc_io/embed-sdk';

function SignButton({ sessionId }: { sessionId: string }) {
  const sdkRef = useRef<ChaindocEmbed | null>(null);
  const instanceRef = useRef<EmbedInstance | null>(null);

  useEffect(() => {
    sdkRef.current = new ChaindocEmbed({
      publicKey: process.env.REACT_APP_CHAINDOC_PUBLIC_KEY!,
    });

    return () => {
      sdkRef.current?.destroy();
    };
  }, []);

  const handleSign = useCallback(() => {
    if (!sdkRef.current) return;

    instanceRef.current = sdkRef.current.openSignatureFlow({
      sessionId,
      onSuccess: (data) => {
        console.log('Підписано!', data.signatureId);
        instanceRef.current?.close();
      },
      onCancel: () => {
        instanceRef.current?.close();
      },
    });
  }, [sessionId]);

  return <button onClick={handleSign}>Підписати документ</button>;
}

Інтеграція з Vue 3

SignButton.vue
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { ChaindocEmbed, type EmbedInstance } from '@chaindoc_io/embed-sdk';

const props = defineProps<{ sessionId: string }>();

let sdk: ChaindocEmbed | null = null;
let instance: EmbedInstance | null = null;

onMounted(() => {
  sdk = new ChaindocEmbed({
    publicKey: import.meta.env.VITE_CHAINDOC_PUBLIC_KEY,
  });
});

onUnmounted(() => {
  sdk?.destroy();
});

function openSignature() {
  if (!sdk) return;
  
  instance = sdk.openSignatureFlow({
    sessionId: props.sessionId,
    onSuccess: (data) => {
      console.log('Підписано!', data.signatureId);
      instance?.close();
    },
    onCancel: () => {
      instance?.close();
    },
  });
}
</script>

<template>
  <button @click="openSignature">Підписати документ</button>
</template>

Вбудований режим

Замість модального вікна вбудуйте інтерфейс підписування прямо на сторінку:

terminal
const instance = chaindoc.openSignatureFlow({
  sessionId,
  mode: 'inline',
  container: document.getElementById('signature-container'),
  
  onSuccess: (data) => {
    console.log('Підписано!');
  },
});

Темізація

Налаштуйте зовнішній вигляд світлими або темними темами:

terminal
const instance = chaindoc.openSignatureFlow({
  sessionId,
  theme: 'dark',
  // ... інші опції
});

// Змініть тему динамічно
instance.changeTheme('light');

Повний приклад робочого процесу

Ось у чому справа: Server SDK на бекенді створює документи та сесії, Embed SDK на фронтенді показує інтерфейс підписування. Чесно кажучи, це найзручніший спосіб інтеграції.

1Бекенд: завантаження документаВикористовуйте Server SDK для завантаження файлу та створення документа

2Бекенд: створення запиту на підписСтворіть запит на підпис з увімкненим вбудованим потоком

3Бекенд: генерація сесіїСтворіть вбудовану сесію для кожного підписанта

4Фронтенд: ініціалізація Embed SDKІніціалізуйте SDK з публічним ключем

5Фронтенд: відкриття процесу підписуванняВідкрийте інтерфейс підписування з ID сесії

6Фронтенд: обробка успіхуОбробіть підписаний документ та оновіть інтерфейс

// server.ts
import { Chaindoc } from '@chaindoc_io/server-sdk';

const chaindoc = new Chaindoc({
  secretKey: process.env.CHAINDOC_SECRET_KEY!,
});

// Завантаження та створення документа
const { media } = await chaindoc.media.upload([pdfFile]);
const doc = await chaindoc.documents.create({
  name: 'Contract',
  description: 'Service agreement',
  media: media[0],
  status: 'published',
  hashtags: ['#contract'],
  meta: [],
});

// Створення запиту на підпис
const sigRequest = await chaindoc.signatures.createRequest({
  versionId: doc.document.versions[0].uuid,
  recipients: [{ email: 'signer@example.com' }],
  deadline: new Date('2024-12-31'),
  embeddedFlow: true,
});

// Створення сесії
const session = await chaindoc.embedded.createSession({
  email: 'signer@example.com',
  metadata: {
    documentId: doc.documentId,
    signatureRequestId: sigRequest.signatureRequest.uuid,
  },
});

// Поверніть sessionId на фронтенд
res.json({ sessionId: session.sessionId });

Кращі практики

  • Ініціалізуйте SDK один раз за життєвий цикл сторінки/компонента
  • Завжди знищуйте екземпляр SDK при розмонтуванні компонента
  • Обробляйте всі callback-події (onSuccess, onError, onCancel)
  • Зберігайте API ключі в змінних середовища
  • Використовуйте TypeScript для кращої типобезпечності
  • Реалізуйте належну обробку помилок з ChaindocError
  • Тестуйте з sandbox ключами перед production розгортанням

Конфігурація середовища

// Backend
const chaindoc = new Chaindoc({
  secretKey: 'sk_live_xxxxx',
});

// Frontend
const embed = new ChaindocEmbed({
  publicKey: 'pk_live_xxxxx',
  environment: 'production',
});

Що робити далі

  • Встановлення — налаштування npm, конфігурація середовища та провайдери під конкретні фреймворки
  • API документація — повний довідник REST ендпоінтів
  • Webhooks — сповіщення про події в реальному часі для вашого бекенду
  • Швидкий старт — надішліть ваш перший підпис за 10 хвилин
  • Безпека — керування API ключами та харднінг production