Spaces:
Sleeping
Sleeping
| using System; | |
| using System.Net.Http; | |
| using System.Text; | |
| using System.Text.Json; | |
| using System.Threading.Tasks; | |
| namespace KSTools.Licensing | |
| { | |
| /// <summary> | |
| /// KSTools 授權 API 客戶端 | |
| /// 負責與授權管理系統的 API 通信 | |
| /// </summary> | |
| public class ApiClient | |
| { | |
| private static readonly string DEFAULT_API_BASE = "https://your-space.hf.space/api"; | |
| private static readonly HttpClient httpClient = new HttpClient() { Timeout = TimeSpan.FromSeconds(30) }; | |
| private readonly string _apiBase; | |
| /// <summary> | |
| /// 初始化 API 客戶端 | |
| /// </summary> | |
| /// <param name="apiBase">API 基礎 URL,如果為空則使用預設值</param> | |
| public ApiClient(string apiBase = null) | |
| { | |
| _apiBase = string.IsNullOrEmpty(apiBase) ? DEFAULT_API_BASE : apiBase.TrimEnd('/'); | |
| // 設定 HTTP 客戶端標頭 | |
| httpClient.DefaultRequestHeaders.Clear(); | |
| httpClient.DefaultRequestHeaders.Add("User-Agent", "KSTools-Revit-Plugin/1.0"); | |
| } | |
| /// <summary> | |
| /// 啟用授權 | |
| /// </summary> | |
| /// <param name="licenseCode">授權碼</param> | |
| /// <param name="hardwareId">硬體指紋ID,如果為空則自動生成</param> | |
| /// <returns>啟用結果</returns> | |
| public async Task<ActivationResult> ActivateLicenseAsync(string licenseCode, string hardwareId = null) | |
| { | |
| try | |
| { | |
| if (string.IsNullOrEmpty(licenseCode)) | |
| { | |
| return new ActivationResult | |
| { | |
| Success = false, | |
| Message = "授權碼不能為空" | |
| }; | |
| } | |
| // 如果沒有提供硬體ID,自動生成 | |
| if (string.IsNullOrEmpty(hardwareId)) | |
| { | |
| hardwareId = HardwareFingerprint.GetHardwareId(); | |
| } | |
| var request = new | |
| { | |
| license_code = licenseCode, | |
| hardware_id = hardwareId, | |
| machine_name = Environment.MachineName | |
| }; | |
| var json = JsonSerializer.Serialize(request, new JsonSerializerOptions | |
| { | |
| PropertyNamingPolicy = JsonNamingPolicy.CamelCase | |
| }); | |
| var content = new StringContent(json, Encoding.UTF8, "application/json"); | |
| var response = await httpClient.PostAsync($"{_apiBase}/license/activate", content); | |
| var resultJson = await response.Content.ReadAsStringAsync(); | |
| if (response.IsSuccessStatusCode) | |
| { | |
| var apiResponse = JsonSerializer.Deserialize<ApiActivationResponse>(resultJson, new JsonSerializerOptions | |
| { | |
| PropertyNamingPolicy = JsonNamingPolicy.CamelCase | |
| }); | |
| return new ActivationResult | |
| { | |
| Success = apiResponse.Success, | |
| Message = apiResponse.Message, | |
| ExpiresAt = apiResponse.ExpiresAt, | |
| UserName = apiResponse.UserName, | |
| HardwareId = apiResponse.HardwareId | |
| }; | |
| } | |
| else | |
| { | |
| return new ActivationResult | |
| { | |
| Success = false, | |
| Message = $"HTTP 錯誤 {response.StatusCode}: {resultJson}" | |
| }; | |
| } | |
| } | |
| catch (HttpRequestException ex) | |
| { | |
| return new ActivationResult | |
| { | |
| Success = false, | |
| Message = $"網路連接錯誤: {ex.Message}" | |
| }; | |
| } | |
| catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) | |
| { | |
| return new ActivationResult | |
| { | |
| Success = false, | |
| Message = "請求超時,請檢查網路連接" | |
| }; | |
| } | |
| catch (Exception ex) | |
| { | |
| return new ActivationResult | |
| { | |
| Success = false, | |
| Message = $"未知錯誤: {ex.Message}" | |
| }; | |
| } | |
| } | |
| /// <summary> | |
| /// 驗證授權 | |
| /// </summary> | |
| /// <param name="licenseCode">授權碼</param> | |
| /// <param name="hardwareId">硬體指紋ID,如果為空則自動生成</param> | |
| /// <returns>驗證結果</returns> | |
| public async Task<ValidationResult> ValidateLicenseAsync(string licenseCode, string hardwareId = null) | |
| { | |
| try | |
| { | |
| if (string.IsNullOrEmpty(licenseCode)) | |
| { | |
| return new ValidationResult | |
| { | |
| Valid = false, | |
| Message = "授權碼不能為空" | |
| }; | |
| } | |
| // 如果沒有提供硬體ID,自動生成 | |
| if (string.IsNullOrEmpty(hardwareId)) | |
| { | |
| hardwareId = HardwareFingerprint.GetHardwareId(); | |
| } | |
| var request = new | |
| { | |
| license_code = licenseCode, | |
| hardware_id = hardwareId, | |
| machine_name = Environment.MachineName | |
| }; | |
| var json = JsonSerializer.Serialize(request, new JsonSerializerOptions | |
| { | |
| PropertyNamingPolicy = JsonNamingPolicy.CamelCase | |
| }); | |
| var content = new StringContent(json, Encoding.UTF8, "application/json"); | |
| var response = await httpClient.PostAsync($"{_apiBase}/license/validate", content); | |
| var resultJson = await response.Content.ReadAsStringAsync(); | |
| if (response.IsSuccessStatusCode) | |
| { | |
| var apiResponse = JsonSerializer.Deserialize<ApiValidationResponse>(resultJson, new JsonSerializerOptions | |
| { | |
| PropertyNamingPolicy = JsonNamingPolicy.CamelCase | |
| }); | |
| return new ValidationResult | |
| { | |
| Valid = apiResponse.Valid, | |
| Message = apiResponse.Message, | |
| ExpiresAt = apiResponse.ExpiresAt, | |
| UserName = apiResponse.UserName, | |
| HardwareId = apiResponse.HardwareId | |
| }; | |
| } | |
| else | |
| { | |
| return new ValidationResult | |
| { | |
| Valid = false, | |
| Message = $"HTTP 錯誤 {response.StatusCode}: {resultJson}" | |
| }; | |
| } | |
| } | |
| catch (HttpRequestException ex) | |
| { | |
| return new ValidationResult | |
| { | |
| Valid = false, | |
| Message = $"網路連接錯誤: {ex.Message}" | |
| }; | |
| } | |
| catch (TaskCanceledException ex) when (ex.InnerException is TimeoutException) | |
| { | |
| return new ValidationResult | |
| { | |
| Valid = false, | |
| Message = "請求超時,請檢查網路連接" | |
| }; | |
| } | |
| catch (Exception ex) | |
| { | |
| return new ValidationResult | |
| { | |
| Valid = false, | |
| Message = $"未知錯誤: {ex.Message}" | |
| }; | |
| } | |
| } | |
| /// <summary> | |
| /// 測試 API 連接 | |
| /// </summary> | |
| /// <returns>是否連接成功</returns> | |
| public async Task<bool> TestConnectionAsync() | |
| { | |
| try | |
| { | |
| var response = await httpClient.GetAsync($"{_apiBase.Replace("/api", "")}/health"); | |
| return response.IsSuccessStatusCode; | |
| } | |
| catch | |
| { | |
| return false; | |
| } | |
| } | |
| } | |
| /// <summary> | |
| /// API 啟用回應模型 | |
| /// </summary> | |
| internal class ApiActivationResponse | |
| { | |
| public bool Success { get; set; } | |
| public string Message { get; set; } | |
| public DateTime? ExpiresAt { get; set; } | |
| public string UserName { get; set; } | |
| public string HardwareId { get; set; } | |
| } | |
| /// <summary> | |
| /// API 驗證回應模型 | |
| /// </summary> | |
| internal class ApiValidationResponse | |
| { | |
| public bool Valid { get; set; } | |
| public string Message { get; set; } | |
| public DateTime? ExpiresAt { get; set; } | |
| public string UserName { get; set; } | |
| public string HardwareId { get; set; } | |
| } | |
| /// <summary> | |
| /// 授權啟用結果 | |
| /// </summary> | |
| public class ActivationResult | |
| { | |
| /// <summary> | |
| /// 啟用是否成功 | |
| /// </summary> | |
| public bool Success { get; set; } | |
| /// <summary> | |
| /// 狀態訊息 | |
| /// </summary> | |
| public string Message { get; set; } | |
| /// <summary> | |
| /// 授權到期時間 | |
| /// </summary> | |
| public DateTime? ExpiresAt { get; set; } | |
| /// <summary> | |
| /// 授權用戶名稱 | |
| /// </summary> | |
| public string UserName { get; set; } | |
| /// <summary> | |
| /// 硬體指紋ID | |
| /// </summary> | |
| public string HardwareId { get; set; } | |
| } | |
| /// <summary> | |
| /// 授權驗證結果 | |
| /// </summary> | |
| public class ValidationResult | |
| { | |
| /// <summary> | |
| /// 授權是否有效 | |
| /// </summary> | |
| public bool Valid { get; set; } | |
| /// <summary> | |
| /// 狀態訊息 | |
| /// </summary> | |
| public string Message { get; set; } | |
| /// <summary> | |
| /// 授權到期時間 | |
| /// </summary> | |
| public DateTime? ExpiresAt { get; set; } | |
| /// <summary> | |
| /// 授權用戶名稱 | |
| /// </summary> | |
| public string UserName { get; set; } | |
| /// <summary> | |
| /// 硬體指紋ID | |
| /// </summary> | |
| public string HardwareId { get; set; } | |
| } | |
| } |