跳到正文
開發文件快速開始

把授權接進你的軟體

用約 15 分鐘完成一個受授權保護的匯出功能:取得設定、執行示例、串接自己的應用程式,再驗證權限拒絕。前提是已安裝對應語言的開發環境。

SDK 負責請求、裝置識別、驗證簽章、憑證儲存、快取和心跳。你提供客戶輸入的授權碼和業務函數,無需自己組裝 HTTP 請求或儲存 activation_id。

  1. 準備串接包控制臺生成產品設定
  2. 生成匯出檔案檢查授權與業務結果
  3. 接到軟體啟動、業務入口、退出

1. 在控制臺準備串接包

打開 快速開始,填寫軟體名稱,選擇綁定裝置或浮動席位,點擊“建立產品,下一步”。系統會準備產品、策略、測試授權、公鑰和 1.0.0 版本。選擇語言,下載并解壓已設定的串接包。

包里有兩個設定:sdk-demo.json 含測試授權碼,留給你自己測試;product.json 只含產品設定和公鑰,可以隨軟體分發。

首次串接建議選擇綁定裝置。預設示例有 export 功能,先不設定次數限制;已有產品需要在策略和授權中允許同名功能。

2. 檢查環境并匯出一個檔案

在解壓根目錄打開終端,保留 product.json、sdk-demo.json、start.ps1、start.sh 和 sdk 目錄。選擇語言和系統后執行下列命令;環境檢查不傳送啟用請求。

在解壓目錄執行

成功標志:退出碼為 0,出現下列輸出,并生成 licensed-report.txt。去掉測試參數后再執行,SDK 會恢復本機憑證,綁定裝置不會重復占用名額。

成功輸出
License OK: export is available
Export completed: licensed-report.txt

缺少工具時先安裝對應開發環境;C/C++ 還需 libcurl 開發檔案。Windows MinGW 可傳入 -CurlRoot。瀏覽器接受證書警告不會讓 SDK 信任證書,測試伺服器的證書也必須被執行環境信任。

3. 接到客戶的軟體里

在現有項目目錄執行官網安裝器。九種語言共用版本 0.10.0,安裝器先校驗 SHA-256,再安裝依賴或解壓構建包。僅將 product.json 加入應用程式資源。

加入現有項目

使用已下載的串接包離線安裝

將 SDK_ROOT 換成解壓目錄的絕對路徑。

本機源碼依賴

當前語言的可執行檔案:。複製其業務入口到自己的項目,查看完整程式碼 →

應用程式中的位置要做的事
啟動或啟用視窗傳入 product.json 和客戶授權碼。啟用成功后再次啟動傳空字串;界面應用程式在管理後台任務中完成首次聯網啟用。
匯出按鈕、快捷鍵、菜單或命令把自己的匯出函數傳給 RunFeature。SDK 先檢查權限,允許時才呼叫業務函數;保持同一個 client 存活。
應用程式退出關閉 client,停止心跳;浮動席位歸還,綁定裝置登記保留。

4. 驗證沒有權限時無法匯出

確認策略未包含 licentivo_denied_probe,然后執行以下命令。應返回非零退出碼,且不建立 denied-report.txt;請使用尚不存在的輸出檔案檢查。

權限拒絕測試

5. 需要按次數收費時

將業務函數傳給 RunMeteredFeature,并提供穩定的任務編號。SDK 自動預留次數、成功后確認、失敗時取消,并記錄待確認任務。查看計次串接和重試 →

測試設定和客戶授權要分開。

正式安裝包只分發所需 SDK 和 product.json。每位客戶使用自己的授權碼;不分發 sdk-demo.json、授權快取、裝置憑證或廠商管理 API Key。cache_path 留空時,SDK 自動選擇當前使用者的私有目錄。

先分清這三個名字

姓名誰使用做什么
授權金鑰 lv_lic_…購買軟體的客戶在自己的軟體里啟用。換機臨時碼 lv_tmp_… 也填在同一位置。
產品 IDSDK / 軟體開發者告訴伺服器正在驗證哪個產品,可隨軟體分發。
管理 API Key廠商自己的伺服器自動簽發、續期和管理授權。客戶軟體的啟用不需要它。

心跳間隔與允許離線時長在 授權策略分別設定;授權有效期從首次啟用開始。功能次數、浮動席位和離線檔案啟用可以在基礎串接完成后添加。

暫時不註冊也可以打開 線上體驗查看請求與返回。需要自動簽發授權時,繼續讀 管理 API Key中查看。

客戶端 SDK

將業務函數交給 SDK:普通功能用 RunFeature,計次功能用 RunMeteredFeature。請求、驗證簽章、快取和心跳由 SDK 處理。

執行前準備

在控制臺 快速開始下載已設定的串接包。演示使用私有的 sdk-demo.json;放進實際軟體時使用 product.json,客戶授權碼作為啟動參數傳入。下方“下載 SDK”是通用源碼包,尚未填寫你的產品設定。

設定檔的每一項是什么?
product.json · 共用產品設定
{
  "base_url": "https://www.licentivo.com",
  "product_id": "PRODUCT_UUID",
  "license_key": "",
  "device_name": "Customer app",
  "app_version": "1.0.0",
  "trusted_keys": {
    "SIGNING_KEY_UUID": "BASE64URL_PUBLIC_KEY"
  },
  "timeout_seconds": 10,
  "allow_http": false
}
base_url
授權伺服器位址,只填網域和端口,不加 /api/v1。本機測試可用 https://127.0.0.1:8080中查看。
product_id
這個軟體對應的產品 ID,必須與授權所屬產品一致。
license_key
product.json 中留空。用 OpenWithLicense 的參數傳入客戶自己的 lv_lic_… 或換機的 lv_tmp_…;不會修改共用設定檔。
app_version
當前軟體版本,格式為主版本.次版本.補丁,例如 1.0.0。開啟版本范圍或維護期后必須填寫;改版本后要重新聯網驗證。
device_name
控制臺顯示的裝置名稱,方便你識別裝置;不用于決定裝置身份。
trusted_keys
產品的簽章金鑰 ID 和公鑰。正式發布時隨你的應用程式或經過認證的更新分發,不能直接信任陌生回應提供的公鑰。
cache_path
可省略或留空,自動使用當前使用者的私有目錄;也可指定應用程式自己的私有檔案位置。
timeout_seconds
單次請求超時秒數,預設 10,可設 1–120;臨時網路錯誤最多嘗試兩次。
proxy_url
可選代理位址。Java 使用 HTTP 代理;Node.js 設定代理時需要安裝 undici。證書校驗仍保持開啟。
allow_http
正式環境保持 false,使用 HTTPS。本機測試可設為 true,但只允許 localhost 或本機回環位址。

不需要手填 device_id,SDK 會讀取本機身份。product.json 中的產品公鑰可以分發;客戶授權碼與 sdk-demo.json 要儲存在私有位置。

選擇你的語言

以下程式碼與下載包中的檔案一致,會實際生成匯出檔案。示例以環境變量代替啟用輸入框;串接時換成自己的界面輸入,并保留應用程式生命周期內的 client。

統一安裝與版本發布

選擇語言和系統,在自己的項目目錄執行。SDK 由 Licentivo 官網發布,無需 GitHub 帳號。GitHub 與公共包倉庫發布仍暫緩。

官網安裝命令

版本: · 版本安裝包 · SHA-256 校驗檔案 · 發布清單

Windows x64 和 Linux x64 已驗收。macOS 與 ARM64 尚待實機驗證;C/C++ 預編譯包按平臺和編譯器區分。

安裝之后如何引用?
語言項目串接
Goimport licentivo "github.com/spf86/licentivo-sdk"
Javaimplementation(files('.licentivo-sdk/java/v0.10.0/licentivo-sdk-0.10.0.jar'))
C / C++find_package(Licentivo 0.10 REQUIRED) · target_link_libraries(MyApp PRIVATE Licentivo::C) / Licentivo::CPP
C#using Licentivo;
Pythonfrom licentivo import Client
Node.jsimport {Client} from '@licentivo/sdk'
Rustuse licentivo::Client;
Rubyrequire 'licentivo'

Go、Rust 和 C/C++ 使用的 .licentivo-sdk 目錄應保留在項目中。更新時指定新版本,不會覆蓋 product.json 或客戶授權快取。

用 SDK 執行受保護的業務,退出時關閉 client。

Go · 客戶端授權
正在加载代码…

按快速開始的腳本執行此檔案 →

使用其他客戶授權碼,或執行完整協議演示

在終端中設定環境變量,再執行快速開始的腳本,不加測試參數。授權碼不是管理 API Key。

當前終端的環境變量

執行成功會輸出 License OK: export is available。將它放到正式應用程式時,不必讓客戶設定環境變量;由啟用視窗取得輸入;SDK 自動儲存本機憑證。不要把客戶授權碼放進日志。

執行下載包里的完整演示

解壓 ZIP,保留其中的目錄結構,把 sdk-demo.json 放到解壓后的根目錄。選擇執行系統,在這個目錄打開終端,執行:

終端命令

演示結束時會釋放裝置。

此處的完整協議演示用于進階排查。首次串接先執行快速開始里的 start.ps1 或 start.sh;這些串接示例在日常退出時保留綁定裝置登記。

執行一個真正的應用程式示例

示例包含啟用輸入、授權狀態、匯出檔案和主動解除綁定。Java、Python、C# 有視窗,其余語言使用終端菜單。首次輸入授權碼,以后留空恢復。

應用程式示例 · 當前語言和系統

匯出成功會生成 licensed-report.txt。按次數匯出前,請在策略里設定 export 的次數規則。

視窗和菜單演示展示了底層預留介面。新串接建議用下方源碼中的 RunMeteredFeature,九種語言均會儲存待確認記錄;業務執行中途崩潰時,仍需從自己的業務結果核對是否完成。

如何顯示授權狀態?

Status 和 FeatureStatus 只讀本機狀態,不傳送請求,也不等待管理後台網路驗證。狀態變化通知可以用來刷新界面。

狀態含義
active最近一次聯網驗證成功,本機授權有效。
offline_valid本機簽章仍有效,啟動后的聯網確認尚未成功。
verification_required沒有可用簽章,需要啟用或聯網刷新。
expired / revoked / released伺服器明確拒絕授權,應停止受保護操作。
quota_exhausted這次功能計次超出額度,其他已授權功能仍可用。

allowed 表示本機授權是否有效;按次數的功能仍需請求額度。lease_valid_until 是簽章快取截止時間,不是授權最終到期時間。code、request_id 和 retryable 分別說明錯誤、日志編號和能否重試。

各語言的方法名、通知回調和安裝包用法見下載包的 sdk/README.md。官網提供版本安裝包與統一安裝器,公共包倉庫發布仍暫緩。

接到實際應用程式時,放在哪些位置?

應用程式中的位置要做的事
啟動或使用者輸入授權碼后呼叫 OpenWithLicense(C++ 使用構造函數和 Start),SDK 完成啟用并按策略開啟心跳
使用付費功能前呼叫 RunFeature,把業務函數交給 SDK;計次功能使用 RunMeteredFeature
應用程式執行期間保持 client 存活,SDK 按策略中的間隔傳送心跳
應用程式退出時Close / Dispose / Destroy,停止心跳;浮動授權歸還席位,綁定裝置授權保留裝置登記
使用者主動解除綁定時呼叫 Deactivate,再關閉 client

表中的名稱表示對應操作,不同語言的實際方法名以示例為準。心跳、離線快取和聯網刷新的詳細行為見 心跳與離線設定中查看。

管理 API Key

當你希望自己的訂單系統自動簽發授權,或從伺服器讀取授權資料時,使用管理 API Key。它代表你的廠商工作區。

客戶端需要的是哪一種金鑰?

憑證交給誰用來做什么
lv_api_…
管理 API Key
你自己的伺服器建立產品、策略和授權,查看裝置、用量和稽核記錄
lv_lic_…
授權金鑰
客戶的軟體啟用、驗證、傳送心跳和釋放當前裝置
產品公鑰隨客戶端發布檢查伺服器返回的授權簽章是否有效

如果你只串接客戶軟體的授權驗證,使用授權金鑰就夠了。管理 API Key 可以操作整個工作區,不能放進客戶軟體或公開網頁。

建立一個 Key

  1. 用工作區 Owner(所有者)帳號登入,打開 API Key,點擊“建立 API Key”。
  2. 名稱填它的用途,例如“訂單系統”。只查詢時選“只讀”;要建立或修改授權時選“讀寫”。有效期可設為 1–365 天。
  3. 儲存后立即複製完整 Key,它只顯示一次。把它放在你伺服器的私有設定或環境變量中。

傳送第一個管理請求

示例讀取產品清單。將 LICENTIVO_URL 設定為授權伺服器位址,將 LICENTIVO_API_KEY 設定為剛建立的完整 Key,再執行:

curl
curl "$LICENTIVO_URL/api/v1/products?limit=25" \
  -H "Authorization: Bearer $LICENTIVO_API_KEY"

這是 Bash / macOS / Linux 的寫法。Windows PowerShell 請使用 curl.exe,環境變量用 $env:LICENTIVO_URL 和 $env:LICENTIVO_API_KEY。九種語言的完整請求程式碼也放在 SDK 頁的“服務端管理 API Key”選項中查看。

成功時返回 HTTP 200,正文包含 data.items。使用 Bearer Key 的管理請求不需要登入 Cookie 或 CSRF Token。

權限和失效處理

只讀 Key 能查看資源;讀寫 Key 還能建立和修改產品、策略、授權。管理 Key 不用于帳號、團隊、系統設定或收款操作,這些操作需要相應帳號登入。

Key 泄漏或不再使用時,在控制臺撤銷;需要更換時點擊“輪換”。舊 Key 會立即失效,隨后更新你伺服器上的設定。

方案中的 API 呼叫額度統計啟用、驗證、心跳和釋放。這里的管理請求不計入這項額度。

產品與授權 API

把下單后的簽發工作接到你自己的伺服器:先建立產品和策略,再為每位客戶建立授權。前兩項通常只需設定一次。

先在控制臺建立有寫權限的 管理 API Key。以下示例使用 Authorization: Bearer 你的管理Key;這個 Key 保留在廠商伺服器中。

建立成功后儲存哪些值?

產品回應的 data.id 用作 product_id;策略回應的 data.id 用作 policy_id。簽發授權后儲存 data.id 和 data.key。完整授權金鑰只在簽發時返回一次,清單里的 key_prefix 不能用來啟用。

尚未啟用的限期授權,expires_at 和 first_activated_at 都是 null。首次成功啟用后才開始計時;換機不會重新獲得有效天數。

后續管理

方法與路徑(省略 /api/v1)用途與請求正文
GET /products查產品清單。回應 data.items 是記錄數組,data.total 是總數。
GET /licenses/{id}查詢授權詳情和首次啟用、到期時間。
POST /licenses/{id}/renew續期,例如 {"days":30}。成功后沿用原授權。
POST /licenses/{id}/revoke撤銷,請求正文為 {}。
GET /products/{id}/public-keys查看產品公鑰,公開可讀。SDK 分發時固定受信公鑰。
GET /activations查看裝置綁定及執行會話。

清單分頁使用 limit=25&offset=0,limit 最大為 100。其他介面的參數和結構見 OpenAPI 檔案;不同授權方式的串接步驟見左側對應主題。

已有瀏覽器登入會話時,如何呼叫?

使用瀏覽器 Cookie 的寫請求需要 X-CSRF-Token。先 GET /api/v1/auth/csrf,再把 data.csrf_token 放進這個請求頭。Bearer Key 請求不需要 CSRF。

SDK 授權呼叫

選擇你的語言和操作,直接呼叫 SDK。啟用、裝置識別、驗證簽章、快取、心跳,以及計次的預留、確認和取消都由 SDK 處理。

啟動或啟用視窗使用付費功能前應用程式退出時

SDK 呼叫

業務示例中的 client 來自啟動授權,path 是你的匯出路徑,exportReport / export_report 是你自己的業務函數。計次的 jobID 是由應用程式儲存的穩定任務編號。

查看完整程式碼 → · 快速開始 · 查看計次串接和重試 →

業務程式碼放進回調。

權限允許時 SDK 才執行業務。普通 RunFeature 不扣次數;RunMeteredFeature 自動預留、成功后確認、失敗時取消。確認失敗后重試原任務,只補確認,不重復已完成的業務。

展開 HTTP 請求與回應(自定義客戶端或排錯時使用)

下面是 SDK 使用的協議,不需要在使用這九種 SDK 的應用程式中再次實現。

首次啟用執行時心跳業務前檢查權限換機時解除綁定

這八個介面用授權金鑰和裝置身份認證。請求不需要登入 Cookie、CSRF 或廠商管理 Key。浮動授權退出時還要釋放會話;綁定裝置授權日常退出保留綁定。

啟用、驗證或心跳成功后,怎么判斷能用?

  1. 確認 HTTP 200,讀取 data.activation_id。后續驗證、心跳、計次和解除綁定都要帶上這個 ID。
  2. 用預先信任的產品公鑰驗證 data.lease 的簽章,再核對產品、裝置、有效時間和功能。只把 payload 解碼成 JSON,不代表授權有效。
  3. 使用 SDK 時前兩步由 SDK 完成。RunFeature 檢查權限后執行業務;計次功能由 RunMeteredFeature 管理預留、確認和取消。

SDK 會儲存簽章快取并按策略傳送心跳。呼叫失敗時,不要僅因網路超時就抹掉有效快取;如果收到撤銷、釋放、到期等明確拒絕,則按 SDK 的結果阻止受保護功能。

簽章 payload 解碼后,每個欄位是什么意思?

下面只是為了讀懂資料。自行實現驗證簽章時,使用收到的 payload 原始位元組,不能把 JSON 重新排序或序列化后驗證簽章。

payload 內容示例

重試、心跳與計費

啟用、解除綁定和功能計次必須填寫 Idempotency-Key,最長 80 字符,不含空白。新操作生成新值;同一次網路重試保留原值和原正文。驗證與心跳可不填,SDK 仍會自動處理自己的請求編號。

成功的啟用、驗證、心跳和解除綁定請求,每次消耗 1 次平臺 API 呼叫額度。失敗和相同冪等請求的重放不重復計數,本機 CheckFeature 不請求伺服器。當前 Consume 只扣客戶軟體的功能次數,不增加這四類平臺 API 計費統計;quantity 表示本次功能消耗次數。

心跳間隔、離線時長和永久離線分別按 授權策略控制。payload.expires_at 是當前簽章快取的截止時間;授權的最終到期時間在授權詳情中查看,兩者不能混用。

心跳與離線設定

這兩個設定都在“授權策略”中,但解決的是兩件事:有網時多久聯系伺服器,以及聯系不上時還能使用多久。

心跳間隔:多久驗證一次

在“心跳請求間隔(秒)”中填寫 600,SDK 就會在執行期間大約每 10 分鐘傳送一次心跳。每次成功都會取得最新的執行規則,并刷新本機授權快取。

可填寫 600–86400 秒。填寫 0 會關閉定時心跳,應用程式仍可以主動呼叫驗證或刷新。定時請求會增加 0–10% 的隨機延遲,實際間隔不會低于 600 秒。

綁定裝置且快取有效時,啟動會先恢復授權,再在管理後台聯網刷新,關閉定時心跳時也會刷新。不允許離線或使用浮動席位時,啟動必須等伺服器確認。

離線時間:伺服器聯系不上時能用多久

“允許離線方式”有三種選擇。它不會替你修改心跳間隔。

允許指定時長
例如填寫 24 小時:從最近一次成功聯網驗證開始,簽章快取最多有效 24 小時。期間斷網或伺服器臨時故障,軟體可以繼續用;超過這個時間后,需要成功聯網驗證。
不允許離線回退
啟動必須成功聯系伺服器,請求失敗時不會靠磁碟快取放行。執行中取得的短期簽章最多有效 max(10, 心跳间隔) 秒;應用程式需要持續驗證并檢查功能權限。
允許永久離線
已經取得的本機簽章可以長期使用,網路失敗時仍能檢查權限。如果授權本身只有 30 天,仍會在 30 天到期;永久離線不會把期限授權變成永久授權。

介面用 offline_mode 表示這三種選擇,依次為 limited, none, permanent。指定時長時,offline_seconds 為 1–31536000 秒;另外兩種方式填 0。

這幾個組合會怎樣執行?

心跳 / 離線設定實際行為
10 分鐘 / 24 小時有網時每 10 分鐘驗證。斷網后按最后一次成功驗證的時間,最多繼續使用 24 小時
10 分鐘 / 永久離線仍然每 10 分鐘嘗試心跳,成功時更新規則;聯系不上時繼續使用有效簽章
0 / 永久離線有有效快取時,啟動可直接使用,不定時傳送請求。應用程式主動驗證或刷新時仍會聯系伺服器
0 / 24 小時不定時心跳,但快取仍會到期;應用程式要自行安排驗證,不能靠關閉心跳延長離線時間

建議離線時間長于心跳間隔。如果設成“每小時心跳,但只允許離線 1 分鐘”,簽章會在下一次定時心跳前過期,應用程式必須另行驗證。

修改策略后,舊授權會更新嗎?

會。修改心跳或離線設定后,關聯的舊授權和新授權都在下一次成功啟用、驗證或心跳時采用新規則,SDK 用新簽章替換快取。相同 Idempotency-Key 的重試仍會返回原來那次請求的結果。

持續斷網的裝置暫時不知道規則變了,仍按已有簽章使用。僅僅接上網路也不會自動改寫快取,要有一次成功的請求。應用程式可以在網路恢復時主動刷新。

這里更新的是執行規則。

授權的有效天數、裝置上限和功能權益儲存在各份授權中,修改策略不會自動重寫這些權益。要改某份授權的權益,在授權頁面操作。

主動聯網刷新

下面的方法始終嘗試聯系伺服器,包括“永久離線 + 關閉心跳”的情況。成功后更新簽章;網路失敗會報刷新失敗,同時保留仍允許使用的舊快取;明確被撤銷或釋放時清除快取。

語言呼叫方式
Goclient.RefreshOnline(ctx)
Javaclient.refreshOnline()
Cln_refresh_online(client)
C++client.RefreshOnline()
C#await client.RefreshOnline()
Pythonclient.refresh_online()
JavaScriptawait client.refreshOnline()

刷新成功計一次啟用 API 請求。如果剛更新的策略開啟了原來關閉的心跳,再呼叫對應語言的 StartHeartbeat 啟動調度。持續離線時,裝置也無法收到撤銷或釋放通知。

裝置綁定

一份授權設定為單裝置后,客戶把軟體和快取複製到另一臺普通電腦,不能直接繼續使用原電腦的授權。

SDK 怎么知道是哪一臺電腦?

每次啟動時,SDK 讀取作業系統的裝置身份,結合產品 ID 計算裝置哈希。伺服器簽章中包含這個哈希,本機檢查也會核對它。

Windows 讀取 MachineGuid,Linux 讀取 machine-id,macOS 讀取 IOPlatformUUID。原始裝置身份不會上傳,只傳送計算出的哈希;設定檔中的舊 device_id 不會覆蓋實際讀取的本機身份。

把裝置 A 的檔案複製到 B 會怎樣?

  1. A 啟用后,拿到的簽章綁定 A 的裝置哈希。
  2. B 讀取自己的系統身份,得到不同的哈希,因此拒絕 A 的快取。
  3. B 必須聯網重新啟用。如果裝置上限為 1,且 A 還沒釋放,伺服器會拒絕增加 B。

客戶要換電腦,怎么處理?

讓客戶在舊電腦上主動解除綁定,再在新電腦啟用。如果舊電腦損壞,你也可以在控制臺的“裝置啟用”頁面釋放舊綁定。換電腦不會重設授權的到期時間。

作業系統重裝后裝置身份可能變化,需要按新裝置處理。完整克隆作業系統、偽造系統身份或修改客戶端程式屬于更強的攻擊,單靠這個裝置哈希不能保證防住。

允許長期離線時,A 已持有的舊簽章無法馬上得知它被釋放了;它要再次成功聯系伺服器,才能更新這個狀態。離線時間越長,遠端限制越難立即生效。

跨語言裝置哈希算法
九種 SDK 使用相同計算方式
SHA256(UTF8(
  "LicenovaDevice/v2\n"
  + lower(product_id) + "\n"
  + lower(trim(OS_machine_identity))
))

額度與計費

裝置額度統計用了多少臺裝置,API 額度統計向伺服器成功請求了多少次。兩者分別計算,不能用裝置數推算 API 次數。

哪些操作會用掉一次 API 額度?

操作是否計次數
成功啟用、驗證、心跳或釋放每次成功各計 1 次;同一天的多次心跳分別計算
失敗請求,例如授權碼錯誤、額度不足不計
使用同一 Idempotency-Key 重試并返回原結果不重復計
本機 CheckFeature 或檢查簽章快取不計,沒有向伺服器發請求
通過管理 API Key 查詢或簽發授權不計入這項執行 API 額度

一個裝置很多次請求,裝置額度會重復扣嗎?

不會。同一計費周期內,同一產品的同一臺裝置只計一次裝置用量,但它的每次成功心跳都計 API 用量。釋放裝置不會減掉已經產生的用量。

例如 100 臺裝置,每天執行 8 小時,每月 22 天,每 10 分鐘心跳一次,僅心跳就有 105,600 次。再加上 100 次啟用和每天每臺一次額外驗證,總共是 107,900 次中查看。

這些額外驗證是例子里的假設,實際次數取決于你的程式。可在 線上用量估算中修改裝置數、執行時間和請求間隔。

超過方案額度以后怎么收錢?

以“包含 10 萬次 API,超出每次 0.0001 USD”為例:周期內成功呼叫了 12 萬次,超出 2 萬次,API 超額費是 2 USD中查看。

允許超額的方案按管理員設定的單價,從餘額扣除。系統把累計金額四舍五入到分,只扣新增的差額,因此很小的單次價格不會因每次舍入而被重復收費。

裝置超額費另算:超額裝置數 × 裝置單價。某一項設成硬上限時,用完后拒絕該項超額請求;需要扣款但餘額不足時,也會拒絕下一次請求。該失敗請求不增加用量。

API 標為“不限次”時不產生 API 超額費。額度為 0 則沒有免費呼叫,從首次成功請求開始按超額規則處理。具體包含額度、單價和限制請看 當前方案,這里的數字只是計算示例。

方案期限和額度從哪天算?

可以購買 1、3、6 或 12 個月。付款成功后立即生效,一次支付所選期限的總價。

裝置與 API 額度按月重新計算,從方案生效時刻開始。1 月 31 日生效,下一次重設在 2 月最后一天,再下一次在 3 月 31 日;未用完的額度不累積。

沒有購買方案時,使用管理員設定的預設規則,按 UTC 自然月統計。預設裝置費用沿用月結帳單;預設 API 超額費即時扣餘額。購買后使用購買周期的額度,不與預設額度疊加。

執行請求因額度或餘額不足被拒絕后,已有的離線簽章仍按它原來的規則有效。廠商可以在控制臺釋放裝置,不需要占用客戶的執行 API 額度。

浮動席位

浮動授權限制同時執行的程式數量。它適合多人輪流使用同一款軟體,不要求為每臺電腦單獨買授權。

一個例子

客戶有 100 臺電腦,你簽發 10 個浮動席位。前 10 個程式可以啟動,第 11 個收到“席位已滿”。其中一個正常退出并關閉 SDK 后,其他程式就能取得這個席位。同一臺電腦啟動兩個程式,也占兩個席位。

在策略里設定

選擇“浮動席位”,把裝置 / 席位上限設為 10。心跳間隔最低 600 秒;席位租約必須比心跳間隔長,例如 1200 秒。每次心跳續租,崩潰或斷網后,租約到期會回收席位。

浮動授權可以在租約內短暫斷網。離線使用時間會同時受到席位租約約束,不能允許永久離線,也不能用檔案完成完全離線首次啟用。

程式碼需要額外處理什么?

使用 Open / Start 和正常關閉方法即可。SDK 為每個 client 生成獨立會話 ID;不要為一次匯出操作建立一個新 client。把一個 client 保留到整個程式退出。

客戶端的舊浮動快取不會在下一次處理程序啟動時自動恢復席位。租約已經過期時,先重新啟用,取得席位后再恢復業務。

離線檔案啟用

目標電腦完全不能聯網時,用申請檔案和簽章回應完成首次啟用。申請檔案可以通過 U 盤帶到另一臺聯網電腦。

操作步驟

  1. 在目標電腦載入 SDK 設定,呼叫 OfflineRequest("activate"),儲存申請檔案。生成申請不需要訪問伺服器。
  2. 在聯網電腦打開控制臺的“離線檔案啟用”,上傳申請并下載回應。終端客戶也可以在自己的客戶門戶中辦理。
  3. 把回應帶回目標電腦,呼叫 ImportOffline,傳入原申請和回應。SDK 檢查簽章、申請編號、版本以及本機身份,通過后儲存快取。
  4. 用 CheckFeature 檢查授權。離線電腦無需啟動線上心跳;允許離線多久,由授權策略決定。

檔案啟用只支援允許離線的綁定裝置授權。申請有效期 30 天。限時授權從伺服器批準申請時開始計時,因為伺服器無法知道回應檔案什么時候被匯入。

如何離線解除綁定?

在原電腦生成 OfflineRequest("deactivate")。SDK 會先刪除本機快取,再把申請交給廠商或客戶門戶辦理釋放。刪除原電腦快取不能證明沒有其他歷史副本;需要立即阻止舊授權時,應使用需要定期聯網的策略。

各語言的名字

語言生成申請匯入回應
GoOfflineRequest("activate") → []byteImportOffline(requestBytes, responseBytes)
JavaofflineRequest("activate") → JSON 文字importOffline(requestText, responseText)
JavaScriptofflineRequest("activate") → objectimportOffline(requestObject, responseObject)
Cln_offline_request(client, "activate")ln_import_offline(client, requestText, responseText)
C++ / C#OfflineRequest("activate") → JSON 文字ImportOffline(C++ 傳文字,C# 傳位元組)
Pythonoffline_request("activate") → dictimport_offline(requestDict, responseDict)

C 返回的文字由呼叫方使用 ln_free_string 釋放。回應檔案傳入的是檔案本身的內容,不是網頁 API 外層的 data 包裝。

功能次數

“允許匯出”與“每月允許匯出 500 次”是兩條不同的規則。RunFeature 只檢查權限;RunMeteredFeature 在業務成功后確認次數。

設定每月 500 次匯出

在策略的功能清單中添加 export,再增加一條功能額度:功能 export、額度 500、周期“每月”。預設用完就拒絕。允許額外使用時,填寫最多額外次數;系統會記錄超出量,供你的訂單系統處理。

每天和每月額度按 UTC 零點重設;累計額度不重設。修改額度不會刪除已經使用的次數。

匯出成功后,才確認扣次

把自己的業務函數傳給對應 SDK 方法。新任務使用新編號,同一任務重試使用原編號、功能和數量;不同處理程序不要同時執行同一編號。

語言計次業務呼叫
Goclient.RunMeteredFeature(ctx, "export", 1, jobID, exportReport)
Javaclient.runMeteredFeature("export", 1, jobID, this::exportReport)
Node.jsawait client.runMeteredFeature("export", 1, jobID, exportReport)
Pythonclient.run_metered_feature("export", 1, job_id, export_report)
C#await client.RunMeteredFeature("export", 1, jobID, ExportReport)
C++client.RunMeteredFeature("export", 1, jobID, exportReport)
Rustclient.run_metered_feature("export", 1, &job_id, || export_report())?
Rubyclient.run_metered_feature("export", 1, job_id) { export_report }
Cln_run_metered_feature(client, "export", 1, job_id, export_report, context)

先設定 export 的功能額度,再用快速開始的腳本加上 -Metered -OperationID export-job-001(Windows),或 --metered --operation-id export-job-001(Linux / macOS)。

SDK 儲存待確認任務。

業務成功而確認失敗時,再次呼叫同一任務只重試確認,不重復執行業務。若程式在業務執行中途崩潰,SDK 會停止自動重做;核對自己的持久業務結果后,用 ResolveMeteredFeature 確認或取消。遠端扣次和本機業務不構成同一個事務。

需要自己控制預留流程時
  1. 為這次匯出生成并儲存一個業務編號。
  2. Reserve 預留 1 次額度,返回 pending 后再匯出。返回 committed 表示已完成過,不能再次執行。
  3. 匯出成功并儲存結果后,Commit 確認扣次。
  4. 匯出失敗且沒有完成業務時,Cancel 取消預留,不扣次數。

預留預設有效 15 分鐘,遇到 UTC 周期重設會提前結束。直接呼叫 API 可用 reservation_seconds 設定 30–3600 秒。

語言預留確認 / 取消
GoReserve(ctx, "export", 1, jobID)Commit / Cancel(ctx, hold.ID, jobID)
Java / Node.jsreserve("export", 1, jobID)commit / cancel(id, jobID)
Cln_reserve(client, "export", 1, jobID)ln_commit / ln_cancel(client, id, jobID)
C++ / C#Reserve("export", 1, jobID)Commit / Cancel(id, jobID)
Pythonreserve("export", 1, jobID)commit / cancel(id, jobID)

返回欄位怎么讀?

欄位含義
reservation_id / operation_id預留編號與原業務編號,重試繼續使用原值。
status / expires_at預留狀態和截止時間;pending 待完成,committed 已扣次,canceled 已取消,expired 已過期。
consumption.used / reserved本周期已確認次數 / 所有有效任務正在預留的次數。
consumption.limit / remaining基礎額度 / 可用基礎次數。remaining = max(0, limit - used - reserved),不包含允許超出的部分。
consumption.quantity / overage本任務次數 / 已確認的基礎額度超出量;不會替廠商向客戶收款。
consumption.period / reset_atUTC 用量周期 / 下次重設時間;終身額度的 reset_at 為 null。

傳送什么、返回什么和每個欄位的類型,見授權驗證介面中的預留、確認和取消。

確認超時后,只重試確認。

業務已成功時,不取消預留,也不重新匯出。儲存原編號和結果,繼續呼叫 Commit;若預留已過期,保留任務供人工核對。遠端扣次無法與你本機業務組成同一個事務。

Consume 仍可用于直接記賬,但會立即扣次。需要避免業務失敗仍扣次時,請用預留流程。所有計次介面都需要聯網,不計入平臺四類 API 呼叫額度。

版本與維護期

買斷軟體可以永久使用,但不一定永久免費升級。維護期用來決定客戶可以使用哪些發布時間的版本。

買斷當前版本,免費更新一年

策略設為永久授權,維護天數設為 365。客戶首次啟用時開始計算維護期。打開“軟體版本”發布 1.0.0、1.1.0 等版本,填寫實際發布時間。

維護期內發布的版本可以繼續使用;維護期結束后發布的新版本會被拒絕,舊版本仍可使用。客戶續維護后,再到授權“權益與客戶”中延長維護期。

軟體如何傳自己的版本?

在 sdk-demo.json 中填寫 app_version,例如 1.1.0。使用維護期時,這個版本必須先在控制臺發布。版本格式暫時只接受三個數字,例如 1.2.3。版本記錄不能改發布時間,避免改日期改變已經售出的權益。

只想限制 1.x 版本時,也可以設定最小 1.0.0 和最大 1.999.999,不啟用維護期。軟體更新后重新聯網取得新版本的簽章授權,舊版本快取不能直接用于新版本。

提供下載

版本記錄可以附上 HTTPS 下載位址和 SHA-256 校驗值。客戶門戶只展示這份授權有資格使用的版本。當前記錄提供下載連結,不代你上傳安裝包,也不會自動給客戶安裝更新。

客戶門戶

客戶可以自己查授權、查看裝置和解除綁定,不用進入廠商控制臺。

廠商先關聯客戶電子信箱

簽發授權時填寫客戶電子信箱,或打開授權的“權益與客戶”補填。把 客戶門戶連結發給客戶。客戶輸入這個電子信箱,電子郵件中會收到一次性登入連結,15 分鐘內有效;登入狀態保留 24 小時。

客戶只看到關聯到這個電子信箱的授權,不會看到你的產品管理、帳單或其他客戶的資料。電子郵件服務需要先在管理員設定中接好。

客戶換了電腦,但找不到原來的金鑰,怎么辦?

  1. 客戶輸入授權關聯的電子信箱,打開電子郵件里的登入連結。連結只負責登入,不會直接解除綁定。
  2. 在“我的裝置 / 會話”找到舊電腦,點擊“解除綁定并換機”,核對裝置后確認。
  3. 頁面顯示臨時啟用碼,有效期最長 15 分鐘,只能成功啟用一次。客戶可以複製,也可以勾選傳送到自己的電子信箱。
  4. 在新電腦打開你的軟體,在啟用界面輸入臨時碼。SDK 會識別新電腦,綁定原授權并儲存裝置憑證。此后重啟和心跳使用裝置憑證,臨時碼到期不影響已啟用的新電腦。

這一步更換的是裝置綁定。授權編號、原到期時間、功能、客戶歸屬和已用次數都保留;不會另外簽發一份授權。新裝置必須符合原授權策略,也必須有空余裝置名額。

軟體廠商需要改哪里?

升級到當前 SDK。原來接受授權金鑰的輸入框,也可以接受 lv_tmp_ 開頭的臨時碼;傳入設定的 license_key 即可,后面的 Start、驗證和心跳介面照常使用。SDK 會在私有快取目錄儲存裝置憑證檔案;cache_path 可留空。這個檔案要儲存在當前使用者的應用程式資料目錄,不要跟安裝包分發。

成功兌換后,軟體可以把 license_key 留空;保持同一產品、公鑰和 cache_path,重啟時 SDK 會恢復裝置憑證。客戶不用儲存或反復輸入臨時碼。兌換尚未成功時,軟體應保留輸入,以便斷線重試。

啟用碼過期,或關閉了這個頁面

再次登入門戶,可以看到尚未使用的臨時碼。未使用的碼過期后,在對應的已釋放裝置旁點擊“查看 / 取得啟用碼”重新取得;這不會再扣一次換機次數。已經成功使用的碼無法再次兌換,也不能從舊裝置記錄反復領取來繞過次數限制。再次換機請解除綁定當前的新裝置。

新電腦完全離線時

在新電腦的軟體里填入臨時碼,用 SDK 匯出啟用申請。在臨時碼過期前,把檔案帶到聯網電腦并通過門戶生成回應,再帶回新電腦匯入。策略必須允許裝置綁定模式的離線啟用;期限仍按原授權計算。回應檔案包含這臺裝置的授權與憑證,需要妥善保管。

解除綁定次數和舊電腦的狀態

自助釋放次數可以在授權策略中設定,按每份授權每個 UTC 月計數;設定為 0 表示關閉新的門戶自助解除綁定。重復點擊、查看已有碼、過期后重發未用碼不會多扣次數。此限制覆蓋客戶門戶及客戶離線釋放申請,廠商手工釋放和軟體直接使用原授權金鑰呼叫釋放介面不受它限制。

遠端解除綁定會阻止舊裝置下一次聯網驗證;舊電腦上已有的離線快取仍需等聯網或到期才會失效。永久離線快取無法立即遠端停用,需要及時撤銷授權的產品應選擇定期聯網策略。正常複製設定、憑證和快取到另一臺電腦,SDK 會因裝置身份不同拒絕使用。

客戶門戶管理授權使用,廠商的訂單和軟體銷售收款仍由廠商自己的系統完成。

授權事件通知

當授權啟用、續期或被撤銷時,Licentivo 可以向你的伺服器發一條通知,用來同步訂單、客戶和售後系統。

添加通知位址

打開“授權事件通知”,添加你伺服器的 HTTPS 位址,選擇需要的事件。儲存時會顯示一次簽章金鑰,把它儲存在接收通知的伺服器上。正式環境不允許請求本機或內網位址。

接收后檢查簽章

讀取 X-Licentivo-Timestamp、X-Licentivo-Event 和原始請求正文。拼接為“時間戳記 + 點號 + 事件 ID + 點號 + 正文”,用簽章金鑰計算 HMAC-SHA256。加上 sha256= 前綴后,與 X-Licentivo-Signature 做恒定時間比較。時間戳記與當前時間相差超過 5 分鐘時拒絕。

事件 ID 是去重依據。先檢查簽章,再把事件放入自己的事務或隊列,持久化成功后返回 2xx。重復事件返回 2xx 即可,不重復執行訂單操作。

失敗會怎樣?

系統最多自動嘗試 8 次,逐步延長重試間隔。控制臺能查看每次 HTTP 狀態、嘗試時間和錯誤,也可以手動重新投遞。事件與授權操作在同一個資料庫事務里記錄,服務重啟后會繼續投遞。

支援建立、更新、續期、撤銷、啟用、釋放、功能消耗、即將到期、到期和維護期變化事件。通知只帶授權前綴,不包含完整授權金鑰。

批次與策略變更

同一批客戶需要相同授權時,可以一次簽發、續期或撤銷。需要改變舊授權權益時,先預覽影響。

批次簽發或匯入

打開“授權”頁面,點擊“批次簽發 / 匯入”,選擇產品和策略。每行填寫客戶名稱、電子信箱,或者上傳帶 customer,customer_email 表頭的 CSV。每批最多 100 條。成功后下載簽發結果,儲存完整授權碼。

一個批次中的任意一條失敗,整批都不會生效。網路超時后保持當前內容重試;系統按這次操作的請求編號返回原結果,不會再次簽發。

批次續期或撤銷

在授權清單左側勾選記錄,再點擊“批次續期”或“批次撤銷”。表頭的復選框選擇當前頁,翻頁后已選記錄會保留,每批最多 100 份。更換篩選條件、離開授權頁面或刷新頁面會清空選擇。

續期時填寫增加的天數;尚未啟用的授權增加有效天數,已啟用的延長原到期時間,已經過期的從當前時間延長。撤銷前請展開所選記錄核對客戶,撤銷無法恢復。只讀成員不能執行這些操作。

把新策略套用到已有授權

  1. 在“授權策略”中儲存新規則。
  2. 在“授權”頁面勾選同一產品的舊授權,點擊“套用策略”并指定新策略。
  3. 檢查有效期、裝置或席位數、功能、次數和維護期的變化。已經占用的席位多于新上限,或切換綁定方式時還有活躍裝置,系統會要求先處理裝置。
  4. 確認後套用。客戶端下一次聯網驗證取得新的簽章授權;當前完全離線快取不會被遠端修改。

預覽在 10 分鐘內有效。預覽之后授權或策略有變化,需要重新預覽。套用新的有效天數會按原首次啟用時間重新計算到期日,請先檢查預覽中的日期。

常見問題

先看返回的錯誤碼,再核對對應設定。回應里的 request_id 可以幫助你從伺服器日志中找到這次操作,不要把完整金鑰貼進日志或截圖。

啟用失敗,先檢查什么?

檢查伺服器位址能否訪問、產品 ID 是否正確、授權碼是否完整,以及授權是否屬于這個產品。如果伺服器還沒部署,客戶電腦不能用你的 127.0.0.1 位址連線,它表示客戶自己的電腦。

錯誤碼先做什么
LICENSE_INVALID檢查產品 ID、完整授權金鑰和所屬產品
LICENSE_EXPIRED查看授權到期時間,需要繼續使用時由廠商續期
LICENSE_REVOKED
DEVICE_RELEASED
授權已被撤銷或裝置已釋放;客戶端會清除舊快取
DEVICE_LIMIT_REACHED授權的裝置名額已占滿;釋放舊裝置,或修改該授權的裝置上限
API_QUOTA_EXCEEDEDAPI 硬額度已用完;查看當前周期和方案限制
API_BALANCE_INSUFFICIENTAPI 超額餘額不足;檢查對應環境和幣種的餘額
MONTHLY_QUOTA_EXCEEDED裝置硬額度已達到;它與授權的裝置上限是兩項不同限制
IDEMPOTENCY_CONFLICT同一 Key 被用于不同正文;新操作換新 Key,重試保留原正文
IDEMPOTENCY_EXPIRED舊回應或裝置綁定已失效;檢查當前狀態后,為新的操作使用新 Key

斷網后還能用,是否沒有驗證?

允許離線時,SDK 仍會在本機檢查伺服器簽章、產品、裝置、功能和到期時間。它只是沒有聯系伺服器。簽章快取過期,或已聯網收到撤銷、釋放等明確拒絕后,就不能繼續使用。

為什么驗證簽章或裝置檢查不通過?

公鑰不匹配、使用了其他產品的快取、把快取複製到另一臺電腦,都可能導致失敗。核對 trusted_keys 的金鑰 ID 和公鑰是否來自當前產品,再檢查是否更換或重裝了系統。

SDK 報 clock rollback 時,檢查系統時間是否被調回。修正時間后,嘗試主動聯網刷新授權。

完整的錯誤回應

HTTP 403 · 授權被撤銷
{
  "error": {
    "code": "LICENSE_REVOKED",
    "message": "License was revoked"
  },
  "request_id": "99999999-9999-4999-8999-999999999999"
}
欄位含義與處理
error.code · string穩定的錯誤標識,程式按它判斷如何處理,不依賴 message 的文字。
error.message · string說明失敗原因的文字,適合診斷或轉換為面向客戶的提示。
request_id · UUID伺服器為這次 HTTP 請求生成的編號,供查日志。它不是授權 ID,也不是 Idempotency-Key。

400 / 415 先修正欄位或 Content-Type;401 檢查管理 Key;403 按具體錯誤碼處理授權;409 檢查額度、會話或冪等沖突;429 按 Retry-After 等待。超時或 5xx 可以有間隔地重試,寫操作必須沿用原冪等編號和正文,避免重復計次。

請求返回的 JSON 怎么看?

成功返回 data 和 request_id;失敗返回 error.code, error.message 和 request_id。保留錯誤碼和 request_id 就能定位多數問題。

需要檢查電子郵件、支付或部署設定時,繼續看 支援與排查中查看。