跳到正文
LICENTIVO / INTEGRATION

C 軟體授權 SDK:CMake 整合教學

為 C11 應用程式加入授權啟用與功能權限檢查。透過完整 CMake 範例學習裝置憑證還原與授權拒絕處理。

C11更新日期

1. 準備產品與授權

原生 C11 應用程式可使用 C SDK 啟用客戶授權,並在呼叫業務回呼前檢查功能權限。先使用裝置綁定授權與不計量的匯出功能,確認基本流程可運作後,再加入用量計數。

裝置額度按目前啟用裝置計算,釋放後返還;一般授權離線仍占用,浮動授權租約到期後自動返還。

  1. 在控制台「產品」複製產品 ID,點擊同一產品的「簽章公鑰」,將每一組金鑰 ID、公鑰填入初始化程式碼,取代 YOUR_PRODUCT_ID、YOUR_KEY_ID 和 YOUR_PUBLIC_KEY。快速接入也可直接複製已填好的程式碼。無需設定檔;SDK 預設連線至 https://www.licentivo.com。
  2. 在「快速整合」建立或選擇產品,在策略中啟用名為 export 的功能,並準備測試授權。

2. 安裝 SDK

先安裝 CMake 3.18 或更新版本。Windows x64 使用 Visual Studio 2022 C++ Build Tools 與相符的 MSVC SDK 套件,並指定 -G "Visual Studio 17 2022" -A x64;Linux x64 使用 C11/C++17 編譯器。將 SDK_PREFIX 替換為安裝程式輸出的 CMake 前綴路徑。 將範例原始碼儲存為 app.c,並將下方 CMakeLists.txt 儲存到同一目錄。

請安裝與編譯器、架構相符的共用版 libcurl 開發套件。Windows MSVC x64 使用者需將 CURL_DIR 替換為包含 CURLConfig.cmake 的目錄,在本機執行時將 curl 的 bin 目錄加入 PATH,發佈應用程式時一併提供所需 DLL;Linux 使用者請安裝發行版提供的共用版 libcurl 開發套件。

Windows · PowerShell
& ([scriptblock]::Create((Invoke-WebRequest 'https://www.licentivo.com/assets/sdk/releases/v0.11.6/install.ps1').Content)) -Language c -Toolchain msvc
Linux · Bash
curl --fail --silent --show-error --location --proto '=https' --proto-redir '=https' 'https://www.licentivo.com/assets/sdk/releases/v0.11.6/install.sh' | bash -s -- c
CMake · CMakeLists.txt
cmake_minimum_required(VERSION 3.18)
project(licensed_app LANGUAGES C)
find_package(Licentivo 0.11.6 REQUIRED)
add_executable(licensed_app app.c)
target_link_libraries(licensed_app PRIVATE Licentivo::C)
set_target_properties(licensed_app PROPERTIES C_STANDARD 11 C_STANDARD_REQUIRED ON)
Windows x64 · PowerShell · MSVC
cmake -S . -B build -G "Visual Studio 17 2022" -A x64 -DCMAKE_PREFIX_PATH="SDK_PREFIX" -DCURL_DIR="CURL_DIR"
if ($LASTEXITCODE -ne 0) { throw 'CMake configure failed. Check the SDK prefix and matching libcurl development package.' }
cmake --build build --config Release --target licensed_app
if ($LASTEXITCODE -ne 0) { throw 'Build failed.' }
Linux x64 · Bash
set -e
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_PREFIX_PATH="SDK_PREFIX"
cmake --build build --target licensed_app

3. 保護一次實際匯出

將 SDK 初始化接到自己軟體的啟動或啟用入口,從啟用視窗讀取客戶授權碼,傳入產品 ID、信任公鑰並保持用戶端存活。將 ln_run_feature 放在實際業務入口,以自己的功能取代匯出範例函式。

C11 · app.c
#include "licentivo.h"
#include <stdio.h>
#include <stdlib.h>

/* BEGIN LICENTIVO PRODUCT */
/* Copy Product ID and all key ID/public key pairs from Console > Products > Signing public keys. */
static const char *PRODUCT_ID = "YOUR_PRODUCT_ID";
static const char *TRUSTED_KEYS_JSON = "{\"YOUR_KEY_ID\":\"YOUR_PUBLIC_KEY\"}";
/* END LICENTIVO PRODUCT */

static const char *setting(const char *name, const char *fallback) {
    const char *value = getenv(name);
    return value && value[0] ? value : fallback;
}

static int export_report(void *context) {
    const char *path = (const char *)context;
    /* Replace this write with your existing, non-metered export operation. */
    FILE *file = fopen(path, "w");
    if (!file) { perror("Export write failed"); return 0; }
    int wrote = fputs("A report generated by the licensed application.\n", file) >= 0;
    int closed = fclose(file) == 0;
    return wrote && closed;
}

int main(void) {
    /* Keep the handle to report startup errors. A GUI supplies the activation input. */
    ln_client *client = ln_init_product(PRODUCT_ID, TRUSTED_KEYS_JSON, setting("LICENTIVO_LICENSE_KEY", ""));
    if (!client) {
        fputs("Startup failed: check the product ID and public keys and supply a license key for first activation.\n", stderr);
        return 2;
    }
    if (!ln_start(client)) {
        fprintf(stderr, "Startup failed: %s\n", ln_last_error(client));
        ln_destroy(client);
        return 2;
    }
    const char *feature = setting("LICENTIVO_FEATURE", "export");
    const char *path = setting("LICENTIVO_OUTPUT", "licensed-report.txt");
    int ok = setting("LICENTIVO_METERED", "")[0] == '1'
        ? ln_run_metered_feature(client, feature, 1, setting("LICENTIVO_OPERATION_ID", ""), export_report, (void *)path)
        : ln_run_feature(client, feature, export_report, (void *)path);
    if (!ok) {
        char *status = ln_feature_status(client, feature);
        fprintf(stderr, "Export denied or failed: %s; %s\n", status ? status : "status unavailable", ln_last_error(client));
        ln_free_string(status);
    }
    if (ok) printf("License OK: %s is available\nExport completed: %s\n", feature, path);
    ln_destroy(client); /* Real app: destroy on shutdown; no Deactivate on normal exit. */
    return ok ? 0 : 2;
}

4. 在應用程式結束時關閉用戶端

本命令列範例執行一次操作後結束。整合桌面應用程式時,在啟動時建立一個用戶端,在匯出按鈕或命令中呼叫功能回呼,直到應用程式結束才關閉用戶端。

首次啟用後,後續啟動可將 LICENTIVO_LICENSE_KEY 留空,在相同使用者及快取位置還原私有裝置憑證。憑證儲存在使用者應用程式資料目錄,不隨安裝套件散布。關閉用戶端會停止心跳並歸還浮動席位;一般結束不應取消裝置綁定。

只有策略允許、簽章授權仍有效時才能離線使用。授權過期或功能遭拒時持續阻止業務操作;功能次數計量需要連線。

保留 ln_client 控制代碼直到結束。ln_start 執行啟動驗證,受保護業務交由 ln_run_feature 或計次介面呼叫。業務回呼成功回傳 1,失敗回傳 0;狀態字串以 ln_free_string 釋放,應用程式結束時呼叫 ln_destroy。

5. 執行並核對結果

  1. 使用允許 export 的有效授權執行,確認產生 licensed-report.txt。
  2. 清空 LICENTIVO_LICENSE_KEY,以相同使用者再次執行,確認可還原已儲存的裝置憑證。
  3. 將 LICENTIVO_FEATURE 改為授權未提供的功能,並將 LICENTIVO_OUTPUT 改為新檔名。程式應提示拒絕,而且不產生新檔案。
  4. 僅在策略允許且簽章授權未到期時測試離線重新啟動。背景更新發生錯誤後,也不能略過失敗的功能檢查。
Windows · PowerShell
$env:LICENTIVO_LICENSE_KEY = 'YOUR_TEST_LICENSE_KEY'
./build/Release/licensed_app.exe
Remove-Item Env:LICENTIVO_LICENSE_KEY
./build/Release/licensed_app.exe
Linux x64 · Bash
LICENTIVO_LICENSE_KEY=YOUR_TEST_LICENSE_KEY ./build/licensed_app
unset LICENTIVO_LICENSE_KEY
./build/licensed_app

常見整合問題

檢查產品 ID、每組金鑰 ID 和公鑰、客戶輸入的授權碼。公鑰屬於產品;客戶授權與本機憑證分別管理。開發測試授權碼及廠商管理 API Key 不隨客戶安裝包發送。

功能遭拒、裝置數已滿或授權過期:在控制台核對授權與策略,並向客戶顯示 SDK 錯誤。授權失敗時不能呼叫匯出函式。

一般功能介面只檢查權限;計次介面負責預留與結算已設定的用量。每項實際業務使用獨立且穩定的操作編號;中斷還原前先核對持久化業務結果。

CMake 找不到 Licentivo 時,以安裝器輸出的 CMake prefix 取代設定命令中的 SDK_PREFIX。編譯器、架構與 libcurl 必須和原生套件相符。