QQ扫码登录接口调用详解:原理与PHP实现

本文将详细介绍如何使用QQ扫码登录API接口,包括接口调用原理、实现步骤以及完整的PHP示例代码。

一、接口概述

1.1 接口基本信息

  • 接口地址https://api.ahfi.cn/api/getqq
  • 返回格式:JSON
  • 请求方式:GET
  • 主要功能
    • 获取QQ登录二维码
    • 检测扫码登录状态
    • 获取登录后的用户凭证

1.2 接口调用流程

  1. 获取登录二维码
  2. 用户使用手机QQ扫码
  3. 检测登录状态
  4. 获取登录凭证和用户信息

二、接口调用原理

2.1 二维码获取原理

当调用do=getqrpic接口时,QQ服务器会生成一个临时的登录二维码,并返回:

  • qrsig:用于后续检测登录状态的唯一标识
  • data:Base64编码的二维码图片数据

2.2 登录状态检测原理

使用do=qrlogin接口并传入qrsig参数,服务器会返回:

  • saveOK:状态码(0表示成功)
  • 登录成功后会返回用户信息:
    • uin:QQ号码
    • skey/pskey/superkey:登录凭证
    • nick:用户昵称

2.3 安全机制

  1. 每个二维码有有效期(通常5分钟)
  2. qrsig是临时的,登录成功后失效
  3. 返回的key有使用时效性

三、PHP实现步骤

3.1 准备工作

确保服务器已开启:

  • PHP 5.4+
  • file_get_contents支持HTTPS
  • Session支持

3.2 获取二维码实现

// 获取二维码
function getQQQRCode() {
    $api_url = 'https://api.ahfi.cn/api/getqq?do=getqrpic';
    $context = stream_context_create([
        'http' => ['timeout' => 10],
        'ssl' => ['verify_peer' => false]
    ]);
    
    $response = file_get_contents($api_url, false, $context);
    return json_decode($response, true);
}

// 使用示例
$qrData = getQQQRCode();
if ($qrData && $qrData['saveOK'] == 0) {
    $_SESSION['qrsig'] = $qrData['qrsig'];
    echo '<img src="data:image/png;base64,'.$qrData['data'].'">';
}

3.3 检测登录状态实现

function checkQQLogin($qrsig) {
    $check_url = "https://api.ahfi.cn/api/getqq?do=qrlogin&qrsig=".urlencode($qrsig);
    $response = file_get_contents($check_url);
    return json_decode($response, true);
}

// 使用示例
if (isset($_SESSION['qrsig'])) {
    $status = checkQQLogin($_SESSION['qrsig']);
    if ($status['saveOK'] == 0 && isset($status['uin'])) {
        $_SESSION['qq_user'] = $status;
        echo "登录成功!QQ号:".$status['uin'];
    }
}

四、完整PHP页面实现

4.1 前端页面 (index.php)

<?php
session_start();

// 如果已经登录,显示用户信息
if (isset($_SESSION['qq_login'])) {
    $user = $_SESSION['qq_login'];
    ?>
    <!DOCTYPE html>
    <html>
    <head>
        <title>QQ登录成功</title>
        <style>
            body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
            .user-info { background-color: #dff0d8; padding: 20px; border-radius: 5px; }
            .logout { margin-top: 20px; }
        </style>
    </head>
    <body>
        <h1>登录成功</h1>
        <div class="user-info">
            <h2>用户信息</h2>
            <p><strong>QQ号:</strong> <?php echo htmlspecialchars($user['uin']); ?></p>
            <p><strong>昵称:</strong> <?php echo htmlspecialchars($user['nick']); ?></p>
            <p><strong>Skey:</strong> <?php echo htmlspecialchars($user['skey']); ?></p>
            <p><strong>Pskey:</strong> <?php echo htmlspecialchars($user['pskey']); ?></p>
            <p><strong>Superkey:</strong> <?php echo htmlspecialchars($user['superkey']); ?></p>
        </div>
        <div class="logout">
            <a href="logout.php">退出登录</a>
        </div>
    </body>
    </html>
    <?php
    exit;
}

// 否则跳转到获取二维码页面
header('Location: get_qrcode.php');
?>

4.2 后端接口 (get_qrcode.php)

<?php
header('Content-Type: text/html; charset=utf-8');
session_start();

// 清除旧的session数据
if (!isset($_GET['keep_session'])) {
    unset($_SESSION['qrsig']);
    unset($_SESSION['qq_login']);
}
?>
<!DOCTYPE html>
<html>
<head>
    <title>QQ扫码登录演示</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
        .qrcode-container { text-align: center; margin: 20px 0; }
        #qrcode { max-width: 300px; margin: 0 auto; }
        .status { padding: 10px; margin: 10px 0; border-radius: 4px; }
        .loading { background-color: #f0f0f0; }
        .success { background-color: #dff0d8; color: #3c763d; }
        .error { background-color: #f2dede; color: #a94442; }
        .refresh-btn { 
            padding: 8px 16px; 
            background-color: #4CAF50; 
            color: white; 
            border: none; 
            border-radius: 4px; 
            cursor: pointer;
            margin-top: 10px;
        }
        .refresh-btn:hover { background-color: #45a049; }
    </style>
</head>
<body>
    <h1>QQ扫码登录演示</h1>
    
    <?php
    // 获取二维码
    $api_url = 'https://api.ahfi.cn/api/getqq?do=getqrpic';
    $context = stream_context_create([
        'http' => [
            'timeout' => 10,
            'ignore_errors' => true
        ],
        'ssl' => [
            'verify_peer' => false,
            'verify_peer_name' => false
        ]
    ]);
    
    $response = file_get_contents($api_url, false, $context);
    $data = json_decode($response, true);
    
    if ($data && isset($data['saveOK']) && $data['saveOK'] == 0) {
        $qrsig = $data['qrsig'];
        $imageData = $data['data'];
        
        // 保存qrsig到session
        $_SESSION['qrsig'] = $qrsig;
        
        // 显示二维码
        echo '<div class="qrcode-container">';
        echo '<img id="qrcode" src="data:image/png;base64,'.$imageData.'" alt="QQ登录二维码">';
        echo '<p>请使用手机QQ扫描上方二维码</p>';
        echo '<button class="refresh-btn" onclick="refreshQRCode()">刷新二维码</button>';
        echo '</div>';
        
        // 显示状态区域
        echo '<div id="status" class="status loading">等待扫码...</div>';
        
        // 自动检测登录状态的JavaScript
        echo '<script>
        function checkLoginStatus() {
            fetch("check_login.php")
                .then(response => {
                    if (!response.ok) {
                        throw new Error("网络响应不正常");
                    }
                    return response.json();
                })
                .then(data => {
                    const statusDiv = document.getElementById("status");
                    
                    if (data.saveOK === 0 && data.uin) {
                        // 登录成功
                        statusDiv.className = "status success";
                        statusDiv.innerHTML = "登录成功! 跳转中...";
                        
                        // 停止轮询
                        clearInterval(checkInterval);
                        
                        // 跳转到用户信息页面
                        setTimeout(() => {
                            window.location.href = "user_info.php";
                        }, 1000);
                    } else if (data.msg) {
                        // 显示状态信息
                        statusDiv.innerHTML = data.msg;
                    }
                })
                .catch(error => {
                    console.error("Error:", error);
                    document.getElementById("status").innerHTML = "检查登录状态时出错";
                });
        }
        
        // 每2秒检查一次登录状态
        const checkInterval = setInterval(checkLoginStatus, 2000);
        
        // 刷新二维码函数
        function refreshQRCode() {
            // 显示加载状态
            document.getElementById("status").className = "status loading";
            document.getElementById("status").innerHTML = "正在获取新二维码...";
            
            // 保留session数据
            window.location.href = "get_qrcode.php?keep_session=1";
        }
        </script>';
    } else {
        $errorMsg = isset($data['msg']) ? $data['msg'] : '获取二维码失败';
        echo '<div class="status error">'.$errorMsg.'</div>';
        echo '<button class="refresh-btn" onclick="location.reload()">重试</button>';
    }
    ?>
</body>
</html>

4.3 检测登录 (check_login.php)

<?php
header('Content-Type: application/json');
session_start();

if (!isset($_SESSION['qrsig'])) {
    echo json_encode(['saveOK' => 1, 'msg' => '未获取到二维码标识']);
    exit;
}

$qrsig = $_SESSION['qrsig'];
$check_url = "https://api.ahfi.cn/api/getqq?do=qrlogin&qrsig=" . urlencode($qrsig);

// 设置请求上下文
$context = stream_context_create([
    'http' => [
        'timeout' => 5, // 5秒超时
        'ignore_errors' => true
    ],
    'ssl' => [
        'verify_peer' => false,
        'verify_peer_name' => false
    ]
]);

// 调用API检查登录状态
$response = file_get_contents($check_url, false, $context);

if ($response === FALSE) {
    // 获取错误信息
    $error = error_get_last();
    echo json_encode([
        'saveOK' => 1,
        'msg' => '检查登录状态失败: ' . ($error['message'] ?? '未知错误')
    ]);
} else {
    $data = json_decode($response, true);
    
    // 如果登录成功,保存用户信息到session
    if ($data && isset($data['saveOK'])) {
        if ($data['saveOK'] == 0 && isset($data['uin'])) {
            $_SESSION['qq_login'] = $data;
        }
        echo $response;
    } else {
        echo json_encode([
            'saveOK' => 1,
            'msg' => '解析API响应失败'
        ]);
    }
}
?>

4.4 用户信息页面 (user_info.php)

<?php
session_start();

// 检查是否已登录
if (!isset($_SESSION['qq_login'])) {
    header('Location: get_qrcode.php');
    exit;
}

$user = $_SESSION['qq_login'];
?>
<!DOCTYPE html>
<html>
<head>
    <title>QQ登录成功</title>
    <style>
        body { font-family: Arial, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px; }
        .user-info { background-color: #f8f9fa; padding: 20px; border-radius: 5px; border: 1px solid #ddd; }
        .info-item { margin-bottom: 10px; }
        .info-label { font-weight: bold; display: inline-block; width: 100px; }
        .logout { margin-top: 20px; }
        .api-response { margin-top: 20px; background-color: #f0f0f0; padding: 15px; border-radius: 5px; }
    </style>
</head>
<body>
    <h1>登录成功</h1>
    
    <div class="user-info">
        <h2>用户信息</h2>
        <div class="info-item">
            <span class="info-label">QQ号:</span>
            <?php echo htmlspecialchars($user['uin'] ?? 'N/A'); ?>
        </div>
        <div class="info-item">
            <span class="info-label">昵称:</span>
            <?php echo htmlspecialchars($user['nick'] ?? 'N/A'); ?>
        </div>
        <div class="info-item">
            <span class="info-label">Skey:</span>
            <?php echo htmlspecialchars($user['skey'] ?? 'N/A'); ?>
        </div>
        <div class="info-item">
            <span class="info-label">Pskey:</span>
            <?php echo htmlspecialchars($user['pskey'] ?? 'N/A'); ?>
        </div>
        <div class="info-item">
            <span class="info-label">Superkey:</span>
            <?php echo htmlspecialchars($user['superkey'] ?? 'N/A'); ?>
        </div>
    </div>
    
    <div class="api-response">
        <h3>原始API响应数据</h3>
        <pre><?php echo htmlspecialchars(json_encode($user, JSON_PRETTY_PRINT)); ?></pre>
    </div>
    
    <div class="logout">
        <a href="logout.php">退出登录</a>
    </div>
</body>
</html>

4.5 退出登录 (logout.php)

<?php
session_start();

// 清除所有session数据
$_SESSION = array();

// 删除session cookie
if (ini_get("session.use_cookies")) {
    $params = session_get_cookie_params();
    setcookie(session_name(), '', time() - 42000,
        $params["path"], $params["domain"],
        $params["secure"], $params["httponly"]
    );
}

// 销毁session
session_destroy();

// 重定向到首页
header('Location: get_qrcode.php');
exit;
?>

完整使用流程

  1. 用户访问 index.php 获取二维码
  2. 使用手机QQ扫描二维码
  3. 前端每2秒通过 check_login.php 检查登录状态
  4. 登录成功后跳转到 user_info.php 显示用户信息
  5. 可以点击退出登录返回初始状态
© 版权声明
THE END
喜欢就支持一下吧
点赞7 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容