找回密码
 立即注册
搜索
热搜: 教程 游戏 工具
查看: 90|回复: 0

[C/C++] 取电脑登录QQ,最新版QQ可取

[复制链接]

发表于 2026-6-9 19:03:26 | 显示全部楼层 |阅读模式


注:我不是原作者,原作者不记得是谁了,最开始是易语言代码,转成C++了的
  1. // qq.hpp - 获取本机已登录 QQ 账号(WinHTTP 版)
  2. // 功能:通过本地 QQ 的 ptlogin 接口(localhost:4301)获取当前已登录的 QQ 账号信息。
  3. // 依赖:需要 nlohmann/json 库(json.hpp)
  4. // 编译:链接 winhttp.lib
  5. #pragma once

  6. #include <windows.h>
  7. #include <winhttp.h>
  8. #include <string>
  9. #include <vector>
  10. #include <random>
  11. #include <stdexcept>

  12. #pragma comment(lib, "winhttp.lib")

  13. namespace qq_local {

  14.     /**
  15.      * @brief QQ 账号信息结构体
  16.      */
  17.     struct QQInfo {
  18.         std::string uin;      ///< QQ 号(字符串形式)
  19.         std::string nickname; ///< 昵称(可能为空)
  20.     };

  21.     /**
  22.      * @brief 忽略 SSL 证书错误(因为本地 4301 端口使用的是自签名证书)
  23.      * @param hRequest WinHTTP 请求句柄
  24.      */
  25.     inline void IgnoreSslErrors(HINTERNET hRequest) {
  26.         DWORD flags = SECURITY_FLAG_IGNORE_UNKNOWN_CA |
  27.             SECURITY_FLAG_IGNORE_CERT_CN_INVALID |
  28.             SECURITY_FLAG_IGNORE_CERT_DATE_INVALID;
  29.         WinHttpSetOption(hRequest, WINHTTP_OPTION_SECURITY_FLAGS,
  30.             &flags, sizeof(flags));
  31.     }

  32.     /**
  33.      * @brief 获取本机当前已登录的所有 QQ 账号
  34.      *
  35.      * 该函数向本地 QQ 服务(localhost.ptlogin2.qq.com:4301)发送请求,
  36.      * 获取已登录账号的 JSON 列表并解析。
  37.      *
  38.      * @return std::vector<QQInfo> 包含所有已登录账号的 vector,若无登录账号则为空。
  39.      *
  40.      * @throws std::runtime_error 当网络请求失败、响应解析失败或接口不可用时抛出异常。
  41.      *
  42.      * @note 使用前必须确保 QQ 客户端正在运行且已登录至少一个账号。
  43.      * @note 该函数会忽略本地 SSL 证书错误,仅用于本地调试。
  44.      * @note 需要 nlohmann/json 库支持。
  45.      */
  46.     inline std::vector<QQInfo> GetLocalQQ() {
  47.         // 1. 生成随机数作为 pt_local_tk(防缓存)
  48.         std::random_device rd;
  49.         std::mt19937 gen(rd());
  50.         std::uniform_int_distribution<long long> dist(1000000000LL, 2000000000LL);
  51.         long long randNum = dist(gen);
  52.         std::string randStr = std::to_string(randNum);
  53.         std::wstring randWstr(randStr.begin(), randStr.end());

  54.         std::wstring path = L"/pt_get_uins?callback=ptui_getuins_CB&pt_local_tk=-" + randWstr;

  55.         // 2. 初始化 WinHTTP 会话
  56.         HINTERNET hSession = WinHttpOpen(L"Mozilla/5.0",
  57.             WINHTTP_ACCESS_TYPE_DEFAULT_PROXY,
  58.             WINHTTP_NO_PROXY_NAME,
  59.             WINHTTP_NO_PROXY_BYPASS, 0);
  60.         if (!hSession) {
  61.             throw std::runtime_error("WinHttpOpen 失败");
  62.         }

  63.         // 3. 连接到本地 QQ 服务(端口 4301)
  64.         HINTERNET hConnect = WinHttpConnect(hSession, L"localhost.ptlogin2.qq.com", 4301, 0);
  65.         if (!hConnect) {
  66.             WinHttpCloseHandle(hSession);
  67.             throw std::runtime_error("WinHttpConnect 失败,请确认 QQ 已启动");
  68.         }

  69.         // 4. 创建请求(HTTPS)
  70.         HINTERNET hRequest = WinHttpOpenRequest(hConnect, L"GET", path.c_str(),
  71.             nullptr, WINHTTP_NO_REFERER,
  72.             WINHTTP_DEFAULT_ACCEPT_TYPES,
  73.             WINHTTP_FLAG_SECURE);
  74.         if (!hRequest) {
  75.             WinHttpCloseHandle(hConnect);
  76.             WinHttpCloseHandle(hSession);
  77.             throw std::runtime_error("WinHttpOpenRequest 失败");
  78.         }

  79.         IgnoreSslErrors(hRequest);

  80.         // 5. 添加请求头(Referer 和 Cookie)
  81.         std::wstring headers = L"Referer: https://ui.ptlogin2.qq.com/\r\n";
  82.         headers += L"Cookie: pt_local_token=-" + randWstr;
  83.         if (!WinHttpAddRequestHeaders(hRequest, headers.c_str(), (DWORD)-1,
  84.             WINHTTP_ADDREQ_FLAG_ADD)) {
  85.             WinHttpCloseHandle(hRequest);
  86.             WinHttpCloseHandle(hConnect);
  87.             WinHttpCloseHandle(hSession);
  88.             throw std::runtime_error("WinHttpAddRequestHeaders 失败");
  89.         }

  90.         // 6. 发送请求
  91.         if (!WinHttpSendRequest(hRequest, nullptr, 0, nullptr, 0, 0, 0)) {
  92.             WinHttpCloseHandle(hRequest);
  93.             WinHttpCloseHandle(hConnect);
  94.             WinHttpCloseHandle(hSession);
  95.             throw std::runtime_error("请求发送失败,请确认 QQ 已登录且本地服务正常");
  96.         }

  97.         // 7. 接收响应
  98.         if (!WinHttpReceiveResponse(hRequest, nullptr)) {
  99.             WinHttpCloseHandle(hRequest);
  100.             WinHttpCloseHandle(hConnect);
  101.             WinHttpCloseHandle(hSession);
  102.             throw std::runtime_error("接收响应失败");
  103.         }

  104.         // 8. 读取响应数据
  105.         std::string response;
  106.         DWORD bytesRead = 0;
  107.         char buffer[4096];
  108.         while (WinHttpReadData(hRequest, buffer, sizeof(buffer), &bytesRead) && bytesRead > 0) {
  109.             response.append(buffer, bytesRead);
  110.         }

  111.         WinHttpCloseHandle(hRequest);
  112.         WinHttpCloseHandle(hConnect);
  113.         WinHttpCloseHandle(hSession);

  114.         // 9. 从响应中提取 JSON 字符串(包裹在 JavaScript 回调中)
  115.         std::string marker = "var var_sso_uin_list=";
  116.         size_t start = response.find(marker);
  117.         if (start == std::string::npos) {
  118.             marker = "var var_sso_uin_list =";
  119.             start = response.find(marker);
  120.             if (start == std::string::npos) {
  121.                 throw std::runtime_error("响应中未找到 var_sso_uin_list,QQ 可能未登录或接口已变更");
  122.             }
  123.         }
  124.         start += marker.length();
  125.         size_t end = response.find(";", start);
  126.         if (end == std::string::npos) {
  127.             throw std::runtime_error("JSON 结束符 ';' 未找到");
  128.         }
  129.         std::string jsonStr = response.substr(start, end - start);

  130.         // 10. 解析 JSON(需要 nlohmann/json.hpp)
  131.         nlohmann::json qqList;
  132.         try {
  133.             qqList = nlohmann::json::parse(jsonStr);
  134.         }
  135.         catch (const nlohmann::json::parse_error& e) {
  136.             throw std::runtime_error("JSON 解析失败: " + std::string(e.what()));
  137.         }

  138.         if (!qqList.is_array()) {
  139.             return {};
  140.         }

  141.         // 11. 转换为 QQInfo 结构体
  142.         std::vector<QQInfo> result;
  143.         for (const auto& item : qqList) {
  144.             QQInfo info;
  145.             if (item.contains("uin")) {
  146.                 if (item["uin"].is_string()) {
  147.                     info.uin = item["uin"].get<std::string>();
  148.                 }
  149.                 else if (item["uin"].is_number()) {
  150.                     uint64_t uin_num = item["uin"].get<uint64_t>();
  151.                     info.uin = std::to_string(uin_num);
  152.                 }
  153.             }
  154.             if (item.contains("nickname") && item["nickname"].is_string()) {
  155.                 info.nickname = item["nickname"].get<std::string>();
  156.             }
  157.             if (!info.uin.empty()) {
  158.                 result.push_back(info);
  159.             }
  160.         }
  161.         return result;
  162.     }

  163. } // namespace qq_local
复制代码


这里是快捷回复,赶紧试试哦
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|92GMBBS

GMT+8, 2026-7-22 13:14

Discuz!

92GMBBS

快速回复 返回顶部 返回列表