# 客户端接入指南

---

本文档面向 Android 开发者，描述的接入方式适合运营在 4399 平台的联机游戏。

| 版本列表   | 变更时间        | 变更内容                                                                         |
|-----------|----------------|------------------------------------------------------------------------------|
| `v3.14.4` | **2024.01.12** | 接口不变，升级一键登录SDK依赖，`AndroidManifest.xml, assets/res资源, so等有更新`，使用jar+res方式接入须注意 |
| `v3.14.5` | **2024.09.20** | -                                                                            |
| `v3.15.0` | **2024.10.11** | -                                                                            |
| `v3.15.1` | **2024.10.18** | -                                                                            |
| `v3.16.0` | **2025.03.17** | 移除 `PopLogoStyle.POPLOGOSTYLE_FOUR` 选项，更新悬浮窗图标主题<br> 增加跳转游戏盒更新接口，用法见游戏更新  |
| `v3.17.0` | **2025.06.03** | -                                                                            |
| `v3.18.0` | **2025.11.06** | -                                                                            |
| `v3.19.0` | **2026.06.18** | 接口不变；**最低API Level 变更为`minSdk 21`;新增 okhttp、kotlin相关依赖，详情见“引入依赖”; 为兼容外部依赖，移除 `armeabi` 的支持** |

## SDK 下载

SDK和相关示例的下载地址可在游戏创建后，进入 **「游戏管理-SDK服务」** 页面获取。

<img src="https://f.abd001.com//common/show?f=cm2741857&s=1bed1769b126f33300" alt="image" width="100%" height="100%">

## SDK 说明

### 用户信息与隐私策略

<div class="v-md-plugin-tip warning">
    <p class="v-md-plugin-tip-title">注意</p>
    <p>如果您是开发者，在为用户提供服务前请阅读<a href="https://ptlogin.4399.com/resource/protocol.html?type=1&aids=1,3,6,7" target="_blank"> 《4399通行证用户服务协议》</a>与<a href="https://ptlogin.4399.com/resource/protocol.html?type=2&aids=4,10" target="_blank">《隐私政策》</a>，了解SDK对个人信息收集范围、处理目的以及权限使用情况。请您向用户提供服务时，告知相关信息并取得用户同意。</p>
    <p>如果您是用户，请在使用我们的服务前阅读<a href="https://ptlogin.4399.com/resource/protocol.html?type=1&aids=1,3,6,7" target="_blank"> 《4399通行证用户服务协议》</a>与<a href="https://ptlogin.4399.com/resource/protocol.html?type=2&aids=4,10" target="_blank">《隐私政策》</a>，了解SDK对个人信息收集范围、处理目的以及权限使用情况。充分理解后再开始使用我们的服务。</p>
</div>

### 功能描述

4399 运营 SDK（以下简称 SDK），为接入的游戏提供4399账户登录、充值、更新、游戏内容展示等功能。

### SDK 组成

#### 客户端 SDK

SDK 优先提供在线`aar`依赖方式，其 Demo 结构遵循 Android Studio（as） 规范，但仍然保留了 `jar+res` 的依赖方式。  
SDK 支持的编译配置 **android:minSdkVersion >= 21**。

#### 服务端 API

需要充值功能、登录服务端校验，参考 [SDK 服务端接入文档](https://sdkftp.4399doc.com/external/operate/3.19/server_api_1.html)

## 集成流程

### 准备

首次接入 SDK，要在 [4399 开放平台](https://open.4399.cn/) 注册应用，主要是提交APK、素材，配置游戏币、充值回调地址等信息。  
完成后，开发者将得到 SDK 的基础参数：`game key`或`GameKey`，游戏在 4399 平台的运营标识（开发者平台的游戏信息页面显示为“游戏ID”）

### 引入依赖

根据游戏需要，以下三种方式可选其一

- *在线aar*  
  若使用*在线aar*，开发者只要在使用 SDK 的 module 的 `build.gradle`中引入以下内容即可

```groovy
repositories {
  maven {
    // 4399 SDK 开放仓库：正式
    url 'https://mvn.4399doc.com/repository/maven-releases'
  }
  maven {
    // 4399 SDK 开放仓库：快照
    url 'https://mvn.4399doc.com/repository/maven-snapshots'
  }
}

dependencies {
  implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])

  // 运营 SDK：建议使用最新正式版本（release仓库中的版本），可通过浏览仓库地址或向运营咨询版本
  implementation "cn.m4399.sdk:operate:3.19.0"

  // volley、support v4、okhttp3、kotlin 是 SDK 使用的外部依赖，若接入方已有，可忽略
  implementation 'com.android.volley:volley:1.2.1'
  //noinspection GradleCompatible
  implementation "com.android.support:support-v4:28.0.0"
  implementation 'com.squareup.okhttp3:okhttp:3.12.8'
  implementation 'com.squareup.okio:okio:1.15.0'
  implementation 'com.squareup.okhttp3:logging-interceptor:3.12.8'
  // kotlin 库支持 1.6.0 以上版本
  implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk7:2.2.0'
  implementation 'org.jetbrains.kotlin:kotlin-stdlib:2.2.0'
  implementation 'org.jetbrains.kotlin:kotlin-android-extensions-runtime:2.2.0'
}
```

*注意：若使用`7.0+`版本的 gradle 及 android build 插件，仓库地址应配置在`settings.gradle`中*

- *本地aar*  
  若使用*本地aar*，则要下载 [在线aar](https://mvn.4399doc.com/repository/maven-releases/cn/m4399/sdk/operate/3.19.0/operate-3.19.0.aar) 和 [jar+res](https://sdkftp.4399doc.com/external/operate/3.19/operate-3.19.0+722.zip) 到本地，并将`aar`整体和`jar`包中的以下文件  
  拷贝到游戏模块的`libs`目录下（若游戏已有类似版本的外部依赖，可忽略）

```
operate/libs/volley-v1.2.1.jar
operate/libs/support-v13-23.2.1.jar
operate/libs/kotlin-android-extensions-runtime-2.2.0.jar  
operate/libs/kotlin-stdlib-2.2.0.jar  
operate/libs/kotlin-stdlib-jdk7-2.2.0.jar  
operate/libs/logging-interceptor-3.12.8.jar  
operate/libs/okhttp-3.12.8.jar  
operate/libs/okio-1.15.0.jar
```

Gradle 文件中注意添加本地依赖

```groovy
dependencies {
  implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar'])
}
```

- *jar+res*  
  [jar+res 依赖引入](https://sdkftp.4399doc.com/external/operate/3.19/jar_res_import.html) 比较繁琐，但是完成后，后续接口调用仍然是一样的。

#### abi 适配与 so 库

若游戏不需要支持所有 [abi](https://developer.android.google.cn/ndk/guides/abis?hl=zh-cn) ，可以按需选用。  
`aar`依赖方式，按以下方式配置需要的`abi`；`jar+res`依赖方式需要手动删除**不需要**的`abi`目录

```
android {
    defaultConfig {
        ndk {
            // 根据游戏需要选择
            abiFilters "armeabi-v7a", "x86", "arm64-v8a"
        }
    }
}
```

### 接口调用：初始化（必须）

**功能简介：** 此接口初始化 SDK 内部状态，并完成“更新、激活、防沉迷”等流程。
<span style="color:red">**SDK 初始化后才能正确调用其他接口**</span>   
**调用时机：** 建议在游戏 `Activity` 的开始处如 `onCreate` 方法中进行

```java
private void initSDK() {
    mOpeCenter = OperateCenter.getInstance();
    OperateConfig config = new OperateConfig.Builder(MainActivity.this)
            // 设置调试模式，可选，默认false, 发布前应设置为false或删除调用
            .setDebugEnabled(false)
            // 设置游戏运营 key，必须
            .setGameKey(GAME_KEY)
            // 设置 SDK 页面方向，必须，应与游戏方向一致，可取值见下文说明
            .setOrientation(GAME_ORIENTATION)
            // 设置悬浮窗风格，可选，悬浮窗更多信息参考下文
            .setPopLogoStyle(PopLogoStyle.POPLOGOSTYLE_ONE)
            // 设置悬浮窗初始位置，可选，有四种，分别在屏幕上下左右
            .setPopWinPosition(PopWinPosition.POS_LEFT)
            // 设置游戏充值是否支持超出金额，可选，true支持，默认false
            .setSupportExcess(GAME_SUPPORT_EXCESS)
            // 设置是否在 Android 9.+系统上兼容全面屏，true兼容，默认false
            .compatNotch(GAME_COMPACT_NOTCH)
            .build();
    mOpeCenter.setConfig(config);

    // 注意：初始化完成后，其他接口才可用
    mOpeCenter.init(MainActivity.this, new OperateCenter.OnInitGlobalListener() {
        /*
         * 初始化回调
         * 只有在init之后， isLogin()返回的状态才可靠
         */
        @Override
        public void onInitFinished(boolean isLogin, User userInfo) {
            // 初始化后处理
        }

        /*
         * 登出账号的回调
         * @param fromUserCenter 标识区分是否从个人中心中登出的，若是则为true，不是为false
         */
        @Override
        public void onUserAccountLogout(boolean fromUserCenter) {
            // 用户登出，游戏应回到自身登录页面
        }

        /*
         * 切换账号回调
         */
        @Override
        public void onSwitchUserAccountFinished(boolean fromUserCenter, User userInfo) {
            // 用户切换，游戏应回到选服页面
        }
    });
}
```

初始化的几点说明

#### 页面方向

- *游戏页面* 应如下配置`android:configChanges`等，否则系统强制方向变化（一般发生是打开外部应用，如支付宝、微信）或系统设置变化时，可能会发生异常

```xml
<!-- 游戏 Activity：
     若覆盖了 android:resizeableActivity="false"，则必须如下设置 android:configChanges
     android:configChanges="orientation|screenSize|keyboardHidden|screenLayout|navigation|smallestScreenSize|fontScale"
     
     不应该使用 android:launchMode="singleTask" 启动模式，可以考虑 singleTop
 -->
```

其中`android:configChanges` 新增的配置项，是为适配 Android 分屏模式而添加的，更多内容参考[多窗口支持](https://developer.android.google.cn/guide/topics/ui/multi-window?hl=zh-cn#config)


**分屏（画中画）兼容**：游戏进入分屏再点击桌面图标启动，会重启游戏页面，而并没有完整的启动应用，这会导致部分功能异常，  
为了兼容这种情况，SDK 为应用默认设置了`android:resizeableActivity="false"`，即不支持分屏模式，  
<span style="color:red;font-weight:700">若游戏出于某些原因必须要覆盖此项，则务必按最低标准设置入口 Activity 和主 Activity的`android:configChanges`</span>，即

```xml
<activity
        android:name=".MainActivity"
        android:configChanges="orientation|screenSize|keyboardHidden|screenLayout|navigation|smallestScreenSize|fontScale"
/>
```

- *SDK 页面*，**方向支持横屏或竖屏，但不支持横竖屏切换**  
  通过`OperateConfig.setOrientation()`设置 SDK 页面方向，值是系统类`android.content.pm.ActivityInfo`定义的常量

| 方向参数                                           | 含义         |
|------------------------------------------------|------------|
| `SCREEN_ORIENTATION_LANDSCAPE`，`int`, 0        | 横屏         |
| `SCREEN_ORIENTATION_PORTRAIT`, `int`, 1        | 竖屏         |
| `SCREEN_ORIENTATION_SENSOR_LANDSCAPE`，`int`, 6 | 横屏，可180度旋转 |
| `SCREEN_ORIENTATION_SENSOR_PORTRAIT`，`int`, 7  | 竖屏         |

- *第三方页面*，其方向一般使用 SDK 默认设置即可，需要锁定可设置`android:screenOrientation`，如下所示

```xml
<!-- 
    4399 SDK：SDK 中除了以'cn.m4399.'开头的 Activity 都是第三方页面，
        假设游戏为横屏，需要锁定它们的方向为横屏，可以设置 android:screenOrientation，
        此设置应与初始化接口中设置的值保持对应，且若编译有错误，可以进一步设置‘tools:replace’
 -->
<activity android:name="com.cmic.gen.sdk.view.GenLoginAuthActivity"
          android:configChanges="orientation|keyboardHidden|screenSize"
          android:launchMode="singleTop"
          android:screenOrientation="landscape"
          android:theme="@style/AppTheme.NoActionBar"
          tools:replace="android:theme, android:screenOrientation" />
```

#### 悬浮窗

悬浮窗会在用户登录后附着在游戏页面上层，点击后打开对页面展示个人信息、设置，和游戏论坛、官网等入口。

*极少数游戏登录 Activity 并不是游戏主 Activity ，则悬浮窗可能发生异常，建议游戏做相应调整*

- 悬浮窗风格  
  可根据游戏的风格选择合适的悬浮窗样式，并通过设置`OperateConfig.setPopLogoStyle()`设置。

| 样式类型|图示|
|-------------------------|----|
| `PopLogoStyle.POPLOGOSTYLE_ONE`（默认） |![image](https://sdkftp.4399doc.com/external/operate/res/m4399_ope_pop_logo_normal_one.png)|
| `PopLogoStyle.POPLOGOSTYLE_TWO` |![image](https://sdkftp.4399doc.com/external/operate/res/m4399_ope_pop_logo_normal_two.png)|
| `PopLogoStyle.POPLOGOSTYLE_THREE` |![image](https://sdkftp.4399doc.com/external/operate/res/m4399_ope_pop_logo_normal_three.png)|

* 悬浮窗初始位置  
  可根据游戏的风格选择合适的悬浮窗样式，并通过设置`OperateConfig.setPopWinPosition()`设置。

|样式类型|位置|
|--------|----|
|`PopWinPosition.POS_LEFT`（默认）| 屏幕左侧|
|`PopWinPosition.POS_RIGHT`|屏幕右侧|
|`PopWinPosition.POS_TOP`|屏幕上侧|
|`PopWinPosition.POS_BOTTOM`|屏幕下侧|

### 接口调用：账号相关

#### 账号登录（必须）

**功能简介：** 需要登录时调用此接口，如果 SDK 已存在有效登录状态，则直接回调，否则将打开登录页面登录。  
**调用时机：** 初始化且回调后

```java
if(mOpeCenter.isLogin()) {
    User user = mOpeCenter.getCurrentAccount();
} else {
    mOpeCenter.login(MainActivity.this,new OnLoginFinishedListener() {
        @Override
        public void onLoginFinished(boolean success,int resultCode,User user) {
            // 登录结束后的游戏逻辑
        }
    });
}
```

**最佳实践**：SDK 初始化时会检查已有登录状态有效，若有效`OperateCenter.isLogin()`会返回`true`，  
游戏直接通过`OperateCenter.getCurrentAccount()`获取用户信息接口即可，而不需要调用登录接口

在登录成功回调的用户信息，即`User`对象（参考 API 详情），包含`state`字段，此值可用于游戏服务端进行 [用户信息二次验证](https://sdkftp.4399doc.com/external/operate/3.19/server_api_1.html)

#### 查询是否有已登录账号

**功能简介：** 查询 SDK 中是否已有登录状态，适用于游戏启动时查询
**调用时机：** 账号登录后

```java
boolean isLogin = mOpeCenter.isLogin();
```

#### 获取当前登录账号信息

**功能简介：** 在 SDK 处于登录状态时，可通过该接口获取当前用户的信息。  
**调用时机：** 账号登录后  
<span style="color:red">注意：User 中的uid是 32 位整数字符串；若要转换为数值，注意溢出的可能性</span>

```java
User user = mOpeCenter.getCurrentAccount();
```

#### 设置角色服务器 id

**功能简介：** 若游戏有区服，则应在角色进入分服时，通过以下接口设置所在服的 id。  
**调用时机：** 账号登录后  
__服务器 id 为不超过10位的数字字符串__

```java
mOpeCenter.setServer(SERVER_ID);
```

#### 账号切换（推荐）

**功能简介：** 用于在游戏内切换账号  
**调用时机：** 账号登录后

```java
 mOpeCenter.switchAccount(MainActivity.this,new OnLoginFinishedListener() {
     @Override
     public void onLoginFinished(boolean success,int resultCode,User userInfo){
         // 用户账号切换结束后的游戏逻辑
     }
 });
```

有时账号切换是由于 SDK 内部发起的，切换成功后 SDK 调用`OnInitGlobalListener.onSwitchUserAccountFinished()`通知游戏

#### 账号登出（推荐）

**功能简介：** 当需要登出账号时调用，SDK 立即清除本地用户状态、通知服务端，并调用`OnInitGlobalListener.onUserAccountLogout()`通知游戏  
**调用时机：** 账号登录后

```java
mOpeCenter.logout();
```

### 接口调用：充值（推荐）
**功能简介：** 若游戏支持内购，调用此接口将支持用户完成支付流程，4399 充值系统支持在微信、QQ钱包、支付宝、云闪付等 APP 内完成支付  
**调用时机：** 账号登录后，用户点击游戏内充值按钮时

- 全局设置是否支持超出金额：`mOpeCenter.setSupportExcess(SUPPORT_EXPRESS)`接口  
  可选，默认不支持，此接口也可以在单笔订单中设置

> **关于超出金额模式（超额）**  
> 由于卡类等充值渠道有金额限制，可能出现*充值金额*无法匹配任何金额的情况；  
> 如果游戏能处理超出*传入金额* 部分的货币，即将多余部分兑换为游戏币发放给用户，则可以设置`true`；  
> 否则，应设置为`false`或不设置，SDK将直接隐藏无匹配金额的充值渠道。

- 调用充值接口

```java
/*
 * 充值，直接传递参数，旧版接口
 *
 * money, 充值金额，整型，单位元，1 ～ 50000，必须
 * mark, 游戏方订单，必须，
 *      支持大小写字母、数字、'|'(竖线)、'-'（中划线）、'_'（下划线），最长32位，不可为空，不可重复
 * commodity, 商品名，可选，不传时认为商品名是游戏币，不能包含字符'&'
 */
mOpeCenter.recharge(MainActivity.this, money, mark, commodity, new OnRechargeFinishedListener() {
    /* 充值操作结果 */
    @Override
    public void onRechargeFinished(boolean success, int resultCode, String msg) {
        if (success) {
            // 充值操作成功，根据服务端回调决定是否道具
            // 注意：操作成功包含了订单成功、订单处理中两种情况
        } else {
            // 充值失败逻辑，resultCode查看文档结尾
        }
    }
});

/*
 * 充值，使用订单类，新版接口
 *
 * 与直接传递参数几乎一样，只是可以对单笔订单设置是否支持超出金额
 */
mOpeCenter.recharge(MainActivity.this,
        // 充值金额，整数，单位元
        new Order(money, mark)
                // 是否支持超出金额，默认不支持
                .supportExcess(false)
                // 商品名，可选，不传时认为商品名是游戏币
                .commodity(COMMODITY_NAME),
        new OperateCenter.OnRechargeFinishedListener() {
            @Override
            public void onRechargeFinished(boolean success, int resultCode, String msg) {

            }
        });
```

### 接口调用：绑定手机
**功能简介：** 以下接口用于用户在游戏内绑定手机、查询绑定手机状态  
**调用时机：** 账号登录后

#### 绑定

```java
/*
 * 绑定手机
 */
mOpeCenter.bindPhone(this,new OpeResultListener() {
    /*
     * resultCode：0、绑定成功；1、取消绑定；2、已绑定；3、网络异常或服务器异常；
     * message：状态说明
     */
    @Override
    public void onResult(int code,@Nullable String message){
    }
});
```

#### 检查绑定状态

```java
/*
 * 检查用户绑定手机的状态
 */
mOpeCenter.checkBindPhoneState(new OpeResultListener() {
    /*
     * resultCode: 0、未绑定手机号；2、已绑定手机号；3、网络异常或服务器异常；6 、账号被踢
     * message：状态说明
     */
    @Override
    public void onResult(int code,@Nullable String message){
    }
});
```

### 接口调用：其他

#### 退出游戏（必须）

**功能简介：** 当用户按“返回键”或者点击游戏内“退出游戏”时，调用，SDK 会弹出对话框挽留，并展示论坛、礼包等游戏内容  
**调用时机：** 初始化且回调后，否则弹出的是默认弹窗，仅确认是否退出游戏

```java
mOpeCenter.shouldQuitGame(MainActivity.this,new OnQuitGameListener() {
    @Override
    public void onQuitGame(boolean shouldQuit){
        // 点击退出对话框上的“退出游戏”时，shouldQuit为true，游戏处理退出业务逻辑
    }
});
```

#### 账号认证（3.8.0+）

**功能简介：** 游戏可以对需要进行发布内容、领取福利、充值等操作的账号，进行认证，认证方式由 SDK 后台控制，可选方式为实名认证和短信认证中的任意组合  
**调用时机：** 账号登录后

```java
mOpeCenter.authenticate(requireActivity(),new OpeResultListener() {
    @Override
    public void onResult(int code,@Nullable String message){
        // code 提示不同类型的错误，message 提示具体信息
    }
});
```

#### 查看SDK版本号

```java
mOpeCenter.getVersion();
```

### 更新支持

SDK 对游戏更新有两类支持方式：
- 游戏盒内更新
- 接口更新

#### 游戏盒更新（3.16+）
**功能简介：** 游戏按自己的需要提示有版本更新，用户点击提示后可跳转到 4399 游戏盒对应更新页面更新  
**调用时机：** 初始化且回调后

使用方式：

- 游戏按需要选择检查更新时机，**使用自己的方式判断是否有新版本，SDK 没有提供查询接口支持**
- 若有新版本可弹窗提示，其中包括跳转 4399 游戏盒更新的入口，假设是一个“立即更新”按钮
- 更新按钮的点击方法里调用 `OerateCenter.upgradeInGameBox` 方法，用户点击时，若已安装游戏盒，将跳转游戏盒，否则将先下载游戏盒
- 注意处理跳转失败的情况

```java
mOpeCenter.upgradeInGameBox(activity, new OpeResultListener() {
    /*
     * code：0、成功；
	 *       1、取消更新，如取消安装游戏盒；
	         2、更新进行中；
			 3、更新失败，主要是 SDK 内部请求失败；
			 5、后台开关未开启；
			 6、SDK未初始化
     * message：code 说明文案
     */
    @Override
    public void onResult(int code, @Nullable String message) {
        // 处理跳转结果
    }
});
```

#### 接口更新

**功能简介：** 在 4399 平台发布的游戏，在有新版本提交后，调用此接口可以返回对应的更新弹窗，让用户在应用内即可完成更新。  
**调用时机：** 初始化且回调后

此功能需要在4399后台提交新版本，并开启相关开关，详情可咨询运营。

更新功能会检查是否有新版本游戏上线，如果有，则显示更新内容、提示用户升级。 按升级内容，可分为全量更新和**增量更新**（只需下载新旧版 APK 文件中的差异部分）。    
按开发者接入方式又可分为自动更新（无需操作，默认初始化完成）和自定义界面更新

自定义界面增量更新接入方法详见： [4399运营SDK增量升级说明](https://sdkftp.4399doc.com/external/operate/3.19/operate_upgrade_api.html)

### 渠道支持

**功能简介：** 接入 SDK 的游戏，希望在多个渠道投放，并分别统计数据，有两种方式打入渠道标识  
**调用时机：** 静态配置，SDK 初始化即读取

- 打包工具自动打包：联系运营使用专用打包工具打入渠道标识，不需要游戏额外处理。  
  但此方式要求游戏关闭`v2SigningEnabled`校验

```groovy
// 游戏 apk 工程的 build.gradle中
signingConfigs {
  release {
    v2SigningEnabled false
  }
}  
```

- 代码写入`meta-data`字段：需要运营与开发人员配合完成，但不会有兼容问题

在游戏模块的 `AndroidManifest.xml`中，设置`FTNN_CHANNEL_ID`字段值，作为渠道标识

```xml

<meta-data android:name="FTNN_CHANNEL_ID" android:value="baidu" />
```

## API 详情

### User 类方法

`User`类中是一系列`getter`方法

```java
public final class User {
  /** uid */
  public String getUid();

  /** 用户名 */
  public String getName();

  /** 昵称 */
  public String getNick();

  /** 登录状态 */
  public String getState();

  /** 绑定的手机号，已脱敏，若已绑定则此字段非空 */
  public String getPhone();
}
```

### 接口 code 列表

| code        | 含义                                   |
|-------------|--------------------------------------|
| `0`         | 成功，通用code                            |
| `1`         | 取消，通用code                            |
| `2`         | 处理中，通用code                           |
| `3`         | 失败，通用code                            |
| `4`         | 超时，通用code                            |
| `5`         | 中止，通用code                            |
| `16`        | 登录成功                                 |
| `17`        | 不能取得游戏盒认证（一般是号被封了）                   |
| `18`        | 登录取消                                 |
| `19`        | 游戏不存在，GameKey问题                      |
| `20`        | 已登录                                  |
| `21`        | 没有初始化                                |
| `22`        | 一键登录失败                               |
| `24`        | 拒绝用户协议与隐私政策                          |
| `25`        | 网络问题，或者服务端问题                         |  
| `50`        | 认证通过                                 |  
| `51`        | 待认证                                  |  
| `52`        | 拒绝认证                                 |  
| `53`        | 跳过认证，此时后台配置允许取消                      |  
| `54`        | 认证审核中                                |  
| `55`        | 取消认证                                 |  
| `56`        | 认证中断，一般由于账号被顶，或踢出                    |
| `57`        | 认证错误，具体消息看对应message                  |
| `6001`      | 充值取消                                 |
| `0`, `9000` | 充值成功                                 |
| `2`, `9001` | 订单处理中，游戏应等待服务端的充值回调状态                |
| `9002`      | 订单已提交，SDK 不能在有限时间内判断订单状态，游戏应以服务端状态为准 |
