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>
This commit is contained in:
@@ -0,0 +1,230 @@
|
||||
#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
|
||||
Reference in New Issue
Block a user