Hướng dẫn setup SumSub – KYC & KYB

3 min read

Hướng dẫn tích hợp SumSub (KYC & KYB) vào ứng dụng Node.js Express

1. Chuẩn bị

Trước khi bắt đầu, hãy đảm bảo bạn đã cài đặt các thư viện cần thiết:

2. Cấu hình Môi trường

Tạo file .env để lưu trữ các thông tin cấu hình từ SumSub. Lưu ý rằng SumSub có thể sử dụng các App Token khác nhau cho flow KYC và KYB tùy thuộc vào cách bạn setup trên dashboard.

Để lấy token Truy cập vào dashboard và tạo theo ảnh:

SUMSUB_BASE_URL=https://api.sumsub.com
SUMSUB_TOKEN=t_kyc_...
SUMSUB_SECRET_KEY=s_kyc_...

3. Code mẫu (ExpressJS)

Dưới đây là ví dụ triển khai đầy đủ bao gồm việc tạo chữ ký bảo mật (HMAC SHA256) và các API endpoint cơ bản. Theo hướng dẫn từ SumSub

Tạo một file service để xử lý logic gọi API đến SumSub.

const axios = require('axios');
const crypto = require('crypto');
require('dotenv').config();

const SUMSUB_BASE_URL = process.env.SUMSUB_BASE_URL

// Hàm lấy cấu hình 
const getConfig = () => {
  return {
    token: process.env.SUMSUB_TOKEN,
    secretKey: process.env.SUMSUB_SECRET_KEY,
  };
};

// Hàm tạo chữ ký bảo mật (Signature)
const generateSignature = (method, url, ts, secretKey, body) => {
  const bodyString = body ? JSON.stringify(body) : '';
  const dataToSign = ts + method + url + bodyString;
  return crypto
    .createHmac('sha256', secretKey)
    .update(dataToSign)
    .digest('hex');
};

// Hàm gửi request đến SumSub
const sendRequest = async (method, url, body = null) => {
  const { token, secretKey } = getConfig(isKyb);
  const timestamp = Math.floor(Date.now() / 1000);
  const fullUrl = `${SUMSUB_BASE_URL}${url}`;

  const signature = generateSignature(method, url, timestamp, secretKey, body);

  const config = {
    method,
    url: fullUrl,
    headers: {
      'X-App-Token': token,
      'X-App-Access-Sig': signature,
      'X-App-Access-Ts': timestamp.toString(),
      'Content-Type': 'application/json',
    },
    data: body,
  };

  try {
    const response = await axios(config);
    return response.data;
  } catch (error) {
    console.error(
      `SumSub API Error [${method} ${url}]:`,
      error.response?.data || error.message,
    );
    throw error;
  }
};

const createApplicant = async (applicantData, levelName) => {
    const url = `/resources/applicants?levelName=${levelName}`;
    const body = { ...applicantData, type };

    return await sendRequest('POST', url, body);
  }

const  generateAccessToken = async (externalUserId, levelName) => {
    const url = '/resources/accessTokens/sdk';
    const body = {
      userId: externalUserId,
      levelName: levelName,
      ttlInSecs: 1800,
    };
    return await sendRequest('POST', url, body);
  }

const getApplicantStatus = async (applicantId) => {
    const url = `/resources/applicants/${applicantId}/one`;
    return await sendRequest('GET', url);
}

Một số endpoint cần thiết – Tạo một file app.js

const express = require('express');
const sumsubService = require('./sumsub.service');
const app = express();

app.use(express.json());

// Endpoint tạo Access Token cho SDK (Frontend dùng token này để init WebSDK)
app.post('/api/sumsub/access-token', async (req, res) => {
  try {
    const { userId, levelName } = req.body;

    const data = await sumsubService.generateAccessToken(
      userId,
      levelName,
    );
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: 'Failed to generate access token' });
  }
});

// Endpoint tạo Applicant (Optional - thường SDK sẽ tự tạo, nhưng backend có thể tạo trước)
app.post('/api/sumsub/applicants', async (req, res) => {
  try {
    const { externalUserId, levelName, info } = req.body;

    const applicantData = {
      externalUserId,
      info, // Thông tin user (firstName, lastName, ...)
    };

    const data = await sumsubService.createApplicant(
      applicantData,
      levelName,
    );
    res.json(data);
  } catch (error) {
    res.status(500).json({ error: 'Failed to create applicant' });
  }
});

// Endpoint nhận Webhook từ SumSub (Cần verify signature - chưa bao gồm trong ví dụ đơn giản này)
app.post('/api/sumsub/webhook', (req, res) => {
  console.log('Webhook received:', req.body);
  // Xử lý logic khi user hoàn thành KYC/KYB
  // ...
  res.sendStatus(200);
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server is running on port ${PORT}`);
});

Để test webhook local, chúng ta có thể dùng dịch vụ bên thứ ba

https://webhook.site/#!/view/ba7c5e1c-af07-4907-9840-7dfda57578b1

Sau khi nhận được webhook có thể dùng Postman để test local

4. Lưu ý quan trọng

Với KYC Flow tại môi trường sandbox kết quả luôn trả về true

Đối với KYB tại môi trường Sandbox kết quả sẽ luôn hiển thị Pending

Để test data với webhook thực tế đối với KYB. Sumsub cung cấp cho chúng ta API để simulate kết quả

https://docs.sumsub.com/reference/simulate-review-response-in-sandbox

Bổ sung thêm vào sumsub service

async function simulateReviewResponse(
    applicantId: string,
    reviewData: SimulateReviewResponseDto,
  ) {
    try {
      logger.debug(
        `Simulating review response for applicant ${applicantId}: ${JSON.stringify(reviewData)}`,
      );

      const response = await this.sendRequest(
        'POST',
        `/resources/applicants/${applicantId}/status/testCompleted`,
        reviewData,
      );

      logger.debug(
        `Successfully simulated review response for applicant ${applicantId}`,
      );

      return { data: response.data, status: response.status };
    } catch (error) {
      logger.error(
        `Failed to simulate review response for applicant ${applicantId}: ${error.message}`,
      );
      if (error.response) {
        throw new HttpException(
          `SumSub API error: ${error.response.data?.description || error.message}`,
          error.response.status,
        );
      }
      throw error;
    }
  }

Với SimulateReviewResponseDto

enum ReviewRejectType {
  RETRY = 'RETRY',
  FINAL = 'FINAL',
}

export class SimulateReviewResponseDto {
  reviewAnswer: SumSubResult;
}


Hy vọng hướng dẫn và đoạn code mẫu trên sẽ giúp các bạn khởi tạo nhanh chóng và dễ dàng tích hợp SumSub vào dự án của mình, tiết kiệm thời gian nghiên cứu tài liệu ban đầu. Chúc các bạn thành công!

Avatar photo

Leave a Reply

Your email address will not be published. Required fields are marked *