ed4a561704
- 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>
231 lines
6.9 KiB
C++
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
|