# 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>
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 工程:确认工程属性中AutoGenerateBindingRedirects为true,否则运行时可能报System.Text.Json/System.Memory的FileNotFoundException。
# 调用形式与返回值
命名空间 PJY,核心类 PJYSDK(实现 IDisposable,可长期持有,线程安全)。
- 每个 API 同步返回
PJYResult,不抛业务异常:Code:0 成功;负数为本地/SDK 错误;正数为服务端业务错误码IsOk:Code == 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(); // 退出时调用,释放绑定并停止心跳
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; } // 默认写控制台
2
3
Debug:开启后会在控制台输出每次请求的详细信息(密码字段自动脱敏)AutoHeartbeat:是否自动开启心跳,默认true,不建议修改(需在登录前设置)Log:自定义日志输出函数,如接入你自己的日志组件
# 初始化
# 创建 SDK
var sdk = new PJYSDK(appKey, appSecret); // 实现 IDisposable,可长期持有
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| appKey | 是 | string | 软件的 app_key,开发者后台获取 |
| appSecret | 是 | string | 软件的 app_secret,开发者后台获取 |
# 设置设备唯一 ID
void SetDeviceID(string deviceId);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| deviceId | 是 | string | 用户设备唯一标识(长度不超过45位) |
建议用硬件信息哈希或首次生成后持久化的 GUID,卸载重装尽量不变。
# 设置卡密
void SetCard(string card);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| card | 是 | string | 用户填写的卡密(长度不超过45位) |
# 设置用户账号
void SetUser(string username, string password);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| username | 是 | string | 用户名(长度不超过20位) |
| password | 是 | string | 用户密码(长度 6-30 位) |
# 心跳
登录成功后 SDK 自动启动心跳任务,无需手动管理。
# 心跳失败回调
public Action<PJYResult> OnHeartbeatFailed { get; set; }
心跳返回 Code != 0 时触发(在线程池线程上,WinForms/WPF 更新界面请用
Invoke/Dispatcher)。常见的 Code == 10214 表示登录状态已失效
(超时未发心跳、被挤下线、后台冻结等),应引导用户重新登录;
处理模板见上方使用示例。
# 获取心跳结果
PJYResult GetHeartbeatResult();
Code == 0 表示心跳正常;-9 表示还未开始验证;其余 Message 包含错误信息。
# 获取剩余时长
long GetTimeRemaining();
返回剩余有效秒数,不发起网络请求。
# 卡密登录
调用前需先设置卡密与设备 ID。登录成功后自动启动心跳。
PJYResult CardLogin();
返回值:成功时 Result 包含 card_type(卡密类型)、expires(过期时间)、
expires_ts(过期时间戳秒)、config(自定义配置)等字段;
也可以直接读登录快照 sdk.LoginResult 的 CardType / Expires / ExpiresTs / Config 属性。
# 卡密退出登录
PJYResult CardLogout();
退出登录会停止心跳。
# 卡密解绑设备
需在开发者后台配置软件允许解绑,且需在卡密登录后调用。
PJYResult CardUnbindDevice();
# 卡密设置解绑密码
需在开发者后台配置软件允许解绑。该密码用于设备丢失等情况解绑。需在卡密登录后调用。
PJYResult SetCardUnbindPassword(string password);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| password | 是 | string | 解绑密码,6-10位 |
# 卡密通过密码解绑设备
无需登录,调用前需先设置卡密。
PJYResult CardUnbindDeviceByPassword(string password);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| password | 是 | string | 解绑密码,6-10位 |
# 卡密充值(以卡充卡)
PJYResult CardRecharge(string card, string useCard);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| card | 是 | string | 被充值的卡密 |
| useCard | 是 | string | 用于充值的卡密 |
# 用户注册(通过卡密)
调用前需先设置设备 ID。
PJYResult UserRegister(string username, string password, string card);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| username | 是 | string | 用户名(不超过20位) |
| password | 是 | string | 密码(6-30位) |
| card | 是 | string | 注册使用的卡密 |
# 用户登录
调用前需先设置用户账号与设备 ID。登录成功自动心跳。
PJYResult UserLogin();
# 用户退出登录
PJYResult UserLogout();
# 用户修改密码
PJYResult UserChangePassword(string username, string password, string newPassword);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| username | 是 | string | 用户名 |
| password | 是 | string | 当前密码 |
| newPassword | 是 | string | 新密码(6-30位) |
# 用户充值(通过卡密)
PJYResult UserRecharge(string username, string card);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| username | 是 | string | 用户名 |
| card | 是 | string | 充值卡密 |
# 用户解绑设备
需在用户登录后调用。
PJYResult UserUnbindDevice();
# 试用登录
调用前需先设置设备 ID。登录成功自动心跳。
PJYResult TrialLogin();
# 试用退出登录
PJYResult TrialLogout();
仅清除本地状态并停止心跳,无网络请求。
# 获取卡密配置
PJYResult GetCardConfig(); // 成功时 ret.GetString("config") 为配置内容
# 更改卡密配置
PJYResult UpdateCardConfig(string config);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| config | 是 | string | 自定义配置(不超过512位) |
# 获取用户配置
PJYResult GetUserConfig(); // 成功时 ret.GetString("config") 为配置内容
# 更改用户配置
PJYResult UpdateUserConfig(string config);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| config | 是 | string | 自定义配置(不超过512位) |
# 获取软件配置
PJYResult GetSoftwareConfig();
# 获取软件公告
PJYResult GetSoftwareNotice(); // 成功时 ret.GetString("notice") 为公告内容
# 获取软件最新版本
PJYResult GetSoftwareLatestVersion(string currentVersion);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| currentVersion | 是 | string | 当前本地版本(不超过30位) |
成功时 Result 包含 version、download_url、update_log。
# 获取远程变量
PJYResult GetRemoteVar(string key);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 远程变量名(不超过64位) |
# 获取远程数据
PJYResult GetRemoteData(string key);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 数据 key(不超过64位) |
# 操作远程数据
# 新增远程数据
PJYResult CreateRemoteData(string key, string value);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 数据 key(不超过64位) |
| value | 是 | string | 数据值(不超过256位) |
# 修改远程数据
PJYResult UpdateRemoteData(string key, string value);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 数据 key(不超过64位) |
| value | 是 | string | 数据值(不超过256位) |
# 删除远程数据
PJYResult DeleteRemoteData(string key);
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| key | 是 | string | 数据 key(不超过64位) |
# 调用远程函数
// parameters 会被序列化为 JSON 传给服务端(传数组即参数列表);
// 成功时返回值的 Result 是远程函数返回内容解析后的 JSON
PJYResult CallRemoteFunc(string funcName, object parameters);
2
3
| 参数 | 必传 | 类型 | 说明 |
|---|---|---|---|
| funcName | 是 | string | 远程函数名(不超过64位) |
| parameters | 是 | JSON数组 | 参数列表,如 new[] {1, 2} |
示例 远程函数定义(JavaScript):
function add(a, b) {
return a + b;
}
2
3
调用:
PJYResult ret = sdk.CallRemoteFunc("add", new[] { 1, 2 });
if (ret.IsOk)
{
Console.WriteLine($"计算结果: {ret.Result}");
}
2
3
4
5
# 释放资源
sdk.Dispose(); // 或用 using 声明;内部会停止心跳任务并释放 HTTP 连接
提示:
- 所有方法同步返回
PJYResult,用IsOk/Code判断,不抛业务异常;OnHeartbeatFailed/Log回调在线程池线程触发,更新 UI 需Invoke/Dispatcher; 返回码含义见接入须知中的对照表。