# 业务插件（RTwoGameBusiness）TCP接口说明

## 1. 文档概述

### 1.1 版本

| 版本号 | 日期 | 作者 | 变更内容 | 状态 |
|-------|------|------|---------|------|
| 1.0 | 2025-05-29 | JJX | 初始创建 | 正式发布 |
| 1.1 | 2025-06-15 | JJX | 添加get-system-info接口说明和更新check-unis-net-state接口说明 | 正式发布 |

### 1.2 目的

本文档详细描述RTwoGameBusiness业务插件提供的TCP接口规范，用于游戏客户端与业务插件之间的通信。该文档面向开发人员、测试人员和集成人员，提供接口的详细说明、参数格式、错误码以及使用示例。

### 1.3 适用范围

- 开发人员：用于实现游戏客户端与业务插件的通信
- 测试人员：用于验证接口功能和性能
- 集成人员：用于系统集成和故障排查
- 维护人员：用于系统维护和问题定位

### 1.4 接口概述

RTwoGameBusiness插件通过TCP协议提供服务，主要包括以下功能类别：

1. **用户卡功能**：用户信息查询、刷卡登录等
2. **点数卡功能**：点数查询、充值、扣点等
3. **游戏记录功能**：游戏积分、金币、宝石、卡牌、投币记录等
4. **4G网络控制**：4G模块状态查询、启动和停止等

## 2. 基础信息

### 2.1 服务端口

RTwoGameBusiness插件默认监听TCP端口：**12103**

该端口可通过配置文件修改，修改后需重启插件生效。

### 2.2 通信协议

- 通信协议：TCP
- 字符编码：UTF-8
- 数据格式：JSON

### 2.3 请求格式

所有请求都应遵循以下JSON格式：

```json
{
  "command": "命令名称",
  "data": {
    // 根据不同命令类型包含不同的参数
  },
  "ts": 1621234567890  // 可选，请求时间戳（毫秒）
}
```

### 2.4 响应格式

所有响应都遵循以下JSON格式：

```json
{
  "result": true,       // 响应结果，true成功，false失败
  "errMsg": "",         // 错误信息，成功时为空
  "statusCode": 0,      // 状态码，0表示成功，非0表示各种错误
  "command": "命令名称", // 关联的指令标识
  "data": {             // 返回数据，根据不同接口有不同结构
    // 根据不同命令返回不同的数据
  },
  "ts": 1621234567890   // 可选，响应时间戳（毫秒）
}
```

## 3. 接口详细说明

根据功能分类，本章节将详细介绍RTwoGameBusiness插件提供的所有TCP接口。

### 3.1 用户卡功能接口

#### 3.1.1 用户信息查询 (select-user-info)

该接口用于查询用户卡所绑定的用户信息，并可选择性地返回排行榜数据。

**请求命令**：`select-user-info`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| cardId | string | 是(与cardSn二选一) | 卡ID |
| cardSn | string | 是(与cardId二选一) | 卡序列号 |
| gameLevel | string | 否 | 游戏关卡，不传则返回所有关卡的排行榜 |
| topLimit | int | 否 | 排行榜条数限制，默认为10 |
| topType | int | 否 | 排行榜类型：0=积分排行榜（默认），1=时长排行榜 |

**请求示例**：

```json
{
  "command": "select-user-info",
  "data": {
    "cardId": "1234567890",
    "gameLevel": "1",
    "topLimit": 10,
    "topType": 0
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| cardId | string | 卡ID |
| cardSn | string | 卡序列号 |
| userName | string | 用户名称 |
| userAvatar | string | 用户头像URL |
| userSex | int | 用户性别：0-未知 1-男 2-女 |
| topType | int | 排行榜类型：0=积分排行榜，1=时长排行榜 |
| leaderboards | object | 按游戏关卡分组的排行榜，key为游戏关卡 |

**leaderboards对象内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| rank | int | 用户在此排行榜中的排名 |
| score | int | 用户在此排行榜中的积分（当topType=0时有效） |
| duration | int | 用户在此排行榜中的游戏时长（当topType=1时有效） |
| gameLevel | string | 游戏关卡 |
| records | array | 排行榜记录列表 |

**records数组内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| id | int | 记录ID |
| cardId | string | 卡ID |
| userName | string | 用户名称 |
| score | int | 游戏得分 |
| gameDuration | int | 游戏时长（秒） |
| playTime | string | 游戏时间（格式化字符串） |
| gameLevel | string | 游戏关卡 |
| gameType | string | 游戏类型 |
| skinId | string | 皮肤ID |
| playerCount | int | 共同游戏的玩家数量 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "select-user-info",
  "data": {
    "cardId": "1234567890",
    "cardSn": "A1B2C3D4",
    "userName": "玩家001",
    "userAvatar": "http://example.com/avatar/001.jpg",
    "userSex": 1,
    "topType": 0,
    "leaderboards": {
      "1": {
        "rank": 3,
        "score": 1500,
        "gameLevel": "1",
        "records": [
          {
            "id": 123,
            "cardId": "9876543210",
            "userName": "玩家088",
            "score": 2000,
            "gameDuration": 300,
            "playTime": "2025-05-28 14:30:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_001",
            "playerCount": 1
          },
          {
            "id": 124,
            "cardId": "8765432109",
            "userName": "玩家072",
            "score": 1800,
            "gameDuration": 280,
            "playTime": "2025-05-28 15:20:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_002",
            "playerCount": 1
          },
          {
            "id": 125,
            "cardId": "1234567890",
            "userName": "玩家001",
            "score": 1500,
            "gameDuration": 260,
            "playTime": "2025-05-28 16:10:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_003",
            "playerCount": 1
          }
        ]
      }
    }
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（卡ID和卡序列号都为空） |
| 40 | 用户不存在 |

**备注**：
1. 卡ID和卡序列号必须至少提供一个，优先使用卡ID查询。
2. 如果未指定排行榜类型，默认返回积分排行榜。
3. 如果未指定游戏关卡，将返回所有关卡的排行榜数据。
4. 排行榜数据按分数或时长降序排列。

#### 3.1.2 刷卡登录 (cwyz-swipe-card)

该接口用于处理游戏中的刷卡操作，关联用户与游戏。

**请求命令**：`cwyz-swipe-card`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| cardSn | string | 是 | 卡序列号 |
| playerIdx | int | 是 | 玩家索引，用于多人游戏时区分不同玩家位置 |

**请求示例**：

```json
{
  "command": "cwyz-swipe-card",
  "data": {
    "cardSn": "A1B2C3D4",
    "playerIdx": 1
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| cardId | string | 卡ID |
| cardSn | string | 卡序列号 |
| userName | string | 用户名称 |
| userAvatar | string | 用户头像URL |
| userSex | int | 用户性别：0-未知 1-男 2-女 |
| playerIdx | int | 玩家索引 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "cwyz-swipe-card",
  "data": {
    "cardId": "1234567890",
    "cardSn": "A1B2C3D4",
    "userName": "玩家001",
    "userAvatar": "http://example.com/avatar/001.jpg",
    "userSex": 1,
    "playerIdx": 1
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（卡序列号为空） |
| 40 | 用户卡不存在 |
| 30 | 网络错误（与服务器通信失败） |

**备注**：
1. 刷卡操作会尝试从服务器获取最新的用户信息，如果网络不可用，会使用本地存储的用户信息。
2. 玩家索引用于区分多人游戏时的不同位置，通常从1开始，对应游戏机的不同位置。
3. 如果卡片未绑定用户，会返回默认的用户信息。

### 3.2 点数卡功能接口

#### 3.2.1 查询剩余点数 (get-remaining-points)

该接口用于查询当前游戏机剩余的点数，用于显示给用户或判断是否有足够点数执行出卡操作。

**请求命令**：`get-remaining-points`

**请求参数**：
无需参数

**请求示例**：

```json
{
  "command": "get-remaining-points",
  "data": {}
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| remainingPoints | int | 剩余点数 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "get-remaining-points",
  "data": {
    "remainingPoints": 100
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 20 | 数据库错误（读取点数卡信息失败） |

**备注**：
1. 此接口会返回所有已绑定点数卡的剩余点数总和。
2. 如果没有任何点数卡，返回的剩余点数为0。
3. 点数信息优先从本地数据库获取，确保即使在网络不可用时也能正常工作。

#### 3.2.2 绑定点卡 (bind-point-card)

该接口用于绑定新的点数卡到游戏机上。

**请求命令**：`bind-point-card`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| cardCode | string | 是 | 点卡卡号 |

**请求示例**：

```json
{
  "command": "bind-point-card",
  "data": {
    "cardCode": "PC12345678"
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| remainingPoints | int | 绑定后的剩余点数 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "bind-point-card",
  "data": {
    "remainingPoints": 100
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（卡号为空） |
| 20 | 数据库错误（绑定点数卡失败） |
| 60 | 卡片不存在（点卡号无效） |
| 61 | 点卡已使用 |

**备注**：
1. 绑定点卡后，点数将自动添加到游戏机的总点数中。
2. 一个点卡只能被绑定一次，绑定后不能重复使用。
3. 点卡绑定后立即生效，无需重启游戏机。

#### 3.2.3 出卡扣点 (deduct-points)

该接口用于游戏出卡时扣除相应点数。

**请求命令**：`deduct-points`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| pointsToDeduct | int | 否 | 需要扣除的点数，默认为1 |
| playerIdx | int | 否 | 机台位置索引，默认为1 |

**请求示例**：

```json
{
  "command": "deduct-points",
  "data": {
    "pointsToDeduct": 1,
    "playerIdx": 1
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| remainingPoints | int | 扣除后的剩余点数 |
| isUploaded | bool | 是否已上报到服务器 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "deduct-points",
  "data": {
    "remainingPoints": 99,
    "isUploaded": true
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（扣点数量无效） |
| 20 | 数据库错误（扣点操作失败） |
| 50 | 点数不足 |

**备注**：
1. 扣点操作会根据当前配置的扣点模式执行（本地模式、实时模式或混合模式）。
2. 如果使用本地模式，操作会先在本地执行，然后在适当时机上报到服务器。
3. 如果使用实时模式，操作会直接上报到服务器，并立即返回结果。
4. 如果点数不足，将返回错误码50。
5. 每次扣点操作都会记录在扣点记录表中，用于后续统计和审计。

### 3.3 游戏记录功能接口

#### 3.3.1 保存游戏积分 (cwyz-score-save)

该接口用于保存玩家的游戏积分和相关游戏数据，同时可以获取游戏排行榜信息。

**请求命令**：`cwyz-score-save`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| cardId | string | 是 | 卡ID，用于关联用户 |
| score | int | 是 | 游戏得分 |
| gameLevel | string | 是 | 游戏关卡 |
| gameType | string | 是 | 游戏类型 |
| topLimit | int | 否 | 排行榜总数，默认为10 |
| gameDuration | int | 否 | 游戏时长（秒） |
| golds | int | 否 | 获得金币数量 |
| gemstone | int | 否 | 获得的未鉴定宝石数量 |
| playerIdx | int | 否 | 玩家索引，默认为1 |
| skinId | string | 否 | 皮肤ID |
| playerCount | int | 否 | 共同游戏的玩家数量，默认为1 |

**请求示例**：

```json
{
  "command": "cwyz-score-save",
  "data": {
    "cardId": "1234567890",
    "score": 1500,
    "gameLevel": "1",
    "gameType": "standard",
    "topLimit": 10,
    "gameDuration": 300,
    "golds": 50,
    "gemstone": 2,
    "playerIdx": 1,
    "skinId": "skin_001",
    "playerCount": 1
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| gameType | string | 游戏类型 |
| leaderboards | object | 按游戏关卡分组的排行榜，key为游戏关卡 |

**leaderboards对象内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| rank | int | 用户在此排行榜中的排名 |
| score | int | 用户在此排行榜中的积分 |
| gameLevel | string | 游戏关卡 |
| records | array | 排行榜记录列表 |

**records数组内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| id | int | 记录ID |
| cardId | string | 卡ID |
| userName | string | 用户名称 |
| score | int | 游戏得分 |
| gameDuration | int | 游戏时长（秒） |
| playTime | string | 游戏时间（格式化字符串） |
| gameLevel | string | 游戏关卡 |
| gameType | string | 游戏类型 |
| skinId | string | 皮肤ID |
| playerCount | int | 共同游戏的玩家数量 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "cwyz-score-save",
  "data": {
    "gameType": "standard",
    "leaderboards": {
      "1": {
        "rank": 3,
        "score": 1500,
        "gameLevel": "1",
        "records": [
          {
            "id": 123,
            "cardId": "9876543210",
            "userName": "玩家088",
            "score": 2000,
            "gameDuration": 300,
            "playTime": "2025-05-28 14:30:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_001",
            "playerCount": 1
          },
          {
            "id": 124,
            "cardId": "8765432109",
            "userName": "玩家072",
            "score": 1800,
            "gameDuration": 280,
            "playTime": "2025-05-28 15:20:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_002",
            "playerCount": 1
          },
          {
            "id": 125,
            "cardId": "1234567890",
            "userName": "玩家001",
            "score": 1500,
            "gameDuration": 260,
            "playTime": "2025-05-28 16:10:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_003",
            "playerCount": 1
          }
        ]
      }
    }
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（必填参数缺失） |
| 20 | 数据库错误（保存积分失败） |
| 40 | 用户不存在 |

**备注**：
1. 如果提供了金币(golds)参数且大于0，系统会自动调用保存金币记录的功能。
2. 如果提供了宝石(gemstone)参数且大于0，系统会自动调用保存宝石记录的功能。
3. 积分数据会根据游戏类型和游戏关卡进行分类，便于后续查询。
4. 响应中的排行榜数据包含当前用户的排名和指定数量的最高分记录。
5. 如果用户卡ID不存在，系统会尝试创建一个游客记录。

#### 3.3.2 获取游戏排行榜 (cwyz-query-score-top)

该接口用于获取游戏排行榜信息。

**请求命令**：`cwyz-query-score-top`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| gameType | string | 是 | 游戏类型 |
| gameLevel | string | 否 | 游戏关卡，不传则返回所有关卡的排行榜 |
| topLimit | int | 否 | 需要查询的排行榜条数，默认为10 |
| isGlobal | bool | 否 | 是否获取全网排名，默认为false（即默认获取本地排名） |

**请求示例**：

```json
{
  "command": "cwyz-query-score-top",
  "data": {
    "gameType": "standard",
    "gameLevel": "1",
    "topLimit": 10,
    "isGlobal": false
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| gameType | string | 游戏类型 |
| leaderboards | object | 按游戏关卡分组的排行榜，key为游戏关卡 |

**leaderboards对象内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| rank | int | 用户在此排行榜中的排名 |
| score | int | 用户在此排行榜中的积分 |
| gameLevel | string | 游戏关卡 |
| records | array | 排行榜记录列表 |

**records数组内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| id | int | 记录ID |
| cardId | string | 卡ID |
| userName | string | 用户名称 |
| score | int | 游戏得分 |
| gameDuration | int | 游戏时长（秒） |
| playTime | string | 游戏时间（格式化字符串） |
| gameLevel | string | 游戏关卡 |
| gameType | string | 游戏类型 |
| skinId | string | 皮肤ID |
| playerCount | int | 共同游戏的玩家数量 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "cwyz-query-score-top",
  "data": {
    "gameType": "standard",
    "leaderboards": {
      "1": {
        "rank": 3,
        "score": 1500,
        "gameLevel": "1",
        "records": [
          {
            "id": 123,
            "cardId": "9876543210",
            "userName": "玩家088",
            "score": 2000,
            "gameDuration": 300,
            "playTime": "2025-05-28 14:30:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_001",
            "playerCount": 1
          },
          {
            "id": 124,
            "cardId": "8765432109",
            "userName": "玩家072",
            "score": 1800,
            "gameDuration": 280,
            "playTime": "2025-05-28 15:20:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_002",
            "playerCount": 1
          },
          {
            "id": 125,
            "cardId": "1234567890",
            "userName": "玩家001",
            "score": 1500,
            "gameDuration": 260,
            "playTime": "2025-05-28 16:10:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_003",
            "playerCount": 1
          }
        ]
      }
    }
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（必填参数缺失） |
| 20 | 数据库错误（获取排行榜失败） |
| 40 | 用户不存在 |

**备注**：
1. 排行榜数据包含当前用户的排名和指定数量的最高分记录。
2. 如果用户卡ID不存在，系统会尝试创建一个游客记录。

#### 3.3.3 获取游戏时长排行榜 (cwyz-query-duration-top)

该接口用于获取游戏时长排行榜信息。

**请求命令**：`cwyz-query-duration-top`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| gameType | string | 是 | 游戏类型 |
| gameLevel | string | 否 | 游戏关卡，不传则返回所有关卡的排行榜 |
| topLimit | int | 否 | 需要查询的排行榜条数，默认为10 |
| isGlobal | bool | 否 | 是否获取全网排名，默认为false（即默认获取本地排名） |

**请求示例**：

```json
{
  "command": "cwyz-query-duration-top",
  "data": {
    "gameType": "standard",
    "gameLevel": "1",
    "topLimit": 10,
    "isGlobal": false
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| gameType | string | 游戏类型 |
| leaderboards | object | 按游戏关卡分组的排行榜，key为游戏关卡 |

**leaderboards对象内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| rank | int | 用户在此排行榜中的排名 |
| duration | int | 用户在此排行榜中的游戏时长（秒） |
| gameLevel | string | 游戏关卡 |
| records | array | 排行榜记录列表 |

**records数组内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| id | int | 记录ID |
| cardId | string | 卡ID |
| userName | string | 用户名称 |
| score | int | 游戏得分 |
| gameDuration | int | 游戏时长（秒） |
| playTime | string | 游戏时间（格式化字符串） |
| gameLevel | string | 游戏关卡 |
| gameType | string | 游戏类型 |
| skinId | string | 皮肤ID |
| playerCount | int | 共同游戏的玩家数量 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "cwyz-query-duration-top",
  "data": {
    "gameType": "standard",
    "leaderboards": {
      "1": {
        "rank": 2,
        "duration": 280,
        "gameLevel": "1",
        "records": [
          {
            "id": 123,
            "cardId": "9876543210",
            "userName": "玩家088",
            "score": 1800,
            "gameDuration": 320,
            "playTime": "2025-05-28 14:30:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_001",
            "playerCount": 1
          },
          {
            "id": 124,
            "cardId": "1234567890",
            "userName": "玩家001",
            "score": 1500,
            "gameDuration": 280,
            "playTime": "2025-05-28 15:20:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_002",
            "playerCount": 1
          },
          {
            "id": 125,
            "cardId": "8765432109",
            "userName": "玩家072",
            "score": 1200,
            "gameDuration": 240,
            "playTime": "2025-05-28 16:10:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_003",
            "playerCount": 1
          }
        ]
      }
    }
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（游戏类型为空） |
| 20 | 数据库错误（获取排行榜失败） |

**备注**：
1. 该接口专门用于获取按游戏时长排序的排行榜。
2. 排行榜数据按游戏时长降序排列。
3. 如果设置isGlobal为true，将获取全网的排行榜数据，可能需要更长的响应时间。

#### 3.3.4 统一获取游戏排行榜 (cwyz-query-top)

该接口统一了获取积分排行榜和时长排行榜的功能，通过topType参数区分不同类型的排行榜。

**请求命令**：`cwyz-query-top`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| gameType | string | 是 | 游戏类型 |
| gameLevel | string | 否 | 游戏关卡，不传则返回所有关卡的排行榜 |
| topLimit | int | 否 | 需要查询的排行榜条数，默认为10 |
| topType | int | 是 | 排行榜类型：0=积分排行榜，1=时长排行榜 |
| isGlobal | bool | 否 | 是否获取全网排名，默认为false（即默认获取本地排名） |

**请求示例**：

```json
{
  "command": "cwyz-query-top",
  "data": {
    "gameType": "standard",
    "gameLevel": "1",
    "topLimit": 10,
    "topType": 0,
    "isGlobal": false
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| gameType | string | 游戏类型 |
| topType | int | 排行榜类型：0=积分排行榜，1=时长排行榜 |
| leaderboards | object | 按游戏关卡分组的排行榜，key为游戏关卡 |

**leaderboards对象内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| rank | int | 用户在此排行榜中的排名 |
| score | int | 用户在此排行榜中的积分（当topType=0时有效） |
| duration | int | 用户在此排行榜中的游戏时长（当topType=1时有效） |
| gameLevel | string | 游戏关卡 |
| records | array | 排行榜记录列表 |

**records数组内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| id | int | 记录ID |
| cardId | string | 卡ID |
| userName | string | 用户名称 |
| score | int | 游戏得分 |
| gameDuration | int | 游戏时长（秒） |
| playTime | string | 游戏时间（格式化字符串） |
| gameLevel | string | 游戏关卡 |
| gameType | string | 游戏类型 |
| skinId | string | 皮肤ID |
| playerCount | int | 共同游戏的玩家数量 |

**响应示例（积分排行榜）**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "cwyz-query-top",
  "data": {
    "gameType": "standard",
    "topType": 0,
    "leaderboards": {
      "1": {
        "rank": 3,
        "score": 1500,
        "gameLevel": "1",
        "records": [
          {
            "id": 123,
            "cardId": "9876543210",
            "userName": "玩家088",
            "score": 2000,
            "gameDuration": 300,
            "playTime": "2025-05-28 14:30:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_001",
            "playerCount": 1
          },
          {
            "id": 124,
            "cardId": "8765432109",
            "userName": "玩家072",
            "score": 1800,
            "gameDuration": 280,
            "playTime": "2025-05-28 15:20:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_002",
            "playerCount": 1
          },
          {
            "id": 125,
            "cardId": "1234567890",
            "userName": "玩家001",
            "score": 1500,
            "gameDuration": 260,
            "playTime": "2025-05-28 16:10:00",
            "gameLevel": "1",
            "gameType": "standard",
            "skinId": "skin_003",
            "playerCount": 1
          }
        ]
      }
    }
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（游戏类型为空或排行榜类型无效） |
| 20 | 数据库错误（获取排行榜失败） |

**备注**：
1. 该接口可以根据topType参数灵活获取不同类型的排行榜。
2. 当topType=0时，排行榜按积分降序排列；当topType=1时，排行榜按游戏时长降序排列。
3. 如果设置isGlobal为true，将获取全网的排行榜数据，可能需要更长的响应时间。
4. 推荐使用该接口代替单独的积分排行榜和时长排行榜接口，提高代码复用性。

#### 3.3.5 保存出卡记录 (cwyz-outcard-save)

该接口用于记录游戏中玩家获得卡片的信息。

**请求命令**：`cwyz-outcard-save`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| cardId | string | 是 | 卡ID，用于关联用户 |
| cardStar | int | 是 | 卡片星级 |
| cardType | string | 是 | 卡片类型 |
| cardName | string | 是 | 卡片名称 |
| gameType | string | 是 | 游戏类型 |
| playerIdx | int | 否 | 玩家索引，默认为1 |

**请求示例**：

```json
{
  "command": "cwyz-outcard-save",
  "data": {
    "cardId": "1234567890",
    "cardStar": 4,
    "cardType": "monster",
    "cardName": "火焰龙",
    "gameType": "standard",
    "playerIdx": 1
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| success | bool | 操作是否成功 |
| cardId | string | 卡ID |
| userName | string | 用户名称 |
| cardStar | int | 卡片星级 |
| cardType | string | 卡片类型 |
| cardName | string | 卡片名称 |
| drawTime | string | 出卡时间（格式化字符串） |
| playerIdx | int | 玩家索引 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "cwyz-outcard-save",
  "data": {
    "success": true,
    "cardId": "1234567890",
    "userName": "玩家001",
    "cardStar": 4,
    "cardType": "monster",
    "cardName": "火焰龙",
    "drawTime": "2025-05-28 16:30:45",
    "playerIdx": 1
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（必填参数缺失） |
| 20 | 数据库错误（保存出卡记录失败） |
| 40 | 用户不存在 |

**备注**：
1. 出卡记录会保存在本地数据库中，并在网络可用时上传到服务器。
2. 出卡时间使用服务器时间，确保统一性。
3. 卡片星级通常为1-5，表示卡片的稀有程度。
4. 卡片类型可以是游戏定义的任何类型，如"monster"、"magic"、"trap"等。

#### 3.3.6 保存硬币记账 (cwyz-coin-save)

该接口用于记录玩家投币和消耗硬币的信息。

**请求命令**：`cwyz-coin-save`

**请求参数**：

| 参数名 | 类型 | 必填 | 说明 |
|-------|------|------|------|
| cardId | string | 是 | 卡ID，用于关联用户 |
| coinCount | int | 是 | 硬币数量 |
| type | int | 是 | 类型：1=投币，2=消耗 |
| playerIdx | int | 否 | 玩家索引，默认为1 |

**请求示例**：

```json
{
  "command": "cwyz-coin-save",
  "data": {
    "cardId": "1234567890",
    "coinCount": 5,
    "type": 1,
    "playerIdx": 1
  }
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| success | bool | 操作是否成功 |
| cardId | string | 卡ID |
| userName | string | 用户名称 |
| coinCount | int | 硬币数量 |
| type | int | 操作类型：1=投币，2=消耗 |
| balance | int | 当前余额 |
| processTime | string | 处理时间（格式化字符串） |
| playerIdx | int | 玩家索引 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "cwyz-coin-save",
  "data": {
    "success": true,
    "cardId": "1234567890",
    "userName": "玩家001",
    "coinCount": 5,
    "type": 1,
    "balance": 15,
    "processTime": "2025-05-28 17:15:30",
    "playerIdx": 1
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 10 | 参数错误（必填参数缺失或硬币数量为0） |
| 20 | 数据库错误（保存硬币记录失败） |
| 40 | 用户不存在 |
| 50 | 余额不足（当type=2，消耗硬币时） |

**备注**：
1. 硬币记账会记录玩家的投币和消耗情况，便于统计和分析。
2. 类型为1表示投币（增加余额），类型为2表示消耗（减少余额）。
3. 响应中的balance字段表示操作后的硬币余额。
4. 如果是消耗操作且余额不足，将返回错误码50。
5. 所有操作都会记录在硬币记账表中，用于后续统计和审计。

### 3.4 4G网络控制接口

#### 3.4.1 查询4G模块信息 (query-4g-info)

该接口用于查询4G网络模块的详细信息，包括网络状态、信号强度、SIM卡信息等。

**请求命令**：`query-4g-info`

**请求参数**：
无需参数

**请求示例**：

```json
{
  "command": "query-4g-info",
  "data": {}
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| mnc | string | 网络MNC码 |
| cid | string | 基站CID |
| lac | string | 位置区域码 |
| serialPort | string | 串口名称 |
| dbm | int | 信号强度 |
| revision | string | 模块固件版本 |
| sim | string | SIM卡ICCID |
| imsi | string | SIM卡IMSI |
| imei | string | 设备IMEI |
| ndisEnabled | bool | NDIS网卡状态 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "query-4g-info",
  "data": {
    "mnc": "01",
    "cid": "123456",
    "lac": "7890",
    "serialPort": "COM3",
    "dbm": -65,
    "revision": "EG25GGBR07A08M2G",
    "sim": "898600123456789012345",
    "imsi": "460012345678901",
    "imei": "862512345678901",
    "ndisEnabled": true
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 80 | 4G模块不存在 |
| 81 | 4G模块通信错误 |

**备注**：
1. 信号强度(dbm)通常在-50到-120之间，数值越大（越接近0）表示信号越强。
2. ndisEnabled表示4G网卡是否启用，true表示已启用，false表示已禁用。
3. 如果设备没有4G模块，将返回错误码80。
4. 该接口仅查询信息，不会改变任何网络设置。

#### 3.4.2 禁用4G网络 (stop-4g-net)

该接口用于禁用4G网络，可用于节省流量或解决网络冲突问题。

**请求命令**：`stop-4g-net`

**请求参数**：
无需参数

**请求示例**：

```json
{
  "command": "stop-4g-net",
  "data": {}
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| success | bool | 操作是否成功 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "stop-4g-net",
  "data": {
    "success": true
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 80 | 4G模块不存在 |
| 81 | 4G模块通信错误 |
| 82 | 网络已经处于禁用状态 |

**备注**：
1. 该接口会关闭4G网卡，停止所有网络通信。
2. 操作成功后，设备将无法通过4G网络连接互联网，但可以通过其他网络接口（如WiFi、有线网络）连接。
3. 4G网络禁用后，可通过start-4g-net接口重新启用。
4. 如果设备没有4G模块，将返回错误码80。

#### 3.4.3 启用4G网络 (start-4g-net)

该接口用于启用4G网络，恢复设备的移动网络连接。

**请求命令**：`start-4g-net`

**请求参数**：
无需参数

**请求示例**：

```json
{
  "command": "start-4g-net",
  "data": {}
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| success | bool | 操作是否成功 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "start-4g-net",
  "data": {
    "success": true
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |
| 80 | 4G模块不存在 |
| 81 | 4G模块通信错误 |
| 83 | 网络已经处于启用状态 |
| 84 | SIM卡异常 |

**备注**：
1. 该接口会启用4G网卡，恢复移动网络连接。
2. 操作成功后，设备将能够通过4G网络连接互联网。
3. 网络连接过程可能需要几秒到几十秒不等，取决于网络信号强度和运营商网络状况。
4. 如果设备没有4G模块或SIM卡异常，将返回相应的错误码。

### 3.5 世宇接口状态

#### 3.5.1 检查世宇接口状态 (check-unis-net-state)

该接口用于检查与世宇服务器的连接状态。

**请求命令**：`check-unis-net-state`

**请求参数**：
无需参数

**请求示例**：

```json
{
  "command": "check-unis-net-state",
  "data": {}
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| state | int | 世宇网络连接状态: 0-断开连接 1-有线网络 2-4G网络 3-服务异常 4-系统异常 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "check-unis-net-state",
  "data": {
    "state": 1
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |

**网络状态代码说明**：

| 网络状态码 | 描述 | 说明 |
|-----------|------|------|
| 0 | 网络断开 | 无网络连接 |
| 1 | 有线网络 | 有线网络连接正常且能访问世宇服务器 |
| 2 | 4G网络 | 4G网络连接正常且能访问世宇服务器 |
| 3 | 服务异常 | 网络连接正常但无法登录世宇服务器 |
| 4 | 系统异常 | 网络连接正常但无法获取登录凭证 |

**备注**：
1. 该接口用于检查业务插件与世宇服务器的连接状态。
2. 检查过程包括网络连接检测和世宇服务器登录尝试。
3. 有线网络和4G网络状态表示网络连接正常且可成功登录世宇服务器。
4. 服务异常表示网络连接正常但无法登录世宇服务器，可能是服务器问题。
5. 系统异常表示网络连接正常但无法获取登录凭证，可能是配置问题。

#### 3.5.2 获取系统信息 (get-system-info)

该接口用于获取系统综合信息，包括网络状态、版本信息、磁盘信息和剩余点数。

**请求命令**：`get-system-info`

**请求参数**：
无需参数

**请求示例**：

```json
{
  "command": "get-system-info",
  "data": {}
}
```

**响应参数**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| networkState | int | 网络状态代码: 0-断开连接 1-有线网络 2-4G网络 3-服务异常 4-系统异常 |
| networkStateDesc | string | 网络状态描述文本 |
| versionInfo | object | 版本信息对象 |
| diskInfos | array | 磁盘信息数组 |
| remainingPoints | int | 剩余点数 |

**versionInfo对象内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| gameVersion | string | 游戏版本 |
| updaterVersion | string | 更新器版本 |
| businessVersion | string | 业务模块版本 |
| consoleVersion | string | 控制台版本 |
| deviceId | string | 设备ID |

**diskInfos数组内部结构**：

| 参数名 | 类型 | 说明 |
|-------|------|------|
| driveLetter | string | 盘符 |
| freeSpace | string | 可用空间（格式化后的字符串） |
| totalSpace | string | 总空间（格式化后的字符串） |
| usedSpace | string | 已用空间（格式化后的字符串） |
| freePercent | float | 可用空间百分比 |

**响应示例**：

```json
{
  "result": true,
  "errMsg": "",
  "statusCode": 0,
  "command": "get-system-info",
  "data": {
    "networkState": 1,
    "networkStateDesc": "有线网络",
    "versionInfo": {
      "gameVersion": "1.0.5",
      "updaterVersion": "1.2.0",
      "businessVersion": "1.1.0",
      "consoleVersion": "1.0.8",
      "deviceId": "ABCDEF123456"
    },
    "diskInfos": [
      {
        "driveLetter": "C:",
        "freeSpace": "50.5 GB",
        "totalSpace": "100 GB",
        "usedSpace": "49.5 GB",
        "freePercent": 50.5
      },
      {
        "driveLetter": "D:",
        "freeSpace": "120 GB",
        "totalSpace": "500 GB",
        "usedSpace": "380 GB",
        "freePercent": 24.0
      }
    ],
    "remainingPoints": 100
  }
}
```

**错误码说明**：

| 状态码 | 说明 |
|-------|------|
| 0 | 成功 |
| 1 | 通用错误 |

**备注**：
1. 该接口汇总了系统的多项信息，便于快速了解系统状态。
2. 网络状态检测逻辑与check-unis-net-state接口保持一致。
3. 版本信息通过向更新器发送get-version-info指令获取。
4. 磁盘信息按盘符字母顺序排列。
5. 剩余点数与get-remaining-points接口返回的值一致。
