# C# 快速接入

泡椒云网络验证官方提供的 C# SDK,以混淆后的 PJYSDK.dll 二进制分发, 支持 .NET Framework 4.6.2+、.NET Core 2.0+、.NET 5/6/7/8+, WinForms / WPF / 控制台均可用,支持 Windows / Linux / macOS。

# 接入须知

# 获取方式

  • 下载地址:请登录开发者后台,在首页「最新SDK」处下载
  • 压缩包内容:
    • lib/net6.0/PJYSDK.dll:.NET 6/7/8+ 用
    • lib/netstandard2.0/PJYSDK.dll:.NET Framework 4.6.2+ / .NET Core 2.x 用
    • demo/:控制台示例工程(卡密登录 + 自动心跳)
    • 使用文档.md:离线版使用文档

# 引用 SDK

按你的目标框架选择对应目录下的 PJYSDK.dll,拷到工程内(如 libs/)。

SDK 风格工程(推荐):在 .csproj 中添加:

<ItemGroup>
  <Reference Include="PJYSDK">
    <HintPath>libs/PJYSDK.dll</HintPath>
  </Reference>
</ItemGroup>
1
2
3
4
5

Visual Studio 界面操作:右键工程 →「添加」→「项目引用」→「浏览」→ 选中 PJYSDK.dll

# 依赖说明

  • net6.0 版:无额外依赖。
  • netstandard2.0 版:需要 NuGet 包 System.Text.Json(6.0 及以上版本): dotnet add package System.Text.Json 或 NuGet 管理器安装。
  • 旧式 packages.config 风格的 .NET Framework 工程:确认工程属性中 AutoGenerateBindingRedirectstrue,否则运行时可能报 System.Text.Json / System.MemoryFileNotFoundException

# 调用形式与返回值

命名空间 PJY,核心类 PJYSDK(实现 IDisposable,可长期持有,线程安全)。

  • 每个 API 同步返回 PJYResult,不抛业务异常:
    • Code:0 成功;负数为本地/SDK 错误;正数为服务端业务错误码
    • IsOkCode == 0 的快捷判断
    • Message:提示信息,可直接展示给用户
    • Result:响应数据(JsonElement?),用 GetString(key) / GetInt64(key) 快捷读取
  • 网络异常由 SDK 内部自动重试并切换备用域名,重试耗尽返回 Code == -1
  • 响应签名校验失败返回 Code == -98 / -99(数据被篡改或代理劫持)。

常见本地错误码:-1 连接服务器失败;-2 未登录就调用了需要登录的接口; -4 未设置卡密/账号;-5 未设置设备号;-9 还未开始验证(心跳未启动)。

# 使用示例

using System;
using PJY;

using var sdk = new PJYSDK("AppKey", "AppSecret");  // 开发者后台获取
sdk.Debug = true;  // 调试期打开,正式发布建议关掉

// 心跳在登录成功后自动开启;失败时回调(线程池线程上触发,操作 UI 需 Invoke)
sdk.OnHeartbeatFailed = ret =>
{
    Console.WriteLine($"心跳失败: {ret.Code} {ret.Message}");

    // 10214 = 其他设备登录被顶号:不要重登(会把对方再顶下去,互相踢),提示后直接退出
    if (ret.Code == 10214)
    {
        Console.WriteLine("账号已在其他设备登录,程序即将退出");
        Environment.Exit(1);
    }

    // 其余情况(网络抖动、心跳过期等):尝试重登一次恢复会话
    Console.WriteLine("心跳失败,尝试重新登录...");
    PJYResult loginRet = sdk.CardLogin();  // 用户账号模式改调 sdk.UserLogin()
    if (!loginRet.IsOk)
    {
        // 重登也失败(如卡密已过期/被封禁/服务器不可达),提示后退出
        Console.WriteLine($"重新登录失败: {loginRet.Message},程序即将退出");
        Environment.Exit(1);
    }
    Console.WriteLine("重新登录成功,验证已恢复");
};

sdk.SetDeviceID("你的设备唯一ID");  // 需自行生成,保证一机一码
sdk.SetCard("卡密");

// 卡密登录,成功后自动开始心跳保活
PJYResult ret = sdk.CardLogin();
if (!ret.IsOk)
{
    Console.WriteLine($"登录失败: {ret.Message}");
    return;
}
Console.WriteLine($"登录成功,卡密类型: {sdk.LoginResult.CardType}");
Console.WriteLine($"到期时间: {sdk.LoginResult.Expires}");
Console.WriteLine($"剩余时间(秒): {sdk.GetTimeRemaining()}");

// 你的业务逻辑……

sdk.CardLogout();  // 退出时调用,释放绑定并停止心跳
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 可更改配置

public bool Debug { get; set; }          // 默认 true
public bool AutoHeartbeat { get; set; }  // 默认 true
public Action<string> Log { get; set; }  // 默认写控制台
1
2
3
  • Debug:开启后会在控制台输出每次请求的详细信息(密码字段自动脱敏)
  • AutoHeartbeat:是否自动开启心跳,默认 true,不建议修改(需在登录前设置)
  • Log:自定义日志输出函数,如接入你自己的日志组件

# 初始化

# 创建 SDK

var sdk = new PJYSDK(appKey, appSecret);  // 实现 IDisposable,可长期持有
1
参数 必传 类型 说明
appKey string 软件的 app_key,开发者后台获取
appSecret string 软件的 app_secret,开发者后台获取

# 设置设备唯一 ID

void SetDeviceID(string deviceId);
1
参数 必传 类型 说明
deviceId string 用户设备唯一标识(长度不超过45位)

建议用硬件信息哈希或首次生成后持久化的 GUID,卸载重装尽量不变。

# 设置卡密

void SetCard(string card);
1
参数 必传 类型 说明
card string 用户填写的卡密(长度不超过45位)

# 设置用户账号

void SetUser(string username, string password);
1
参数 必传 类型 说明
username string 用户名(长度不超过20位)
password string 用户密码(长度 6-30 位)

# 心跳

登录成功后 SDK 自动启动心跳任务,无需手动管理。

# 心跳失败回调

public Action<PJYResult> OnHeartbeatFailed { get; set; }
1

心跳返回 Code != 0 时触发(在线程池线程上,WinForms/WPF 更新界面请用 Invoke/Dispatcher)。常见的 Code == 10214 表示登录状态已失效 (超时未发心跳、被挤下线、后台冻结等),应引导用户重新登录; 处理模板见上方使用示例

# 获取心跳结果

PJYResult GetHeartbeatResult();
1

Code == 0 表示心跳正常;-9 表示还未开始验证;其余 Message 包含错误信息。

# 获取剩余时长

long GetTimeRemaining();
1

返回剩余有效秒数,不发起网络请求。

# 卡密登录

调用前需先设置卡密与设备 ID。登录成功后自动启动心跳。

PJYResult CardLogin();
1

返回值:成功时 Result 包含 card_type(卡密类型)、expires(过期时间)、 expires_ts(过期时间戳秒)、config(自定义配置)等字段; 也可以直接读登录快照 sdk.LoginResultCardType / Expires / ExpiresTs / Config 属性。

# 卡密退出登录

PJYResult CardLogout();
1

退出登录会停止心跳。

# 卡密解绑设备

需在开发者后台配置软件允许解绑,且需在卡密登录后调用。

PJYResult CardUnbindDevice();
1

# 卡密设置解绑密码

需在开发者后台配置软件允许解绑。该密码用于设备丢失等情况解绑。需在卡密登录后调用。

PJYResult SetCardUnbindPassword(string password);
1
参数 必传 类型 说明
password string 解绑密码,6-10位

# 卡密通过密码解绑设备

无需登录,调用前需先设置卡密。

PJYResult CardUnbindDeviceByPassword(string password);
1
参数 必传 类型 说明
password string 解绑密码,6-10位

# 卡密充值(以卡充卡)

PJYResult CardRecharge(string card, string useCard);
1
参数 必传 类型 说明
card string 被充值的卡密
useCard string 用于充值的卡密

# 用户注册(通过卡密)

调用前需先设置设备 ID。

PJYResult UserRegister(string username, string password, string card);
1
参数 必传 类型 说明
username string 用户名(不超过20位)
password string 密码(6-30位)
card string 注册使用的卡密

# 用户登录

调用前需先设置用户账号与设备 ID。登录成功自动心跳。

PJYResult UserLogin();
1

# 用户退出登录

PJYResult UserLogout();
1

# 用户修改密码

PJYResult UserChangePassword(string username, string password, string newPassword);
1
参数 必传 类型 说明
username string 用户名
password string 当前密码
newPassword string 新密码(6-30位)

# 用户充值(通过卡密)

PJYResult UserRecharge(string username, string card);
1
参数 必传 类型 说明
username string 用户名
card string 充值卡密

# 用户解绑设备

需在用户登录后调用。

PJYResult UserUnbindDevice();
1

# 试用登录

调用前需先设置设备 ID。登录成功自动心跳。

PJYResult TrialLogin();
1

# 试用退出登录

PJYResult TrialLogout();
1

仅清除本地状态并停止心跳,无网络请求。

# 获取卡密配置

PJYResult GetCardConfig();  // 成功时 ret.GetString("config") 为配置内容
1

# 更改卡密配置

PJYResult UpdateCardConfig(string config);
1
参数 必传 类型 说明
config string 自定义配置(不超过512位)

# 获取用户配置

PJYResult GetUserConfig();  // 成功时 ret.GetString("config") 为配置内容
1

# 更改用户配置

PJYResult UpdateUserConfig(string config);
1
参数 必传 类型 说明
config string 自定义配置(不超过512位)

# 获取软件配置

PJYResult GetSoftwareConfig();
1

# 获取软件公告

PJYResult GetSoftwareNotice();  // 成功时 ret.GetString("notice") 为公告内容
1

# 获取软件最新版本

PJYResult GetSoftwareLatestVersion(string currentVersion);
1
参数 必传 类型 说明
currentVersion string 当前本地版本(不超过30位)

成功时 Result 包含 versiondownload_urlupdate_log

# 获取远程变量

PJYResult GetRemoteVar(string key);
1
参数 必传 类型 说明
key string 远程变量名(不超过64位)

# 获取远程数据

PJYResult GetRemoteData(string key);
1
参数 必传 类型 说明
key string 数据 key(不超过64位)

# 操作远程数据

# 新增远程数据

PJYResult CreateRemoteData(string key, string value);
1
参数 必传 类型 说明
key string 数据 key(不超过64位)
value string 数据值(不超过256位)

# 修改远程数据

PJYResult UpdateRemoteData(string key, string value);
1
参数 必传 类型 说明
key string 数据 key(不超过64位)
value string 数据值(不超过256位)

# 删除远程数据

PJYResult DeleteRemoteData(string key);
1
参数 必传 类型 说明
key string 数据 key(不超过64位)

# 调用远程函数

// parameters 会被序列化为 JSON 传给服务端(传数组即参数列表);
// 成功时返回值的 Result 是远程函数返回内容解析后的 JSON
PJYResult CallRemoteFunc(string funcName, object parameters);
1
2
3
参数 必传 类型 说明
funcName string 远程函数名(不超过64位)
parameters JSON数组 参数列表,如 new[] {1, 2}

示例 远程函数定义(JavaScript):

function add(a, b) {
  return a + b;
}
1
2
3

调用:

PJYResult ret = sdk.CallRemoteFunc("add", new[] { 1, 2 });
if (ret.IsOk)
{
    Console.WriteLine($"计算结果: {ret.Result}");
}
1
2
3
4
5

# 释放资源

sdk.Dispose();  // 或用 using 声明;内部会停止心跳任务并释放 HTTP 连接
1

提示:

  • 所有方法同步返回 PJYResult,用 IsOk / Code 判断,不抛业务异常;
  • OnHeartbeatFailed / Log 回调在线程池线程触发,更新 UI 需 Invoke/Dispatcher; 返回码含义见接入须知中的对照表。