Skip to content

C++ SDK

提供 A7Client 参考实现,依赖 libcurl(HTTP)与 OpenSSL(MD5)。RC4 为内联手写实现(C++ 标准库未内置)。

依赖

bash
# Debian / Ubuntu
sudo apt install libcurl4-openssl-dev libssl-dev
# 编译时链接:-lcurl -lcrypto

完整参考实现

a7client.hpp

cpp
#pragma once
#include <string>
#include <map>
#include <sstream>
#include <iomanip>
#include <openssl/md5.h>
#include <curl/curl.h>

class A7Client {
public:
    A7Client(const std::string& appId, const std::string& appKey,
             const std::string& base = "https://api.a7p.cn/api/verify")
        : appId_(appId), appKey_(appKey), base_(base) {}

    static std::string md5(const std::string& text) {
        unsigned char out[MD5_DIGEST_LENGTH];
        MD5(reinterpret_cast<const unsigned char*>(text.data()), text.size(), out);
        std::ostringstream ss;
        for (unsigned char c : out) ss << std::hex << std::setw(2) << std::setfill('0') << (int)c;
        return ss.str();
    }

    // RC4 加密,返回大写 HEX
    static std::string rc4Hex(const std::string& key, const std::string& data) {
        unsigned char s[256];
        for (int i = 0; i < 256; i++) s[i] = (unsigned char)i;
        int j = 0;
        for (int i = 0; i < 256; i++) {
            j = (j + s[i] + (unsigned char)key[i % key.size()]) % 256;
            unsigned char t = s[i]; s[i] = s[j]; s[j] = t;
        }
        std::string out;
        out.resize(data.size());
        int x = 0, y = 0;
        for (size_t i = 0; i < data.size(); i++) {
            x = (x + 1) % 256;
            y = (y + s[x]) % 256;
            unsigned char t = s[x]; s[x] = s[j]; s[j] = t;
            out[i] = (char)((unsigned char)data[i] ^ s[(s[x] + s[y]) % 256]);
        }
        std::ostringstream ss;
        for (unsigned char c : out)
            ss << std::hex << std::uppercase << std::setw(2) << std::setfill('0') << (int)c;
        return ss.str();
    }

    // 简易 POST,返回响应体
    std::string post(const std::string& url, const std::string& body,
                     const std::map<std::string,std::string>& headers) {
        CURL* c = curl_easy_init();
        std::string resp;
        struct cb { std::string* p; static size_t w(char* b, size_t s, size_t n, void* u)
            { auto* self = (cb*)u; self->p->append(b, s*n); return s*n; } };
        cb ctx{&resp};
        curl_easy_setopt(c, CURLOPT_URL, url.c_str());
        curl_easy_setopt(c, CURLOPT_POSTFIELDS, body.c_str());
        curl_easy_setopt(c, CURLOPT_WRITEFUNCTION, cb::w);
        curl_easy_setopt(c, CURLOPT_WRITEDATA, &ctx);
        struct curl_slist* h = nullptr;
        h = curl_slist_append(h, "Content-Type: application/x-www-form-urlencoded");
        for (auto& kv : headers)
            h = curl_slist_append(h, (kv.first + ": " + kv.second).c_str());
        curl_easy_setopt(c, CURLOPT_HTTPHEADER, h);
        curl_easy_perform(c);
        curl_slist_free_all(h);
        curl_easy_cleanup(c);
        return resp;
    }

    void init() {
        long ts = (long)time(nullptr);
        std::string sign = md5(appId_ + appKey_ + std::to_string(ts) + appKey_);
        std::string body = "AppId=" + appId_ + "&AppKey=" + appKey_
                         + "&TimeStamp=" + std::to_string(ts) + "&Sign=" + sign;
        std::string r = post(base_, body, {});
        // 简化:假设返回含 "api_password":"...",真实项目请解析 JSON
        size_t pos = r.find("api_password");
        // ... 解析逻辑由业务层实现
        apiPassword_ = "PARSED_FROM_RESPONSE";
    }

    std::string call(const std::string& action, const std::map<std::string,std::string>& params) {
        if (apiPassword_.empty()) init();
        std::string plain = "action=" + action;
        for (auto& kv : params) plain += "&" + kv.first + "=" + kv.second;
        long ts = (long)time(nullptr);
        std::string data = rc4Hex(apiPassword_, plain);
        std::string sign = md5(apiPassword_ + std::to_string(ts) + data);
        std::string body = "TimeStamp=" + std::to_string(ts)
                         + "&Data=" + data + "&Sign=" + sign;
        return post(base_, body, {{"X-Api-Password", apiPassword_}});
    }

private:
    std::string appId_, appKey_, base_, apiPassword_;
};

JSON 解析需自行补充

示例的 init() 返回体解析为占位,建议引入 nlohmann/json 等库解析 data.api_password,再补充到 apiPassword_。RC4 与 MD5 实现已完整可用。

使用示例

cpp
A7Client client("150018", "YOUR_APP_KEY");
std::map<std::string, std::string> params = {
    {"Card", "UTDE-7TCX-N5AT-ZDSP"},
    {"Mac", "TEST-ABC-123"},
};
std::string resp = client.call("SingleLogin", params);
// 解析 resp 中的 code / data.token

注意事项

  • apiPassword_ 仅保存在实例成员。
  • 推荐用 nlohmann/json 替代示例中的字符串查找解析。
  • 更多接口参数见 API 参考

相关链接

A7验证 · 软件授权与网络验证平台