Giao thức CLV1 đã công khaiĐọc đặc tả
Mục lục thư viện

Thư viện tài liệuBắt đầu theo ngôn ngữ

Bắt đầu với C++

Bài này đưa một chương trình C++ từ con số không tới lần kích hoạt license đầu tiên, rồi tới bản build cho khách: cài SDK và ba thư viện nó cần, vài dòng mã, chạy thử, xem kết quả trên dashboard, xử lý lỗi và phát hành.

7 phút đọc

Cần có

  • Trình biên dịch C++17 và CMake 3.21 trở lên. Trên Windows, Visual Studio 2022 có sẵn cả CMake lẫn vcpkg.
  • Ba thư viện: libsodium, libcurl và nlohmann-json. Windows lấy qua vcpkg; Debian, Ubuntu cài bằng sudo apt install g++ cmake pkg-config libsodium-dev libcurl4-openssl-dev nlohmann-json3-dev. SDK chưa được build thử trên macOS.
  • Một ứng dụng trên dashboard. Trang Tích hợp › Kết nối phần mềm của nó có địa chỉ API, App ID, khoá công khai và nút Tạo key thử nghiệm. Địa chỉ API kết thúc bằng /api, không có /v1: https://<trang ClavisAUH của bạn>/api.

1. Cài SDK

Tải clavisauh-cpp-0.1.0.zip ở trang Tải về, kiểm SHA-256 như trang đó hướng dẫn, rồi giải nén: bạn có thư mục clavisauh-cpp-0.1.0 với mã nguồn SDK. SDK được build cùng dự án của bạn bằng add_subdirectory. Một CMakeLists.txt cho dự án của bạn, với thư mục vừa giải nén nằm cạnh (CLAVISAUH_DIR cho phép đặt ở chỗ khác):

cmake_minimum_required(VERSION 3.21)
project(your_app LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 17)

set(CLAVISAUH_DIR "${CMAKE_CURRENT_SOURCE_DIR}/clavisauh-cpp-0.1.0" CACHE PATH "The ClavisAUH C++ SDK")
add_subdirectory("${CLAVISAUH_DIR}" clavisauh)

add_executable(your_app main.cpp)
target_link_libraries(your_app PRIVATE clavisauh::clavisauh)
if(MSVC)
  target_compile_options(your_app PRIVATE /utf-8)
endif()

Trên Windows, khai báo ba thư viện trong vcpkg.json cạnh CMakeLists.txt, vcpkg tự tải và build chúng ở lần cấu hình đầu (baseline là phiên bản vcpkg SDK đã được thử):

{
  "dependencies": ["libsodium", "curl", "nlohmann-json"],
  "builtin-baseline": "9eec002df1cd109f8f104cd966a763daf9751489"
}

Cấu hình và build, với đường dẫn tới thư mục SDK vừa giải nén:

# Windows, trong Developer PowerShell for VS 2022 (có sẵn cmake và VCPKG_ROOT)
cmake -B build "-DCMAKE_TOOLCHAIN_FILE=$env:VCPKG_ROOT/scripts/buildsystems/vcpkg.cmake" -DCLAVISAUH_DIR=C:/duong-dan/clavisauh-cpp-0.1.0
cmake --build build --config Release
# Linux
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCLAVISAUH_DIR=/duong-dan/clavisauh-cpp-0.1.0
cmake --build build

SDK chưa có trên vcpkg hay Conan; khi có, bài này sẽ ghi thêm cách cài từ đó.

2. Mã tối thiểu

Các khối dưới đây là từng phần của một file; file đầy đủ, kèm hàm phụ, ở bước 3.

Tạo client một lần khi phần mềm khởi động. Địa chỉ API, App ID và khoá công khai là ba giá trị ở trang Kết nối phần mềm: mẫu đọc chúng từ biến môi trường, phần mềm của bạn thì ghi thẳng vào mã. Khoá thiết bị nằm trong một file (trên Windows được niêm phong bằng DPAPI); phiên và token offline gắn với khoá này, còn suất trên license đi theo các định danh đã băm của máy. Mẫu đặt phần này trong settings.hpp để năm kịch bản dùng chung, cùng các hàm phụ đọc cài đặt và báo lỗi:

// What every scenario reads from the environment, and the client they all start from.
#pragma once

#include <cstdlib>
#include <iostream>
#include <optional>
#include <stdexcept>
#include <string>

#include "clavisauh/clavisauh.hpp"

namespace sample {

inline std::optional<std::string> optional(const char* name) {
  const char* value = std::getenv(name);
  return value ? std::optional<std::string>(value) : std::nullopt;
}

inline std::string env(const char* name) {
  auto value = optional(name);
  if (!value) throw std::runtime_error(std::string(name) + " is not set");
  return *value;
}

inline std::string lang() { return optional("CLAVIS_LANG").value_or("en"); }
inline std::string state() { return optional("CLAVIS_STATE_DIR").value_or(".clavis"); }

inline clavisauh::Client make_client(std::optional<std::string> app_version = std::nullopt) {
  clavisauh::Options options;
  options.base_url = env("CLAVIS_BASE_URL");
  options.app_id = env("CLAVIS_APP_ID");
  options.app_public_keys = {env("CLAVIS_APP_KEY")};
  options.device = clavisauh::default_device();
  // The same key every run: sessions and offline tokens stay with this machine.
  options.device_key = clavisauh::load_or_create_device_key(state() + "/device.key");
  options.app_version = std::move(app_version);
  return clavisauh::Client(options);
}

// The sentence for the person using the software, then a line for the CI to read.
inline int fail(const clavisauh::ClavisError& e) {
  std::cout << e.user_message(lang()) << "\n" << "FAIL " << e.code << "\n";
  return 1;
}

}  // namespace sample

Kích hoạt key của khách. Khi không có mạng, token offline lưu lần trước giữ phần mềm chạy tiếp:

std::optional<clavisauh::json> grant;
try {
  client.init();
  grant = client.activate(sample::env("CLAVIS_LICENSE"));
} catch (const clavisauh::ClavisError& e) {
  // No answer (network_error, timeout...): a token saved last time keeps the software working.
  std::ifstream file(saved);
  std::stringstream token;
  token << file.rdbuf();
  if (!e.retryable() || !file || !client.verify_offline(token.str())) return sample::fail(e);
  std::cout << "Offline: using the license saved on this machine\n";
}

Khoá công khai chỉ dùng để kiểm chữ ký, nhúng vào phần mềm là an toàn. Đừng bao giờ nhúng một khoá bí mật nào.

3. Chạy thử

Cách nhanh nhất là dự án mẫu, đã nối sẵn SDK và cài đặt của ứng dụng:

  1. Ở trang Kết nối phần mềm, chọn C++, bấm Tạo key thử nghiệm rồi Tải dự án mẫu (.zip), và giải nén.
  2. Chạy ./run.sh <key thử nghiệm> trên Linux, hoặc .\run.cmd <key thử nghiệm> trong Developer PowerShell for VS 2022 trên Windows. Lần đầu trên Windows, vcpkg tải và build ba thư viện, mất vài phút.

Mẫu in License active until <ngày>, rồi OK k1 active ở dòng cuối. Chạy lại trên cùng máy vẫn thành công và không tốn thêm suất: server nhận ra máy qua các định danh đã băm (Thiết bị, HWID và chuyển máy). Khoá thiết bị, dùng để ký yêu cầu, nằm trong thư mục .clavis dưới thư mục bạn chạy lệnh (hoặc trong CLAVIS_STATE_DIR). Container tạo mới cho mỗi lần chạy thì lần nào cũng giống một máy mới, xem Câu hỏi thường gặp. Muốn chạy trong dự án của bạn: lưu nguyên K1 dưới đây thành main.cpp, settings.hpp để cạnh, dùng CMakeLists.txt ở trên, build, đặt bốn cài đặt CLAVIS_* (CLAVIS_BASE_URL, CLAVIS_APP_ID, CLAVIS_APP_KEY là khoá công khai, CLAVIS_LICENSE) rồi chạy your_app. Toàn bộ kịch bản K1:

// K1 · License key only: activate on this machine, keep the session alive, work offline for a while.
#include <fstream>
#include <sstream>

#include "settings.hpp"

int main() {
  auto client = sample::make_client("1.0.0");
  const std::string saved = sample::state() + "/offline.token";

  std::optional<clavisauh::json> grant;
  try {
    client.init();
    grant = client.activate(sample::env("CLAVIS_LICENSE"));
  } catch (const clavisauh::ClavisError& e) {
    // No answer (network_error, timeout...): a token saved last time keeps the software working.
    std::ifstream file(saved);
    std::stringstream token;
    token << file.rdbuf();
    if (!e.retryable() || !file || !client.verify_offline(token.str())) return sample::fail(e);
    std::cout << "Offline: using the license saved on this machine\n";
  }

  if (grant) {
    const auto& license = (*grant)["license"];
    std::cout << "License " << license["status"].get<std::string>() << " until "
              << (license["expiresAt"].is_string() ? license["expiresAt"].get<std::string>() : "forever") << "\n";
    // Every few minutes while the software runs; sessions end after an hour without one.
    client.heartbeat();
    if (client.offline_token()) std::ofstream(saved) << *client.offline_token();
    client.logout();
  }
  std::cout << "OK k1 " << (grant ? (*grant)["license"]["status"].get<std::string>() : "offline") << "\n";
  return 0;
}

4. Thấy trên dashboard

  • Tích hợp › Kết nối phần mềm: bước 4 chuyển sang Đã kết nối, kèm cpp/0.1.0 và hệ điều hành của máy.
  • Phát hành & bản quyền › License: key chuyển từ Chưa dùng sang Đang dùng.
  • Người dùng cuối › Thiết bị & phiên: máy vừa chạy, cùng phiên nó vừa mở.

5. Xử lý lỗi

Mọi lần bị từ chối là một clavisauh::ClavisError có ba thứ bạn cần:

  • e.code: mã trong bảng Mã lỗi, ví dụ invalid_credentials hay device_limit.
  • e.user_message("vi"): câu cho người dùng phần mềm của bạn, tiếng Việt hoặc "en", hiện thẳng được.
  • e.retryable(): true khi không nhận được câu trả lời (mất mạng, quá chậm, máy chủ bận); để một lúc rồi thử lại có thể thành công.

Câu trả lời không mang đúng chữ ký của ứng dụng bị từ chối bằng clavisauh::ClavisVerificationError (cũng là một ClavisError), với mã unsigned_response, invalid_response_signature, unknown_key hoặc stale_response. Hãy coi đó như không có câu trả lời; thường là địa chỉ API hoặc khoá công khai trong phần mềm bị sai.

Khi phần mềm đang chạy, gửi heartbeat đều đặn để giữ phiên, khoảng mỗi 5 tới 30 phút: phiên hết sau 60 phút không có heartbeat.

// Every few minutes while the software runs; sessions end after an hour without one.
client.heartbeat();

Lưu token offline mới nhất, để lần sau không có mạng vẫn mở được:

if (client.offline_token()) std::ofstream(saved) << *client.offline_token();

Mọi gói đều có token offline, mặc định dùng được 7 ngày; Premium tự chọn thời hạn, còn Chế độ chỉ online thì tắt hẳn. Xem License offline. Cần xem từng lượt gọi khi dò lỗi thì gán một hàm cho options.debug: SDK gửi mỗi lượt gọi và kết quả cho hàm đó, key chỉ hiện bốn ký tự đầu và cuối, mật khẩu không bao giờ hiện.

6. Đóng gói và phát hành

  • Ghi địa chỉ API, App ID và khoá công khai vào mã hoặc vào file cấu hình đi cùng bản build. Máy khách không cần biến môi trường nào.
  • Đặt thư mục trạng thái (khoá thiết bị, token offline) ở nơi người dùng ghi được, riêng cho từng người dùng: %APPDATA%\TênPhầnMềm trên Windows, ~/.config/ten-phan-mem trên Linux. Đừng đặt trong thư mục cài đặt.
  • Truyền options.app_version đúng phiên bản bạn phát hành: server dùng nó để chặn bản quá cũ và báo có bản mới, xem Bản phát hành có ký và cập nhật.
  • Windows: muốn một file .exe không cần cài gì thêm, cấu hình với -DVCPKG_TARGET_TRIPLET=x64-windows-static và đặt CMAKE_MSVC_RUNTIME_LIBRARY thành MultiThreaded, như công cụ dòng lệnh clavis của ClavisAUH. Với triplet mặc định, phát hành kèm các DLL vcpkg chép cạnh file chạy và bộ Visual C++ Redistributable.
  • Linux: máy khách cần libsodium và libcurl của hệ thống (Debian, Ubuntu: apt install libsodium23 libcurl4).
  • Chạy thử bản phát hành tới OK k1 active trên một máy sạch trước khi phát hành.
  • Trước khi bán, bật Đã phát hành công khai ở Tích hợp › Cài đặt ứng dụng. Mọi key TEST ngừng hoạt động, nên key thử nào lỡ lọt ra ngoài cũng không dùng được nữa.

Câu hỏi thường gặp

Phần mềm có cần mạng mỗi lần mở không? Kích hoạt và heartbeat cần mạng. Khi mất mạng, token đã lưu giữ phần mềm chạy tiếp, mặc định 7 ngày hoặc theo thời hạn chọn trên Premium, được kiểm ngay trên máy mà không cần server.

Dùng với Qt hay MFC được không? SDK là C++17 thuần, không phụ thuộc thư viện giao diện nào; gọi được từ bất kỳ dự án C++17 nào build bằng CMake. Mỗi lượt gọi chờ mạng, nên đừng gọi trên luồng giao diện.

Khi nào dùng thư viện C thay cho SDK này? Thư viện C là chính SDK này bọc sau các hàm C, dành cho ngôn ngữ khác (Delphi, Lua, Python ctypes…) hoặc khi bạn chỉ muốn một file clavis.dll có sẵn. Dự án C++ dùng thẳng SDK.

Giới hạn tính năng theo gói license thế nào? client.has("ten_tinh_nang") cho biết license có quyền tính năng đó không; tạo quyền trong Gói license và quyền tính năng.

Khách cài lại hệ điều hành hay đổi máy thì sao? Cài lại trên cùng máy, server vẫn nhận ra máy nhờ dấu nhận diện phần cứng đã băm. Máy mới chiếm một suất mới; hết suất thì khách nhận device_limit, và bạn Đặt lại thiết bị trong trang License. Xem Thiết bị, HWID và chuyển máy.

Liên quan

Bạn cần giúp gì?

Câu hỏi thường gặp

ClavisAUH là gì?

Dịch vụ bản quyền và xác thực cho phần mềm desktop: license key, khoá thiết bị, đăng nhập người dùng và phản hồi có chữ ký. Tất cả quản lý trên một dashboard

Vì sao kẻ crack không làm giả được server?

SDK chỉ tin câu trả lời ký bằng khoá bí mật của ứng dụng. Khoá đó không bao giờ rời server của chúng tôi, nên server giả không ký được và bị từ chối

Trong file chạy của tôi có gì?

Mã ứng dụng và khoá công khai. Không có bí mật nào, vì mỗi thiết bị tự tạo cặp khoá riêng ở lần chạy đầu

Có chạy được khi offline không?

Có. Mọi gói đều có token offline có chữ ký dùng được 7 ngày, ứng dụng tự kiểm tra tại máy. Premium cho bạn chọn bao lâu. License đã thu hồi vẫn có thể chạy offline trong khoảng đó, trừ khi Chế độ chỉ online đang bật

Hỗ trợ những ngôn ngữ nào?

Hiện có JavaScript và TypeScript. Tiếp theo là C++, C# và Python, cùng một giao thức công khai

Gói Basic có miễn phí thật không?

Có. Không giới hạn thời gian, không cần thẻ. Cần nhiều hơn thì lên Premium

Liên hệ