commit 3894315759c2e0248f9ac10b589fc25da347379d Author: hpd840321 Date: Mon Apr 6 17:42:09 2026 +0800 feat: add native/Java auth SDK, docs, CI, and examples Made-with: Cursor diff --git a/.github/workflows/ci-java.yml b/.github/workflows/ci-java.yml new file mode 100644 index 0000000..9c4590b --- /dev/null +++ b/.github/workflows/ci-java.yml @@ -0,0 +1,28 @@ +name: ci-java + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +jobs: + maven: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "17" + cache: maven + - name: Build native (.so) + run: | + sudo apt-get update + sudo apt-get install -y build-essential cmake + cmake -S native -B native/build -DCMAKE_BUILD_TYPE=Release + cmake --build native/build --parallel + - name: Maven verify + run: mvn -f java/pom.xml -B verify + env: + LD_LIBRARY_PATH: ${{ github.workspace }}/native/build diff --git a/.github/workflows/ci-native.yml b/.github/workflows/ci-native.yml new file mode 100644 index 0000000..6e88fcd --- /dev/null +++ b/.github/workflows/ci-native.yml @@ -0,0 +1,40 @@ +name: ci-native + +on: + push: + branches: [main, master] + pull_request: + branches: [main, master] + +jobs: + build: + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest, windows-latest] + steps: + - uses: actions/checkout@v4 + - name: Set up JDK (JNI) + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: "17" + - name: Configure & build (Unix) + if: runner.os != 'Windows' + run: | + cmake -S native -B native/build -DCMAKE_BUILD_TYPE=Release + cmake --build native/build --parallel + - name: Configure & build (Windows) + if: runner.os == 'Windows' + run: | + cmake -S native -B native/build -DCMAKE_BUILD_TYPE=Release + cmake --build native/build --config Release --parallel + - name: Test (Unix) + if: runner.os != 'Windows' + working-directory: native/build + run: ctest --output-on-failure + - name: Test (Windows) + if: runner.os == 'Windows' + working-directory: native/build + run: ctest -C Release --output-on-failure diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..e241dd9 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,16 @@ +name: release + +on: + push: + tags: + - "v*.*.*" + +jobs: + placeholder: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Tag pushed + run: | + echo "Release workflow placeholder — attach native ZIP & Maven publish in later milestone." + echo "Ref ${GITHUB_REF}" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9741d22 --- /dev/null +++ b/.gitignore @@ -0,0 +1,41 @@ +# Build +**/build/ +**/target/ +**/out/ +cmake-build-*/ + +# Java +*.class +*.jar +*.war +*.iml +.idea/ +.settings/ +.project +.classpath + +# Native +*.o +*.obj +*.so +*.dylib +*.dll +*.a +*.lib +*.exp +*.pdb + +# OS / IDE +.DS_Store +*.swp +*.swo +.vscode/ + +# Maven +dependency-reduced-pom.xml + +# Python +__pycache__/ +*.py[cod] +.venv/ +venv/ diff --git a/docs/.gitkeep b/docs/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/docs/bitanswer-authorization-overview.md b/docs/bitanswer-authorization-overview.md new file mode 100644 index 0000000..51eadff --- /dev/null +++ b/docs/bitanswer-authorization-overview.md @@ -0,0 +1,147 @@ +# 比特授权云:机制与授权模式梳理 + +> 依据公开文档站点整理,主要页面入口:[欢迎页](https://doc.bitanswer.cn/docs/welcome/)、[授权模式分类](https://doc.bitanswer.cn/category/docs/license-models/)、[客户端 API](https://doc.bitanswer.cn/category/docs/client-api/)、[授权设计与创建](https://doc.bitanswer.cn/docs/function/licensing-design-creation/)、[基本授权过程](https://doc.bitanswer.cn/docs/application-development/development-process/)、[SDK 概述](https://doc.bitanswer.cn/docs/client-api/sdk-overview/)。 +> 整理日期:2026-04-06 + +--- + +## 1. 总体机制:控制台与产品模型 + +比特授权云将「卖什么、怎么控、怎么发到客户端」拆成多层概念: + + +| 概念 | 作用 | +| ---------------- | -------------------------------------------------------------- | +| **产品(Product)** | 对应一套或一组软件;内建 **特征项(功能/加密点)** 与 **配置项(小型安全存储,键值字符串)**。 | +| **模版(Template)** | 产品特征项的**子集**,常对应一个发行版本(如「简单版 / 专业版」)。 | +| **业务(Business)** | 定义**商业模式 + 授权类型**(云、集团、单机浮动、演示、帐号等)及各类**授权属性**(有效期、终端数、离线策略等)。 | +| **授权码 SN** | 16 位全球唯一标识;用户付费后发放;客户端用 SN 做激活、续期、升级。 | + + +集成侧:**库文件与头文件与产品绑定**,混用会导致 `**Login` 返回 0x105**(文档明确说明)。 + +典型流程:规划功能与模块 → 控制台建立产品与模版 → 下载对应开发模块 → 建立业务 → 生成并分发授权码 → 客户端激活与运行时校验。 + +### 1.1 保护方式与平台 + +- **保护方式**:[欢迎页](https://doc.bitanswer.cn/docs/welcome/) 说明提供 **API** 与 **外壳** 两种;可组合使用以提高安全性。 +- **平台**:Windows(32/64)、Linux(含 ARM/x86)、macOS、Android、iOS 等;其它语言可通过动态库集成。 + +--- + +## 2. SDK 侧:与模式无关的共性(运行时语义) + +来源:[SDK 概述](https://doc.bitanswer.cn/docs/client-api/sdk-overview/) + + +| 名词 | 含义 | +| --------------------- | ----------------------------------------- | +| **资源** | 需要保护或控制的功能或数据单元。 | +| **授权** | 将资源访问权下放给设备或用户。 | +| **激活** | 将设备/用户与权限绑定(典型:在线更新许可,再登录)。 | +| **授权升级** | 增加或减少资源访问权限。 | +| **授权检查** | 检查是否拥有某资源权限。 | +| **授权文件 / License 文件** | **单机类**授权保存在设备本地的许可数据。 | +| **特征项** | 与程序中「加密点 / 功能开关」对应;可有版本;类型包括只读、读写、算法、密钥等。 | +| **内存授权** | 将已有 License 传入 API 校验,**无激活过程**。 | + + +文档强调:在**集团授权**场景下,**QueryFeature** 与 **ReleaseFeature** 应**成对**调用(占用与释放模块用户数)。 + +示例主流程(文档 C 示例):`Bit_Login(..., BIT_MODE_AUTO)` → 失败则输入 SN → `Bit_UpdateOnline` 激活 → 再 `Bit_Login` → 结束 `Bit_Logout`。 + +--- + +## 3. 授权模式分述 + +文档中「本地授权」与「云授权」的区分要点:[云授权](https://doc.bitanswer.cn/docs/license-models/cloud-license/) 页指出,除云授权外,其它方式通常需向客户端发放与**硬件指纹绑定**的电子许可证,激活后往往**不必**再连授权服务器(云授权则运行时实时连网、授权数据不落客户端)。 + +### 3.1 云授权 + +- **文档**:[云授权](https://doc.bitanswer.cn/docs/license-models/cloud-license/) +- **许可数据**:始终在云端;客户端不保存完整授权数据。 +- **标识**:**授权码 SN**;文档描述为同一 SN 同一时间仅一台计算机使用。验证时上传 **SN + 本机硬件指纹**。 +- **安全会话**:验证通过后握手,用产品预置密钥派生**会话密钥**,后续通讯加密(文档类比网银并强调更复杂)。 +- **心跳**:约 **每 20 分钟**与服务器心跳以保持会话。 +- **多进程**:同一客户端同一 SN 最多 **10 个进程**;控制台可管理在线状态。 +- **管控**:授权属性变更可对在线客户端快速生效。 +- **局限**:运行期通常需联网;文档提及 **云授权 2.0** 改善依赖并支持高优先级登录、短时离线等。 +- **业务属性**:使用时间、次数、有效期;可设终端限制等。 + +### 3.2 单机浮动授权 + +- **文档**:[单机浮动授权](https://doc.bitanswer.cn/docs/license-models/local-license/) +- **运行期**:激活后一般**不连**外部授权服务器即可使用(与云授权对比)。 +- **激活**:客户端提交 **SN + 硬件指纹**,服务器验证后下发与本机绑定的**本地许可**;复制到其它机器不可用。 +- **许可存放**:本机;对比——集团授权在**集团服务器**,云授权在**云端**。 +- **常见业务属性**: + - **离线 vs 智能连接**:完全离线,或联网时后台自动校验/升级且不打断用户。 + - **强制认证**:最大离线时长,到期必须再连服务器。 + - **安装限制**:激活次数上限(多客户端**共享**该次数池)。 + - **终端限制**:允许多少台机器激活。 +- **失效与恢复**:许可损坏、硬盘问题或硬件变更可致失效;可按规则重新下载许可(可能消耗安装次数或终端名额)。 + +### 3.3 集团授权 + +- **文档**:[集团授权](https://doc.bitanswer.cn/docs/license-models/group-license/) +- **形态**:开发商**自建授权服务器**,对局域网或互联网用户做**并发**控制。 +- **控制台**:创建业务时选择「集团授权」;可配置**用户数(并发上限)**,默认描述为最多 **999** 并发。 +- **服务端组件**(需单独下载安装): + - 集团服务安装程序 `bit_service.exe`(Windows 服务),默认端口 **8273**(通讯)、**8274**(Web 管理)。 + - **集团服务扩展模块(.EXT)**:与**产品绑定**,不可混用。 + - **集团授权管理中心**:浏览器访问,默认示例 `http://localhost:8274`。 +- **客户端**:需配置集团服务器地址(API 或配置文件),参见 [部署和配置客户端](https://doc.bitanswer.cn/docs/application-development/application-distribution/) 等文档。 + +### 3.4 比特 ID 授权 + +- **文档**:[比特 ID 授权](https://doc.bitanswer.cn/docs/license-models/bitid-license/) +- **机制**:在**单机授权**基础上增加 **USB 比特 ID** 绑定;插硬件的机器才能正常使用。 +- **场景**:离线环境下便于带硬件换机;控制台可追踪、注销设备。 + +### 3.5 演示授权 + +- **文档**:[演示授权](https://doc.bitanswer.cn/docs/license-models/demo-license/) +- **特点**:演示码可被**多台客户端重复使用**;有有效期(如 15–180 天);**重装无法**简单延长试用期;可改为正式 SN。 +- **数据**:激活需连授权中心,可统计演示用户量、分布等。 +- **归类**:文档说明为**本地授权**——激活后使用**不必**再连服务器。 + +### 3.6 帐号授权 + +- **文档**:[帐号授权](https://doc.bitanswer.cn/docs/license-models/account-license/) +- **对象**:从设备授权扩展到**人/帐号**,常为**订阅**模式。 +- **集成路径**: + 1. **库直连**:`Bit_LoginByPassword`(业务 GUID、密钥、帐号、密码等)。 + 2. **OIDC**(文档更推荐):托管登录页取得 `code` → `POST /oidc/token` 换 **access_token** → `Bit_LoginByToken`。 +- **实践建议**:认证模块(Launchpad)与主程序分离,token 传入主程序。 + +--- + +## 4. 授权设计与特征项、配置项(摘要) + +来源:[授权设计与创建](https://doc.bitanswer.cn/docs/function/licensing-design-creation/) + +- **业务可配维度**(随授权类型不同而变化)包括:连接类型、强制认证周期、安装限制、有效期、集团用户数、起止日期、使用次数、终端限制等。 +- **授权内容更新生效**: + - **云授权**:可较快反映到客户端(文档称可无需重启应用)。 + - **集团 / 单机**:一般在客户端**下次连服务器**时同步;智能连接、强制认证会影响同步时机。 +- **特征项类型**:只读、读写、算法、密钥等;均支持 QueryFeature / ReleaseFeature;集团场景下成对调用尤其重要。 +- **配置项(Data)**:存配置与小数据,UTF-8;**不宜**替代特征项做安全控制;客户端可能有缓存,异常断电有丢失风险。 + +--- + +## 5. 模式对照表(便于与自研抽象对齐) + + +| 维度 | 云授权 | 单机 / 演示 / 比特 ID(本地类) | 集团授权 | 帐号授权 | +| ---- | ------------ | -------------------- | ---------- | --------------- | +| 判定位置 | 云端实时 | 本地许可(可选定期/智能连网同步) | 集团服务器(并发) | 云端 + token/密码 | +| 长期联网 | 一般需要 | 通常不强制(依业务属性) | 依部署与策略 | 登录/刷新时需要 | +| 并发模型 | SN + 在线会话/心跳 | 终端数、安装次数等 | 并发用户数 | 订阅/帐号维度 | +| 典型标识 | SN | SN(演示码策略特殊) | SN + 服务器地址 | 帐号 / OIDC token | + + +--- + +## 6. 免责声明 + +本文档为对 **doc.bitanswer.cn** 公开页面的**学习性整理**,不替代原厂文档;产品行为、默认值与 API 以官方网站与最新版本为准。 \ No newline at end of file diff --git a/docs/bitanswer-client-api-overview.md b/docs/bitanswer-client-api-overview.md new file mode 100644 index 0000000..b8901dc --- /dev/null +++ b/docs/bitanswer-client-api-overview.md @@ -0,0 +1,349 @@ +# 比特授权云:客户端 API 梳理(基于官方文档) + +> 来源:[C 语言接口定义 v2](https://doc.bitanswer.cn/docs/client-api/c-interface-definitions-v2/)、[Java 语言接口 v2](https://doc.bitanswer.cn/docs/client-api/java-interface-v2/)、[SDK 概述](https://doc.bitanswer.cn/docs/client-api/sdk-overview/)、[典型场景](https://doc.bitanswer.cn/docs/client-api/examples-of-using-the-sdk/)。 +> 其它语言入口(文档中心列举):[Delphi](https://doc.bitanswer.cn/docs/client-api/delphi-interface/)、[C#](https://doc.bitanswer.cn/docs/client-api/csharp-interface/)、[VB.Net](https://doc.bitanswer.cn/docs/client-api/vb-net-interface/)、[VB6](https://doc.bitanswer.cn/docs/client-api/vb6-interface/)。 +> 整理日期:2026-04-06 +> **说明**:本文为对公开文档的**纲要式整理**,参数细节、错误码与边界条件以官方页面及随产品下发的 `bitanswer.h`/接口文件为准。 +> **本地对照**:已与仓库内手工备份的 C 接口 `[docs/c.md](c.md)`、Java 接口 `[docs/java.md](java.md)` 交叉核对(见文末「审核说明」及 **附录 A**)。 + +--- + +## 1. SDK 交付形态与前置条件 + +- **获取方式**:在比特授权云平台「模块下载」获取与**产品绑定**的静态库/动态库及接口定义;**不同产品库不可混用**(文档说明 `Login` 不匹配会返回 `0x105` 类错误)。 +- **C**:头文件 `bitanswer.h` + 平台库(文档示例如 `libxxx_xxx_x64.a`)。 +- **Java**:JNI + 主封装类 `**BitAnswer`**(方法名为 camelCase,语义与 C API 大体一一对应;签名与枚举见 **附录 A** / `[docs/java.md](java.md)`)。 +- **支持平台(SDK 概述列举)**:Windows、Linux、Android、ARM Linux、MIPS Linux、macOS、iOS、HarmonyOS、QNX 等。 + +**运行期共性概念(SDK 概述)** + + +| 概念 | 含义 | +| -------------------------- | ---------------------------------------------------------------------------------------- | +| `application_data` / 产品识别码 | 编译进接口定义、与产品一一对应,多数 API 必填。 | +| `BIT_HANDLE` / 会话句柄 | `Bit_Login` / `Bit_LoginEx` 等成功后返回,后续特征项/心跳等依赖此句柄。 | +| `BIT_STATUS` | API 返回状态码;具体取值与错误码见官方「错误码」文档。 | +| 授权文件默认目录(典型场景) | Linux:`{当前用户}/BitAnswer`;Windows:`{系统盘}/ProgramData/BitAnswer`;可用 `Bit_SetRootPath` 自定义。 | + + +--- + +## 2. URL / 地址约定(`Bit_Login` 的 `szURL` 等) + +文档说明 `szURL` 可表达多种「授权来源」(节选): + + +| 形式 | 含义 | +| ----------------------------- | --------------------------------------------------------------------------------------- | +| `bit://ip:port` | 集团授权服务地址。 | +| `http://ip:port` | 授权服务中心(如云/E3 等)。 | +| `root://路径` | 仅在该路径下查找授权,效果类似先 `Bit_SetRootPath`。 | +| `lic://文件路径` / 目录 / License 串 | 内存或本地文件加载:`lic://` 可加载文件内容、目录下 `*.lic`、或直接传入 License 串;**多个路径用逗号分隔**(`c.md` 示例为半角 `,`)。 | +| 简写 | 文档示例:`/tmp,/data,127.0.0.1:8273` 等与 `lic://...`/`bit://...` 组合等价写法。 | + + +**配置优先级(文档)**:同一设置同时存在时 — **环境变量 > 调用 API 传入 > 配置文件**(`bit_config.xml`,典型场景详述多 `Server`/`Proxy` 节点)。 + +--- + +## 3. 登录模式与标识(`LOGIN_MODE` / `LoginMode`) + +与 `Bit_Login` / `Bit_LoginEx` 的 `mode` 为**按位组合**。文档列出的典型取值(C 名 / Java 名对应): + + +| C(示意) | Java(示意) | 语义摘要 | +| -------------------------------------- | --------------------------- | ------------------------------------ | +| `BIT_MODE_LOCAL` | `LOCAL` | 仅本地(单机、BIT-ID、内存授权等)。 | +| `BIT_MODE_REMOTE` | `REMOTE` | 仅远端(云、帐号、集团等)。 | +| `BIT_MODE_AUTO` | `AUTO` | 本地与远端都尝试;**优先级:本地 > 远端**(在已配置远端前提下)。 | +| `BIT_MODE_CACHE` | `CACHE` | 云授权 SN 缓存,便于下次免输 SN。 | +| `BIT_MODE_USB` | `USB` | USB 相关授权。 | +| `LOGIN_MODE_PROCESS` | `PROCESS` | **集团**:按进程占并发点;其它模式无效。 | +| `LOGIN_MODE_SESSION` | `SESSION` | **集团**:更细粒度会话占点。 | +| `LOGIN_MODE_HIGH_PRIORITY` | `HIGH_PR` | **云**:高优先级登录可挤占普通登录。 | +| `LOGIN_MODE_NO_NETWORK` | `NO_NETWORK` | 禁止库联网。 | +| `LOGIN_MODE_CHECK_USERNAME` | `CHECK_USERNAME` | **集团**:设备+用户名才视为同一点。 | +| `LOGIN_MODE_USE_SESSIONID` | `USE_SESSIONID` | `Logout` 不释放点数,由第三方维护心跳。 | +| `LOGIN_MODE_HIGH_PERFORMANCE` | `HIGH_PERFORMANCE` | **集团**:合并请求降负载。 | +| `LOGIN_MODE_PERSISTENT_CONN` | `PERSISTENT_CONN` | **集团**长连接。 | +| `LOGIN_MODE_CREATE_HANDLE_ONLY` | `CREATE_HANDLE_ONLY` | 仅创建句柄,**真正校验推迟到 Query**。 | +| `LOGIN_MODE_CREATE_NEW_HANDLE` | `CREATE_NEW_HANDLE` | 每次唯一句柄,属性互不干扰。 | +| `LOGIN_MODE_MID` / `ACCOUNT` / `GROUP` | `MID` / `ACCOUNT` / `GROUP` | 按设备、帐号、分组名占点等。 | + + +C 示例中常写作 `LOGIN_MODE(BIT_MODE_REMOTE | LOGIN_MODE_HIGH_PERFORMANCE)` 等形式,即用 `LOGIN_MODE` 宏包装按位或(见 `c.md`)。 + +**szSN / sn 常见形态(文档)**:云平台 SN;`#0` / `#bitid:0` 等形式选 BIT-ID;`<口令>` 激活口令;`SN<口令>` 拼接;帐号授权可与密码类参数配合(具体见帐号授权专章)。 + +--- + +## 4. API 分组:认证与会话(C 名为主,Java 对照) + + +| 功能 | C API | Java API(文档) | +| ---------- | ------------------------------------------- | ----------------------------------- | +| 登录 | `Bit_Login`, `Bit_LoginEx` | `login`, `loginEx` | +| 帐号 Token | `Bit_LoginByToken`, `Bit_LoginByTokenEx` | `loginByToken`, `loginByTokenEx` | +| 帐号密码 | `Bit_LoginByPassword` | `loginByPassword` | +| 登出 | `Bit_Logout` | `logout` | +| 浮动迁出 | `Bit_Revoke`(在线/离线迁出、请求码) | `revoke`, `revokeOnline` | +| 删除本机 SN 数据 | `Bit_RemoveSn` | `removeSn` | +| 手动心跳 | `Bit_Heartbeat`(10s 内最多触发一次等说明) | `heartbeat` | +| Session 控制 | `Bit_SessionControl`, `Bit_SetSessionState` | `sessionControl`, `setSessionState` | + + +--- + +## 5. API 分组:激活与离线/在线升级 + + +| 功能 | C API | Java(`BitAnswer`,`docs/java.md`) | +| -------- | ----------------------------------------------- | ----------------------------------------------------------------- | +| 在线激活/升级 | `Bit_UpdateOnline` | `void updateOnline(String url, String sn)` | +| 取升级请求串 | `Bit_GetRequestInfo`(绑定类型、设备码 `REQ_TYPE_MID` 等) | `String getRequestInfo(String sn, BindingType type)` | +| 应用升级包 | `Bit_ApplyUpdateInfo` | `String applyUpdateInfo(String updateInfo)` | +| 远程集团应用升级 | `Bit_ApplyUpdateInfoEx` | **`java.md` 未收录**;若需远程集团升级请以随包接口为准 | +| 用请求串换升级码 | `Bit_GetUpdateInfo` | `String getUpdateInfo(String url, String sn, String requestInfo)` | + + +**典型场景补充** + +- **在线**:`Bit_UpdateOnline(NULL, sn, application_data)`;BIT-ID 可用 `#0` 等形式。 +- **离线**:本机 `Bit_GetRequestInfo` → 联网换取 License 串 → 本机 `Bit_ApplyUpdateInfo`;涉密场景可用**设备码**缩短人工传递长度。 +- **内存授权**:从离线包取 ``,拼 `lic://...` 作为 `Bit_Login` 的 url,模式 `BIT_MODE_LOCAL`。 + +--- + +## 6. API 分组:特征项(功能模块与加密点) + + +| 功能 | C API | Java API(文档) | +| ------------ | ---------------------------------------------- | -------------------------------------- | +| 批量 Query | `Bit_BatchBegin`, `Bit_BatchEnd` | `batchBegin`, `batchEnd` | +| 基础占用/释放 | `Bit_QueryFeature`, `Bit_ReleaseFeature` | `queryFeature`, `releaseFeature` | +| 集团扩展占用 | `Bit_QueryFeatureEx`, `Bit_ReleaseFeatureEx` | `queryFeatureEx`, `releaseFeatureEx` | +| 按名称+版本/队列 | `Bit_QueryFeatureEx2`, `Bit_ReleaseFeatureEx2` | `queryFeatureEx2`, `releaseFeatureEx2` | +| 查存在/有效期(不占点) | `Bit_GetFeatureInfo2`, `Bit_GetFeatureInfoEx2` | `getFeatureInfo2`, `getFeatureInfoEx2` | +| Ticket 信息 | `Bit_GetTicketInfo` | `getTicketInfo` | +| 算法特征 | `Bit_ConvertFeature` | `convertFeature` | +| 密钥特征加解密 | `Bit_EncryptFeature`, `Bit_DecryptFeature` | `encryptFeature`, `decryptFeature` | +| 读写特征值 | `Bit_ReadFeature`, `Bit_WriteFeature` | `readFeature`, `writeFeature` | + + +文档强调:**集团授权**下 `QueryFeature` / `ReleaseFeature`(及 Ex 系列)需**成对**使用以正确占用/释放并发用户数;`QueryFeatureEx` 支持多种 `mode`(默认非阻塞、尽可能占用、仅检查计数等)。 + +--- + +## 7. API 分组:配置项(Data) + + +| 功能 | C API | Java API(文档) | +| ------- | ------------------------------------------- | ----------------------------------- | +| 读 | `Bit_GetDataItem` | `getDataItem` | +| 写/创建 | `Bit_SetDataItem` | `setDataItem` | +| 枚举数量/名称 | `Bit_GetDataItemNum`, `Bit_GetDataItemName` | `getDataItemNum`, `getDataItemName` | +| 删(授权码侧) | `Bit_RemoveDataItem` | `removeDataItem` | + + +Java 文档对名称/值长度有简要限制说明(如名称最长 128 字节、值 1024 字节量级,以官方为准)。 + +--- + +## 8. API 分组:信息查询 + +与 `c.md` 中 **「信息获取」** 大节对应。该节除下表外,还包括版本/句柄/诊断等 API(为减少重复,详见 **§10**)。 + + +| 功能 | C API | 说明(摘要) | +| ------- | -------------------- | ------------------------------------------------ | +| 会话信息 | `Bit_GetSessionInfo` | XML 或字段型信息:SN/特征/配置项摘要、服务器时间、授权类型组合、起止日期、离线分钟数等。 | +| 本机/环境信息 | `Bit_GetInfo` | 已激活 SN 列表、特征列表、集团服务器发现、BIT-ID 列表、升级错误详情等。 | +| 集团服务信息 | `Bit_GetServerInfo` | **无需先 Login**;查集团侧授权/特征等 XML。 | + + +**与 `c.md` 源码块核对**:`Bit_GetServerInfo` 小节内的函数名被写成 `Bit_GeServerInfo`(缺字母 `t`),与章节标题不一致,应视为复制/排版笔误;集成时以 **`bitanswer.h`** 为准。 + +--- + +## 9. API 分组:借出 / 归还(浮动与集团场景扩展) + +文档在 C / Java 接口中均用「借出操作」类章节描述。**C** 名称见下左列;**Java(`BitAnswer`)** 见 [`docs/java.md`](java.md) 及下表。 + + +| C API | Java 方法(`docs/java.md`) | +| ----------------------------- | ----------------------------------------------------------------------------------------------- | +| `Bit_GetBorrowRequest` | `String getBorrowRequest(String sn, int durationDay)` | +| `Bit_GetBorrowFeatureRequest` | `String getBorrowFeatureRequest(int durationDay, String borrowScope)` | +| `Bit_CheckOutSn` | `void checkOutSn(String url, int featureId)` | +| `Bit_CheckOutSnEx` | `void checkOutSnEx(String url, int featureId, String xmlScope, int durationDays)` | +| `Bit_CheckOut` | `void checkOut(String url, String scope, String featureList, int durationDays)` | +| `Bit_CheckOutFeatures` | `void checkOutFeatures(String url, int[] featureList, int durationDays)` | +| `Bit_CheckIn` | `void checkIn(String url, int featureId)` | +| `Bit_CheckInEx` | `void checkInEx(String url, int featureId, String xmlScope)` | +| `Bit_ApplyBorrowInfo` | `void ApplyBorrowInfo(String borrowInfo)`(文档锚点为大写 `ApplyBorrowInfo`;参数类型应以实际 SDK 的 `String` 为准) | + + +参数语义、`scope` / `featureList` XML 格式等以原文为准。Java 文档注明 **applyUpdateInfo** 可兼容离线借出串(与 `ApplyBorrowInfo` 重叠场景见原文)。 + +--- + +## 10. API 分组:路径、代理、属性与其它工具 + +对应 `c.md` 中 **「信息获取」** 后半(`Bit_GetVersion` 起)与 **「属性设置」** 全节。常见于部署与诊断: + + +| C API | 用途摘要 | +| ----------------------------------- | ------------------- | +| `Bit_SetRootPath` | 授权文件根路径。 | +| `Bit_SetProxy` | HTTP/SOCKS 等代理参数。 | +| `Bit_SetLocalServer` | 本地/集团服务发现相关设置(见原文)。 | +| `Bit_GetProductPath` | 产品路径查询。 | +| `Bit_GetVersion` | 库版本。 | +| `Bit_GetLastError` | 上一 API 错误码。 | +| `Bit_GetNextHandle` | 枚举/遍历句柄(见原文)。 | +| `Bit_SetAttr` / `Bit_SetCustomInfo` | 句柄/会话属性与自定义信息。 | +| `Bit_TestBitService` | 探测集团服务等可达性。 | + +**Java(`docs/java.md`)对应**:`int getVersion()` · `String getProductPath()` · `int getLastError()` · `void testBitService(String url, String sn, int featureId)` · `void setRootPath(String rootPath)` · `void setLocalServer(String hostName, int port, int timeout)` · `void setProxy(String hostName, int port, String userId, String password)` · `void setAttr(int type, byte[] pValue)` · `void setCustomInfo(...)`(`String` / `int` 重载)。**未在 `java.md` 列出**:`Bit_GetNextHandle` 的 Java 对等方法(若需遍历句柄请查随包 JNI 或新版文档)。 + +--- + +## 附录 A:Java `BitAnswer` API(依据 [`docs/java.md`](java.md)) + +### A.1 类型与构造 + +| 项 | 说明 | +|----|------| +| **主类** | `BitAnswer`(实例方法;通过 JNI 调用 native,与 C SDK 同库) | +| **构造方法** | `BitAnswer()`;`BitAnswer(String url, String sn, LoginMode mode)`(便捷构造,等价于再调用 `login` 的用法以官方示例为准) | +| **错误处理** | 多数 API 为 `void` 或返回数据;`int getLastError()` 返回**当前线程**最近一次调用的错误码(成功为 `0`,见 `java.md`) | + +### A.2 文档中出现的枚举 / 参数类型(用于方法签名) + +| 名称 | 用途(节选) | +|------|----------------| +| `LoginMode` | `login` / `loginEx`、构造器第三参数;与 C 侧 `LOGIN_MODE` 按位语义对应,Java 侧为枚举常量(`LOCAL`、`REMOTE`、`AUTO`、`CACHE`、`USB`、`PROCESS`、`SESSION`、`HIGH_PR`、`NO_NETWORK`、`CHECK_USERNAME`、`USE_SESSIONID`、`HIGH_PERFORMANCE`、`PERSISTENT_CONN`、`CREATE_HANDLE_ONLY`、`CREATE_NEW_HANDLE`、`MID`、`ACCOUNT`、`GROUP`) | +| `BindingType` | `getRequestInfo`:`EXISTING`、`LOCAL`、`USB_STORAGE` | +| `BatchMode` | `batchBegin`:`BIT_BATCH_MODE_CONTINUE`、`BIT_BATCH_MODE_BREAK` | +| `SessionType` | `getSessionInfo`:`XML_TYPE_SN_INFO`、`XML_TYPE_FEATURE_INFO`、`XML_TYPE_DATA_INFO`、`BIT_SERVER_ADDRESS`、`BIT_SERVER_TIME`、`BIT_CONTROL_TYPE` 及各日期/次数/离线字段常量(见 `java.md`) | +| `InfoType` | `getInfo`:`BIT_INFO_SERVER_ADDRESS`、`BIT_INFO_SN`、`BIT_INFO_SN_FEATURE` 等 | +| `ServerInfoType` | `getServerInfo`:`BIT_SERVER_INFO_SN`、`BIT_SERVER_INFO_SN_FEATURE`、`BIT_SERVER_INFO_SN_LICENSE` 等 | +| `SessionCtlType` | `sessionControl`:`SESSION_CTL_LOGOUT`、`SESSION_CTL_CHECK` | +| **`setAttr` 的 type** | `ATTR_HB_RETRY_FAILED_CALLBACK`、`ATTR_WAIT_TIMEOUT`、`ATTR_RETRY_COUNT` 等(见 `java.md`) | +| **`setCustomInfo` 的 infoId** | `CustomInfo`:`CUSTOM_CLIENT_ID`、`CUSTOM_OPTION` 等(`java.md` 列至 `CUSTOM_GROUP_NAME(0xA)`) | + +### A.3 方法签名全表(与 C 对照) + +**认证** + +| Java | +|------| +| `void login(String url, String sn, LoginMode mode)` | +| `void loginEx(String url, String sn, int featureId, String xmlScope, LoginMode mode)` | +| `void loginByToken(String url, String token)` | +| `void loginByTokenEx(String url, String businessGuid, String token, String idpGuid, String grantType)` | +| `void loginByPassword(String url, String guid, String secret, String account, String password)` | +| `void logout()` | +| `String revoke(String sn)` | +| `void revokeOnline(String url, String sn)` | +| `void removeSn(String sn)` | +| `int heartbeat()` | +| `String sessionControl(String url, String sessionId, SessionCtlType type)` | +| `void setSessionState(int state, byte[] pReserved)` | + +**激活升级**(另见 **§5** 表格) + +**特征项** + +| Java | +|------| +| `void batchBegin(BatchMode mode)` · `int[] batchEnd()` | +| `int queryFeature(int featureId)` · `int releaseFeature(int featureId)` | +| `int queryFeatureEx(int featureId, int mode, int required, String scope)` · `int releaseFeatureEx(int featureId, int consumed, String scope)` | +| `long queryFeatureEx2(String featureName, int mode, int required, String scope)` · `void releaseFeatureEx2(byte[] ticket, int consumed)` | +| `int getFeatureInfo2(String featureName, String scope)` · `String getFeatureInfoEx2(String featureName, String scope)` | +| `String getTicketInfo(byte[] ticket, int type)`(`type` 如 `BIT_TICKET_TYPR_USERS`,原文档拼写如此) | +| `int convertFeature(int featureId, int para1, int para2, int para3, int para4)` | +| `byte[] encryptFeature(int featureId, byte[] pPlainBuffer)` · `byte[] decryptFeature(int featureId, byte[] pCipherBuffer)` | +| `int readFeature(int featureId)` · `void writeFeature(int featureId, int featureValue)` | + +**配置项** + +| Java | +|------| +| `byte[] getDataItem(String dataItemName)` · `void setDataItem(String dataItemName, byte[] dataItemValue)` | +| `int getDataItemNum()` · `String getDataItemName(int index)` · `void removeDataItem(String dataItemName)` | + +(`java.md`:配置项名称最大 128 字节等限制与 C 侧一致。) + +**信息获取** + +| Java | +|------| +| `String getSessionInfo(SessionType type)` · `String getInfo(String sn, InfoType type)` | +| `String getServerInfo(String url, String sn, String scope, ServerInfoType type)` | +| `int getVersion()` · `void testBitService(String url, String sn, int featureId)` · `String getProductPath()` · `int getLastError()` | + +**借出操作**(另见 **§9** 表) + +### A.4 与 C 覆盖差异(据 `docs/java.md` 全文) + +| C API | Java(`docs/java.md`) | +|-------|------------------------| +| `Bit_ApplyUpdateInfoEx` | 未收录 | +| `Bit_GetNextHandle` | 未收录 | + +**补充**:C 侧 `Bit_GetRequestInfo` 的 `BINDING_TYPE` 含 **`REQ_TYPE_MID`(设备码)**;`java.md` 在 `getRequestInfo` 的 `BindingType` 中仅列出 `EXISTING`、`LOCAL`、`USB_STORAGE`。设备码流程在 Java 是否另有接口,以 **随包 SDK / 更新版 `java.md`** 为准。 + +### A.5 文档小瑕疵(复制源) + +- `loginEx` 说明中「Login 等价于 LoginEx」与 C 页类似,易误解;需包含**指定 featureId** 时用 `loginEx`。 +- `batchBegin` 正文写「由 **Bit_batchEnd** 提交」应为 **`batchEnd`(Java)** / **`Bit_BatchEnd`(C)**。 +- `ApplyBorrowInfo` 参数写 `string` 应为 Java **`String`**。 + +--- + +## 11. C API 名称索引(供检索) + +下列名称与 `c.md` 中全部 `## [Bit_…]` 小节一致,共 **59** 个独立函数(其中 `Bit_CheckOutSn` / `Bit_CheckOutSnEx` 合并在同一文档小节)。若与头文件有出入以 **`bitanswer.h`** 为准: + +`Bit_ApplyBorrowInfo` · `Bit_ApplyUpdateInfo` · `Bit_ApplyUpdateInfoEx` · `Bit_BatchBegin` · `Bit_BatchEnd` · `Bit_CheckIn` · `Bit_CheckInEx` · `Bit_CheckOut` · `Bit_CheckOutFeatures` · `Bit_CheckOutSn` · `Bit_CheckOutSnEx` · `Bit_ConvertFeature` · `Bit_DecryptFeature` · `Bit_EncryptFeature` · `Bit_GetBorrowFeatureRequest` · `Bit_GetBorrowRequest` · `Bit_GetDataItem` · `Bit_GetDataItemName` · `Bit_GetDataItemNum` · `Bit_GetFeatureInfo2` · `Bit_GetFeatureInfoEx2` · `Bit_GetInfo` · `Bit_GetLastError` · `Bit_GetNextHandle` · `Bit_GetProductPath` · `Bit_GetRequestInfo` · `Bit_GetServerInfo` · `Bit_GetSessionInfo` · `Bit_GetTicketInfo` · `Bit_GetUpdateInfo` · `Bit_GetVersion` · `Bit_Heartbeat` · `Bit_Login` · `Bit_LoginEx` · `Bit_LoginByPassword` · `Bit_LoginByToken` · `Bit_LoginByTokenEx` · `Bit_Logout` · `Bit_QueryFeature` · `Bit_QueryFeatureEx` · `Bit_QueryFeatureEx2` · `Bit_ReadFeature` · `Bit_ReleaseFeature` · `Bit_ReleaseFeatureEx` · `Bit_ReleaseFeatureEx2` · `Bit_RemoveDataItem` · `Bit_RemoveSn` · `Bit_Revoke` · `Bit_SessionControl` · `Bit_SetAttr` · `Bit_SetCustomInfo` · `Bit_SetDataItem` · `Bit_SetLocalServer` · `Bit_SetProxy` · `Bit_SetRootPath` · `Bit_SetSessionState` · `Bit_TestBitService` · `Bit_UpdateOnline` · `Bit_WriteFeature` + +--- + +## 12. 与mgmt/运营侧 API 的边界 + +开发者控制台还提供 **[Backoffice API](https://doc.bitanswer.cn/category/docs/backoffice-api/)**(REST/数据结构),用于授权码、用户、业务等**服务端自动化**,与上表**客户端安全库 API** 不同层。若需「控制台可调用的 HTTP API」,请单独以 Backoffice 文档为准。 + +--- + +## 13. 免责声明 + +本文档不替代比特授权云官方文档与随 SDK 发布的法律/技术支持条款;集成与合规问题请咨询官方渠道。 + +--- + +## 14. 对照本地备份的审核结论(2026-04-06) + +### 14.1 `docs/c.md` + +| 项 | 结论 | +|----|------| +| **函数覆盖** | `c.md` 中列出的全部 Bit 客户端 API 均已在本梳理的分组或 §11 索引中覆盖;**无遗漏**。 | +| **章节结构** | 「信息获取」后半与「属性设置」对应 §8 / §10,表头已说明。 | +| **Bit_GetServerInfo** | `c.md` 代码块误写为 `Bit_GeServerInfo`;§8 已注释。 | +| **Bit_LoginEx 说明** | `c.md` 中 `featured=0` 等笔误;本梳理未复述。 | +| **多路径分隔符** | 已标明示例为半角 `,`。 | +| **登录模式** | 与 `c.md` 表一致;已补充 `LOGIN_MODE(...)` 宏。 | +| **§11 索引** | 以 `c.md` 小节为对齐基准。 | + +### 14.2 `docs/java.md` + +| 项 | 结论 | +|----|------| +| **对等性** | `java.md` 中 **`BitAnswer` 实例方法**与 C API 基本全覆盖;**附录 A** 为完整签名与枚举清单。 | +| **缺失相对 C** | `Bit_ApplyUpdateInfoEx`、`Bit_GetNextHandle` 在 `java.md` 中未出现(§A.4)。 | +| **`getServerInfo`** | Java 文档写为 `getServerInfo`;无 C 页 `GeServerInfo` 笔误问题。 | +| **借出** | §9 已按 `java.md` 补全 `checkOut*` / `checkIn*` / `ApplyBorrowInfo` 等 Java 方法表。 | + + diff --git a/docs/c.md b/docs/c.md new file mode 100644 index 0000000..7d0874e --- /dev/null +++ b/docs/c.md @@ -0,0 +1,1880 @@ +# 比特授权云 · C 语言接口定义(离线摘录) + +> 本文档由官网页面离线摘录并整理排版,便于本地检索。官方地址: + +--- + +## 认证 + + +### Bit_Login / Bit_LoginEx + +```c +BIT_STATUS Bit_Login( + BIT_PCSTR szURL, + BIT_PCSTR szSN, + BIT_UCHAR *pApplicationData, + BIT_HANDLE *pHandle, + LOGIN_MODE mode); + +BIT_STATUS Bit_LoginEx( + BIT_PCSTR szURL, + BIT_PCSTR szSN, + BIT_UINT32 featureId, + BIT_PCSTR szReserved, + BIT_UCHAR *pApplicationData, + BIT_HANDLE *pHandle, + LOGIN_MODE mode); +``` +授权登录。初始化运行环境,获取操作句柄。必须在除升级函数之外的其它操作前执行。根据登录模式的不同可能需要连接授权服务器。 + +Bit_Login 等价于 Bit_LoginEx(…, featureId=0,szReserved=NULL, …),当需要登录包含指定特征项的授权时才需要调用Bit_LoginEx。 + +### 参数 + +- **szURL** - [IN] 自定义授权服务地址,包括端口,如未使用自定义授权服务器则为NULL。授权服务地址可以是网络地址、本地授权目录以及License串。 + + +| **类型** | **格式** | **说明** | +| ------------- | -------------------------------- | ------------------------------------------------------------------------------ | +| **授权服务器地址** | `bit://ip:port`或`http://ip:port` | “`bit://`”开头表示集团授权服务地址 “`http://`”开头表示授权服务中心地址,一般是E3系统或者比特授权云的地址 | +| **授权文件路径** | `root://xxx` | 传入授权文件所在路径,Login就只会在该路径下查找授权,该设置等同于调用Bit_SetRootPath接口 | +| **License文件** | `lic://xxx` | 传入文件路径:读取文件内容,并加载到内存里使用 传入目录:自动加载该目录下的*.lic的授权文件 传入License串:将该License串加载到内存里使用 | + + +允许设置多个授权路径,通过“,”拆分。 + +如下: + +```c +lic:///tmp,lic:///data,bit://127.0.0.1:8273 +/tmp,/data,127.0.0.1:8273 // 等价第1条 +``` +> 注意:该接口支持通过[配置文件](https://doc.bitanswer.cn/docs/client-api/examples-of-using-the-sdk/#%E9%85%8D%E7%BD%AE%E6%96%87%E4%BB%B6)和[环境变量](https://doc.bitanswer.cn/docs/client-api/examples-of-using-the-sdk/#%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F)来设置该值,如果同时设置优先级为:环境变量 > API传入 > 配置文件。 + +- **szSN** - [IN] 授权码(SN)字符串。如果为空(空串或NULL)则尝试寻找所有当前本机可用的SN。 + + +| **类型** | **格式** | **说明** | +| -------------------------------- | ---------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | +| **授权码** | 比特授权云平台产生的SN 示例:`JNLTGZSE********` | 检查指定SN的License | +| **BIT-ID(BIT-ID硬件,类似于加密的USB设备)** | 格式:#`<序号>` 或 #bitid:`<序号>` 说明:`<序号>` 为 BIT-ID 的索引号,从 0 开始递增 示例:#0、#1、#`bitid:0、#bitid:1` | 使用BIT-ID授权 | +| **激活口令(帐号授权密码或SN激活口令)** | <`xxx`> 通过“<>”包裹起来,中间部分为密码 示例:<1234>, <1233>65447> | 激活口令,是指授权码激活时,需要输入的一种口令,激活后不再需要,目前仅支持浮动授权 使用帐号授权时保存的是帐号授权的密码(已经不推荐),其它授权代表激活口令 | +| **既输入SN又输入激活口令** | `xxx`,授权码后边紧跟“<>” 示例:`JNLTGZSE********`<123> | | + + +- **featureId** - [IN] 登录授权所需要包含的特征项ID。 +- **szReserved** - [IN] 一个xml串,表示登录的SN范围。 + +  xml格式如下: + +```xml + + + +``` +- **pApplicationData** - [IN] 产品识别码,在Bitanswer SDK头文件里。 +- **pHandle** - [OUT] 通过Login函数返回的上下文句柄。 +- **mode** - [IN] 登录模式,按位操作。 + + +| **值** | **说明** | +| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- | +| **BIT_MODE_LOCAL(0x01)** | 只检查本地授权(单机授权、BIT-ID授权、内存授权) | +| **BIT_MODE_REMOTE(0x02)** | 只检查远端授权(云授权、帐号授权、集团授权) | +| **BIT_MODE_AUTO(0x03)** | 既检查本地授权,也检查远端授权(配置了远端IP的条件下) 优先级:本地授权 > 远端授权 | +| **BIT_MODE_CACHE(0x4)** | 云授权缓存 由于云授权SN比较难记,但登录时又必须传输,则可以使用该选项将SN串缓存起来,下次使用Login登录时可以不输入SN | +| **BIT_MODE_USB(0x8)** | USB授权 | +| **LOGIN_MODE_PROCESS(0x10)** | 按进程模式登录 **集团授权**:普通模式一台机器占用一个用户数,进程模式是一个进程占用一个用户数 **其它授权**:不生效 | +| **LOGIN_MODE_SESSION(0x40)** | Session模式登录 **集团授权**:该模式比LOGIN_MODE_PROCESS控制的更细,一次会话占用一个点 **其它授权**:不生效 | +| **LOGIN_MODE_HIGH_PRIORITY(0x20)** | 高优先级登录 **云授权:**用户可以通过高优先级登录来挤掉普通登录。如果登录模式都是高优先级或者普通优先级则不生效 **其它授权:**不生效 | +| **LOGIN_MODE_NO_NETWORK(0x200)** | 禁用网络 禁止库联网时使用 | +| **LOGIN_MODE_CHECK_USERNAME(0x800)** | 检查当前设备的用户名 **集团授权:**默认情况下:一台的设备用户名不一样,会被识别为同一个机器,加了该模式,会识别为不同的设备。即:原来一台设备占用一个点,加了这个选项,“一台设备 + 用户名”占用一个点 **其它授权**:不生效 | +| **LOGIN_MODE_USE_SESSIONID(0x1000)** | Logout时不释放点数,并由第三方程序维护心跳 | +| **LOGIN_MODE_HIGH_PERFORMANCE(0x2000)** | 使用高性能模式登录 **集团授权:**将Login的两次请求转化为一次请求,可以减少服务负载 **其它授权:**不支持 | +| **LOGIN_MODE_PERSISTENT_CONN(0x4000)** | 使用长连接模式登录,只有集团授权支持,其它授权不支持 通过长连接可以减少TCP的频繁创建带来的性能损耗,但是会增加服务的socket连接数 | +| **LOGIN_MODE_CREATE_HANDLE_ONLY(0x10000)** | 仅创建handle,不检查License **集团授权:**Login默认情况下会连接集团服务并占用一个用户数,加了该模式之后,在调用Query相关接口时才会连接服务器 **其它授权:**Login默认情况下会检查授权的可用性,加了该模式之后,在Query时才会检查 | +| **LOGIN_MODE_CREATE_NEW_HANDLE(0x20000)** | 创建新handle,每次创建的handle唯一 Login的请求默认都发pid 可以针对每一个handle进行设置属性,不会相互影响 | +| **LOGIN_MODE_MID(0x40000)** | 按设备占点(当没有设置LOGIN_MODE_ACCOUNT和LOGIN_MODE_GROUP时,默认按设备扣点) | +| **LOGIN_MODE_ACCOUNT(0x80000)** | 按帐号占点 | +| **LOGIN_MODE_GROUP(0x100000)** | 按分组名占点 | + + +### 示例 + +```c +// 使用高性能模式检查集团授权 +BIT_HANDLE handle = NULL; +BIT_STATUS status = Bit_Login( + NULL, NULL, application_data, + &handle, LOGIN_MODE(BIT_MODE_REMOTE | LOGIN_MODE_HIGH_PERFORMANCE )); +if (status == BIT_SUCCESS) { + // 校验成功 +} + +// 使用Session + 长连接模式检查集团授权 +BIT_HANDLE handle = NULL; +BIT_STATUS status = Bit_Login( + NULL, NULL, application_data, + &handle, LOGIN_MODE(BIT_MODE_REMOTE | LOGIN_MODE_SESSION | LOGIN_MODE_PERSISTENT_CONN )); +if (status == BIT_SUCCESS) { + // 校验成功 +} + +// 使用内存License +BIT_HANDLE handle = NULL; +BIT_CHAR *pLicense = "lic://xxxxxxx"; +BIT_STATUS status = Bit_Login(pLicense, NULL, application_data, &handle, BIT_MODE_AUTO); +if (status == BIT_SUCCESS) { + // 校验成功 +} + +// 先检查单机授权吗,如果没有再检查集团授权或云授权 +BIT_HANDLE handle = NULL; +BIT_STATUS status = Bit_Login(NULL, NULL, application_data, &handle, BIT_MODE_AUTO); +if (status == BIT_SUCCESS) { + // 校验成功 +} + +// 检查包含指定特征项的授权 +BIT_HANDLE handle = NULL; +BIT_UINT32 featureId = 1; +BIT_STATUS status = Bit_LoginEx(NULL, NULL, featureId, NULL, application_data, &handle, BIT_MODE_AUTO); +if (status == BIT_SUCCESS) { + // 校验成功 +} +``` + +### Bit_LoginByToken + +```c +BIT_STATUS Bit_LoginByToken( + BIT_PCSTR pUrl, + BIT_PCSTR pToken, + BIT_UCHAR *pApplicationData, + BIT_HANDLE *pHandle) +``` +帐号授权的登录接口。仅支持两种认证方式,这里是使用比特授权云平台自己产生的access_token进行认证。 + +### 参数 + +- **pUrl** - [IN] 服务器地址,可以为空。 +- **pToken** - [IN] 第三方身份源颁发的token或id_token,通过前缀区分。 + + +| **值** | **说明** | +| ----------------- | ---------------- | +| **token:xxx或xxx** | 使用access_token登录 | + + +- **pApplicationData** - [IN] 产品识别码,记录在接口定义文件中,与产品一一对应。 +- **pHandle** - [OUT] 通过Login函数返回的上下文句柄。 + +### Bit_LoginByTokenEx + +```c +BIT_STATUS Bit_LoginByTokenEx( + BIT_PCSTR pUrl, + BIT_PCSTR pBusinessGuid, + BIT_PCSTR pToken, + BIT_PCSTR pIdpGuid, + BIT_PCSTR pGrantType, + BIT_UCHAR *pApplicationData, + BIT_HANDLE *pHandle) +``` +帐号授权的登录接口。仅支持两种认证方式,这里是使用OIDC协议产生的id_token认证。 + +### 参数 + +- **pUrl** - [IN] 服务器地址,可以为空。 +- **pBussinessGuid** - [IN] 业务guid,在比特授权云平台获取。 +- **pToken** - [IN] 第三方身份源颁发的token或id_token,通过前缀区分。 + + +| **值** | **说明** | +| ---------------- | ------------ | +| **id_token:xxx** | 使用id_token登录 | + + +- **pIdpGuid** - [IN] 第三方身份源guid,在比特授权云平台获取。参数为空表示使用比特授权云平台产生的token进行登录,即Bit_LoginByToken。 +- **pGrantType** - [IN] 授权类型。固定值为“bitanswer:idp:oidc:id_token”。 +- **pApplicationData** - [IN] 产品识别码,记录在接口定义文件中,与产品一一对应。 +- **pHandle** - [OUT] 通过Login函数返回的上下文句柄。 + +### Bit_LoginByPassword + +```c +BIT_STATUS Bit_LoginByPassword( + BIT_PCSTR szURL, + BIT_PCSTR szBusinessGuid, + BIT_PCSTR szBusinessSecret, + BIT_PCSTR szAccount, + BIT_PCSTR szPassword, + BIT_UCHAR *pApplicationData, + BIT_HANDLE *pHandle); +``` +通过用户名和密码登录帐号授权。 + +### 参数 + +- **szURL** - [IN] 服务器地址,可以为空。 +- **pBussinessGuid** - [IN] 业务编号,在比特授权云平台获取。 +- **szBusinessSecret** [IN] 业务密钥,在比特授权云平台获取。 +- **szAccount** - [IN] 用户帐号。 +- **szPassword** - [IN] 用户密码。 +- **pApplicationData** - [IN] 产品识别码,记录在接口定义文件中,与产品一一对应。 +- **pHandle** - [OUT] 通过Login函数返回的上下文句柄。 + +### Bit_Logout + +```c +BIT_STATUS Bit_Logout ( + BIT_HANDLE handle) +``` +此函数用于释放上下文句柄,退出登录状态,与Login相关接口一一对应。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 + +### Bit_Revoke + +```c +BIT_STATUS Bit_Revoke ( + BIT_PCSTR szURL, + BIT_PCSTR szSN, + BIT_UCHAR *pApplicationData, + BIT_CHAR *pRevocationInfo, + BIT_UINT32 *pRevocationInfoSize) +``` +从客户端迁出已激活的浮动授权码。授权码迁出后,可以用于其它的客户端。根据输入参数的不同,本函数可用于在线或离线迁出。 + +### 参数 + +- **szURL** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **szSN** - [IN] 授权码(SN)字符串。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **pRevocationInfo** - [OUT] 迁出请求码的存储区地址。为NULL表示进行在线迁出,否则API将执行手工离线迁出,请求码应发给服务器进行确认。 +- **pRevocationInfoSize** - [IN/OUT] 输入时为请求码存储区大小,输出时为请求码长度。如此参数为NULL,函数将选择在线迁出。 + +### Bit_RemoveSn + +```c +BIT_STATUS Bit_RemoveSn ( + BIT_PCSTR szSN, + BIT_UCHAR *pApplicationData) +``` +删除指定授权码在本机的授权数据。 + +### 参数 + +- **szSN** - [IN] 授权码(SN)字符串。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 + +### Bit_Heartbeat + +```c +BIT_STATUS Bit_Heartbeat( + BIT_HANDLE handle, + BIT_UINT32 *pReconnectsNum) +``` +手动心跳,可以无限次调用,10s只会触发一次。 + +注:当自动心跳停止后,调用该接口可以尝试恢复自动心跳。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **pReconnectsNum** - [OUT] 保存心跳失败次数,开发上可以根据该次数决定是否退出程序。 + +### Bit_SessionControl + +```c +BIT_STATUS Bit_SessionControl( + BIT_PCSTR szURL, + BIT_PCSTR pSessionId, + BIT_UINT32 type, + BIT_UCHAR *pApplicationData, + BIT_CHAR *pValue, + BIT_UINT32 *pValueLen) +``` +控制或设置session的信息。具体使用场景可参考《浏览器并发控制》文档。 + +### 参数 + +- **szURL** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **pSessionId** - [IN] Login后的sessionId,通过[Bit_GetSessionInfo](https://doc.bitanswer.cn/docs/client-api/c-interface-definitions-v2/#Bit_GetSessionInfo)可以获取。 +- **type** - [IN] 类型。 + + +| **类型** | **说明** | +| --------------------------- | ------------------ | +| **SESSION_CTL_LOGOUT(0x1)** | 释放session | +| **SESSION_CTL_CHECK(0x2)** | 触发心跳并获取sessionId状态 | + + +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **pValue** - [OUT] 数据缓存区。 +- **pValueLen** - [IN/OUT] 输入时是数据缓存区的大小,输出时是实际数据长度。 + +### Bit_SetSessionState + +```c +BIT_STATUS Bit_SetSessionState ( + BIT_HANDLE handle, + BIT_UINT32 state, + BIT_VOID *pReserved) +``` +设置客户端的状态为空闲状态或繁忙状态或激活状态。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **state** - [IN] 设置客户端的状态选项。 + + +| **值** | **说明** | +| ------------------------ | -------------------------------------------------- | +| **SESSION_STATE_UNSET** | 默认值,表示不设置客户端的状态,服务端根据心跳状态来维护session,心跳断开则释放session | +| **SESSION_STATE_IDLE** | 表示设置客户端为空闲态,服务端会在空闲时间超过设10分钟后自动释放session | +| **SESSION_STATE_BUSY** | 表示设置客户端为繁忙状态,服务端不会自动释放,直到心跳断开或者客户端主动释放 | +| **SESSION_STATE_ACTIVE** | 表示设置客户端为活跃状态,重新计算空闲时间 | + + +- **pReserved** - [OUT] 目前保留必须传NULL。 + +### 示例 + +```c +BIT_STATUS status = BIT_SUCCESS; +BIT_UINT32 reserved = 0; + +if (用户正在操作) { + status = Bit_SetSessionState (handle, SESSION_STATE_ACTIVE, &reserved); +} else if (用户空闲) { + status = Bit_SetSessionState (handle, SESSION_STATE_IDLE, &reserved); +} +``` + +## 激活升级 + + +### Bit_UpdateOnline + +```c +BIT_STATUS Bit_UpdateOnline ( + BIT_PCSTR szURL, + BIT_PCSTR szSN, + BIT_UCHAR *pApplicationData) +``` +此函数用于与授权服务器在线连接,自动完成本地授权的升级操作。本函数需要进行网络连接。 + +### 参数 + +- **szURL** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **szSN** - [IN] 该参数可以传入授权码;激活口令;帐号密码;BIT-ID序号。传入方式参考[Bit_Login](https://doc.bitanswer.cn/docs/client-api/c-interface-definitions-v2/#Bit_LoginBit_LoginEx)的szSN参数说明。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 + +### 示例 + +```c +BIT_CHAR *pSn = "<授权码>"; +BIT_STATUS status = Bit_UpdateOnline("", pSn, application_data); +if (status == BIT_SUCCESS) { + // 激活或升级成功 +} +``` + +### Bit_GetRequestInfo + +```c +BIT_STATUS Bit_GetRequestInfo ( + BIT_PCSTR szSN, + BIT_UCHAR *pApplicationData, + BINDING_TYPE type, + BIT_CHAR *pRequestInfo, + BIT_UINT32 *pRequestInfoSize) +``` +获取当前运行环境的升级请求码,用于发起本地授权激活及升级请求。如果第一次调用返回错误码260,说明传入的pRequestInfoSize太小,可传入返回的pRequestInfoSize再重新调用一次。 + +### 参数 + +- **szSN** - [IN] 授权码(SN)字符串。如果为空(空串或NULL)则尝试寻找所有当前本机可用的SN。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **type** - [IN] 获取请求码的类型。 + + +| **类型** | **说明** | +| -------------------- | ----------------------- | +| **BINDING_EXISTING** | 使用当前绑定类型,对已激活授权码进行升级时使用 | +| **BINDING_LOCAL** | 使用本机指纹进行绑定 | +| **REQ_TYPE_MID** | 获取设备码 | + + +- **pRequestInfo** - [OUT] 用于存储请求码的存储区地址。 +- **pRequestInfoSize** - [IN/OUT] 输入时为请求码存储区大小,输出时为请求码长度。 + +### 示例 + +```c +// 获取请求串 +BIT_CHAR *pSn = "<授权码>"; +BIT_CHAR buff[1024] = { 0 }; +BIT_UINT32 len = sizeof(buff); +BIT_STATUS status = Bit_GetRequestInfo (pSn, application_data, BINDING_LOCAL, buff, &len); +if (status == BIT_SUCCESS) { + // 请求串保存在buff里 +} + +// 获取设备码 +BIT_STATUS status = Bit_GetRequestInfo (NULL, application_data, REQ_TYPE_MID, buff, &len); +if (status == BIT_SUCCESS) { + // 设备码保存在buff里 +} +``` + +### Bit_ApplyUpdateInfo + +```c +BIT_STATUS Bit_ApplyUpdateInfo( + BIT_UCHAR *pApplicationData, + BIT_PCSTR pUpdateInfo, + BIT_CHAR *pReceipt, + BIT_UINT32 *pReceiptSize) +``` +应用升级码完成本地授权激活或升级。本函数必须在获取请求码的同一环境下执行。 + +### 参数 + +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **pUpdateInfo** - [IN] 由授权服务器获得的本地授权升级码。 +- **pReceiptInfo** - [OUT] 确认码,记录升级状态,可在控制台上解析。 +- **pReceiptInfoSize** - [IN/OUT] 输入时为存储区大小,输出时为确认码长度。 + +### 示例 + +```c +// 获取请求串 +BIT_CHAR *pUpdateInfo = "<升级串>"; +BIT_CHAR buff[1024] = { 0 }; +BIT_UINT32 len = sizeof(buff); + +BIT_STATUS status = Bit_ApplyUpdateInfo(application_data, pUpdateInfo, buff, &len); +if (status == BIT_SUCCESS) { + // 升级串使用成功,Buff里保存的是确认串 +} +``` + +### Bit_ApplyUpdateInfoEx + +```c +BIT_STATUS Bit_ApplyUpdateInfoEx( + BIT_CHAR *pScope, + BIT_UCHAR *pApplicationData, + BIT_PCSTR pUpdateInfo, + BIT_CHAR *pReceipt, + BIT_UINT32 *pReceiptSize); +``` +应用升级码完成远程集团授权激活或升级。一般不建议使用。 + +### 参数 + +- **pScope** - [IN] 集团服务的URL。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **pUpdateInfo** - [IN] 由授权服务器获得的本地授权升级码。 +- **pReceiptInfo** - [OUT] 确认码,记录升级状态,可在控制台上解析。pReceiptInfoSize - [IN/OUT] 输入时为存储区大小,输出时为确认码长度。 + +### Bit_GetUpdateInfo + +```c +BIT_STATUS Bit_GetUpdateInfo ( + BIT_PCSTR szURL, + BIT_PCSTR szSN, + BIT_UCHAR *pApplicationData, + BIT_PCSTR pRequestInfo, + BIT_CHAR *pUpdateInfo, + BIT_UINT32 *pUpdateInfoSize) +``` +使用请求码与授权服务器进行连接,获取升级码。本函数需要进行网络连接。 + +### 参数 + +- **szURL** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **szSN** - [IN] 授权码(SN)字符串。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **pRequestInfo** - [IN] 由获取请求码函数得到的请求码。 +- **pUpdateInfo** - [OUT] 由授权服务器获得的本地授权升级码。 +- **pUpdateInfoSize** - [IN/OUT] 输入时为存储区大小,输出时为升级码长度。 + +## 特征项操作 + + +### Bit_BatchBegin + +```c +BIT_STATUS Bit_BatchBegin( + BIT_HANDLE handle, + BIT_UINT32 mode) +``` +开启批量Query模式,调用此API后调用的所有Query相关API,全部由Bit_BatchEnd接口批量提交连接集团服务。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **mode** - [IN] 批量请求的行为模式。 + + +| **类型** | **说明** | +| --------------------------------- | ----------------------------- | +| **BIT_BATCH_MODE_CONTINUE (0x0)** | 批量提交过程中,遇到失败的接口会记录错误信息,并且继续执行 | +| **BIT_BATCH_MODE_BREAK (0x01)** | 批量提交过程中,遇到失败的接口会记录错误信息,直接返回错误 | + + +### Bit_BatchEnd + +```c +BIT_STATUS Bit_BatchEnd( + BIT_HANDLE handle, + BIT_UINT32 *pResultList, + BIT_UINT32 *pResultListSize) +``` +批量提交Query请求。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **pResultList** - [OUT] 按顺序返回每个接口的错误码,0表示成功,非0表示失败,传NULL表示清理添加的批量数据。 +- **pResultListSize** - [OUT] 返回调用接口的数量。 + +### 示例 + +```c +// 开启批次 +Bit_BatchBegin(handle, BIT_BATCH_MODE_CONTINUE); +BIT_UINT32 result[3] = { 0 }; +BIT_UINT32 resultNum = 3; +BIT_TICKET ticket = NULL; +BIT_UINT32 capacity = 0; +Bit_QueryFeature(handle, 1, &capacity); +Bit_QueryFeatureEx2(handle, "test", 0, 10, "1.0", &ticket); +// 批量提交 +Bit_BatchEnd(handle, result,& resultNum) ; +if (result[0] == BIT_SUCCESS) +{ + // Bit_QueryFeature(1) success +} +if (result[1] == BIT_SUCCESS) +{ + // Bit_QueryFeatureEx2 ("test") success} +} +``` + +### Bit_QueryFeature + +```c +BIT_STATUS Bit_QueryFeature ( + BIT_HANDLE handle, + BIT_UINT32 featureId, + BIT_UINT32 *pCapacity) +``` +开发商可以对软件的某个功能进行单独授权,当程序运行该模块时,可以通过该接口检查是否可用。 + +对于单机授权:只检查特征项是否可用。 + +云/帐号/集团授权:调用该接口将占用一个用户数,用户数占满时,调用该接口会报错。开发商可以通过该方式来控制并发。(当客户端断开连接后,服务端会自动释放占用的用户数) + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureId** - [IN] 特征项ID。 +- **pCapacity** - [OUT] 当不为NULL时,获取特征项当前可用用户数。 + +重复调用引用会+1,通过Bit_ReleaseFeature来减少引用,当引用减少到0时,释放占用的用户数。 + +### 示例 + +```c +BIT_UINT32 featureId = 1; +BIT_UINT32 capacity = 0; +BIT_STATUS status = Bit_QueryFeature(handle, featured, &capacity); +if (status == BIT_SUCCESS) { + // 特征项1有效 +} +``` + +### Bit_ReleaseFeature + +```c +BIT_STATUS Bit_ReleaseFeature ( + BIT_HANDLE handle, + BIT_UINT32 featureId, + BIT_UINT32 *pCapacity) +``` +释放所占用的用户数,该函数和Bit_QueryFeature一一对应。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureId** - [IN] 特征项ID。 +- **pCapacity** - [OUT] 当不为NULL时,获取特征项当前可用用户数。 + +### 示例 + +```c +BIT_UINT32 capacity = 0; +BIT_STATUS status = Bit_QueryFeature(handle, 1, capacity); +if (status != BIT_SUCCESS) { + return; +} +// 执行业务逻辑 + +// 执行后,进行释放 +status = Bit_ReleaseFeature(handle, 1, &capacity); +``` + +### Bit_QueryFeatureEx + +```c +BIT_STATUS Bit_QueryFeatureEx ( + BIT_HANDLE handle, + BIT_UINT32 featureId, + BIT_UINT32 mode, + BIT_UINT32 required, + BIT_UINT32 *pCapacity, + BIT_PCSTR xmlScope) +``` +集团授权专用,该接口支持占用指定用户数,支持通过特征项版本进行检查。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureId** - [IN] 特征项ID。 +- **mode** - [IN] + + +| **类型** | **说明** | +| ----------------------------- | ------------------------------------------------------------------------------------- | +| **BIT_QUERY_DEFAULT(0x0)** | 非阻塞占用required个用户数,如果用户数不够将返回错误 | +| **BIT_QUERY_AVAILABLE(0x01)** | 尽可能的占用required个用户数,如果用户数不够将占用剩余用户数 例如:Feature剩余10个用户数。Required需要占用20个,则返回成功,并占用10个用户数 | +| **BIT_QUERY_CHECK(0x02)** | 获取当前session占用的用户数 | +| **BIT_QUERY_TEST(0x100)** | 该类型可以与上面的选项组合使用,检查操作是否可以成功,但并不占用用户数 例如:(BIT_QUERY_DEFAULT | + + +- **required** - [IN] 请求的用户数,该接口可以调用多次,实际的占用的用户数为,每次调用的最大值。 + +  示例: + +  第一次:required了10个。 + +  第二次:required了8个,此时总共占用10个。 + +  第三次:required了15个,此时总共占用15个。 + +- **pCapacity** - [OUT] 当不为NULL时,获取特征项当前可用用户数。 +- **xmlScope** - [IN] 可以传入特征项版本。示例“1.0”,“2.0”,如果为空,则匹配任意版本的特征项。 + +### 示例 + +```c +// 占用特征项ID为8的10个用户数: + +BIT_UINT32 capacity = 0; +BIT_STATUS status = Bit_QueryFeatureEx ( + handle, + 8, + BIT_QUERY_DEFAULT, + 10, + &capacity, + NULL); +if (status == BIT_SUCCESS) { + // 特征项“8”用户数占用成功 + // 执行业务逻辑代码 +} +``` + +### Bit_ReleaseFeatureEx + +```c +BIT_STATUS Bit_ReleaseFeatureEx ( + BIT_HANDLE handle, + BIT_UINT32 featureId, + BIT_UINT32 consumed, + BIT_UINT32 *pCapacity, + BIT_PCSTR xmlScope) +``` +集团授权专用,释放指定的用户数。该接口与Bit_QueryFeatureEx对应。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureId** - [IN] 特征项ID。 +- **consumed** - [IN] 释放指定用户数,如果为0,表示释放全部用户数。 +- **pCapacity** - [OUT] 返回剩余用户数。 +- **xmlScope** - [IN] 可以传入特征项版本。注意:必须与Bit_QueryFeatureEx的输入的版本一致,才可以释放。 + +### 示例 + +```c +// 释放占用特征项ID为8的2个用户数: + +BIT_UINT32 capacity = 0; +BIT_STATUS status = Bit_ReleaseFeatureEx ( + handle, + 8, + 2, + &capacity, + NULL) +if (status == BIT_SUCCESS) { + // 用户数释放成功 +} +``` + +### Bit_QueryFeatureEx2 + +```c +BIT_STATUS Bit_QueryFeatureEx2 ( + BIT_HANDLE handle, + BIT_PCSTR featureName, + BIT_UINT32 mode, + BIT_UINT32 required, + BIT_PCSTR xmlScope, + BIT_TICKET *pTicket) +``` +可以使用“特征项名称 + 特征项版本”进行用户数占用,支持队列模式。 + +对于单机授权:只检查特征项是否可用。 + +云/帐号/集团授权:调用该接口将占用一个用户数,用户数占满时,调用该接口会报错。开发商可以通过该方式来控制并发。(当客户端断开连接后,服务端会自动释放占用的用户数) + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureName** - [IN] 特征项名称。 +- **mode** - [IN] + + +| **类型** | **说明** | +| ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **BIT_QUERY_DEFAULT(0x00)** | 非阻塞占用required个用户数,如果用户数不够将返回错误 **注意:**云/帐号授权仅支持该模式 | +| **BIT_QUERY_AVAILABLE(0x01)** | 尽可能的占用required个用户数,如果用户数不够将占用剩余用户数。 例如:Feature剩余10个用户数。Required需要占用20个,则返回成功,并占用10个用户数。 | +| **BIT_QUERY_WAIT(0x03)** | 加入等待队列,可以设置超时,超时后,将自动返回 | +| **BIT_QUERY_QUEUE(0x04)** | 加入队列,通过Bit_GetTicketInfo可以查看队列状态 | +| **BIT_QUERY_TEST(0x100)** | 该类型可以与上面的选项组合使用,检查操作是否可以成功,但并不占用用户数 例如:(BIT_QUERY_DEFAULT | +| **BIT_QUERY_SHARED_USERS(0x200)** | User用户数共享。 默认情况下调用该接口的用户数是不共享的,即:第一次QueryFeatureEx2了10个用户数,第二次QueryFeatureEx2了10个用户数,总共占用20个用户数。 当设置了该属性,如果两次QueryFeature的特征项名称、版本都一致,则用户数是可以合并的,例如:两次各QueryFeatureEx2了10个用户数,则总共占用10用户数。 | +| **BIT_QUERY_SERVICE_RANDOM(0x400)** | IP随机。 该模式需要与Login的LOGIN_MODE_CREATE_HANDLE_ONLY配合使用。 设置了该模式后,当Login的handle没有登录过,则在连接服务器时会随机轮询IP。 默认情况下,客户端会按配置的IP顺序挨个查找,设置了该模式会随机轮询,从而减少排在前面的IP负载。 | +| **BIT_QUERY_USE_ID(0x800)** | 使用featureId占用feature。 设置了该模式后,featureName参数必须传入纯数字的字符串,例如“1”,客户端会将该字符串转化为featureId发送给服务端来占用featureId为1的feature。 | +| **BIT_QUERY_MID_ONLY(0x1000)** | 按MID占用特征项。 - 未指定MID_ONLY时:默认优先占用已绑定MID的特征项;若不存在,则占用未绑定MID的特征项。- 指定MID_ONLY时:仅允许占用已绑定MID的特征项,具体场景及返回结果如下: - 若集团服务的所有特征项均未绑定MID,返回错误码1924。 - 若集团服务存在绑定MID的特征项,但客户端传入的MID与集团授权绑定的MID不匹配,返回错误码416。 - 若集团服务存在绑定MID的特征项,且客户端传入的MID与集团授权绑定的MID匹配,正常占用特征项。**版本支持:**14.5.0及以上版本新增类型,需配合14.5.0及以上版本的集团服务和客户端库使用 | + + +- **required** - [IN] 请求的用户数。 +- **xmlScope** - [IN] 可以传入特征项版本。示例:“1.0”,“2.1”。 +- **pTicket** - [OUT] + +### 示例 + +```c +// 占用特征项A 1.0版本,5个用户数: + +BIT_TICKET ticket = NULL; +BIT_STATUS status = Bit_QueryFeatureEx2 ( + handle, + "特征项A", + BIT_QUERY_DEFAULT, + 5, + "1.0", + &ticket); + +if (status == BIT_SUCCESS) { + // 占用成功,执行业务逻辑 +} +``` + +### Bit_ReleaseFeatureEx2 + +```c +BIT_STATUS Bit_ReleaseFeatureEx2 ( + BIT_TICKET ticket, + BIT_UINT32 consumed) +``` +释放ticket所占用的用户数。该函数和Bit_QueryFeatureEx2一一对应。 + +### 参数 + +- **ticket** - [IN] 通过QueryFeatureEx2返回的句柄。 +- **consumed** - [IN] 保留值,必须是0。 + +### 示例 + +```c +BIT_STATUS status = Bit_ReleaseFeatureEx2 (ticket, 0); +if (status == BIT_SUCCESS) { + // 释放ticket占用的用户数 +} +``` +**特征项Query相关接口比较** + + +| **函数** | **特征项ID** | **特征项名称** | **特征项版本** | **一次Query多个用户数** | **队列** | **用户数递增/递减** | +| ----------------------- | --------- | --------- | --------- | ---------------- | ------ | ------------ | +| **Bit_QueryFeature** | 支持 | | | | | | +| **Bit_QueryFeatureEx** | 支持 | | 支持 | 支持 | | 支持 | +| **Bit_QueryFeatureEx2** | 支持 | 支持 | 支持 | 支持 | 支持 | | + + +### Bit_GetFeatureInfo2 + +```c +BIT_STATUS Bit_GetFeatureInfo2 ( + BIT_HANDLE handle, + BIT_PCSTR featureName, + BIT_PCSTR xmlScope, + BIT_INT32 *pExpired) +``` +检查特征项是否存在,不会占用授权码或特征项的用户数,获取特征项的剩余有效期。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureName** - [IN] 产品的特征项名称。 +- **xmlScope** - [IN] 查找范围,可以通过 xml 格式传入版本,也可以直接传入版本的字符串。 + +```xml + + 1.1 + + + +``` +- **pExpired** - [OUT] 返回该特征项的剩余有效期,正数代表剩余有效期,负数代表过期天数,36500代表永久有效。 + +### Bit_GetFeatureInfoEx2 + +```c +BIT_STATUS Bit_GetFeatureInfoEx2( + BIT_HANDLE handle, + BIT_PCSTR featureName, + BIT_PCSTR xmlScope, + BIT_CHAR *pFeatureInfo, + BIT_UINT32 *pFeatureInfoSize); +``` +获取指定feature的信息,以XML格式返回。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureName** - [IN] 产品的特征项名称。 +- **xmlScope** - [IN] 查找范围,可以通过 xml 格式传入版本,也可以直接传入版本的字符串。 + +```xml + + 1.1 + + + +``` +- **pFeatureInfo** - [OUT] feature信息存储区地址。 +- **pFeatureInfoSize** - [IN/OUT] 会话存储区大小。 + +### Bit_GetTicketInfo + +```c +BIT_STATUS Bit_GetTicketInfo( + BIT_TICKET ticket, + BIT_UINT32 type, + BIT_CHAR *pXmlInfo, + BIT_UINT32 *pSize) +``` +获取ticket信息。 + +### 参数 + +- **ticket** - [IN] Bit_QueryFeatureEx2产生的句柄。 +- **type** - [IN] 类型。 + + +| **类型** | **说明** | +| ------------------------------ | -------------- | +| **BIT_TICKET_TYPE_USERS(0x1)** | 获取ticket占用的用户数 | +| **BIT_TICKET_TYPE_CHECK(0x2)** | 检查当前ticket的状态 | +| **BIT_TICKET_TYPE_INFO(0x3)** | 获取当前ticket的信息 | + + +- **pXmlInfo** - [OUT] ticket信息存储区地址。 +- **pSize** - [IN/OUT] 输入时为存储区长度,输出时为返回信息的长度。 + +BIT_TICKET_TYPE_INFO返回的xml信息如下 + +```c + + + + 1 + test + 10 + 1.0 + + + + + 4HAYJUOA******** + Local/group + + 1.0 + 3 + + + + 4HAYJUOA******** + Local/group + + 2.0 + 7 + + + +``` + +### Bit_ConvertFeature + +```c +BIT_STATUS Bit_ConvertFeature( + BIT_HANDLE handle, + BIT_UINT32 featureId, + BIT_UINT32 para1, + BIT_UINT32 para2, + BIT_UINT32 para3, + BIT_UINT32 para4, + BIT_UINT32 *pResult); +``` +使用“算法”类型的特征项对输入参数进行变换操作,得到唯一对应的4字节结果。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureId** - [IN] 产品的特征项ID。 +- **para1** - [IN] 变换输入因子1。 +- **para2** - [IN] 变换输入因子2。 +- **para3** - [IN] 变换输入因子3。 +- **para4** - [IN] 变换输入因子4。 +- **pResult** - [OUT] 变换结果。 + +### 示例 + +```c +BIT_HANDLE handle = xx, +BIT_UINT32 featureId = xx; +BIT_UINT32 par1 = 0x1234; +BIT_UINT32 par2 = 0x2234; +BIT_UINT32 par3 = 0x3234; +BIT_UINT32 par4 = 0x4234; +BIT_UINT32 convertResult; +BIT_STATUS status = Bit_ConvertFeature(handle, featureId, par1, par2, par3, par4, &convertResult); +``` + +### Bit_EncryptFeature + +```c +BIT_STATUS Bit_EncryptFeature( + BIT_HANDLE handle, + BIT_UINT32 featureId, + BIT_VOID *pPlainBuffer, + BIT_VOID *pCipherBuffer, + BIT_UINT32 dataBufferSize); +``` +使用“密钥”类型的特征项对输入的明文进行加密,返回密文结果。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureId** - [IN] 产品的特征项ID。 +- **pPlainBuffer** - [IN] 数据缓存区地址,用于存储明文数据。 +- **pCipherBuffer** - [OUT] 数据缓存区地址,用于存储密文数据。 +- **bufferSize** - [IN] 数据长度,最大长度为256字节。 + +### 示例 + +```c +BIT_HANDLE handle = xx, +BIT_UINT32 featureId = xx; +BIT_UCHAR plainbuffer[256] = "this is plain data"; +BIT_UCHAR cipherbuffer[256] = { 0 }; +BIT_UINT32 dataLen = strlen(plainbuffer); + +BIT_STATUS status = Bit_EncryptFeature(handle, featureId, plainbuffer, cipherbuffer, dataLen); +``` + +### Bit_DecryptFeature + +```c +BIT_STATUS Bit_DecryptFeature( + BIT_HANDLE handle, + BIT_UINT32 featureId, + BIT_VOID *pCipherBuffer, + BIT_VOID *pPlainBuffer, + BIT_UINT32 dataBufferSize); +``` +使用“密钥”类型的特征项对输入的密文进行解密,返回明文结果。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureId** - [IN] 产品的特征项ID。 +- **pCipherBuffer** - [IN] 数据缓存区地址,用于存储密文数据。 +- **pPlainBuffer** - [OUT] 数据缓存区地址,用于存储明文数据。 +- **bufferSize** - [IN] 数据长度,最大长度为256字节。 + +### 示例 + +```c +BIT_HANDLE handle = xx, +BIT_UINT32 featureId = xx; +BIT_UCHAR plainbuffer[256] = { 0 }; +BIT_UCHAR cipherbuffer[256] ="xxxxxxxxx"; +BIT_UINT32 dataLen = 16; + +BIT_STATUS status = Bit_DecryptFeature(handle, featureId, cipherbuffer, plainbuffer, dataLen); +``` + +### Bit_ReadFeature + +```c +BIT_STATUS Bit_ReadFeature( + BIT_HANDLE handle, + BIT_UINT32 featureId, + BIT_UINT32 *pFeatureValue); +``` +读取特征项的数据内容,可用于“只读”和“读写”特征类型。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureId** - [IN] 产品的特征项ID。 +- **pFeatureValue** - [OUT] 特征项数据缓存区地址,用于存储读出的数据。 + +### Bit_WriteFeature + +```c +BIT_STATUS Bit_WriteFeature( + BIT_HANDLE handle, + BIT_UINT32 featureId, + BIT_UINT32 featureValue); +``` +更新“读写”类型的特征项的数据内容。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **featureId** - [IN] 产品的特征项ID。 +- **featureValue** - [IN] 特征项数据值。 + +## 配置项操作 + + +### Bit_GetDataItem + +```c +BIT_STATUS Bit_GetDataItem ( + BIT_HANDLE handle, + BIT_PCSTR szDataItemName, + BIT_VOID *pDataItemValue, + BIT_UINT32 *pDataItemValueSize) +``` +读取指定的配置项数据。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **szDataItemName** - [IN] 数据项名称,名称最大长度为128字节。 +- **pDataItemValue** - [OUT] 数据缓存区地址,数据最大长度为1024字节。 +- **pDataItemValueSize** - [IN/OUT] 数据项长度。 + +### Bit_SetDataItem + +```c +BIT_STATUS Bit_SetDataItem ( + BIT_HANDLE handle, + BIT_PCSTR szDataItemName, + BIT_VOID *pDataItemValue, + BIT_UINT32 dataItemValueSize) +``` +创建或更新配置项。如果相同名称的配置项存在,则会更新其中的数据;否则将添加新的授权码配置项。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **szDataItemName** - [IN] 数据项名称,名称最大长度为128字节。 +- **pDataItemValue** - [IN] 数据项数据缓存区地址,数据最大长度为1024字节。 +- **dataItemValueSize** - [IN] 数据项长度。 + +### Bit_GetDataItemNum + +```c +BIT_STATUS Bit_GetDataItemNum ( + BIT_HANDLE handle, + BIT_UINT32 *pNum) +``` +此函数用于获取可访问配置项的数量,一般用于配置项的枚举操作。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **pNum** - [OUT] 可访问的数据项总数,包括了所有可以访问到的产品、模版及授权码的数据项。 + +### Bit_GetDataItemName + +```c +BIT_STATUS Bit_GetDataItemName ( + BIT_HANDLE handle, + BIT_UINT32 index, + BIT_CHAR *pDataItemName, + BIT_UINT32 *pDataItemNameSize) +``` +根据配置项索引获取其名称,一般用于配置项的枚举操作。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **index** - [IN] 数据项索引。 +- **pDataItemName** - [OUT] 用于存储数据项名称的存储区地址。 +- **pDataItemNameSize** - [IN/OUT] 数据项名称存储区大小。 + +### Bit_RemoveDataItem + +```c +BIT_STATUS Bit_RemoveDataItem ( + BIT_HANDLE handle, + BIT_PCSTR szDataItemName) +``` +删除指定的配置项。该操作无法删除通过控制台设置的产品配置项或模版配置项。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **szDataItemName** - [IN] 数据项名称,名称最大长度为128字节。 + +## 信息获取 + + +### Bit_GetSessionInfo + +```c +BIT_STATUS Bit_GetSessionInfo ( + BIT_HANDLE handle, + SESSION_TYPE type, + BIT_CHAR *pSessionInfo, + BIT_UINT32 *pSessionInfoSize) +``` +获取当前会话信息,以字符串形式返回。根据获取的内容不同,返回结果可能是XML格式或非XML格式。返回数据中的日期项已根据客户端的本地时区进行调整。如果Login时未指定SN,返回串为当前系统所有可用SN的综合结果。 + +当函数返回BIT_ERR_BUFFER_SMALL时,pSessionInfoSize保存的是实际数据的大小。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。 +- **type** - [IN] 获取会话信息类型。 + + +| 类型 | 说明 | +| ----------------------------- | ------------------------------------------------------------------------------------------------ | +| **XML_TYPE_SN_INFO** | 获取当前会话中授权码的授权信息,以XML形式返回。未做限制的授权项将不会返回 | +| **XML_TYPE_FEATURE_INFO** | 获取当前会话中授权码的特征项信息,以XML形式返回 | +| **XML_TYPE_SN_FEATURE_INFO** | 获取当前会话中授权码及授权码特征项的授权信息,以XML形式返回 **版本支持:**14.5.2及以上版本客户端库和集团服务支持返回MID信息(设置时才显示)、特征项的index(用于唯一标识) | +| **XML_TYPE_DATA_INFO** | 获取当前会话中授权码的配置项信息,以XML形式返回 | +| **BIT_SERVER_ADDRESS** | 授权服务器IP地址。单机授权不支持 | +| **BIT_SERVER_TIME** | 授权服务器系统时间。如果是本地授权,将返回本机系统时间 | +| **BIT_CONTROL_TYPE** | 授权类型。是以逗号分隔的以下几种类型的组合:Group(集团授权), Smart(智能连接), Float(可浮动), Demo(演示授权), USB(U盘授权), Force(强制认证) | +| **BIT_VOLUME_NUMBER** | 允许使用的机器数量 | +| **BIT_START_DATE** | 授权开始日期,Unlimited表示无限制 | +| **BIT_END_DATE** | 授权结束日期,Unlimited表示无限制 | +| **BIT_EXPIRATION_DAYS** | 授权有效期,单位为天。有效期从激活时间算起,Unlimited表示无限制 | +| **BIT_USAGE_NUMBER** | 最大使用次数 | +| **BIT_CONSUMED_USAGE_NUMBER** | 对于设定最大使用次数的授权码,返回当前使用次数 | +| **BIT_ACTIVATE_DATE** | 授权码激活时间 | +| **BIT_USER_LIMIT** | 集团授权用户数,返回纯数字。对其它方式的授权返回0 | +| **BIT_LAST_UPDATE_DATE** | 最后与服务器连接时间 | +| **BIT_MAX_OFFLINE_MINUTES** | 强制认证最大离线时间(分钟),返回Unlimited表示无强制认证 | +| **BIT_SESSION_ID** | 获取当前会话的字符串sessionId | +| **BIT_SERVER_HB_STATUS** | 获取心跳状态,pSessionInfo无数据,状态通过函数返回值区分 | +| **BIT_TICKET_LIST_BIN** | 获取TICKET列表 | + + +- **pSessionInfo** - [OUT] 会话信息存储区地址。可以为NULL,此时仅用于获取存储区大小。 +- **pSessionInfoSize** - [IN/OUT] 会话存储区大小。 + +### 示例 + +```c +BIT_UINT32 buffSize = 10240; +BIT_CHAR *pBuff = (BIT_CHAR *)malloc(buffSize); +if (pBuff == NULL) { + return; +} +memset(pBuff, 0, buffSize); +BIT_STATUS status = Bit_GetSessionInfo (handle, + XML_TYPE_SN_INFO, + pBuff, + & buffSize); + +if (status == BIT_ERR_BUFFER_SMALL) { + free(pBuff); + pBuff = malloc(buffSize + 1); + memset(pBuff, 0, buffSize + 1); + + status = Bit_GetSessionInfo (handle, + XML_TYPE_SN_INFO, + pBuff, + &buffSize); +} + +if (status == BIT_SUCCESS) { + // pBuff 保存的是需要查找的数据 +} +free(pBuff); +``` + +### Bit_GetInfo + +```c +BIT_STATUS Bit_GetInfo ( + BIT_PCSTR szSN, + BIT_UCHAR *pApplicationData, + INFO_TYPE type, + BIT_CHAR *pInfo, + BIT_UINT32 *pInfoSize) +``` +获取本地授权信息。 + +如果要获取集团授权的信息,则szSN输入“`@bit://ip:port`”,会获取集团授权信息(仅支持type=BIT_INFO_SN)。 + +由于集团授权需要登录才能获取信息,而登录需要占用用户数,此方式提供了一个在不登录的情况下来获取集团授权信息。 + +### 参数 + +- **szSN** - [IN] 输入要检索的SN,如果为NULL,表示获取所有SN。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **type** - [IN] 类型。 + + +| **类型** | **说明** | +| --------------------------- | --------------------------------------- | +| **BIT_INFO_SERVER_ADDRESS** | 获取局域网内的集团授权服务器地址列表 | +| **BIT_INFO_SN** | 获取本机已激活的授权码列表 | +| **BIT_INFO_SN_FEATURE** | 获取本机已激活授权码的特征项列表 **版本支持:**集团授权支持返回MID信息 | +| **BIT_INFO_SN_LICENSE** | 获取本机已激活授权码的授权信息 | +| **BIT_INFO_UPDATE_ERROR** | 获取指定授权码的升级错误详细信息。是否存在详细信息由授权码类型及错误类型决定 | +| **BIT_INFO_CONFIG** | 获取当前产品的配置文件信息 | +| **BIT_INFO_TOKEN_LIST** | 获取当前机器上可用的BIT-ID列表信息 | + + +- **pInfo** - [OUT] 数据缓存区地址。 +- **pInfoSize** - [IN/OUT] 输入时是数据缓存区大小,输出时是实际数据的长度。 + +### Bit_GetServerInfo + +```c +BIT_STATUS Bit_GetServerInfo( + BIT_PCSTR szURL, + BIT_PCSTR szSN, + BIT_PCSTR xmlScope, + BIT_UCHAR *pApplicationData, + BIT_INFO_EX_TYPE type, + BIT_CHAR *pServerInfo, + BIT_UINT32 *pServerInfoSize); +``` +获取集团服务的License信息,数据以XML格式返回。调用此函数前客户端不需要执行登录操作。 + +### 参数 + +- szURL - [IN] 指定集团授权服务器地址,包括端口。 +- szSN - [IN] 授权码(SN)字符串。 +- xmlScope- [IN] 查询指定特征项的信息,以XML格式传入。14.6.0及以上版本支持传入groupName指定查询分组,具体使用规则参见下文xmlScope使用说明。 +- pApplicationData - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- type- [IN] 获取信息类型。 + + +| **类型** | **说明** | +| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **BIT_SERVER_INFO_SN** | 获取集团服务的授权码列表 | +| **BIT_SERVER_INFO_SN_FEATURE** | 获取集团服务的授权码的特征项列表 **版本支持:**14.5.2及以上版本客户端库和集团服务支持返回MID信息(设置时才显示)、特征项的index(用于唯一标识) | +| **BIT_SERVER_INFO_SN_LICENSE** | 获取集团服务的授权码的授权信息 | +| **BIT_SERVER_INFO_FEATURE_LICENSE** | 获取集团服务的特征项的授权信息 **版本支持:**14.5.2及以上版本客户端库和集团服务支持返回MID信息(设置时才显示)、特征项的index(用于唯一标识) | +| **BIT_SERVER_INFO_SN_USERS** | 获取集团服务被占用的SN的用户信息 **版本支持:**14.6.0及以上版本支持通过xmlScope传入groupName指定查询分组,需配合14.6.0及以上版本集团服务使用 | +| **BIT_SERVER_INFO_FEATURE_USERS** | 获取集团服务被占用的feature的用户信息 **版本支持:**14.6.0及以上版本支持通过xmlScope传入groupName指定查询分组,需配合14.6.0及以上版本集团服务使用 | +| **BIT_SERVER_INFO_FEATURE_USERS_EX** | 获取集团服务被占用的feature的用户信息 **版本支持:**- 14.5.2及以上版本:新增类型,在BIT_SERVER_INFO_FEATURE_USERS基础上,额外多返回属性,包含id,version,index(值为name名称)- 14.6.0及以上版本:支持通过xmlScope传入groupName指定查询分组,需配合14.6.0及以上版本集团服务使用 | + + +- pServiceLicenseInfo - [OUT] 用于存储返回XML信息数据的存储区地址。 +- pServiceLicenseInfoSize - [IN/OUT] 输入的存储区长度。 + +### xmlScope使用说明 + +支持指定特征项查询和指定分组查询两种方式,暂不支持同时指定特征项和分组信息。 + +1. 指定特征项(feature)查询 + +适用于所有BIT_INFO_EX_TYPE类型,通过id、name、version限定待查询的特征项。 + +```xml + + # xxxx处替换为实际特征项参数 + # 允许设置多个 + …… + +``` +1. 指定分组(group)查询 + +仅支持BIT_SERVER_INFO_SN_USERS、BIT_SERVER_INFO_FEATURE_USERS、BIT_SERVER_INFO_FEATURE_USERS_EX三种类型,通过name限定待查询的分组。 + +```c + + # xxxx处替换为实际分组名称 + # 允许设置多个 + …… + +``` +> 说明:通过Bit_SetCustomInfo的CUSTOM_GROUP_NAME(0xA)设置分组。 + +### 返回XML数据说明 + +传入分组名称,仅返回当前分组内的用户信息;不传入分组名称,默认返回所有用户信息。如果客户端调用Bit_SetCustomInfo指定group后,返回的XML数据中,userInfo节点会新增groupName字段。 + +XML返回示例: + +```c + + + + CLMDMJDR******** + 98001 + bit + 127.0.0.1 + 2026-02-26 01:49:28 + bit + + +``` + +### Bit_GetVersion + +```c +BIT_STATUS Bit_GetVersion ( + BIT_UINT32 *pVersion) +``` +获取客户端安全库版本号。 + +### 参数 + +- **pVersion** - [OUT] 客户端安全库版本号。 + +### Bit_GetNextHandle + +```c +BIT_STATUS Bit_GetNextHandle( + BIT_HANDLE handle, + BIT_HANDLE *pNextHandle) +``` +用来遍历当前进程内的handle。 + +### 参数 + +- **handle** – [IN] 当前handle。如果传NULL,pNextHandle返回第一个handle。 +- **pNextHandle** – [OUT] 返回handle指向的下一个handle,如果返回为NULL,则表示已经到了末尾。 + +### 示例 + +```c +BIT_HANDLE nextHandle = NULL; +while (Bit_GetNextHandle(nextHandle , &nextHandle) == BIT_SUCCESS && nextHandle != NULL) { + // 使用nextHandle处理业务逻辑 +} +``` + +### Bit_TestBitService + +```c +BIT_STATUS Bit_TestBitService ( + BIT_PCSTR szURL, + BIT_PCSTR szSN, + BIT_UINT32 featureId, + BIT_UCHAR *pApplicationData) +``` +测试集团授权的特征项是否可用,不会占用授权码或特征项的用户数。 + +### 参数 + +- **szURL** - [IN] 自定义授权服务器地址,需包括端口。如未使用自定义授权服务器则为NULL。 +- **szSN** - [IN] 授权码(SN)字符串。如果为空(空字符串""或NULL)则尝试寻找所有当前本机可用的SN。 +- **featureId** - [IN] 登录授权所需要包含的特征项ID。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 + +> **注意:szSN和featureId为二选一互斥关系**,需遵循以下规则 +> +> - 指定授权码:当szSN不为NULL或空字符串("")时,featureId必须设为0。 +> - 指定特征项:当featureId不为0时,szSN必须设为NULL或空字符串("")。 +> - 特殊情况:允许szSN为NULL或空字符串,且featureId为0。 + +### Bit_GetProductPath + +```c +BIT_STATUS Bit_GetProductPath( + BIT_UCHAR *pApplicationData, + BIT_CHAR *pPath, + BIT_UINT32 lenPath); +``` +获取授权存储目录。 + +### 参数 + +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **pPath** - [OUT] 授权存储目录。 +- **lenPath** - [IN] 指定授权目录pPath数据长度。建议值:Windows:PATH_MAX (260) Linux/Unix:PATH_MAX (4096)。 + +### Bit_GetLastError + +```c +BIT_STATUS Bit_GetLastError(); +``` +获取上一个API调用返回的错误码。 + +### 参数 + +无 + +## 属性设置 + + +### Bit_SetAttr + +```c +BIT_STATUS Bit_SetAttr ( + BIT_HANDLE handle, + BIT_UINT32 type, + BIT_VOID *pValue) +``` +设置全局配置或当前会话的配置。 + +### 参数 + +- **handle** - [IN] 通过Login函数返回的上下文句柄。如果传NULL,表示设置全局,不为NULL表示设置该会话。 +- **type** - [IN] 类型。 + + +| **类型** | **值** | **说明** | +| ------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| **ATTR_HB_STOPED_CALLBACK(0x1)** | void (*T_HbStopedCallback)(BIT_HANDLE, void* pData) | 心跳停止回调函数 心跳停止后会回调该函数,可检测与授权服务的连接状态 **注意事项:**handle不能为NULL | +| **ATTR_WAIT_TIMEOUT(0x2)** | BIT_UINT32 * | 队列等待超时时间 最小16秒,最大15天,默认0表示无限等待 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_RETRY_COUNT(0x3)** | BIT_UINT32 * | 心跳连接重试次数 当心跳时候,总的重试次数 **取值说明:** 0:表示无限重试,直到客户端超时或授权失效,才会停止,默认是0 -1:表示无限重试,无论客户端是否超时或授权失效,都会重试 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_RETRY_INTERVAL(0x4)** | BIT_UINT32 * | 心跳连接重试间隔 心跳失败后下次重试的间隔 最小10秒,最大4小时,默认10秒 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_CONNECT_TIMEOUT(0x5)** | BIT_UINT32 * | 建立连接超时时间 最小1秒,最大32秒,默认32秒 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_CONNECT_RETRY_COUNT(0x6)** | BIT_UINT32 * | 连接重试次数 最小0次,最大10次,默认3次 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_HB_INTERVAL(0x8)** | BIT_UINT32 * | 心跳间隔 最小30秒,默认由服务端控制 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_HB_AUTO_ENABLE(0x9)** | BIT_UINT32 * | 是否启动自动心跳 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_HB_TIMEOUT(0x10)** | BIT_UINT32 * | 心跳周期(超过则被踢出) 集团服务端也可以设置心跳周期,该周期会覆盖服务端的设置 最小60秒,最大30天,默认由服务端控制 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_HB_STOPED_CALLBACK_DATA(0x12)** | void * | 心跳停止回调函数自定义数据 触发心跳停止回调时,会将该值传递到ATTR_HB_STOPED_CALLBACK回调函数的最后一个参数 **注意事项:**handle不能为NULL | +| **ATTR_HB_STOPED_CALLBACK_EX(0x13)** | void (*T_HbStopedCallbackEx)(BIT_HANDLE, BIT_TICKET, BIT_STATUS, void* pData); | 特征项的心跳停止回调函数 **参数说明:** - BIT_HANDLE handle:login接口返回的handle- BIT_TICKET ticket:query接口返回的ticket- BIT_STATUS status:心跳停止返回的错误码- void *pData:开发商自定义数据,需通过ATTR_HB_STOPED_CALLBACK_EX_DATA传入**注意事项:**handle不能为NULL | +| **ATTR_HB_STOPED_CALLBACK_EX_DATA(0x14)** | void * | 特征项的心跳停止回调函数自定义数据 触发特征项的心跳停止回调时,会将该值传递到ATTR_HB_STOPED_CALLBACK_EX回调函数的最后一个参数 **注意事项:**handle不能为NULL | +| **ATTR_HB_RETRY_CALLBACK_EX(0x15)** | void (*T_HbRetryFailedCallbackEx)(BIT_HANDLE, BIT_TICKET, BIT_STATUS, void* pData); | 心跳重试回调函数 **参数说明:** - BIT_HANDLE handle:login接口返回的handle- BIT_TICKET ticket:query接口返回的ticket- BIT_STATUS status:心跳重试返回的错误码- void *pData:开发商自定义数据,需通过ATTR_HB_RETRY_CALLBACK_EX_DATA传入**注意事项:**handle不能为NULL | +| **ATTR_HB_RETRY_CALLBACK_EX_DATA(0x16)** | void * | 心跳重试回调函数自定义数据 触发心跳重试回调时,会将该值传递到ATTR_HB_RETRY_CALLBACK_EX回调函数的最后一个参数 **注意事项:**handle不能为NULL | +| **ATTR_SET_LOGIN_MODE(0x17)** | BIT_UINT32 * | 设置Login的mode值 **注意事项:**handle不能为NULL | +| **ATTR_UNSET_LOGIN_MODE(0x18)** | BIT_UINT32 * | 取消Login的mode值 **注意事项:**handle不能为NULL | +| **ATTR_DISABLE_ENV(0x19)** | BIT_BOOL * | 禁用环境变量 传1表示禁用,设置禁用后客户端库将不再读取环境变量 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_REQUEST_TIMEOUT(0x1A)** | BIT_UINT32 * | 自定义receiveTimeout 最小16秒,最大64秒,默认32秒 **注意事项:**handle可为NULL,也可不为NULL | +| **ATTR_HB_RETRY_FAILED_CALLBACK(0x7)** | void (*T_HbRetryFailedCallback)(BIT_HANDLE, BIT_STATUS, void* pData) | 心跳重试失败回调函数 **参数说明:** - BIT_HANDLE handle:login接口返回的handle- BIT_STATUS status:心跳失败返回的错误码- void *pData:开发商自定义数据,需通过ATTR_HB_RETRY_FAILED_CALLBACK_DATA传入**注意事项:**handle不能为NULL | +| **ATTR_HB_RETRY_FAILED_CALLBACK_DATA(0x11)** | void * | 心跳重试失败回调函数自定义数据 触发心跳失败回调时,会将该值传递到ATTR_HB_RETRY_FAILED_CALLBACK回调函数的最后一个参数 **注意事项:**handle不能为NULL | +| **ATTR_HB_RETRY_FAILED_CALLBACK_EX2(0x1B)** | void (*T_HbRetryFailedCallback)(BIT_HANDLE, BIT_TICKET, BIT_STATUS, BIT_UINT32, BIT_UINT32, BIT_UINT32* pData)) | 心跳重试失败回调函数(Ex2) **参数说明:** - BIT_HANDLE handle:login接口返回的handle- BIT_TICKET ticket:query接口返回的ticket- BIT_STATUS status:心跳失败返回的错误码- BIT_UINT32 currentNumber:当前回调次数- BIT_UINT32 maxNumber:最大回调次数- BIT_UINT32 interval:回调间隔(单位:秒)- void *pData:开发商自定义数据,需通过ATTR_HB_RETRY_FAILED_CALLBACK_EX2_DATA传入**注意事项:**handle不能为NULL | +| **ATTR_HB_RETRY_FAILED_CALLBACK_EX2_DATA(0x1C)** | void * | 心跳重试失败回调自定义数据(Ex2) 触发QueryFeatureEx2的心跳失败回调时,会将该值传递到ATTR_HB_RETRY_FAILED_CALLBACK_EX2回调函数的最后一个参数 **注意事项:**handle不能为NULL | +| **ATTR_HB_RETRY_SUCCESS_CALLBACK(0x1D)** | void (*T_HbRetrySuccessCallbackEx2)(BIT_HANDLE, BIT_TICKET, BIT_UINT32, BIT_UINT32, BIT_UINT32 *pDate) | 心跳重试成功回调函数 **参数说明:** - BIT_HANDLE handle:login接口返回的handle- BIT_TICKET ticket:query接口返回的ticket- BIT_UINT32 currentNumber:当前回调次数- BIT_UINT32 maxNumber:最大回调次数- BIT_UINT32 interval:回调间隔(单位:秒)- void *pData:开发商自定义数据,需通过ATTR_HB_RETRY_SUCCESS_CALLBACK_DATA传入**注意事项:**handle不能为NULL | +| **ATTR_HB_RETRY_SUCCESS_CALLBACK_DATA(0x1E)** | void * | 心跳重试成功回调自定义数据 触发心跳成功回调时,会将该值传递到ATTR_HB_RETRY_SUCCESS_CALLBACK回调函数的最后一个参数 **注意事项:**handle不能为NULL | +| **ATTR_QUEUE_WAIT_CALLBACK(0x21)** | void (*QueueWaitCallback)(BIT_HANDLE, BIT_TICKET, BIT_STATUS, BIT_UINT32, BIT_UINT32 *pUserData) | 排队回调函数 **生效前提(满足其一即可):** - Bit_QueryFeatureEx2接口已设置BIT_QUERY_WAIT(等待模式)- 环境变量BITANSWER_MODE已配置为wait(排队等待模式)**参数说明:** - BIT_HANDLE handle:login接口返回的handle- BIT_TICKET ticket:query接口返回的ticket- BIT_STATUS status:BIT_SUCCESS(表示排队中),其他(表示排队失败)- BIT_UINT32 queueLength:前面排队长度- BIT_UINT32 waitSecond:预计等待总秒数(不足1秒部分会被舍去)- void *pUserData:开发商自定义数据,需通过ATTR_QUEUE_WAIT_CALLBACK_DATA传入**注意事项:**handle不能为NULL **版本支持:**14.5.2及以上版本新增类型,需配合14.5.2及以上版本的集团服务和客户端库使用 | +| **ATTR_QUEUE_WAIT_CALLBACK_DATA(0x22)** | void * | 排队回调自定义数据 触发QueryFeatureEx2的排队回调时,会将该值传递到ATTR_QUEUE_WAIT_CALLBACK回调函数的最后一个参数 **注意事项:**handle不能为NULL | +| **ATTR_ENABLE_DIAGS_LOG(0x1F)** | BIT_UINT32 * | 控制诊断log的生成 **取值说明:**- 0:表示禁用(默认,禁用后环境变量不生效)- 1:表示启动**注意事项:**handle必须为NULL | +| **ATTR_HB_DEFAULT_STOPED_CALLBACK(0x20)** | BIT_BOOL * | 控制心跳停止程序自动退出功能 **取值说明:**- 0:表示禁用(默认)- 1:表示启动,若经过最大次重试次数后仍未重新建立连接,应用程序会默认终止运行,并输出错误信息:“许可证丢失,无法重新连接”(UNIX系统输出至stderr,Windows系统弹出对话框)**注意事项:**- 如果注册了ATTR_HB_STOPED_CALLBACK或ATTR_HB_STOPED_CALLBACK_EX默认退出行为将不再生效- handle不能为NULL**版本支持:**14.5.0及以上版本新增类型 | +| **ATTR_LOGIN_URL_SCOPE(0x23)** | BIT_UINT32 * | 控制Login连接的服务器类型 **取值说明:**- ATTR_LOGIN_URL_UNKNOW (0x0) - 默认行为,加载配置中所有类型的服务器- ATTR_LOGIN_URL_WS (0x1) - 表示仅连接ws类型服务(云授权服务器)- ATTR_LOGIN_URL_BIT (0x2) - 表示仅连接bit类型服务(集团授权服务器)**注意事项:**- 调用SetAttr接口时,第一个参数handle必须传入NULL,表示该配置全局生效;若传入非NULL值,接口会返回错误码259- handle必须为NULL**示例:**- 场景:环境变量中配置了混合类型的服务器地址:`bit://127.0.0.1:8273,ws:bitanswer.cn`,需仅连接bit类型服务器- API调用:SetAttr(NULL, ATTR_LOGIN_URL_SCOPE(0x23), 2)- 执行结果:程序仅加载并连接`bit://127.0.0.1:8273`(bit类型服务器),忽略ws类型的`ws:bitanswer.cn`**版本支持:**14.5.4及以上版本新增类型 | + + +- **pValue** - [IN] 不同类型,对应了不同的值。 + +### 示例 + +```c +// 设置队列等待超时为20秒 + +BIT_UINT32 value = 20; +BIT_STATUS status = Bit_SetAttr (handle, ATTR_WAIT_TIMEOUT, &value); +if (status == BIT_SUCCESS) { + // 设置成功 +} +``` + +### Bit_SetProxy + +```c +BIT_STATUS Bit_SetProxy ( + BIT_UCHAR *pApplicationData, + BIT_PCSTR szHostName, + BIT_UINT32 nPort, + BIT_PCSTR szUserID, + BIT_PCSTR szPassword) +``` +设置代理服务的地址和端口。 + +### 参数 + +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **szHostName** - [IN] 代理服务所在机器的IP地址。 + +> 说明: +> +> - 14.3.0及以上版本,将该参数扩展为支持`Type:HostName`格式,其中Type表示服务器类型,可取值为ws或bit,ws表示云授权服务器,bit表示集团授权服务器。 +> - 为保持向后兼容,若不指定`Type://前缀`,则默认视为ws类型。 + +- **nPort** - [IN] 代理服务开启的通讯端口。 +- **szUserID** - [IN] 代理服务所在机器的用户名。 +- **szPassword** - [IN] 代理服务所在机器的密码。 + +### Bit_SetCustomInfo + +```c +BIT_STATUS Bit_SetCustomInfo ( + BIT_UINT32 infoId, + BIT_VOID *pInfoData, + BIT_UINT32 infoDataSize) +``` +设置客户端运行自定义信息,需要在程序的最开始调用。 + +### 参数 + +- **infoId** - [IN] 自定义信息类型。 + + +| **类型** | **值** | **说明** | +| --------------------------------- | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **CUSTOM_CLIENT_ID(0x1)** | 字符串 | 自定义终端标识,配置后该自定义标识会发送给服务器并用于今后的机器指纹匹配 **注意:**必须同时将CUSTOM_OPTION_CLOUD_CLIENTID选项设置为启用状态,此配置才能生效 | +| **CUSTOM_ACCOUNT_LOCAL(0x2)** | 字符串 | 自定义客户端用户帐号,用于集团服务标识客户端用户 | +| **CUSTOM_COMMENT(0x3)** | 字符串 | 自定义客户端登录注释,用于集团服务管理员获取用户登录请求信息 | +| **CUSTOM_OPTION(0x4)** | BIT_UINT32 | 按位进行操作 - CUSTOM_OPTION_SD1_FIRST (0x1) - 仅限Android选项,只检查第一张SD卡- - CUSTOM_OPTION_HIDE_FOLDER (0x2) - 隐藏默认的BitAnswer文件夹- CUSTOM_OPTION_SOAP_USERNAME (0x4) - 机器用户信息添加到soap头中- CUSTOM_OPTION_CONFINED_LINK (0x8) - 取消连接次数限制(1800)- CUSTOM_OPTION_BINARY_NAME(0x10) – 客户向集团服务发送进程名- CUSTOM_OPTION_DOCKER_INFO(0x40) – 客户端向服务端发送设备运行于Docker环境时的标识信息- CUSTOM_OPTION_CLOUD_CLIENTID(0x20) – 用于启用CUSTOM_CLIENT_ID(自定义终端标识)功能,开启后,系统会将已设置的CUSTOM_CLIENT_ID作为该设备的唯一标识,用于今后的机器指纹匹配与管理(需配合14.5.0及以上版本的集团服务和客户端库使用)**示例:** 既要取消连接次数限制,又要隐藏BitAnswer目录,则传入:(CUSTOM_OPTION_HIDE_FOLDER | +| **CUSTOM_PRODUCT_CODE(0x6)** | 字符串 | 自定义授权目录名称 | +| **CUSTOM_ACCOUNT_DEVELOPER(0x7)** | 字符串 | 自定义登录帐号,用于帐号授权 (既使用account登录,又设置了此选项,则直接忽略) | +| **CUSTOM_VENDOR_CODE(0x8)** | 字符串 | 自定义开发商信息目前仅用于自定义环境变量名称 | +| **CUSTOM_HTTP_HEADER(0x9)** | 字符串 类似于“`auth:xxxx`”,普遍用于自定义认证信息 | 自定义HTTP头,所有联网的请求都会自带这个请求头 | +| **CUSTOM_GROUP_NAME(0xA)** | 字符串 | 设置自定义分组名 当开发商需要按照自定义的分组扣点(比如:部门,角色,窗口名等),可以设置此选项,并结合Bit_Login的LOGIN_MODE设置扣点方式 | + + +- **pInfoData** - [IN] 自定义信息的存储地址。 +- **infoDataSize** - [IN] 自定义信息长度。针对CUSTOM_OPTION类型,该参数应为BIT_UINT32类型大小。 + +### 示例 + +```c +// 设置字符串类型 +// 自定义终端标识 +BIT_PCSTR clientID = "Machine-123"; +BIT_STATUS status = Bit_ SetCustomInfo (CUSTOM_CLIENT_ID, clientID, strlen(clientID)); +if (status == BIT_SUCCESS) { + // 设置成功 +} + +// 设置BIT_UINT32类型 +// 机器用户信息添加到soap头中 +BIT_UINT32 optSoapUserName = 4; +BIT_STATUS status = Bit_ SetCustomInfo (CUSTOM_OPTION, & optSoapUserName, sizeof(optSoapUserName)); +if (status == BIT_SUCCESS) { + // 设置成功 +} +``` + +### Bit_SetRootPath + +```c +BIT_STATUS Bit_SetRootPath ( + BIT_PCSTR szPath) +``` +设置授权文件的存储路径。 + +### 参数 + +- **szPath** - [IN] 数据缓存区地址,用于存储授权文件的路径。 + +### Bit_SetLocalServer + +```c +BIT_STATUS Bit_SetLocalServer ( + BIT_UCHAR *pApplicationData, + BIT_PCSTR szHostName, + BIT_UINT32 nPort, + BIT_UINT32 nTimeoutSecondes) +``` +设置集团服务的地址和端口。 + +### 参数 + +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **szHostName** - [IN] 集团服务所安装机器的IP地址。 +- **nPort** - [IN] 客户端应用程序的通讯端口,默认为8273。 +- **nTimeoutSecondes** - [IN] 客户端超时秒数。 + +## 借出操作 + + +### Bit_GetBorrowRequest + +```c +BIT_STATUS Bit_GetBorrowRequest( + BIT_PCSTR szSN, + BIT_UCHAR *pApplicationData, + BIT_UINT32 nDurationDays, + BIT_CHAR *pRequestInfo, + BIT_UINT32 *pRequestInfoSize) +``` +获取借出请求串,用来离线借出。 + +### 参数 + +- **szSN** - [IN] 指定要借出的SN,如果为NULL,找满足条件的第一个SN。 +- **pApplicationData** - [IN] 产品识别码,在Bitanswer SDK头文件里。 +- **nDurationDays** - [IN] 借出时间。100年代表永久借出(分发),0表示产生归还串。 +- **pRequestInfo** - [OUT] 借出请求串缓存区地址。 +- **pRequestInfoSize** - [IN/OUT] 输入的是缓存区大小,输出的是示例数据的大小。 + +### Bit_GetBorrowFeatureRequest + +```c +BIT_STATUS Bit_GetBorrowFeatureRequest( + BIT_PCSTR pReserve, + BIT_UCHAR *pApplicationData, + BIT_UINT32 nDurationDays, + BIT_PCSTR pBorrowScope, + BIT_CHAR *pRequestInfo, + BIT_UINT32 *pRequestInfoSize) +``` +获取借出请求串,该接口支持指定特征项借出。 + +### 参数 + +- **pReserve** - [IN] 保留,必须是NULL。 +- **pApplicationData** - [IN] 产品识别码,在Bitanswer SDK头文件里。 +- **nDurationDays** - [IN] 借出时间。 +- **pBorrowScope** - [IN] xml结构。 +- **pRequestInfo** - [OUT] 借出请求串缓存区地址。 +- **pRequestInfoSize** - [IN/OUT] 输入的是缓存区大小,输出的是示例数据的大小。 + +### Scope示例 + +```xml + + + + … + +``` + +### Bit_CheckOutSn / Bit_CheckOutSnEx + +```c +BIT_STATUS Bit_CheckOutSn( + BIT_PCSTR szURL, + BIT_UINT32 featureId, + BIT_UCHAR *pApplicationData, + BIT_UINT32 nDurationDays); + +BIT_STATUS Bit_CheckOutSnEx( + BIT_PCSTR szURL, + BIT_UINT32 featureId, + BIT_PCSTR pScope, + BIT_UCHAR *pApplicationData, + BIT_UINT32 nDurationDays); +``` +从授权服务器在线借出一个完整的授权码,以允许客户端服务器单独使用。被借出的授权码必须具有可借出属性,并在客户端成功借出后减少一个可用用户数。被借出的用户数在到期后将自动返还给服务器。 + +### 参数 + +- **szURL** - [IN] 集团授权服务器地址,包括端口。如输入NULL,则使用配置文件地址;如输入 * 号,则使用广播查找地址。 +- **featured** - [IN] 指定借出授权码需要包含的特征项ID,为0则寻找第一个可借出授权码。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **pScope** - [IN] xml结构,允许传NULL。 +- **nDurationDays** - [IN] 借出时间,单位为天。借出时间不能超过被借出集团授权的强制认证周期或有效期。 + +### Scope示例 + +```xml + + ws + xxx + xxx + + + +``` + +### Bit_CheckOut + +```c +BIT_STATUS Bit_CheckOut( + BIT_PCSTR szURL, + BIT_PCSTR pScope, + BIT_PCSTR pFeatureList, + BIT_UCHAR *pApplicationData, + BIT_UINT32 nDurationDays) +``` +从授权服务器在线借出授权码或者特征项。 + +### 参数 + +- **szURL** 集团授权服务器地址,包括端口。如输入NULL,则从本地配置文件或者环境变量读取服务地址。 +- **pScope** xml结构,允许传NULL。 + +```xml + + ws + xxx + + + +``` +- **pFeatureList** xml结构,指定借出的特征项列表,如果不传则借出整个SN。 + +```xml + + + + + +``` +当feature指定了借出时间,则会覆盖nDurationDays该时间,没有指定,则借出nDurationDays天。 + +借出feature时,如果指定了版本,则直接大于等于借出版本的特征项,只借一个,如果没有指定版本,则该特征项的所有版本都借出一个。 + +- **pApplicationData** 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **nDurationDays** 借出时间,单位为天,最大不超过100年。 + +```c +// 借出特征项1和特征项2,各借10天 +BIT_STATUS status = Bit_CheckOut( + "bit://127.0.0.1:8273", + NULL, + "", + application_data, + 10); + +if (status == BIT_SUCCESS) { + // 借出成功 +} + +// 借出特征项1(5天) 和 特征项2(2天) +BIT_STATUS status = Bit_CheckOut( + "bit://127.0.0.1:8273", + NULL, + "", + application_data, + 5); + +if (status == BIT_SUCCESS) { + // 借出成功 +} +``` + +### Bit_CheckOutFeatures + +```c +BIT_STATUS Bit_CheckOutFeatures( + BIT_PCSTR szURL, + BIT_UCHAR *pApplicationData, + BIT_UINT32 *pFeatureList, + BIT_UINT32 nFeatureInList, + BIT_UINT32 nDurationDays); +``` +从集团授权服务器借出一组特征项,这些特征项必须包含在同一个授权码中。被借出的集团授权码必须具有可借出属性,并在客户端成功借出后减少一个可用用户数。被借出的用户数在到期后将自动返还给集团服务器。 + +### 参数 + +- **szURL** - [IN] 集团授权服务器地址,包括端口。如输入NULL,则使用配置文件地址;如输入 * 号,则使用广播查找地址。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **pFeatureList** - [IN] 要借出的特征项列表。 +- **nFeatureInList** - [IN] 要借出的特征项数量。 +- **nDurationDays** - [IN] 借出时间,单位为天,最大不超过100年。 + +### 示例 + +```c +// 借出特征项1和特征项2,借3天 +BIT_UINT32 borrowFeature[2] = { 0 }; +borrowFeature[0] = 1; +borrowFeature[1] = 2; + +BIT_STATUS status = Bit_CheckOutFeatures("bit://127.0.0.1:8273", + application_data, + borrowFeature, + 2, + 3); + +if (status == BIT_SUCCESS) { + // 借出成功 +} else { + // 借出失败 +} +``` + +### Bit_CheckIn + +```c +BIT_STATUS Bit_CheckIn( + BIT_PCSTR szURL, + BIT_UINT32 featureId, + BIT_UCHAR *pApplicationData) +``` +提前返还从集团授权服务器借出的授权。要提前返还授权,该授权码必须具有允许提前返还属性。 + +### 参数 + +- **szURL** - [IN] 集团授权服务器地址,包括端口。如输入NULL,则使用配置文件地址;如输入 * 号,则使用广播查找地址。 +- **featureId** - [IN] 指定要返还授权码需要包含的特征项ID,为0则寻找第一个可返还授权码。 +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 + +### Bit_CheckInEx + +```c +BIT_STATUS Bit_CheckInEx( + BIT_PCSTR szURL, + BIT_UINT32 featureId, + BIT_PCSTR szScope, + BIT_UCHAR *pApplicationData) +``` +提前返还从授权服务器借出的授权。要提前返还授权,该授权码必须具有允许提前返还属性。 + +### 参数 + +- **szURL** - [IN] 集团授权服务器地址,包括端口。如输入NULL,则使用配置文件地址;如输入 * 号,则使用广播查找地址。 +- **featureId** - [IN] 指定要返还授权码需要包含的特征项ID,为0则寻找第一个可返还授权码。 +- **xmlScope** - [IN] xml结构,允许传NULL。 + +```xml + + ws + +``` +用于指定借出的参数,格式:wsxxxx,type设定为ws时表示从云授权服务器借出和归还。 + +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 + +### Bit_ApplyBorrowInfo + +```c +BIT_STATUS Bit_ApplyBorrowInfo( + BIT_UCHAR *pApplicationData, + BIT_PCSTR pBorrowInfo) +``` +客户端应用离线借出串,Bit_ApplyUpdateInfo可以兼容该接口。 + +### 参数 + +- **pApplicationData** - [IN] 产品识别码。记录在接口定义文件中,与产品一一对应。 +- **pBorrowInfo** - [IN] 借出请求串。 diff --git a/docs/java.md b/docs/java.md new file mode 100644 index 0000000..dc14a45 --- /dev/null +++ b/docs/java.md @@ -0,0 +1,1202 @@ +# 比特授权云 · Java 语言接口(离线摘录) + +> 本文档由官网页面离线摘录并整理排版,便于本地检索。官方地址: + +--- + +## 构造方法详细信息 + + +### BitAnswer + +```java +public BitAnswer() +public BitAnswer(String url, String sn, LoginMode mode) +``` + +## 认证 + + +### login / loginEx + +```java +void login (String url, + String sn, + LoginMode mode) + +void loginEx (String url, + String sn, + int featureId, + String xmlScope, + LoginMode mode) +``` +授权登录。初始化运行环境,获取操作句柄。必须在除升级函数之外的其它操作前执行。根据登录模式的不同可能需要连接授权服务器。 + +Login 等价于 LoginEx(featureId=0);当需要登录包含指定特征项的授权时才需要调用LoginEx。 + +### 参数 + +- **url** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **sn** - [IN] 授权码(SN)字符串。如果为空(空串或NULL)则尝试寻找所有当前本机可用的SN。 +- **featureId** - [IN] 登录授权所需要包含的特征项ID。 +- **xmlScope** - [IN] 登录范围。用于提供更多的登录条件,格式为标准XML字符串。目前保留,必须为NULL +- **mode** - [IN] 登录模式,按位操作。 + + +| **值** | **说明** | +| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------- | +| **LOCAL** | 只检查本地授权(单机授权、BIT-ID授权、内存授权) | +| **REMOTE** | 只检查远端授权(云授权、帐号授权、集团授权) | +| **AUTO** | 既检查本地授权,也检查远端授权(配置了远端IP的条件下) 优先级:本地授权 > 远端授权 | +| **CACHE** | 云授权缓存 由于云授权SN比较难记,但登录时又必须传输,则可以使用该选项将SN串缓存起来,下次使用Login登录时可以不输入SN | +| **USB** | USB授权 | +| **PROCESS** | 按进程模式登录 **集团授权**:普通模式一台机器占用一个用户数,进程模式是一个进程占用一个用户数 **其它授权**:不生效 | +| **SESSION** | Session模式登录 **集团授权**:该模式比LOGIN_MODE_PROCESS控制的更细,一次会话占用一个点 **其它授权**:不生效 | +| **HIGH_PR** | 高优先级登录 **云授权:**用户可以通过高优先级登录来挤掉普通登录。如果登录模式都是高优先级或者普通优先级则不生效 **其它授权:**不生效 | +| **NO_NETWORK** | 禁用网络 禁止库联网时使用 | +| **CHECK_USERNAME** | 检查当前设备的用户名 **集团授权:**默认情况下:一台的设备用户名不一样,会被识别为同一个机器,加了该模式,会识别为不同的设备。即:原来一台设备占用一个点,加了这个选项,“一台设备 + 用户名”占用一个点 **其它授权**:不生效 | +| **USE_SESSIONID** | Logout时不释放点数,并由第三方程序维护心跳 | +| **HIGH_PERFORMANCE** | 使用高性能模式登录 **集团授权:**将Login的两次请求转化为一次请求,可以减少服务负载 **其它授权:**不支持 | +| **PERSISTENT_CONN** | 使用长连接模式登录,只有集团授权支持,其它授权不支持 通过长连接可以减少TCP的频繁创建带来的性能损耗,但是会增加服务的socket连接数 | +| **CREATE_HANDLE_ONLY** | 仅创建handle,不检查license **集团授权:**Login默认情况下会连接集团服务并占用一个用户数,加了该模式之后,在调用Query相关接口时才会连接服务器 **其它授权:**Login默认情况下会检查授权的可用性,加了该模式之后,在Query时才会检查 | +| **CREATE_NEW_HANDLE** | 创建新handle,每次创建的handle唯一 Login的请求默认都发pid 可以针对每一个handle进行设置属性,不会相互影响 | +| **MID** | 按设备占点(当没有设置LOGIN_MODE_ACCOUNT和LOGIN_MODE_GROUP时,默认按设备扣点) | +| **ACCOUNT** | 按帐号占点 | +| **GROUP** | 按分组名占点 | + + +### 返回 + +无 + +### loginByToken + +```java +void loginByToken (String url, + String token) +``` +帐号授权的登录接口。仅支持两种认证方式,这里是使用比特授权云平台自己产生的access_token进行认证。 + +### 参数 + +- **url** - [IN] 服务器地址,可以为空。 +- **token** - [IN] 第三方身份源颁发的token或id_token,通过前缀区分。 + +### 返回 + +无 + +### loginByTokenEx + +```java +void loginByTokenEx (String url, + String businessGuid, + String token, + String idpGuid, + String grantType) +``` +帐号授权的登录接口。仅支持两种认证方式,这里是使用OIDC协议产生的id_token认证。 + +### 参数 + +- **url** - [IN] 服务器地址,可以为空。 +- **businessGuid** - [IN] 业务guid,在比特授权云平台获取。 +- **token** - [IN] 第三方身份源颁发的token或id_token,通过前缀区分。 +- **idpGuid** - [IN] 第三方身份源guid,在比特授权云平台获取。参数为空表示使用比特授权云平台产生的token进行登录,即Bit_LoginByToken。 +- **grantType** - [IN] 授权类型。固定值为“`bitanswer:idp:oidc:id_token`”。 + +### 返回 + +无 + +### loginByPassword + +```java +void loginByPassword (String url, + String guid, + String secret, + String account, + String password) +``` +通过用户名和密码登录帐号授权。 + +### 参数 + +- **url** - [IN] 服务器地址,可以为空。 +- **guid** - [IN] 业务编号,在比特授权云平台获取。 +- **secret** - [IN] 业务密钥,在比特授权云平台获取。 +- **account** - [IN] 用户帐号。 +- **password** - [IN] 用户密码。 + +### 返回 + +无 + +### logout + +```java +void logout() +``` +此函数用于释放上下文句柄,退出登录状态,与Login相关接口一一对应。 + +### 参数 + +无 + +### 返回 + +无 + +### revoke + +```java +String revoke (String sn) +``` +从客户端迁出已激活的浮动授权码。授权码迁出后,可以用于其它的客户端。根据输入参数的不同,本函数可用于在线或离线迁出。 + +### 参数 + +- **sn** - [IN] 授权码(SN)字符串。 + +### 返回 + +返回用于授权码迁出的请求码。请求码应发给服务器获取迁出升级串(GetUpdateInfo),并在本地应用升级串(ApplyUpdateInfo)后才能最终完成迁出操作。 + +### revokeOnline + +```java +void revokeOnline (String url, + String sn) +``` +从客户端迁出已激活的浮动授权码。授权码迁出后,可以用于其它的客户端。本函数需要进行网络连接。 + +### 参数 + +- **url** - [IN] 服务器地址,可以为空。 +- **sn** - [IN] 授权码(SN)字符串。 + +### 返回 + +无 + +### removeSn + +```java +void removeSn (String sn) +``` +删除指定授权码在本机的授权数据。 + +### 参数 + +- **sn** - [IN] 授权码(SN)字符串。 + +### 返回 + +无 + +### heartbeat + +```java +int heartbeat() +``` +手动心跳,可以无限次调用,10s只会触发一次。 + +注:当自动心跳停止后,调用该接口可以尝试恢复自动心跳。 + +### 参数 + +无 + +### 返回 + +心跳期间的重连次数(0表示无重连,大于0表示心跳过程中发生过连接断开并重新连接)。 + +### sessionControl + +```java +String sessionControl (String url, + String sessionId, + SessionCtlType type) +``` +控制或设置session的信息。具体使用场景可参考《浏览器并发控制》文档。 + +### 参数 + +- **url** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **sessionId** - [IN] 会话ID,登录成功后获取的有效会话标识。 +- **type** - [IN] 类型。 + + +| **类型** | **说明** | +| --------------------------- | ------------------ | +| **SESSION_CTL_LOGOUT(0x1)** | 释放session | +| **SESSION_CTL_CHECK(0x2)** | 触发心跳并获取sessionId状态 | + + +### 返回 + +会话控制结果(字符串格式),根据控制类型返回对应信息。 + +### setSessionState + +```java +void setSessionState (int state, + byte[] pReserved) +``` +设置客户端的状态为空闲状态或繁忙状态或激活状态。 + +### 参数 + +- **state** - [IN] 设置客户端的状态选项。 + + +| **值** | **说明** | +| ------------------------ | -------------------------------------------------- | +| **SESSION_STATE_UNSET** | 默认值,表示不设置客户端的状态,服务端根据心跳状态来维护session,心跳断开则释放session | +| **SESSION_STATE_IDLE** | 表示设置客户端为空闲态,服务端会在空闲时间超过设10分钟后自动释放session | +| **SESSION_STATE_BUSY** | 表示设置客户端为繁忙状态,服务端不会自动释放,直到心跳断开或者客户端主动释放 | +| **SESSION_STATE_ACTIVE** | 表示设置客户端为活跃状态,重新计算空闲时间 | + + +### 返回 + +无 + +## 激活升级 + + +### updateOnline + +```java +void updateOnline (String url, + String sn) +``` +此函数用于与授权服务器在线连接,自动完成本地授权的升级操作。本函数需要进行网络连接。 + +### 参数 + +- **url** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **sn** - [IN] 授权码(SN)字符串。如果为空(空串或NULL)则尝试寻找所有当前本机可用的SN + +### 返回 + +无 + +### getRequestInfo + +```java +String getRequestInfo (String sn, + BindingType type) +``` +获取当前运行环境的升级请求码,用于发起本地授权激活及升级请求。 + +### 参数 + +- **sn** - [IN] 授权码(SN)字符串。如果为空(空串或NULL)则尝试寻找所有当前本机可用的SN +- **type** - [IN] 本地授权绑定类型。 + +### type类型 + +- **EXISTING** - 使用当前绑定类型,对已激活授权码进行升级时使用。 +- **LOCAL** - 使用本机指纹进行绑定 +- **USB_STORAGE** - 使用USB存储器进行绑定 + +### 返回 + +用于完成后续升级操作的升级请求码。 + +### applyUpdateInfo + +```java +String applyUpdateInfo (String updateInfo) +``` +应用升级码完成本地授权激活或升级。本函数必须在获取请求码的同一环境下执行。 + +### 参数 + +- **updateInfo** - [IN] 由授权服务器获得的本地授权升级码。 + +### 返回 + +确认码,记录升级状态,可在控制台上解析。 + +### getUpdateInfo + +```java +String getUpdateInfo (String url, + String sn, + String requestInfo) +``` +使用请求码与授权服务器进行连接,获取升级码。本函数需要进行网络连接。 + +### 参数 + +- **url** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **sn** - [IN] 授权码(SN)字符串 +- **requestInfo** - [IN] 由获取请求码函数得到的请求码。 + +### 返回 + +由授权服务器获得的本地授权升级码。 + +## 特征项操作 + + +### batchBegin + +```java +void batchBegin (BatchMode mode) +``` +开启批量Query模式,调用此API后调用的所有Query相关API,全部由Bit_batchEnd接口批量提交连接集团服务。 + +### 参数 + +- **mode** - [IN] 批量模式,详见BatchMode枚举。 +- **BatchMode类型** + - BIT_BATCH_MODE_CONTINUE- 批量提交过程中,遇到失败的接口会记录错误信息,并且继续执行 + - BIT_BATCH_MODE_BREAK (0x01) 批量提交过程中,遇到失败的接口会记录错误信息,直接返回错误 + +### 返回 + +无 + +### batchEnd + +```java +int[] batchEnd() +``` +批量提交Query请求。 + +### 参数 + +无 + +### 返回 + +批量请求的执行结果数组(每个元素对应一个Query请求的错误码,0表示执行成功,非0表示对应请求失败),结果数组顺序与Query请求调用顺序一致。 + +### queryFeature + +```java +int queryFeature (int featureId) +``` +开发商可以对软件的某个功能进行单独授权,当程序运行该模块时,可以通过该接口检查是否可用。 + +### 参数 + +- **featureId** - [IN] 产品的特征项ID。 + +### 返回 + +当不为NULL时,获取特征项当前可用用户数。 + +### releaseFeature + +```java +int releaseFeature (int featureId) +``` +释放所占用的用户数,该函数和Bit_QueryFeature一一对应。 + +### 参数 + +- **featureId** - [IN] 产品的特征项ID。 + +### 返回 + +当不为NULL时,获取特征项当前可用用户数。 + +### queryFeatureEx + +```java +int queryFeatureEx (int featureId, + int mode, + int required, + String scope) +``` +集团授权专用,该接口支持占用指定用户数,支持通过特征项版本进行检查。 + +### 参数 + +- **featureId** - [IN] 产品的特征项ID。 +- **mode** - [IN] QueryEx的登录模式。 +- **required** - [IN] 表示需要占用的总用户数,总用户数包括当前设备已经占用的用户数,如果传入的数量大于当前特征项的最大用户数,则占用全部用户数。 +- **scope** - [IN] 特征项支持小数版本,可以通过xml格式传入版本,也可以直接传入版本的字符串。 + +### mode类型 + +- **BIT_QUERY_DEFAULT** - 非阻塞登录,占用required个用户数,如果用户数不够将返回错误,pCapacity 保存剩余用户数。 +- **BIT_QUERY_AVAILABLE** - 尽可能的占用 required(不能为 0)个用户数,如果用户数不够将占用剩余的用户数,pCapacity 保存当前申请到的用户数。 +- **BIT_QUERY_CHECK** - pCapacity 返回总共占用的用户数,required 必须为 0。 + +### 返回 + +特征项数据缓存区地址,用于存储读出的数据,根据mode参数的不同返回剩余用户数或者已占用户数。 + +### releaseFeatureEx + +```java +int releaseFeatureEx (int featureId, + int consumed, + String scope) +``` +集团授权专用,释放指定的用户数。该接口与Bit_QueryFeatureEx对应。 + +### 参数 + +- **featureId** - [IN] 产品的特征项ID。 +- **consumed** - [IN] 需要释放的用户数,传0代表释放所有用户数,如果传入的释放数大于当前登录的用户数则释放所有用户数。 +- **scope** - [IN] 特征项支持小数版本,可以通过xml格式传入版本,也可以直接传入版本的字符串。 + +### 返回 + +特征项数据缓存区地址,用于存储读出的数据,返回已释放的用户数。 + +### queryFeatureEx2 + +```java +long queryFeatureEx2 (String featureName, + int mode, + int required, + String scope) +``` +可以使用“特征项名称 + 特征项版本”进行用户数占用,支持队列模式。 + +### 参数 + +- **featureName** - [IN] 产品的特征项名称。 +- **mode** - [IN] QueryEx2的登录模式。 +- **required** - [IN] 表示需要占用的用户数,多次调用可累加占用用户数。 +- **scope** - [IN] 特征项支持小数版本,可以通过 xml 格式传入版本,也可以直接传入版本的字符串。 + +### mode类型 + +- **BIT_QUERY_DEFAULT** - 非阻塞登录,占用required个用户数,如果用户数不够将返回错误。 +- **BIT_QUERY_AVAILABLE** - 尽可能的占用 required(不能为 0)个用户数,如果用户数不够将占用剩余的用户数。 +- **BIT_QUERY_WAIT** - 阻塞队列登录,如果用户数不够,将加入队列阻塞等待。 +- **BIT_QUERY_QUEUE** - 非阻塞队列登录,如果用户数不够,将加入队列,不会阻塞等待。 +- **BIT_QUERY_TEST** - 测试特征项版本是否可用,与DEFAULT、WAIT、QUEUE搭配使用。 + +### 返回 + +输入时指针变量的值必须为0,输出时为当前Query请求的句柄。 + +### releaseFeatureEx2 + +```java +void releaseFeatureEx2 (byte[] ticket, + int consumed) +``` +释放ticket所占用的用户数。该函数和Bit_QueryFeatureEx2一一对应。 + +### 参数 + +- **ticket** - [IN] 通过QueryFeatureEx2函数返回的上下文句柄。 +- **consumed** - [IN] 需要释放的用户数,目前默认必须传0,代表释放所有用户数。 + +### 返回 + +无 + +### getFeatureInfo2 + +```java +int getFeatureInfo2 (String featureName, + String scope) +``` +检查特征项是否存在,不会占用授权码或特征项的用户数,获取特征项的剩余有效期。 + +### 参数 + +- **featureName** - [IN] 产品的特征项名称。 +- **scope** - [IN] 特征项的版本,可以通过xml格式传入版本,也可以直接传入版本的字符串。 + +### 返回 + +返回该特征项的剩余有效期,正数代表剩余有效期,负数代表过期天数,36500代表永久有效。 + +### getFeatureInfoEx2 + +```java +String getFeatureInfoEx2 (String featureName, + String scope) +``` +获取指定feature的信息,以XML格式返回。 + +### 参数 + +- **featureName** - [IN] 特征项名称,需与比特授权云平台配置的特征项名称一致。 +- **scope** - [IN] 查询范围,无需指定版本则传空串。可以通过 xml 格式传入版本,也可以直接传入版本的字符串。示例: + +```xml + + 1.1 + + +``` + +### 返回 + +特征项信息(XML格式字符串),包含特征项ID、类型、有效期、数据长度等内容。 + +### getTicketInfo + +```java +String getTicketInfo (byte[] ticket, + int type) +``` +获取ticket信息。 + +### 参数 + +- **ticket** - [IN] 通过QueryFeatureEx2函数返回的上下文句柄。 +- **type** - [IN] 获取ticket的信息类型。 + +### type类型 + +- **BIT_TICKET_TYPR_USERS** - 获取当前 ticket 占用的用户数 + +### 返回 + +ticket信息存储区地址。 + +### convertFeature + +```java +int convertFeature (int featureId, + int para1, + int para2, + int para3, + int para4) +``` +使用“算法”类型的特征项对输入参数进行变换操作,得到唯一对应的4字节结果。 + +### 参数 + +- **featureId** - [IN] 产品的特征项ID。 +- **para1** - [IN] 变换输入因子1 +- **para2** - [IN] 变换输入因子2 +- **para3** - [IN] 变换输入因子3 +- **para4** - [IN] 变换输入因子4 + +### 返回 + +变换结果。 + +### encryptFeature + +```java +byte[] encryptFeature (int featureId, + byte[] pPlainBuffer) +``` +使用“密钥”类型的特征项对输入的明文进行加密,返回密文结果。 + +### 参数 + +- **featureId** - [IN] 产品的特征项ID。 +- **pPlainBuffer** - [IN] 数据缓存区地址,用于存储明文数据。 + +### 返回 + +数据缓存区地址,用于存储密文数据。 + +### decryptFeature + +```java +byte[] decryptFeature (int featureId, + byte[] pCipherBuffer) +``` +使用“密钥”类型的特征项对输入的密文进行解密,返回明文结果。 + +### 参数 + +- **featureId** - [IN] 产品的特征项ID。 +- **pCipherBuffer** - [IN] 数据缓存区地址,用于存储密文数据。 + +### 返回 + +数据缓存区地址,用于存储明文数据。 + +### readFeature + +```java +int readFeature (int featureId) +``` +读取特征项的数据内容,可用于“只读”和“读写”特征类型。 + +### 参数 + +- **featureId** - [IN] 产品的特征项ID。 + +### 返回 + +特征项数据缓存区地址,用于存储读出的数据。 + +### writeFeature + +```java +void writeFeature (int featureId, + int featureValue) +``` +更新“读写”类型的特征项的数据内容。 + +### 参数 + +- **featureId** - [IN] 产品的特征项ID。 +- **featureValue** - [IN] 特征项数据值。 + +### 返回 + +无 + +## 配置项操作 + + +### getDataItem + +```java +byte[] getDataItem (String dataItemName) +``` +读取指定的配置项数据。 + +### 参数 + +- **dataItemName** - [IN] 数据项名称,名称最大长度为128字节。 + +### 返回 + +数据项数据缓存区地址,数据最大长度为1024字节。 + +### setDataItem + +```java +void setDataItem (String dataItemName, + byte[] dataItemValue) +``` +创建或更新配置项。如果相同名称的配置项存在,则会更新其中的数据;否则将添加新的授权码配置项。 + +### 参数 + +- **dataItemName** - [IN] 数据项名称,名称最大长度为128字节。 +- **dataItemValue** - [IN] 数据项数据缓存区地址,数据最大长度为1024字节。 + +### 返回 + +无 + +### getDataItemNum + +```java +int getDataItemNum() +``` +此函数用于获取可访问配置项的数量,一般用于配置项的枚举操作。 + +### 参数 + +无 + +### 返回 + +可访问的数据项总数,包括了所有可以访问到的产品、模版及授权码的数据项。 + +### getDataItemName + +```java +String getDataItemName (int index) +``` +根据配置项索引获取其名称,一般用于配置项的枚举操作。 + +### 参数 + +- **index** - [IN] 数据项索引。 + +### 返回 + +用于存储数据项名称的存储区地址。 + +### removeDataItem + +```java +void removeDataItem (String dataItemName) +``` +删除指定的配置项。该操作无法删除通过控制台设置的产品配置项或模版配置项。 + +### 参数 + +- **dataItemName** - [IN] 数据项名称,名称最大长度为128字节。 + +### 返回 + +无 + +## 信息获取 + + +### getSessionInfo + +```java +String getSessionInfo (SessionType type) +``` +获取当前会话信息,以字符串形式返回。根据获取的内容不同,返回结果可能是XML格式或非XML格式。返回数据中的日期项已根据客户端的本地时区进行调整。如果Login时未指定SN,返回串为当前系统所有可用SN的综合结果。 + +### 参数 + +- **type** - [IN] 获取会话信息类型。 + +### type类型 + +- **XML_TYPE_SN_INFO** - 获取当前会话中授权码的授权信息,以XML结构表示。未作限制的授权项将不会返回 +- **XML_TYPE_FEATURE_INFO** - 获取当前会话中授权码的特征项信息,以XML结构表示 +- **XML_TYPE_DATA_INFO** - 获取当前会话中授权码的配置项信息,以XML结构表示 +- **BIT_SERVER_ADDRESS** - 授权服务器IP地址。只对云授权有意义,其它授权方式将返回:127.0.0.1 +- **BIT_SERVER_TIME** - 授权服务器系统时间。如果是本地授权,将返回本机系统时间 +- **BIT_CONTROL_TYPE** - 授权类型。是以逗号分隔的以下几种类型的组合:Group(集团授权),Smart(智能连接), Float(可浮动), Demo(演示授权), USB(U盘授权), Force(强制认证) +- **BIT_VOLUME_NUMBER** - 允许使用的机器数量 +- **BIT_START_DATE** - 授权开始日期 +- **BIT_END_DATE** - 授权结束日期 +- **BIT_EXPIRATION_DAYS** - 授权有效期,单位为天。有效期从激活时间算起 +- **BIT_USAGE_NUMBER** - 最大使用次数 +- **BIT_CONSUMED_USAGE_NUMBER** - 对于设定最大使用次数的授权码,返回当前使用次数 +- **BIT_ACTIVATE_DATE** - 授权码激活时间 +- **BIT_USER_LIMIT** - 集团授权用户数。对其它方式的授权返回0 +- **BIT_LAST_UPDATE_DATE** - 最后与服务器连接时间 +- **BIT_MAX_OFFLINE_MINUTES** - 强制认证最大离线时间(分钟) + +### 返回 + +根据输入类型返回的会话信息。 + +### getInfo + +```java +String getInfo (String sn, + InfoType type) +``` +获取本地授权信息。 + +### 参数 + +- **sn** - [IN] 授权码(SN)字符串 +- **type** - [IN] 获取信息类型。 + +### type类型 + +- **BIT_INFO_SERVER_ADDRESS** - 获取局域网内的集团授权服务器地址列表 +- **BIT_INFO_SN** - 获取本机已激活的授权码列表 +- **BIT_INFO_SN_FEATURE** - 获取本机已激活授权码的特征项列表 +- **BIT_INFO_SN_LICENSE** - 获取本机已激活授权码的授权信息 +- **BIT_INFO_UPDATE_ERROR** - 获取指定授权码的升级错误详细信息。是否存在详细信息由授权码类型及错误类型决定 +- **BIT_INFO_CONFIG** - 获取当前产品的配置文件信息 +- **BIT_INFO_TOKEN_LIST** - 获取当前机器上可用的BIT-ID列表信息 + +### 返回 + +根据输入信息类型返回的XML信息数据。 + +### getServerInfo + +```java +String getServerInfo (String url, + String sn, + String scope, + ServerInfoType type) +``` +获取集团服务的license信息,数据以XML格式返回。调用此函数前客户端不需要执行登录操作。 + +### 参数 + +- **url** - [IN] 自定义集团服务器地址,包括端口。如未使用自定义服务器则为NULL。 +- **sn** - [IN] 授权码(SN)字符串。如果为空(空串或NULL)则查询所有可用授权的license信息。 +- **scope** - [IN] 查询范围,XML格式字符串,支持过滤条件;如无需过滤则传空串。 +- **type** - [IN] 查询类型,详见ServerInfoType枚举,指定返回license信息的类型。类型: + - BIT_SERVER_INFO_SN 获取集团服务的授权码列表 + - BIT_SERVER_INFO_SN_FEATURE 获取集团服务的授权码的特征项列表 + - BIT_SERVER_INFO_SN_LICENSE 获取集团服务的授权码的授权信息 + - BIT_SERVER_INFO_FEATURE_LICENSE 获取集团服务的特征项的授权信息 + - BIT_SERVER_INFO_SN_USERS 获取集团服务被占用的SN的用户信息 + - BIT_SERVER_INFO_FEATURE_USERS 获取集团服务被占用的feature的用户信息 + +### 返回 + +集团服务license信息(XML格式字符串),包含授权有效期、特征项列表、可用用户数等内容。 + +### getVersion + +```java +int getVersion() +``` +获取客户端安全库版本号。 + +### 参数 + +无 + +### 返回 + +客户端安全库版本号。 + +### testBitService + +```java +void testBitService (String url, + String sn, + int featureId) +``` +测试集团授权的特征项是否可用,不会占用授权码或特征项的用户数。 + +### 参数 + +- **url** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **sn** - [IN] 授权码(SN)字符串。如果为空(空串或NULL)则尝试寻找所有当前本机可用的SN +- **featureId** - [IN] 登录授权所需要包含的特征项ID + +### 返回 + +无 + +### getProductPath + +```java +String getProductPath() +``` +获取授权存储目录。 + +### 参数 + +无 + +### 返回 + +数据缓存区地址,用于存储授权目录。 + +### getLastError + +```java +int getLastError() +``` +获取上一个API调用返回的错误码。 + +### 参数 + +无 + +### 返回 + +上一个API调用的错误码(0表示成功,非0表示失败)。 + +### 说明 + +仅返回当前线程中最近一次API调用的错误码;若最近一次调用成功,则返回0。 + +## 属性设置 + + +### setAttr + +```java +void setAttr (int type, + byte[] pValue) +``` +设置全局配置或当前会话的配置。 + +### 参数 + +- **type** - [IN] 设置函数功能类型。 + +### type类型 + +- **ATTR_HB_RETRY_FAILED_CALLBACK** - 心跳回调函数 +- **ATTR_WAIT_TIMEOUT** - 阻塞队列超时时间,最小16秒,最大24小时,默认是一直等待 +- **ATTR_RETRY_COUNT** - 客户端连接服务的重试次数。最小0次,最大1024次。默认是0次 +- **ATTR_RETRY_INTERVAL** - 客户端连接服务的重试间隔,最小是10秒,最大是4小时,默认是20秒 +- **ATTR_CONNECT_TIMEOUT** - 网络连接超时时间,最小是1秒,最大是32秒,默认是3秒 +- **ATTR_CONNECT_RETRY_COUNT** - 网络连接重试次数,最小是0次,最大是10次,默认是3次 +- **pValue** - [IN] 阻塞队列超时时间或者是回调函数地址等。 + +### 返回 + +无 + +### setProxy + +```java +void setProxy (String hostName, + int port, + String userId, + String password) +``` +设置代理服务的地址和端口。 + +### 参数 + +- **hostName** - [IN] 代理服务所在机器的IP地址。 +- **port** - [IN] 客户端应用程序的通讯端口,默认为 8273。 +- **userId** - [IN] 代理服务所在机器的用户名。 +- **password** - [IN] 代理服务所在机器的密码。 + +### 返回 + +无 + +### setCustomInfo + +```java +void setCustomInfo (int infoId, + String infoData) +``` +设置客户端运行自定义信息,需要在程序的最开始调用。infoId定义详见CustomInfo类型。 + +### 参数 + +- **infoId** - [IN] 自定义信息ID,详见CustomInfo枚举定义。目前除了CUSTOM_OPTION均可使用该方法。 +- **infoData** - [IN] 自定义信息数据,字符串格式。 + +### 返回 + +无 + +```java +void setCustomInfo (int infoId, + int infoData) +``` +设置客户端运行自定义信息,需要在程序的最开始调用。infoId定义详见CustomInfo类型。 + +### 参数 + +- **infoId** - [IN] 自定义信息ID,详见CustomInfo类型。目前仅针对CUSTOM_OPTION类型使用该方法。 +- **infoData** - [IN] 自定义信息数据,整型格式。CustomInfo类型: + - CUSTOM_CLIENT_ID(1), - 自定义终端标识,配置后该自定义标识会发送给服务器并用于今后的机器指纹匹配 + - CUSTOM_ACCOUNT_LOCAL(2), - 自定义客户端用户帐号,用于集团服务标识客户端用户 + - CUSTOM_COMMENT(3), - 自定义客户端登录注释,用于集团服务管理员获取用户登录请求信息 + - CUSTOM_OPTION(4), - 选项标志位(int类型) + - CUSTOM_SERVICE_INFO(5), - 服务信息 + - CUSTOM_PRODUCT_CODE(6), - 自定义授权目录名称 + - CUSTOM_ACCOUNT_DEVELOPER(7), - 自定义登录帐号,用于帐号授权 (既使用account登录,又设置了此选项,则直接忽略) + - CUSTOM_VENDOR_CODE(8), - 自定义开发商信息目前仅用于自定义环境变量名称 + - CUSTOM_HTTP_HEADER(9), - 自定义HTTP头,所有联网的请求都会自带这个请求头 + - CUSTOM_GROUP_NAME(0xA); - 设置自定义分组名 + +### setRootPath + +```java +void setRootPath (String rootPath) +``` +设置授权文件的存储路径。 + +### 参数 + +- **rootPath** - [IN] 数据缓存区地址,用于存储授权文件的路径。 + +### 返回 + +无 + +### setLocalServer + +```java +void setLocalServer (String hostName, + int port, + int timeout) +``` +设置集团服务的地址和端口。 + +### 参数 + +- **hostName** - [IN] 集团服务所安装机器的IP地址。 +- **port** - [IN] 客户端应用程序的通讯端口,默认为 8273。 +- **timeout** - [IN] 客户端超时秒数。 + +### 返回 + +无 + +## 借出操作 + + +### getBorrowRequest + +```java +String getBorrowRequest (String sn, + int durationDay) +``` +获取借出请求串,用来离线借出。 + +### 参数 + +- **sn** - [IN] 授权码(SN)字符串。如果为空(空串或NULL)则尝试寻找所有当前本机可用的SN。 +- **durationDay** - [IN] 借出有效期,单位为天,需小于等于授权码允许的最大借出天数。 + +### 返回 + +离线借出请求串,用于后续离线借出操作。 + +### getBorrowFeatureRequest + +```java +String getBorrowFeatureRequest (int durationDay, + String borrowScope) +``` +获取借出请求串,该接口支持指定特征项借出。 + +### 参数 + +- **durationDay** - [IN] 借出有效期,单位为天,需小于等于授权码允许的最大借出天数。 +- **borrowScope** - [IN] 指定借出的特征项范围,示例: + +```xml + + + + … + +``` + +### checkOutSn + +```java +void checkOutSn (String url, + int featureId) +``` +从授权服务器在线借出一个完整的授权码,以允许客户端服务器单独使用。被借出的授权码必须具有可借出属性,并在客户端成功借出后减少一个可用用户数。被借出的用户数在到期后将自动返还给服务器。 + +### 参数 + +- **url** - [IN] 集团授权服务器地址,包括端口。如输入NULL,则使用配置文件地址;如输入 * 号,则使用广播查找地址。 +- **featureId** - [IN] 指定借出授权码需要包含的特征项ID,为 0 则寻找第一个可借出授权码。 + +### 返回 + +无 + +### checkOutSnEx + +```java +void checkOutSnEx (String url, + int featureId, + String xmlScope, + int durationDays) +``` +从授权服务器在线借出一个完整的授权码,以允许客户端服务器单独使用。被借出的授权码必须具有可借出属性,并在客户端成功借出后减少一个可用用户数。被借出的用户数在到期后将自动返还给服务器。 + +### 参数 + +- **url** - [IN] 集团授权服务器地址,包括端口。如输入NULL,则使用配置文件地址;如输入 * 号,则使用广播查找地址。 +- **featureId** - [IN] 指定借出授权码需要包含的特征项ID,为 0 则寻找第一个可借出授权码。 +- **xmlScope** - [IN] 用于指定借出的参数,格式:`wsxxxx`,type设定为ws时表示从云授权服务器借出和归还。 +- **durationDays** - [IN] 借出有效期,单位为天,需小于等于授权码允许的最大借出天数。 + +### 返回 + +无 + +### checkOut + +```java +void checkOut (String url, + String scope, + String featureList, + int durationDays) +``` +从授权服务器在线借出授权码或者特征项。 + +### 参数 + +- **url** - [IN] 自定义授权服务器地址,包括端口。如未使用自定义授权服务器则为NULL。 +- **scope** - [IN] 借出范围。示例: + +```xml + + ws + xxx + + +说明: +type:借出类型。目前仅支持ws,表示从外网借出(针对云授权和集团授权) +sn:指定借出的SN +``` +- **featureList** - [IN] 特征项列表,指定借出的特征项列表,如果不传则借出整个SN。示例: + +```xml + + + + + + +当feature指定了借出时间,则会覆盖nDurationDays该时间,没有指定,则借出nDurationDays天。 +借出feature时,如果指定了版本,则直接大于等于借出版本的特征项,只借一个,如果没有指定版本,则该特征项的所有版本都借出一个。 +``` +- **durationDays** - [IN] 借出有效期,单位为天,需小于等于授权码允许的最大借出天数。 + +### 返回 + +无 + +### checkOutFeatures + +```java +void checkOutFeatures (String url, + int[] featureList, + int durationDays) +``` +从集团授权服务器借出一组特征项,这些特征项必须包含在同一个授权码中。被借出的集团授权码必须具有可借出属性,并在客户端成功借出后减少一个可用用户数。被借出的用户数在到期后将自动返还给集团服务器。 + +### 参数 + +- **url** - [IN] 集团授权服务器地址,包括端口。如输入NULL,则使用配置文件地址;如输入 * 号,则使用广播查找地址。 +- **featureList** - [IN] 特征项列表,指定借出的特征项列表,如果不传则借出整个SN。 +- **durationDays** - [IN] 借出有效期,单位为天,需小于等于授权码允许的最大借出天数。 + +### 返回 + +无 + +### checkIn + +```java +void checkIn (String url, + int featureId) +``` +提前返还从集团授权服务器借出的授权。要提前返还授权,该授权码必须具有允许提前返还属性。 + +### 参数 + +- **url** - [IN] 集团授权服务器地址,包括端口。如输入NULL,则使用配置文件地址;如输入 * 号,则使用广播查找地址。 +- **featureId** - [IN] 指定要返还授权码需要包含的特征项ID,为 0 则寻找第一个可返还授权码。 + +### 返回 + +无 + +### checkInEx + +```java +void checkInEx (String url, + int featureId, + String xmlScope) +``` +提前返还从授权服务器借出的授权。要提前返还授权,该授权码必须具有允许提前返还属性。 + +### 参数 + +- **url** - [IN] 集团授权服务器地址,包括端口。如输入NULL,则使用配置文件地址;如输入 * 号,则使用广播查找地址。 +- **featureId** - [IN] 指定要返还授权码需要包含的特征项ID,为 0 则寻找第一个可返还授权码。 +- **xmlScope** - [IN] 用于指定借出的参数,格式:`wsxxxx`,type设定为ws时表示从云授权服务器借出和归还。 + +### 返回 + +无 + +### ApplyBorrowInfo + +```java +void ApplyBorrowInfo (string borrowInfo) +``` +客户端应用离线借出串,ApplyUpdateInfo可以兼容该接口。 + +### 参数 + +- **borrowInfo** - [IN] 离线借出请求串,通过getBorrowRequest或getBorrowFeatureRequest接口获取。 + +### 返回 + +无 diff --git a/examples/cpp/main.cpp b/examples/cpp/main.cpp new file mode 100644 index 0000000..53e49bb --- /dev/null +++ b/examples/cpp/main.cpp @@ -0,0 +1,25 @@ +/* + * C++ 调用示例:初始化、校验许可、销毁句柄。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#include "craftlabs_auth.h" + +#include +#include + +int main() { + AuthHandle h = auth_initialize("{}"); + if (!h) { + return EXIT_FAILURE; + } + AuthResult r = auth_check_license(h); + if (r.success == 0) { + auth_destroy(h); + return EXIT_FAILURE; + } + auth_destroy(h); + std::printf("example cpp ok\n"); + return EXIT_SUCCESS; +} diff --git a/examples/java/ExampleApp.java b/examples/java/ExampleApp.java new file mode 100644 index 0000000..cf867ea --- /dev/null +++ b/examples/java/ExampleApp.java @@ -0,0 +1,21 @@ +import cn.craftlabs.auth.AuthProvider; +import cn.craftlabs.auth.AuthResult; +import cn.craftlabs.auth.bitanswer.BitAnswerProvider; + +/** + * 演示:通过 {@link BitAnswerProvider} 完成初始化与许可校验。 + * + *

版权所有 © 广州创飞人工智能技术有限公司 + * + * @author huangping@craftlabs.cn + */ +public class ExampleApp { + public static void main(String[] args) { + try (AuthProvider p = new BitAnswerProvider()) { + AuthResult r = p.initialize("{}"); + System.out.println("init: " + r.isSuccess() + " " + r.getMessage()); + r = p.checkLicense(); + System.out.println("check: " + r.isSuccess() + " " + r.getMessage()); + } + } +} diff --git a/examples/python/smoke.py b/examples/python/smoke.py new file mode 100644 index 0000000..fa59395 --- /dev/null +++ b/examples/python/smoke.py @@ -0,0 +1,29 @@ +#!/usr/bin/env python3 +"""示例:设置 CRAFTLABS_AUTH_LIBRARY 或 PYTHONPATH 后运行。 + +版权所有 © 广州创飞人工智能技术有限公司 +开发者:huangping@craftlabs.cn +""" + +import os +import sys + +ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..", "..")) +sys.path.insert(0, os.path.join(ROOT, "python")) + +from craftlabs_auth import AuthApi # noqa: E402 + + +def main() -> None: + lib = os.path.join(ROOT, "native", "build", "libcraftlabs_auth_bitanswer.so") + if os.path.isfile(lib): + os.environ.setdefault("CRAFTLABS_AUTH_LIBRARY", lib) + + with AuthApi() as api: + print(api.initialize("{}")) + print(api.check_license()) + print(api.get_license_info()) + + +if __name__ == "__main__": + main() diff --git a/java/craftlabs-auth-bitanswer/pom.xml b/java/craftlabs-auth-bitanswer/pom.xml new file mode 100644 index 0000000..9f44296 --- /dev/null +++ b/java/craftlabs-auth-bitanswer/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + + cn.craftlabs + craftlabs-auth-parent + 1.0.0-SNAPSHOT + + + craftlabs-auth-bitanswer + CraftLabs Auth — Bitanswer adapter + jar + + + + cn.craftlabs + craftlabs-auth-core + + + diff --git a/java/craftlabs-auth-bitanswer/src/main/java/cn/craftlabs/auth/bitanswer/BitAnswerProvider.java b/java/craftlabs-auth-bitanswer/src/main/java/cn/craftlabs/auth/bitanswer/BitAnswerProvider.java new file mode 100644 index 0000000..dc007e0 --- /dev/null +++ b/java/craftlabs-auth-bitanswer/src/main/java/cn/craftlabs/auth/bitanswer/BitAnswerProvider.java @@ -0,0 +1,73 @@ +package cn.craftlabs.auth.bitanswer; + +import cn.craftlabs.auth.AuthProvider; +import cn.craftlabs.auth.AuthResult; +import cn.craftlabs.auth.LicenseInfo; +import cn.craftlabs.auth.internal.NativeBridge; + +/** + * 比特安索(Bitanswer)授权提供者的 Java 封装。 + * + *

在静态初始化块中加载本地库 {@code craftlabs_auth_bitanswer},通过 {@link + * cn.craftlabs.auth.internal.NativeBridge} 将 {@link cn.craftlabs.auth.AuthProvider} 各方法委托给 C + * 端实现。重复调用 {@link #initialize(String)} 会先销毁已有 native 句柄再重新初始化。 + * + *

版权所有 © 广州创飞人工智能技术有限公司 + * + * @author huangping@craftlabs.cn + */ +public final class BitAnswerProvider implements AuthProvider { + static { + System.loadLibrary("craftlabs_auth_bitanswer"); + } + + private long nativeHandle; + + @Override + public AuthResult initialize(String configJson) { + if (nativeHandle != 0L) { + NativeBridge.nativeDestroy(nativeHandle); + nativeHandle = 0L; + } + nativeHandle = NativeBridge.nativeInitialize(configJson != null ? configJson : "{}"); + return new AuthResult(true, "Initialized"); + } + + @Override + public AuthResult activate(String licenseKey) { + return NativeBridge.nativeActivate(nativeHandle, licenseKey); + } + + @Override + public AuthResult checkLicense() { + return NativeBridge.nativeCheckLicense(nativeHandle); + } + + @Override + public LicenseInfo getLicenseInfo() { + return NativeBridge.nativeGetLicenseInfo(nativeHandle); + } + + @Override + public boolean hasFeature(String featureName) { + return NativeBridge.nativeHasFeature(nativeHandle, featureName); + } + + @Override + public AuthResult release() { + return NativeBridge.nativeRelease(nativeHandle); + } + + @Override + public AuthResult heartbeat() { + return NativeBridge.nativeHeartbeat(nativeHandle); + } + + @Override + public void close() { + if (nativeHandle != 0L) { + NativeBridge.nativeDestroy(nativeHandle); + nativeHandle = 0L; + } + } +} diff --git a/java/craftlabs-auth-core/pom.xml b/java/craftlabs-auth-core/pom.xml new file mode 100644 index 0000000..bfb4ed8 --- /dev/null +++ b/java/craftlabs-auth-core/pom.xml @@ -0,0 +1,16 @@ + + + 4.0.0 + + + cn.craftlabs + craftlabs-auth-parent + 1.0.0-SNAPSHOT + + + craftlabs-auth-core + CraftLabs Auth — core API + jar + diff --git a/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/AuthProvider.java b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/AuthProvider.java new file mode 100644 index 0000000..ead73af --- /dev/null +++ b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/AuthProvider.java @@ -0,0 +1,37 @@ +package cn.craftlabs.auth; + +/** + * 授权能力的统一契约:初始化、激活、校验许可、查询特性与释放等生命周期方法。 + * + *

实现类负责加载对应 native 或远端适配器;调用方应在不再使用时调用 {@link #close()} 释放底层资源。 + * + *

版权所有 © 广州创飞人工智能技术有限公司 + * + * @author huangping@craftlabs.cn + */ +public interface AuthProvider extends AutoCloseable { + /** 使用 JSON 配置初始化授权上下文;可重复调用,实现类应妥善处理句柄重置。 */ + AuthResult initialize(String configJson); + + /** 使用许可密钥激活(具体语义由底层供应商决定)。 */ + AuthResult activate(String licenseKey); + + /** 校验当前许可是否有效。 */ + AuthResult checkLicense(); + + /** 返回当前许可详情;具体字段含义与失败时的表现以各 {@link AuthProvider} 实现为准。 */ + LicenseInfo getLicenseInfo(); + + /** 查询指定特性是否开启。 */ + boolean hasFeature(String featureName); + + /** 释放/注销当前许可占用(与 {@link #close()} 侧重点不同,依供应商语义)。 */ + AuthResult release(); + + /** 会话心跳,用于在线校验或租约续期等场景。 */ + AuthResult heartbeat(); + + /** 释放 native 或远端资源;接口关闭后不得再调用其他方法。 */ + @Override + void close(); +} diff --git a/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/AuthResult.java b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/AuthResult.java new file mode 100644 index 0000000..3cc0805 --- /dev/null +++ b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/AuthResult.java @@ -0,0 +1,50 @@ +package cn.craftlabs.auth; + +import java.util.Objects; + +/** + * 单次授权操作的结果:成功与否及 UTF-8 说明信息(可能来自 native,勿假定固定文案)。 + * + *

版权所有 © 广州创飞人工智能技术有限公司 + * + * @author huangping@craftlabs.cn + */ +public final class AuthResult { + private final boolean success; + private final String message; + + public AuthResult(boolean success, String message) { + this.success = success; + this.message = message != null ? message : ""; + } + + public boolean isSuccess() { + return success; + } + + public String getMessage() { + return message; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + AuthResult that = (AuthResult) o; + return success == that.success && Objects.equals(message, that.message); + } + + @Override + public int hashCode() { + return Objects.hash(success, message); + } + + @Override + public String toString() { + return "AuthResult{success=" + success + ", message='" + message + '\'' + '}'; + } +} diff --git a/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/LicenseInfo.java b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/LicenseInfo.java new file mode 100644 index 0000000..b90c637 --- /dev/null +++ b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/LicenseInfo.java @@ -0,0 +1,68 @@ +package cn.craftlabs.auth; + +import java.util.Collections; +import java.util.Date; +import java.util.Map; +import java.util.Objects; + +/** + * 当前许可快照:是否已授权、过期时间及特性开关映射(不可变视图)。 + * + *

版权所有 © 广州创飞人工智能技术有限公司 + * + * @author huangping@craftlabs.cn + */ +public final class LicenseInfo { + private final boolean licensed; + private final Date expirationDate; + private final Map features; + + public LicenseInfo(boolean licensed, Date expirationDate, Map features) { + this.licensed = licensed; + this.expirationDate = expirationDate; + this.features = + features == null ? Collections.emptyMap() : Collections.unmodifiableMap(features); + } + + public boolean isLicensed() { + return licensed; + } + + public Date getExpirationDate() { + return expirationDate; + } + + public Map getFeatures() { + return features; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + LicenseInfo that = (LicenseInfo) o; + return licensed == that.licensed + && Objects.equals(expirationDate, that.expirationDate) + && Objects.equals(features, that.features); + } + + @Override + public int hashCode() { + return Objects.hash(licensed, expirationDate, features); + } + + @Override + public String toString() { + return "LicenseInfo{licensed=" + + licensed + + ", expirationDate=" + + expirationDate + + ", features=" + + features + + '}'; + } +} diff --git a/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/NativeBridge.java b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/NativeBridge.java new file mode 100644 index 0000000..907a0ab --- /dev/null +++ b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/NativeBridge.java @@ -0,0 +1,32 @@ +package cn.craftlabs.auth.internal; + +import cn.craftlabs.auth.AuthResult; +import cn.craftlabs.auth.LicenseInfo; + +/** + * JNI 入口:与 {@code jni_bridge.cpp} 中的 {@code Java_cn_craftlabs_auth_internal_NativeBridge_*} + * 函数签名一一对应,由各 {@code AuthProvider} 实现所在的模块加载同名 native 库后使用。 + * + *

版权所有 © 广州创飞人工智能技术有限公司 + * + * @author huangping@craftlabs.cn + */ +public final class NativeBridge { + private NativeBridge() {} + + public static native long nativeInitialize(String configJson); + + public static native void nativeDestroy(long handle); + + public static native AuthResult nativeActivate(long handle, String licenseKey); + + public static native AuthResult nativeCheckLicense(long handle); + + public static native LicenseInfo nativeGetLicenseInfo(long handle); + + public static native boolean nativeHasFeature(long handle, String featureName); + + public static native AuthResult nativeRelease(long handle); + + public static native AuthResult nativeHeartbeat(long handle); +} diff --git a/java/craftlabs-auth-selfhosted/pom.xml b/java/craftlabs-auth-selfhosted/pom.xml new file mode 100644 index 0000000..15cc07e --- /dev/null +++ b/java/craftlabs-auth-selfhosted/pom.xml @@ -0,0 +1,23 @@ + + + 4.0.0 + + + cn.craftlabs + craftlabs-auth-parent + 1.0.0-SNAPSHOT + + + craftlabs-auth-selfhosted + CraftLabs Auth — self-hosted HTTP adapter + jar + + + + cn.craftlabs + craftlabs-auth-core + + + diff --git a/java/craftlabs-auth-selfhosted/src/main/java/cn/craftlabs/auth/selfhosted/SelfHostedAuthProvider.java b/java/craftlabs-auth-selfhosted/src/main/java/cn/craftlabs/auth/selfhosted/SelfHostedAuthProvider.java new file mode 100644 index 0000000..884e6f0 --- /dev/null +++ b/java/craftlabs-auth-selfhosted/src/main/java/cn/craftlabs/auth/selfhosted/SelfHostedAuthProvider.java @@ -0,0 +1,72 @@ +package cn.craftlabs.auth.selfhosted; + +import cn.craftlabs.auth.AuthProvider; +import cn.craftlabs.auth.AuthResult; +import cn.craftlabs.auth.LicenseInfo; +import cn.craftlabs.auth.internal.NativeBridge; + +/** + * 自研授权(HTTP)适配器的 Java 封装。 + * + *

当前阶段复用与 Bitanswer 相同的 native 桩实现;后续可切换为独立 {@code + * libcraftlabs_auth_selfhosted}。 + * + *

版权所有 © 广州创飞人工智能技术有限公司 + * + * @author huangping@craftlabs.cn + */ +public final class SelfHostedAuthProvider implements AuthProvider { + static { + System.loadLibrary("craftlabs_auth_bitanswer"); + } + + private long nativeHandle; + + @Override + public AuthResult initialize(String configJson) { + if (nativeHandle != 0L) { + NativeBridge.nativeDestroy(nativeHandle); + nativeHandle = 0L; + } + nativeHandle = NativeBridge.nativeInitialize(configJson != null ? configJson : "{}"); + return new AuthResult(true, "Initialized (self-hosted stub)"); + } + + @Override + public AuthResult activate(String licenseKey) { + return NativeBridge.nativeActivate(nativeHandle, licenseKey); + } + + @Override + public AuthResult checkLicense() { + return NativeBridge.nativeCheckLicense(nativeHandle); + } + + @Override + public LicenseInfo getLicenseInfo() { + return NativeBridge.nativeGetLicenseInfo(nativeHandle); + } + + @Override + public boolean hasFeature(String featureName) { + return NativeBridge.nativeHasFeature(nativeHandle, featureName); + } + + @Override + public AuthResult release() { + return NativeBridge.nativeRelease(nativeHandle); + } + + @Override + public AuthResult heartbeat() { + return NativeBridge.nativeHeartbeat(nativeHandle); + } + + @Override + public void close() { + if (nativeHandle != 0L) { + NativeBridge.nativeDestroy(nativeHandle); + nativeHandle = 0L; + } + } +} diff --git a/java/craftlabs-auth-tests/pom.xml b/java/craftlabs-auth-tests/pom.xml new file mode 100644 index 0000000..b0a58fc --- /dev/null +++ b/java/craftlabs-auth-tests/pom.xml @@ -0,0 +1,45 @@ + + + 4.0.0 + + + cn.craftlabs + craftlabs-auth-parent + 1.0.0-SNAPSHOT + + + craftlabs-auth-tests + CraftLabs Auth — integration tests + jar + + + + cn.craftlabs + craftlabs-auth-bitanswer + ${project.version} + + + org.junit.jupiter + junit-jupiter + test + + + + + ${project.basedir}/../../native/build + + + + + + org.apache.maven.plugins + maven-surefire-plugin + + -Djava.library.path=${native.library.path} + + + + + diff --git a/java/craftlabs-auth-tests/src/test/java/cn/craftlabs/auth/BitAnswerProviderTest.java b/java/craftlabs-auth-tests/src/test/java/cn/craftlabs/auth/BitAnswerProviderTest.java new file mode 100644 index 0000000..dcb3e84 --- /dev/null +++ b/java/craftlabs-auth-tests/src/test/java/cn/craftlabs/auth/BitAnswerProviderTest.java @@ -0,0 +1,30 @@ +package cn.craftlabs.auth; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import cn.craftlabs.auth.bitanswer.BitAnswerProvider; +import org.junit.jupiter.api.Test; + +/** + * {@link BitAnswerProvider} 集成测试(依赖 native 桩)。 + * + *

版权所有 © 广州创飞人工智能技术有限公司 + * + * @author huangping@craftlabs.cn + */ +class BitAnswerProviderTest { + + @Test + void initializeCheckAndLicenseInfo_roundTrip() { + try (AuthProvider p = new BitAnswerProvider()) { + AuthResult init = p.initialize("{}"); + assertTrue(init.isSuccess(), init.getMessage()); + AuthResult ok = p.checkLicense(); + assertTrue(ok.isSuccess(), ok.getMessage()); + LicenseInfo info = p.getLicenseInfo(); + assertNotNull(info); + assertTrue(info.isLicensed()); + } + } +} diff --git a/java/pom.xml b/java/pom.xml new file mode 100644 index 0000000..0da01be --- /dev/null +++ b/java/pom.xml @@ -0,0 +1,58 @@ + + + 4.0.0 + + cn.craftlabs + craftlabs-auth-parent + 1.0.0-SNAPSHOT + pom + CraftLabs Auth SDK (parent) + + + craftlabs-auth-core + craftlabs-auth-bitanswer + craftlabs-auth-selfhosted + craftlabs-auth-tests + + + + UTF-8 + 17 + 5.10.2 + + + + + + cn.craftlabs + craftlabs-auth-core + ${project.version} + + + org.junit.jupiter + junit-jupiter + ${junit.version} + test + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.12.1 + + + org.apache.maven.plugins + maven-surefire-plugin + 3.2.5 + + + + + diff --git a/native/CMakeLists.txt b/native/CMakeLists.txt new file mode 100644 index 0000000..1b1cb01 --- /dev/null +++ b/native/CMakeLists.txt @@ -0,0 +1,58 @@ +cmake_minimum_required(VERSION 3.16) +project(craftlabs_auth_bitanswer LANGUAGES C CXX) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +set(CRAFTLABS_AUTH_SRC_DIR "${CMAKE_CURRENT_SOURCE_DIR}") + +option(CRAFTLABS_BUILD_JNI "Build JNI bridge (requires JDK)" ON) +option(CRAFTLABS_BUILD_TESTS "Build native smoke tests" ON) + +set(CRAFTLABS_AUTH_CORE_SOURCES + "${CRAFTLABS_AUTH_SRC_DIR}/src/craftlabs_auth.cpp" + "${CRAFTLABS_AUTH_SRC_DIR}/src/bitanswer/bitanswer_adapter.cpp" + "${CRAFTLABS_AUTH_SRC_DIR}/src/selfhosted/http_client.cpp" + "${CRAFTLABS_AUTH_SRC_DIR}/src/selfhosted/selfhosted_adapter.cpp" +) + +if(CRAFTLABS_BUILD_JNI) + find_package(JNI REQUIRED) + list(APPEND CRAFTLABS_AUTH_CORE_SOURCES + "${CRAFTLABS_AUTH_SRC_DIR}/src/jni/jni_bridge.cpp") +endif() + +add_library(craftlabs_auth_bitanswer SHARED ${CRAFTLABS_AUTH_CORE_SOURCES}) + +target_include_directories(craftlabs_auth_bitanswer + PUBLIC + "${CRAFTLABS_AUTH_SRC_DIR}/include" + PRIVATE + "${CRAFTLABS_AUTH_SRC_DIR}/src" +) + +if(CRAFTLABS_BUILD_JNI) + target_include_directories(craftlabs_auth_bitanswer PRIVATE ${JNI_INCLUDE_DIRS}) +endif() + +if(WIN32) + target_compile_definitions(craftlabs_auth_bitanswer PRIVATE CRAFTLABS_AUTH_PLATFORM_WINDOWS=1) +elseif(APPLE) + target_compile_definitions(craftlabs_auth_bitanswer PRIVATE CRAFTLABS_AUTH_PLATFORM_MACOS=1) +else() + target_compile_definitions(craftlabs_auth_bitanswer PRIVATE CRAFTLABS_AUTH_PLATFORM_LINUX=1) +endif() + +if(CRAFTLABS_BUILD_TESTS) + enable_testing() + add_executable(craftlabs_auth_smoke + "${CRAFTLABS_AUTH_SRC_DIR}/tests/smoke_test.cpp") + target_link_libraries(craftlabs_auth_smoke PRIVATE craftlabs_auth_bitanswer) + target_include_directories(craftlabs_auth_smoke PRIVATE + "${CRAFTLABS_AUTH_SRC_DIR}/include") + set_target_properties(craftlabs_auth_smoke PROPERTIES + BUILD_RPATH "$") + add_test(NAME craftlabs_auth_smoke COMMAND craftlabs_auth_smoke) +endif() diff --git a/native/include/craftlabs_auth.h b/native/include/craftlabs_auth.h new file mode 100644 index 0000000..9c1801b --- /dev/null +++ b/native/include/craftlabs_auth.h @@ -0,0 +1,70 @@ +/* + * CraftLabs 授权 SDK — C 语言 FFI 公共头文件。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#ifndef CRAFTLABS_AUTH_H +#define CRAFTLABS_AUTH_H + +#include + +/* + * FFI / Python(ctypes、cffi)说明 + * ---------------------------------- + * - 所有 `const char*` 均为 **UTF-8** 编码、以 `\0` 结尾。 + * - `AuthHandle`:不透明指针,仅由本库函数产生与销毁(`auth_initialize` / `auth_destroy`)。 + * - `AuthResult`、`LicenseInfo` 使用 `stdint` 定宽字段,避免 `time_t`/`int` 宽度随平台变化导致 Python 侧 Structure 布局错误。 + * - `AuthResult.message`:指向 **由本库管理的静态或内部只读缓冲区**,调用方不得 `free`;在任意后续对本库的再次调用之后视为可能失效(与其它 FFI 语言惯例一致)。 + * - `auth_get_license_info` 返回的 `LicenseInfo*`(及其中 `feature_names` / `feature_values` 指向的数组)须通过 `auth_free_license_info` 释放;释放后不得再读指针成员。 + * - 官方 Python 绑定见仓库 `python/craftlabs_auth/`(ctypes,与本头文件字段一一对应)。 + */ + +#ifdef _WIN32 +#define CRAFTLABS_API __declspec(dllexport) +#else +#define CRAFTLABS_API __attribute__((visibility("default"))) +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void* AuthHandle; + +typedef struct { + int32_t success; /* 1: 成功, 0: 失败 */ + const char* message; /* UTF-8,由库持有,勿 free */ +} AuthResult; + +typedef struct { + int32_t is_licensed; /* 1: 已授权, 0: 否 */ + int64_t expiration_date; /* Unix 纪元秒数(UTC),0 表示无过期限制 */ + const char** feature_names; /* 以 NULL 结尾的指针数组,或长度由 feature_count 给出,由随 LicenseInfo 一并释放 */ + int32_t* feature_values; /* 与 feature_names 一一对应,元素为 0/1 */ + int32_t feature_count; +} LicenseInfo; + +CRAFTLABS_API AuthHandle auth_initialize(const char* config_json); + +CRAFTLABS_API AuthResult auth_activate(AuthHandle handle, const char* license_key); + +CRAFTLABS_API AuthResult auth_check_license(AuthHandle handle); + +CRAFTLABS_API LicenseInfo* auth_get_license_info(AuthHandle handle); + +CRAFTLABS_API void auth_free_license_info(LicenseInfo* info); + +CRAFTLABS_API int32_t auth_has_feature(AuthHandle handle, const char* feature_name); + +CRAFTLABS_API AuthResult auth_release(AuthHandle handle); + +CRAFTLABS_API AuthResult auth_heartbeat(AuthHandle handle); + +CRAFTLABS_API void auth_destroy(AuthHandle handle); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/native/src/bitanswer/bitanswer_adapter.cpp b/native/src/bitanswer/bitanswer_adapter.cpp new file mode 100644 index 0000000..7e8db63 --- /dev/null +++ b/native/src/bitanswer/bitanswer_adapter.cpp @@ -0,0 +1,11 @@ +/* + * 比特安索(Bitanswer)适配器实现(占位)。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#include "bitanswer_adapter.h" + +void bitanswer_adapter_register(void) { + /* 后续里程碑:在此挂接 Bit_LoginEx、Bit_QueryFeature 等与 craftlabs_auth 生命周期对齐。 */ +} diff --git a/native/src/bitanswer/bitanswer_adapter.h b/native/src/bitanswer/bitanswer_adapter.h new file mode 100644 index 0000000..9342d64 --- /dev/null +++ b/native/src/bitanswer/bitanswer_adapter.h @@ -0,0 +1,20 @@ +/* + * 比特安索(Bitanswer)适配器注册入口。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 向核心库注册 Bitanswer 相关钩子;当前里程碑可为空实现,后续接入 Bit_LoginEx / Bit_QueryFeature 等。 + */ +void bitanswer_adapter_register(void); + +#ifdef __cplusplus +} +#endif diff --git a/native/src/craftlabs_auth.cpp b/native/src/craftlabs_auth.cpp new file mode 100644 index 0000000..bb346b5 --- /dev/null +++ b/native/src/craftlabs_auth.cpp @@ -0,0 +1,112 @@ +/* + * CraftLabs 授权 SDK — 核心 C API 实现(含桩逻辑与各适配器注册)。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#include "craftlabs_auth.h" + +#include +#include + +#include "bitanswer/bitanswer_adapter.h" +#include "selfhosted/selfhosted_adapter.h" + +namespace { + +/** 不透明句柄对应的内部状态;后续可扩展为供应商特定字段。 */ +struct AuthContext { + int dummy; +}; + +static const AuthResult k_ok = {1, "stub"}; +static const AuthResult k_fail = {0, "stub failure"}; + +AuthContext* as_ctx(AuthHandle h) { + return reinterpret_cast(h); +} + +void ensure_adapters_registered_once() { + static bool once = false; + if (!once) { + bitanswer_adapter_register(); + selfhosted_adapter_register(); + once = true; + } +} + +} // namespace + +extern "C" { + +CRAFTLABS_API AuthHandle auth_initialize(const char* /* config_json */) { + ensure_adapters_registered_once(); + auto* ctx = new AuthContext{}; + ctx->dummy = 1; + return reinterpret_cast(ctx); +} + +CRAFTLABS_API AuthResult auth_activate(AuthHandle handle, const char* /* license_key */) { + if (!handle) { + return k_fail; + } + (void)as_ctx(handle); + return k_ok; +} + +CRAFTLABS_API AuthResult auth_check_license(AuthHandle handle) { + if (!handle) { + return k_fail; + } + return k_ok; +} + +CRAFTLABS_API LicenseInfo* auth_get_license_info(AuthHandle handle) { + if (!handle) { + return nullptr; + } + auto* info = static_cast(std::malloc(sizeof(LicenseInfo))); + if (!info) { + return nullptr; + } + info->is_licensed = 1; + info->expiration_date = 0; + info->feature_names = nullptr; + info->feature_values = nullptr; + info->feature_count = 0; + return info; +} + +CRAFTLABS_API void auth_free_license_info(LicenseInfo* info) { + std::free(info); +} + +CRAFTLABS_API int32_t auth_has_feature(AuthHandle handle, const char* /* feature_name */) { + if (!handle) { + return 0; + } + return 1; +} + +CRAFTLABS_API AuthResult auth_release(AuthHandle handle) { + if (!handle) { + return k_fail; + } + return k_ok; +} + +CRAFTLABS_API AuthResult auth_heartbeat(AuthHandle handle) { + if (!handle) { + return k_fail; + } + return k_ok; +} + +CRAFTLABS_API void auth_destroy(AuthHandle handle) { + if (!handle) { + return; + } + delete as_ctx(handle); +} + +} diff --git a/native/src/jni/jni_bridge.cpp b/native/src/jni/jni_bridge.cpp new file mode 100644 index 0000000..a4f4efe --- /dev/null +++ b/native/src/jni/jni_bridge.cpp @@ -0,0 +1,151 @@ +/* + * JNI 桥:java 包 cn.craftlabs.auth.internal.NativeBridge 与 craftlabs_auth.h C API 之间的映射。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#include +#include + +#include "craftlabs_auth.h" + +namespace { + +AuthHandle from_jlong(jlong ptr) { + return reinterpret_cast(static_cast(ptr)); +} + +jobject make_auth_result(JNIEnv* env, const AuthResult& r) { + jclass cls = env->FindClass("cn/craftlabs/auth/AuthResult"); + if (!cls) { + return nullptr; + } + jmethodID ctor = env->GetMethodID(cls, "", "(ZLjava/lang/String;)V"); + if (!ctor) { + return nullptr; + } + jboolean ok = (r.success != 0) ? JNI_TRUE : JNI_FALSE; + jstring msg = env->NewStringUTF(r.message ? r.message : ""); + if (!msg) { + return nullptr; + } + jobject out = env->NewObject(cls, ctor, ok, msg); + env->DeleteLocalRef(msg); + return out; +} + +jobject make_license_info(JNIEnv* env, LicenseInfo* info) { + if (!info) { + return nullptr; + } + jclass cls = env->FindClass("cn/craftlabs/auth/LicenseInfo"); + if (!cls) { + return nullptr; + } + jmethodID ctor = env->GetMethodID(cls, "", "(ZLjava/util/Date;Ljava/util/Map;)V"); + if (!ctor) { + return nullptr; + } + jboolean licensed = info->is_licensed ? JNI_TRUE : JNI_FALSE; + + jobject date = nullptr; + if (info->expiration_date != 0) { + jclass dateCls = env->FindClass("java/util/Date"); + jmethodID dateCtor = env->GetMethodID(dateCls, "", "(J)V"); + jlong ms = static_cast(info->expiration_date) * 1000LL; + date = env->NewObject(dateCls, dateCtor, ms); + } + + jclass mapCls = env->FindClass("java/util/HashMap"); + jmethodID mapCtor = env->GetMethodID(mapCls, "", "()V"); + jobject map = env->NewObject(mapCls, mapCtor); + jmethodID put = env->GetMethodID(mapCls, "put", + "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); + for (int i = 0; i < info->feature_count; ++i) { + const char* name = info->feature_names[i]; + int v = info->feature_values[i]; + jstring jn = env->NewStringUTF(name ? name : ""); + jclass boolCls = env->FindClass("java/lang/Boolean"); + jmethodID valueOf = + env->GetStaticMethodID(boolCls, "valueOf", "(Z)Ljava/lang/Boolean;"); + jobject jb = env->CallStaticObjectMethod(boolCls, valueOf, v ? JNI_TRUE : JNI_FALSE); + env->CallObjectMethod(map, put, jn, jb); + env->DeleteLocalRef(jn); + env->DeleteLocalRef(jb); + } + jobject out = env->NewObject(cls, ctor, licensed, date, map); + if (date) { + env->DeleteLocalRef(date); + } + env->DeleteLocalRef(map); + return out; +} + +} // namespace + +extern "C" { + +JNIEXPORT jlong JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeInitialize( + JNIEnv* env, jclass, jstring configJson) { + const char* utf = configJson ? env->GetStringUTFChars(configJson, nullptr) : nullptr; + AuthHandle h = auth_initialize(utf ? utf : "{}"); + if (configJson && utf) { + env->ReleaseStringUTFChars(configJson, utf); + } + return static_cast(reinterpret_cast(h)); +} + +JNIEXPORT void JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeDestroy(JNIEnv*, + jclass, + jlong handle) { + auth_destroy(from_jlong(handle)); +} + +JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeActivate( + JNIEnv* env, jclass, jlong handle, jstring licenseKey) { + const char* utf = licenseKey ? env->GetStringUTFChars(licenseKey, nullptr) : ""; + AuthResult r = auth_activate(from_jlong(handle), utf ? utf : ""); + if (licenseKey && utf) { + env->ReleaseStringUTFChars(licenseKey, utf); + } + return make_auth_result(env, r); +} + +JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeCheckLicense( + JNIEnv* env, jclass, jlong handle) { + AuthResult r = auth_check_license(from_jlong(handle)); + return make_auth_result(env, r); +} + +JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeGetLicenseInfo( + JNIEnv* env, jclass, jlong handle) { + LicenseInfo* info = auth_get_license_info(from_jlong(handle)); + jobject jinfo = make_license_info(env, info); + auth_free_license_info(info); + return jinfo; +} + +JNIEXPORT jboolean JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeHasFeature( + JNIEnv* env, jclass, jlong handle, jstring featureName) { + const char* utf = featureName ? env->GetStringUTFChars(featureName, nullptr) : ""; + int v = auth_has_feature(from_jlong(handle), utf ? utf : ""); + if (featureName && utf) { + env->ReleaseStringUTFChars(featureName, utf); + } + return v ? JNI_TRUE : JNI_FALSE; +} + +JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeRelease(JNIEnv* env, + jclass, + jlong handle) { + AuthResult r = auth_release(from_jlong(handle)); + return make_auth_result(env, r); +} + +JNIEXPORT jobject JNICALL Java_cn_craftlabs_auth_internal_NativeBridge_nativeHeartbeat( + JNIEnv* env, jclass, jlong handle) { + AuthResult r = auth_heartbeat(from_jlong(handle)); + return make_auth_result(env, r); +} + +} diff --git a/native/src/selfhosted/http_client.cpp b/native/src/selfhosted/http_client.cpp new file mode 100644 index 0000000..bb39ac2 --- /dev/null +++ b/native/src/selfhosted/http_client.cpp @@ -0,0 +1,12 @@ +/* + * 自研适配器 HTTP 客户端桩实现。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#include "http_client.h" + +int selfhosted_http_ping(const char* /* base_url */) { + /* 接入 libcurl 等之后再实现真实请求;当前保证注册阶段可链接通过。 */ + return 0; +} diff --git a/native/src/selfhosted/http_client.h b/native/src/selfhosted/http_client.h new file mode 100644 index 0000000..599b67f --- /dev/null +++ b/native/src/selfhosted/http_client.h @@ -0,0 +1,22 @@ +/* + * 自研适配器用的最小 HTTP 门面(后续可接 libcurl / WinHTTP)。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * 对给定基地址做连通性探测;当前为占位实现。 + * @param base_url 服务根 URL,可为空(实现定义行为)。 + * @return 0 表示占位成功,非 0 预留为错误码。 + */ +int selfhosted_http_ping(const char* base_url); + +#ifdef __cplusplus +} +#endif diff --git a/native/src/selfhosted/selfhosted_adapter.cpp b/native/src/selfhosted/selfhosted_adapter.cpp new file mode 100644 index 0000000..9dc971d --- /dev/null +++ b/native/src/selfhosted/selfhosted_adapter.cpp @@ -0,0 +1,12 @@ +/* + * 自研 HTTP 授权适配器实现。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#include "selfhosted_adapter.h" +#include "http_client.h" + +void selfhosted_adapter_register(void) { + (void)selfhosted_http_ping(""); +} diff --git a/native/src/selfhosted/selfhosted_adapter.h b/native/src/selfhosted/selfhosted_adapter.h new file mode 100644 index 0000000..3b79859 --- /dev/null +++ b/native/src/selfhosted/selfhosted_adapter.h @@ -0,0 +1,18 @@ +/* + * 自研 HTTP 授权适配器 — 注册入口。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +/** 注册自研适配器依赖(如 HTTP 客户端探测);可与 Bitanswer 注册并存。 */ +void selfhosted_adapter_register(void); + +#ifdef __cplusplus +} +#endif diff --git a/native/tests/smoke_test.cpp b/native/tests/smoke_test.cpp new file mode 100644 index 0000000..e4cc45a --- /dev/null +++ b/native/tests/smoke_test.cpp @@ -0,0 +1,34 @@ +/* + * Native 库冒烟测试。 + * + * 版权所有 © 广州创飞人工智能技术有限公司 + * 开发者:huangping@craftlabs.cn + */ +#include "craftlabs_auth.h" + +#include +#include + +int main() { + AuthHandle h = auth_initialize("{}"); + if (!h) { + std::fprintf(stderr, "auth_initialize returned null\n"); + return EXIT_FAILURE; + } + AuthResult r = auth_check_license(h); + if (r.success == 0) { + std::fprintf(stderr, "auth_check_license failed\n"); + auth_destroy(h); + return EXIT_FAILURE; + } + LicenseInfo* info = auth_get_license_info(h); + if (!info) { + std::fprintf(stderr, "auth_get_license_info returned null\n"); + auth_destroy(h); + return EXIT_FAILURE; + } + auth_free_license_info(info); + auth_destroy(h); + std::printf("native smoke ok\n"); + return EXIT_SUCCESS; +}