把授權接進你的軟體
用約 15 分鐘完成一個受授權保護的匯出功能:取得設定、執行示例、串接自己的應用程式,再驗證權限拒絕。前提是已安裝對應語言的開發環境。
SDK 負責請求、裝置識別、驗證簽章、憑證儲存、快取和心跳。你提供客戶輸入的授權碼和業務函數,無需自己組裝 HTTP 請求或儲存 activation_id。
- 準備串接包控制臺生成產品設定
- 生成匯出檔案檢查授權與業務結果
- 接到軟體啟動、業務入口、退出
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_… 也填在同一位置。 |
| 產品 ID | SDK / 軟體開發者 | 告訴伺服器正在驗證哪個產品,可隨軟體分發。 |
| 管理 API Key | 廠商自己的伺服器 | 自動簽發、續期和管理授權。客戶軟體的啟用不需要它。 |
心跳間隔與允許離線時長在 授權策略分別設定;授權有效期從首次啟用開始。功能次數、浮動席位和離線檔案啟用可以在基礎串接完成后添加。
暫時不註冊也可以打開 線上體驗查看請求與返回。需要自動簽發授權時,繼續讀 管理 API Key中查看。
客戶端 SDK
將業務函數交給 SDK:普通功能用 RunFeature,計次功能用 RunMeteredFeature。請求、驗證簽章、快取和心跳由 SDK 處理。
執行前準備
在控制臺 快速開始下載已設定的串接包。演示使用私有的 sdk-demo.json;放進實際軟體時使用 product.json,客戶授權碼作為啟動參數傳入。下方“下載 SDK”是通用源碼包,尚未填寫你的產品設定。
設定檔的每一項是什么?
{
"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++ 預編譯包按平臺和編譯器區分。
安裝之后如何引用?
| 語言 | 項目串接 |
|---|---|
| Go | import licentivo "github.com/spf86/licentivo-sdk" |
| Java | implementation(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; |
| Python | from licentivo import Client |
| Node.js | import {Client} from '@licentivo/sdk' |
| Rust | use licentivo::Client; |
| Ruby | require 'licentivo' |
Go、Rust 和 C/C++ 使用的 .licentivo-sdk 目錄應保留在項目中。更新時指定新版本,不會覆蓋 product.json 或客戶授權快取。
用 SDK 執行受保護的業務,退出時關閉 client。
正在加载代码…使用其他客戶授權碼,或執行完整協議演示
在終端中設定環境變量,再執行快速開始的腳本,不加測試參數。授權碼不是管理 API Key。
執行成功會輸出 License OK: export is available。將它放到正式應用程式時,不必讓客戶設定環境變量;由啟用視窗取得輸入;SDK 自動儲存本機憑證。不要把客戶授權碼放進日志。
執行下載包里的完整演示
解壓 ZIP,保留其中的目錄結構,把 sdk-demo.json 放到解壓后的根目錄。選擇執行系統,在這個目錄打開終端,執行:
此處的完整協議演示用于進階排查。首次串接先執行快速開始里的 start.ps1 或 start.sh;這些串接示例在日常退出時保留綁定裝置登記。
這段管理程式碼如何執行?
先在你的伺服器環境中設定 LICENTIVO_URL 和 LICENTIVO_API_KEY,分別填授權伺服器位址和完整的管理 Key。示例會讀取產品清單,并輸出 HTTP 狀態和返回內容。
返回 HTTP 200 且包含 data.items,說明請求成功。返回 401 時檢查 Key 是否完整、過期或已被撤銷。Key 的建立方法和權限見 管理 API Key中查看。
執行一個真正的應用程式示例
示例包含啟用輸入、授權狀態、匯出檔案和主動解除綁定。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
- 用工作區 Owner(所有者)帳號登入,打開 API Key,點擊“建立 API Key”。
- 名稱填它的用途,例如“訂單系統”。只查詢時選“只讀”;要建立或修改授權時選“讀寫”。有效期可設為 1–365 天。
- 儲存后立即複製完整 Key,它只顯示一次。把它放在你伺服器的私有設定或環境變量中。
傳送第一個管理請求
示例讀取產品清單。將 LICENTIVO_URL 設定為授權伺服器位址,將 LICENTIVO_API_KEY 設定為剛建立的完整 Key,再執行:
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 處理。
業務示例中的 client 來自啟動授權,path 是你的匯出路徑,exportReport / export_report 是你自己的業務函數。計次的 jobID 是由應用程式儲存的穩定任務編號。
查看完整程式碼 → · 快速開始 · 查看計次串接和重試 →
權限允許時 SDK 才執行業務。普通 RunFeature 不扣次數;RunMeteredFeature 自動預留、成功后確認、失敗時取消。確認失敗后重試原任務,只補確認,不重復已完成的業務。
展開 HTTP 請求與回應(自定義客戶端或排錯時使用)
下面是 SDK 使用的協議,不需要在使用這九種 SDK 的應用程式中再次實現。
這八個介面用授權金鑰和裝置身份認證。請求不需要登入 Cookie、CSRF 或廠商管理 Key。浮動授權退出時還要釋放會話;綁定裝置授權日常退出保留綁定。
啟用、驗證或心跳成功后,怎么判斷能用?
- 確認 HTTP 200,讀取
data.activation_id。后續驗證、心跳、計次和解除綁定都要帶上這個 ID。 - 用預先信任的產品公鑰驗證
data.lease的簽章,再核對產品、裝置、有效時間和功能。只把 payload 解碼成 JSON,不代表授權有效。 - 使用 SDK 時前兩步由 SDK 完成。RunFeature 檢查權限后執行業務;計次功能由 RunMeteredFeature 管理預留、確認和取消。
SDK 會儲存簽章快取并按策略傳送心跳。呼叫失敗時,不要僅因網路超時就抹掉有效快取;如果收到撤銷、釋放、到期等明確拒絕,則按 SDK 的結果阻止受保護功能。
簽章 payload 解碼后,每個欄位是什么意思?
下面只是為了讀懂資料。自行實現驗證簽章時,使用收到的 payload 原始位元組,不能把 JSON 重新排序或序列化后驗證簽章。
重試、心跳與計費
啟用、解除綁定和功能計次必須填寫 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 的重試仍會返回原來那次請求的結果。
持續斷網的裝置暫時不知道規則變了,仍按已有簽章使用。僅僅接上網路也不會自動改寫快取,要有一次成功的請求。應用程式可以在網路恢復時主動刷新。
授權的有效天數、裝置上限和功能權益儲存在各份授權中,修改策略不會自動重寫這些權益。要改某份授權的權益,在授權頁面操作。
主動聯網刷新
下面的方法始終嘗試聯系伺服器,包括“永久離線 + 關閉心跳”的情況。成功后更新簽章;網路失敗會報刷新失敗,同時保留仍允許使用的舊快取;明確被撤銷或釋放時清除快取。
| 語言 | 呼叫方式 |
|---|---|
| Go | client.RefreshOnline(ctx) |
| Java | client.refreshOnline() |
| C | ln_refresh_online(client) |
| C++ | client.RefreshOnline() |
| C# | await client.RefreshOnline() |
| Python | client.refresh_online() |
| JavaScript | await client.refreshOnline() |
刷新成功計一次啟用 API 請求。如果剛更新的策略開啟了原來關閉的心跳,再呼叫對應語言的 StartHeartbeat 啟動調度。持續離線時,裝置也無法收到撤銷或釋放通知。
裝置綁定
一份授權設定為單裝置后,客戶把軟體和快取複製到另一臺普通電腦,不能直接繼續使用原電腦的授權。
SDK 怎么知道是哪一臺電腦?
每次啟動時,SDK 讀取作業系統的裝置身份,結合產品 ID 計算裝置哈希。伺服器簽章中包含這個哈希,本機檢查也會核對它。
Windows 讀取 MachineGuid,Linux 讀取 machine-id,macOS 讀取 IOPlatformUUID。原始裝置身份不會上傳,只傳送計算出的哈希;設定檔中的舊 device_id 不會覆蓋實際讀取的本機身份。
把裝置 A 的檔案複製到 B 會怎樣?
- A 啟用后,拿到的簽章綁定 A 的裝置哈希。
- B 讀取自己的系統身份,得到不同的哈希,因此拒絕 A 的快取。
- B 必須聯網重新啟用。如果裝置上限為 1,且 A 還沒釋放,伺服器會拒絕增加 B。
客戶要換電腦,怎么處理?
讓客戶在舊電腦上主動解除綁定,再在新電腦啟用。如果舊電腦損壞,你也可以在控制臺的“裝置啟用”頁面釋放舊綁定。換電腦不會重設授權的到期時間。
作業系統重裝后裝置身份可能變化,需要按新裝置處理。完整克隆作業系統、偽造系統身份或修改客戶端程式屬于更強的攻擊,單靠這個裝置哈希不能保證防住。
允許長期離線時,A 已持有的舊簽章無法馬上得知它被釋放了;它要再次成功聯系伺服器,才能更新這個狀態。離線時間越長,遠端限制越難立即生效。
跨語言裝置哈希算法
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 盤帶到另一臺聯網電腦。
操作步驟
- 在目標電腦載入 SDK 設定,呼叫 OfflineRequest("activate"),儲存申請檔案。生成申請不需要訪問伺服器。
- 在聯網電腦打開控制臺的“離線檔案啟用”,上傳申請并下載回應。終端客戶也可以在自己的客戶門戶中辦理。
- 把回應帶回目標電腦,呼叫 ImportOffline,傳入原申請和回應。SDK 檢查簽章、申請編號、版本以及本機身份,通過后儲存快取。
- 用 CheckFeature 檢查授權。離線電腦無需啟動線上心跳;允許離線多久,由授權策略決定。
檔案啟用只支援允許離線的綁定裝置授權。申請有效期 30 天。限時授權從伺服器批準申請時開始計時,因為伺服器無法知道回應檔案什么時候被匯入。
如何離線解除綁定?
在原電腦生成 OfflineRequest("deactivate")。SDK 會先刪除本機快取,再把申請交給廠商或客戶門戶辦理釋放。刪除原電腦快取不能證明沒有其他歷史副本;需要立即阻止舊授權時,應使用需要定期聯網的策略。
各語言的名字
| 語言 | 生成申請 | 匯入回應 |
|---|---|---|
| Go | OfflineRequest("activate") → []byte | ImportOffline(requestBytes, responseBytes) |
| Java | offlineRequest("activate") → JSON 文字 | importOffline(requestText, responseText) |
| JavaScript | offlineRequest("activate") → object | importOffline(requestObject, responseObject) |
| C | ln_offline_request(client, "activate") | ln_import_offline(client, requestText, responseText) |
| C++ / C# | OfflineRequest("activate") → JSON 文字 | ImportOffline(C++ 傳文字,C# 傳位元組) |
| Python | offline_request("activate") → dict | import_offline(requestDict, responseDict) |
C 返回的文字由呼叫方使用 ln_free_string 釋放。回應檔案傳入的是檔案本身的內容,不是網頁 API 外層的 data 包裝。
功能次數
“允許匯出”與“每月允許匯出 500 次”是兩條不同的規則。RunFeature 只檢查權限;RunMeteredFeature 在業務成功后確認次數。
設定每月 500 次匯出
在策略的功能清單中添加 export,再增加一條功能額度:功能 export、額度 500、周期“每月”。預設用完就拒絕。允許額外使用時,填寫最多額外次數;系統會記錄超出量,供你的訂單系統處理。
每天和每月額度按 UTC 零點重設;累計額度不重設。修改額度不會刪除已經使用的次數。
匯出成功后,才確認扣次
把自己的業務函數傳給對應 SDK 方法。新任務使用新編號,同一任務重試使用原編號、功能和數量;不同處理程序不要同時執行同一編號。
| 語言 | 計次業務呼叫 |
|---|---|
| Go | client.RunMeteredFeature(ctx, "export", 1, jobID, exportReport) |
| Java | client.runMeteredFeature("export", 1, jobID, this::exportReport) |
| Node.js | await client.runMeteredFeature("export", 1, jobID, exportReport) |
| Python | client.run_metered_feature("export", 1, job_id, export_report) |
| C# | await client.RunMeteredFeature("export", 1, jobID, ExportReport) |
| C++ | client.RunMeteredFeature("export", 1, jobID, exportReport) |
| Rust | client.run_metered_feature("export", 1, &job_id, || export_report())? |
| Ruby | client.run_metered_feature("export", 1, job_id) { export_report } |
| C | ln_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 會停止自動重做;核對自己的持久業務結果后,用 ResolveMeteredFeature 確認或取消。遠端扣次和本機業務不構成同一個事務。
需要自己控制預留流程時
- 為這次匯出生成并儲存一個業務編號。
- Reserve 預留 1 次額度,返回 pending 后再匯出。返回 committed 表示已完成過,不能再次執行。
- 匯出成功并儲存結果后,Commit 確認扣次。
- 匯出失敗且沒有完成業務時,Cancel 取消預留,不扣次數。
預留預設有效 15 分鐘,遇到 UTC 周期重設會提前結束。直接呼叫 API 可用 reservation_seconds 設定 30–3600 秒。
| 語言 | 預留 | 確認 / 取消 |
|---|---|---|
| Go | Reserve(ctx, "export", 1, jobID) | Commit / Cancel(ctx, hold.ID, jobID) |
| Java / Node.js | reserve("export", 1, jobID) | commit / cancel(id, jobID) |
| C | ln_reserve(client, "export", 1, jobID) | ln_commit / ln_cancel(client, id, jobID) |
| C++ / C# | Reserve("export", 1, jobID) | Commit / Cancel(id, jobID) |
| Python | reserve("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_at | UTC 用量周期 / 下次重設時間;終身額度的 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 小時。
客戶只看到關聯到這個電子信箱的授權,不會看到你的產品管理、帳單或其他客戶的資料。電子郵件服務需要先在管理員設定中接好。
客戶換了電腦,但找不到原來的金鑰,怎么辦?
- 客戶輸入授權關聯的電子信箱,打開電子郵件里的登入連結。連結只負責登入,不會直接解除綁定。
- 在“我的裝置 / 會話”找到舊電腦,點擊“解除綁定并換機”,核對裝置后確認。
- 頁面顯示臨時啟用碼,有效期最長 15 分鐘,只能成功啟用一次。客戶可以複製,也可以勾選傳送到自己的電子信箱。
- 在新電腦打開你的軟體,在啟用界面輸入臨時碼。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 份。更換篩選條件、離開授權頁面或刷新頁面會清空選擇。
續期時填寫增加的天數;尚未啟用的授權增加有效天數,已啟用的延長原到期時間,已經過期的從當前時間延長。撤銷前請展開所選記錄核對客戶,撤銷無法恢復。只讀成員不能執行這些操作。
把新策略套用到已有授權
- 在“授權策略”中儲存新規則。
- 在“授權”頁面勾選同一產品的舊授權,點擊“套用策略”并指定新策略。
- 檢查有效期、裝置或席位數、功能、次數和維護期的變化。已經占用的席位多于新上限,或切換綁定方式時還有活躍裝置,系統會要求先處理裝置。
- 確認後套用。客戶端下一次聯網驗證取得新的簽章授權;當前完全離線快取不會被遠端修改。
預覽在 10 分鐘內有效。預覽之后授權或策略有變化,需要重新預覽。套用新的有效天數會按原首次啟用時間重新計算到期日,請先檢查預覽中的日期。
常見問題
先看返回的錯誤碼,再核對對應設定。回應里的 request_id 可以幫助你從伺服器日志中找到這次操作,不要把完整金鑰貼進日志或截圖。
啟用失敗,先檢查什么?
檢查伺服器位址能否訪問、產品 ID 是否正確、授權碼是否完整,以及授權是否屬于這個產品。如果伺服器還沒部署,客戶電腦不能用你的 127.0.0.1 位址連線,它表示客戶自己的電腦。
| 錯誤碼 | 先做什么 |
|---|---|
LICENSE_INVALID | 檢查產品 ID、完整授權金鑰和所屬產品 |
LICENSE_EXPIRED | 查看授權到期時間,需要繼續使用時由廠商續期 |
LICENSE_REVOKEDDEVICE_RELEASED | 授權已被撤銷或裝置已釋放;客戶端會清除舊快取 |
DEVICE_LIMIT_REACHED | 授權的裝置名額已占滿;釋放舊裝置,或修改該授權的裝置上限 |
API_QUOTA_EXCEEDED | API 硬額度已用完;查看當前周期和方案限制 |
API_BALANCE_INSUFFICIENT | API 超額餘額不足;檢查對應環境和幣種的餘額 |
MONTHLY_QUOTA_EXCEEDED | 裝置硬額度已達到;它與授權的裝置上限是兩項不同限制 |
IDEMPOTENCY_CONFLICT | 同一 Key 被用于不同正文;新操作換新 Key,重試保留原正文 |
IDEMPOTENCY_EXPIRED | 舊回應或裝置綁定已失效;檢查當前狀態后,為新的操作使用新 Key |
斷網后還能用,是否沒有驗證?
允許離線時,SDK 仍會在本機檢查伺服器簽章、產品、裝置、功能和到期時間。它只是沒有聯系伺服器。簽章快取過期,或已聯網收到撤銷、釋放等明確拒絕后,就不能繼續使用。
為什么驗證簽章或裝置檢查不通過?
公鑰不匹配、使用了其他產品的快取、把快取複製到另一臺電腦,都可能導致失敗。核對 trusted_keys 的金鑰 ID 和公鑰是否來自當前產品,再檢查是否更換或重裝了系統。
SDK 報 clock rollback 時,檢查系統時間是否被調回。修正時間后,嘗試主動聯網刷新授權。
完整的錯誤回應
{
"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 就能定位多數問題。
需要檢查電子郵件、支付或部署設定時,繼續看 支援與排查中查看。
介面的全部欄位可在 OpenAPI 檔案中查看。