Files
verify/sdk/cpp/verify_client.hpp
T
admin ed4a561704 feat: add application API documentation and C++ SDK
- Add complete API documentation for application integration (docs/API_DOCUMENT.md)
- Fix check-update API to use version ID comparison instead of string comparison
- Add validation: client version must exist in server version list
- Add support for patch/incremental updates with base_version check
- Add C++ SDK with HTTP client, JSON parser, and crypto support
- Add simple_test.cpp for standalone testing on Windows

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-28 11:58:44 +08:00

231 lines
6.9 KiB
C++

#ifndef VERIFY_CLIENT_HPP
#define VERIFY_CLIENT_HPP
#include <string>
#include <map>
#include <functional>
#include <memory>
#include <vector>
#ifdef USE_OPENSSL
#include <openssl/evp.h>
#include <openssl/rand.h>
#endif
#ifdef USE_SYSTEM_CURL
#include <curl/curl.h>
#else
// 简化的CURL模拟 - 用于测试
#endif
#include "json.hpp"
namespace verify {
using json = nlohmann::json;
class CryptoException : public std::exception {
public:
explicit CryptoException(const std::string& msg) : message_(msg) {}
const char* what() const noexcept override { return message_.c_str(); }
private:
std::string message_;
};
class ApiException : public std::exception {
public:
ApiException(int code, const std::string& msg) : code_(code), message_(msg) {}
int code() const { return code_; }
const char* what() const noexcept override { return message_.c_str(); }
private:
int code_;
std::string message_;
};
enum class EncryptType {
None,
AES,
RC4
};
class Crypto {
public:
Crypto(EncryptType type, const std::string& key);
~Crypto();
std::string encrypt(const std::string& plaintext);
std::string decrypt(const std::string& ciphertext);
private:
EncryptType type_;
std::string key_;
std::string encryptAES(const std::string& plaintext);
std::string decryptAES(const std::string& ciphertext);
std::string encryptRC4(const std::string& plaintext);
std::string decryptRC4(const std::string& ciphertext);
std::vector<uint8_t> padKey(const std::vector<uint8_t>& key, size_t targetLen);
};
class HttpClient {
public:
HttpClient();
~HttpClient();
void setBaseUrl(const std::string& url);
void setTimeout(int seconds);
void addHeader(const std::string& key, const std::string& value);
void clearHeaders();
json get(const std::string& path);
json post(const std::string& path, const json& body);
json postForm(const std::string& path, const std::map<std::string, std::string>& fields, const std::map<std::string, std::string>& files = {});
std::vector<uint8_t> download(const std::string& path);
void setCrypto(std::shared_ptr<Crypto> crypto);
private:
std::string baseUrl_;
int timeout_ = 30;
std::map<std::string, std::string> headers_;
std::shared_ptr<Crypto> crypto_;
static size_t writeCallback(void* contents, size_t size, size_t nmemb, std::string* userp);
static size_t writeBinaryCallback(void* contents, size_t size, size_t nmemb, std::vector<uint8_t>* userp);
std::string buildUrl(const std::string& path);
json processResponse(const std::string& response);
};
struct AppConfig {
uint64_t id;
std::string name;
std::string description;
std::string iconUrl;
std::string status;
std::string billingType;
std::string loginPolicy;
int maxDevices;
std::string multiOpenMode;
int maxInstances;
bool enableTrial;
double trialBalance;
int heartbeatInterval;
int heartbeatTimeout;
};
struct UserInfo {
uint64_t userId;
std::string username;
double balance;
std::string status;
};
struct DeviceInfo {
uint64_t id;
std::string deviceId;
std::string deviceName;
std::string deviceType;
std::string status;
int onlineSessions;
std::string createdAt;
};
struct VersionInfo {
bool hasUpdate;
std::string latestVersion;
std::string downloadUrl;
int64_t fileSize;
std::string fileHash;
std::string entryFile;
std::string updateNotes;
std::string updateStrategy;
std::string updateType;
std::string updateMethod;
};
class Client {
public:
Client(const std::string& baseUrl, const std::string& appKey);
~Client();
void setToken(const std::string& token);
void setEncryptType(EncryptType type, const std::string& key);
void setTimeout(int seconds);
// Application info
AppConfig getAppInfo();
VersionInfo checkUpdate(const std::string& version = "");
std::vector<json> getAnnouncements();
// User authentication
uint64_t registerUser(const std::string& username,
const std::string& password,
const std::string& deviceId,
const std::string& deviceName = "",
const std::string& deviceType = "windows",
const std::string& instanceId = "",
const std::string& email = "",
const std::string& emailCode = "");
json login(const std::string& username,
const std::string& password,
const std::string& deviceId,
const std::string& deviceName = "",
const std::string& deviceType = "windows",
const std::string& instanceId = "");
void sendEmailCode(const std::string& email, const std::string& purpose = "register");
void resetPassword(const std::string& email, const std::string& code, const std::string& newPassword);
void changePassword(const std::string& username, const std::string& oldPassword, const std::string& newPassword);
// Account
UserInfo getAccount(uint64_t userId);
json heartbeat(uint64_t userId, const std::string& deviceId, const std::string& instanceId = "");
// Recharge
json recharge(const std::string& username, const std::string& cardKey, const std::string& deviceId);
json trial(uint64_t userId);
// Device management
std::vector<DeviceInfo> getDevices();
json getDeviceCount(uint64_t userId);
void unbindDevice(uint64_t userId, const std::string& deviceId);
void unbindDeviceWithAuth(const std::string& username, const std::string& password, const std::string& deviceId);
std::vector<json> getInstances(uint64_t userId);
void forceOfflineInstance(uint64_t userId, const std::string& instanceId);
// Cloud data
json getConstants();
json getConstant(const std::string& key);
std::vector<uint8_t> downloadConstant(const std::string& key);
json getVariables();
json getVariable(const std::string& key);
std::vector<uint8_t> downloadVariable(const std::string& key);
json uploadVariable(const std::string& key, const std::string& filePath);
void updateVariables(const std::map<std::string, std::string>& variables);
json createVariableRecord(const std::string& key, const json& data);
json getVariableRecords(const std::string& key, int page = 1, int pageSize = 20);
void deleteVariableRecord(const std::string& key, uint64_t recordId);
// Dynamic code
json executeDynamicCode(const std::string& key, const json& params, uint64_t targetUserId = 0);
private:
std::string baseUrl_;
std::string appKey_;
std::string token_;
std::shared_ptr<HttpClient> http_;
std::shared_ptr<Crypto> crypto_;
EncryptType encryptType_ = EncryptType::None;
std::string buildPath(const std::string& endpoint);
};
} // namespace verify
#endif // VERIFY_CLIENT_HPP