up
This commit is contained in:
@@ -0,0 +1,220 @@
|
||||
using System;
|
||||
using System.Net.Http;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DeviceSDK
|
||||
{
|
||||
public class DeviceClient : IDisposable
|
||||
{
|
||||
private readonly string _baseUrl;
|
||||
private readonly string _encryptKey;
|
||||
private readonly HttpClient _httpClient;
|
||||
private bool _disposed;
|
||||
|
||||
public DeviceClient(string baseUrl, string encryptKey)
|
||||
{
|
||||
_baseUrl = baseUrl.TrimEnd('/');
|
||||
_encryptKey = encryptKey;
|
||||
_httpClient = new HttpClient
|
||||
{
|
||||
Timeout = TimeSpan.FromSeconds(30)
|
||||
};
|
||||
}
|
||||
|
||||
// 设备注册
|
||||
public async Task<DeviceRegisterResponse> RegisterDeviceAsync(DeviceRegisterRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await PostAsync("/api/devices/register", request);
|
||||
return JsonSerializer.Deserialize<DeviceRegisterResponse>(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new DeviceSDKException("设备注册失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// 设备验证
|
||||
public async Task<DeviceValidateResponse> ValidateDeviceAsync(string uid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await GetAsync($"/api/devices/{uid}/validate");
|
||||
var result = JsonSerializer.Deserialize<ApiResponse>(response);
|
||||
|
||||
if (result.Code != 0)
|
||||
{
|
||||
throw new DeviceSDKException(result.Error);
|
||||
}
|
||||
|
||||
var decrypted = DecryptResponse(result.Data);
|
||||
return JsonSerializer.Deserialize<DeviceValidateResponse>(decrypted);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new DeviceSDKException("设备验证失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// 更新启动次数
|
||||
public async Task<StartCountResponse> UpdateStartCountAsync(string uid)
|
||||
{
|
||||
try
|
||||
{
|
||||
var response = await PostAsync($"/api/devices/{uid}/start", null);
|
||||
return JsonSerializer.Deserialize<StartCountResponse>(response);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new DeviceSDKException("更新启动次数失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
// 绑定授权码
|
||||
public async Task BindLicenseAsync(string uid, string licenseCode)
|
||||
{
|
||||
try
|
||||
{
|
||||
var request = new { license_code = licenseCode };
|
||||
var response = await PostAsync($"/api/devices/{uid}/license", request);
|
||||
var result = JsonSerializer.Deserialize<ApiResponse>(response);
|
||||
|
||||
if (result.Code != 0)
|
||||
{
|
||||
throw new DeviceSDKException(result.Error);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new DeviceSDKException("绑定授权码失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<string> GetAsync(string path)
|
||||
{
|
||||
var response = await _httpClient.GetAsync(_baseUrl + path);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
private async Task<string> PostAsync(string path, object data)
|
||||
{
|
||||
var content = data == null ? null :
|
||||
new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
|
||||
|
||||
var response = await _httpClient.PostAsync(_baseUrl + path, content);
|
||||
response.EnsureSuccessStatusCode();
|
||||
return await response.Content.ReadAsStringAsync();
|
||||
}
|
||||
|
||||
private string DecryptResponse(string encrypted)
|
||||
{
|
||||
try
|
||||
{
|
||||
var cipherBytes = Convert.FromBase64String(encrypted);
|
||||
var keyBytes = Encoding.UTF8.GetBytes(_encryptKey);
|
||||
|
||||
using var aes = Aes.Create();
|
||||
aes.Key = keyBytes;
|
||||
|
||||
var iv = new byte[16];
|
||||
Array.Copy(cipherBytes, 0, iv, 0, 16);
|
||||
aes.IV = iv;
|
||||
|
||||
using var decryptor = aes.CreateDecryptor();
|
||||
var cipher = new byte[cipherBytes.Length - 16];
|
||||
Array.Copy(cipherBytes, 16, cipher, 0, cipher.Length);
|
||||
|
||||
var plainBytes = decryptor.TransformFinalBlock(cipher, 0, cipher.Length);
|
||||
return Encoding.UTF8.GetString(plainBytes);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
throw new DeviceSDKException("解密响应失败", ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (!_disposed)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
_httpClient?.Dispose();
|
||||
}
|
||||
_disposed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 请求和响应模型
|
||||
public class DeviceRegisterRequest
|
||||
{
|
||||
public string Uid { get; set; }
|
||||
public string DeviceModel { get; set; }
|
||||
public string LicenseCode { get; set; }
|
||||
}
|
||||
|
||||
public class DeviceRegisterResponse
|
||||
{
|
||||
public int Code { get; set; }
|
||||
public string Message { get; set; }
|
||||
public DeviceRegisterData Data { get; set; }
|
||||
}
|
||||
|
||||
public class DeviceRegisterData
|
||||
{
|
||||
public string Uid { get; set; }
|
||||
public string DeviceModel { get; set; }
|
||||
public string Status { get; set; }
|
||||
}
|
||||
|
||||
public class DeviceValidateResponse
|
||||
{
|
||||
public string Status { get; set; }
|
||||
public string LicenseType { get; set; }
|
||||
public DateTime ExpireTime { get; set; }
|
||||
public int StartCount { get; set; }
|
||||
public int MaxUses { get; set; }
|
||||
public long Timestamp { get; set; }
|
||||
}
|
||||
|
||||
public class StartCountResponse
|
||||
{
|
||||
public int Code { get; set; }
|
||||
public string Message { get; set; }
|
||||
public StartCountData Data { get; set; }
|
||||
}
|
||||
|
||||
public class StartCountData
|
||||
{
|
||||
public int StartCount { get; set; }
|
||||
public string Status { get; set; }
|
||||
public DateTime LastActiveAt { get; set; }
|
||||
}
|
||||
|
||||
internal class ApiResponse
|
||||
{
|
||||
public int Code { get; set; }
|
||||
public string Error { get; set; }
|
||||
public string Data { get; set; }
|
||||
}
|
||||
|
||||
// 自定义异常
|
||||
public class DeviceSDKException : Exception
|
||||
{
|
||||
public DeviceSDKException(string message) : base(message) { }
|
||||
public DeviceSDKException(string message, Exception innerException)
|
||||
: base(message, innerException) { }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
# Device SDK for C#
|
||||
|
||||
## 安装
|
||||
将 `DeviceSDK.cs` 添加到你的项目中。
|
||||
|
||||
## 初始化
|
||||
|
||||
```csharp
|
||||
var client = new DeviceClient(
|
||||
baseUrl: "http://your-server:8080", // 服务器地址
|
||||
encryptKey: "your-32-byte-encrypt-key-here123456" // 32字节加密密钥
|
||||
);
|
||||
```
|
||||
|
||||
## API 使用说明
|
||||
|
||||
### 1. 设备注册
|
||||
|
||||
```csharp
|
||||
// 基本注册(无授权码)
|
||||
var response = await client.RegisterDeviceAsync(new DeviceRegisterRequest {
|
||||
Uid = "device-001",
|
||||
DeviceModel = "test-model"
|
||||
});```
|
||||
|
||||
|
||||
|
||||
```csharp
|
||||
// 带授权码的注册
|
||||
var response = await client.RegisterDeviceAsync(new DeviceRegisterRequest {
|
||||
Uid = "device-001",
|
||||
DeviceModel = "test-model",
|
||||
License = "your-license-code-here"
|
||||
});
|
||||
```
|
||||
|
||||
### 2. 设备验证
|
||||
|
||||
```csharp
|
||||
var validateResponse = await client.ValidateDeviceAsync("device-001");
|
||||
Console.WriteLine($"设备状态: {validateResponse.Status}");
|
||||
Console.WriteLine($"授权类型: {validateResponse.LicenseType}");
|
||||
Console.WriteLine($"过期时间: {validateResponse.ExpireTime}");
|
||||
```
|
||||
|
||||
### 3. 更新启动次数
|
||||
|
||||
```csharp
|
||||
var startCountResponse = await client.UpdateStartCountAsync("device-001");
|
||||
Console.WriteLine($"当前启动次数: {startCountResponse.Data.StartCount}");
|
||||
```
|
||||
|
||||
### 4. 绑定授权码
|
||||
|
||||
```csharp
|
||||
var bindLicenseResponse = await client.BindLicenseAsync("device-001", "your-license-code-here");
|
||||
Console.WriteLine($"绑定结果: {bindLicenseResponse.Data.Success}");
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
SDK 使用 `DeviceSDKException` 统一处理错误:
|
||||
|
||||
```csharp
|
||||
try {
|
||||
// 调用 API 的代码
|
||||
} catch (DeviceSDKException e) {
|
||||
Console.WriteLine($"错误码: {e.ErrorCode}, 错误信息: {e.Message}");
|
||||
}
|
||||
```
|
||||
|
||||
## 响应数据结构
|
||||
|
||||
```csharp
|
||||
// 设备验证响应
|
||||
public class DeviceValidateResponse
|
||||
{
|
||||
public string Status { get; set; } // 设备状态
|
||||
public string LicenseType { get; set; } // 授权类型
|
||||
public DateTime ExpireTime { get; set; } // 过期时间
|
||||
public int StartCount { get; set; } // 启动次数
|
||||
public int MaxUses { get; set; } // 最大使用次数
|
||||
}
|
||||
// 启动次数响应
|
||||
public class StartCountResponse
|
||||
{
|
||||
public int Code { get; set; }
|
||||
public string Message { get; set; }
|
||||
public StartCountData Data { get; set; }
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
Reference in New Issue
Block a user