<?php
include(dirname(__DIR__) . '/includes/common.php');
if (is_file(dirname(__DIR__) . '/includes/node_link_helper.php')) {
	include_once dirname(__DIR__) . '/includes/node_link_helper.php';
}
$act=isset($_GET['act'])?daddslashes($_GET['act']):null;
if($islogin2!=1)exit('{"code":-1,"msg":"未登录，鉴权失败"}');

$biz = isset($_REQUEST['biz']) ? daddslashes($_REQUEST['biz']) : 'cloud';
$biz = $biz === 'dg' ? 'dg' : 'cloud';
$qq_table = $biz === 'dg' ? 'pre_dg_qq' : 'pre_qq';
if($biz === 'dg' && (($conf['dg_open'] ?? '0') != '1')){
    exit(json_encode(['code'=>-1,'msg'=>'代挂系统未开启'], JSON_UNESCAPED_UNICODE));
}
if($biz === 'cloud' && (($conf['cloud_enabled'] ?? '1') != '1')){
    exit(json_encode(['code'=>-1,'msg'=>'云端系统未开启'], JSON_UNESCAPED_UNICODE));
}

define('ERROR_NOT_LOGIN', -1);
define('ERROR_PARAM_EMPTY', -2);
define('ERROR_QQ_INVALID', -3);
define('ERROR_QQ_BLACKLIST', -4);
define('ERROR_API_NOT_FOUND', -5);
define('ERROR_API_MAX_USERS', -6);
define('ERROR_API_BINDING', -7);
define('ERROR_NO_PERMISSION', -100);
define('ERROR_NO_CATEGORY', -200);
define('ERROR_EXPIRED', -201);
define('ERROR_FREE_EXPIRED', -202);
define('ERROR_API_PASSWORD', -8);

function json_error($code, $msg, $additional_data = []) {
    $response = ['code' => $code, 'msg' => $msg];
    if (!empty($additional_data)) {
        $response = array_merge($response, $additional_data);
    }
    exit(json_encode($response, JSON_UNESCAPED_UNICODE));
}

function json_success($msg = '操作成功', $data = []) {
    $response = ['code' => 1, 'msg' => $msg];
    if (!empty($data)) {
        $response = array_merge($response, $data);
    }
    exit(json_encode($response, JSON_UNESCAPED_UNICODE));
}

/**
 * 判断登录接口引用是否为空（避免 'link_123'==0 在 PHP 中被当成 0）
 */
function is_empty_login_ref($v) {
	if (is_string($v) && strpos($v, 'link_') === 0) {
		return false;
	}
	return ($v === null || $v === '' || $v === false || $v === 0 || $v === '0');
}

function is_login_success_result($ret, $frame_type = 'dulu') {
    $retcode = $ret['retcode'] ?? -1;
    $frame_code = $ret['code'] ?? -1;
    $bool = $ret['bool'] ?? false;
    $msg = (string)($ret['msg'] ?? '');
    if ($frame_type === 'xlz') {
        return $retcode == 200 && ($frame_code == 1 || $frame_code == 0);
    }
    return ($frame_code == 0 || $bool === true || ($retcode == 200 && strpos($msg, '登录成功') !== false));
}

// ============================================
// 参数验证函数
// ============================================
function validate_qq($qq) {
	$qq = trim((string)$qq);
	if ($qq === '' || !preg_match('/^\d{5,11}$/', $qq)) {
		json_error(ERROR_QQ_INVALID, 'QQ账号格式不正确');
	}
	return $qq;
}

function validate_api_id($id) {
	$id_str = strval($id);
	if (strpos($id_str, 'link_') === 0) {
		return $id_str;
	}
	if (empty($id) || $id == 0) {
		json_error(ERROR_PARAM_EMPTY, '接口ID不能为空');
	}
	return intval($id);
}

function check_blacklist($qq) {
    global $conf;
    if (in_array($qq, explode("-", $conf['blacklist']))) {
        json_error(ERROR_QQ_BLACKLIST, '你的下单账号已被拉黑，无法下单！');
    }
}

// ============================================
// 业务函数（保持不变）
// ============================================
function check_category_permission($qq, $cid, $user_zid) {
	global $DB, $qq_table;
	
	$endtime_arr = [];
	$rs = $DB->query("SELECT endtime_arr FROM {$qq_table} WHERE qq='{$qq}' AND zid='{$user_zid}' LIMIT 1");
	if($rs && $row = $rs->fetch()){
		$endtime_arr = json_decode($row['endtime_arr'], true);
		if(!is_array($endtime_arr)) $endtime_arr = [];
	}
	
	if(!isset($endtime_arr[$cid]) && !isset($endtime_arr['9999'])){
		return false;
	}
	
	return true;
}

function save_qq_pwd($qq, $pwd) {
	global $DB, $userrow, $qq_table;
	if(empty($pwd)) return false;
	
	$qqrow = $DB->getRow("SELECT * FROM `{$qq_table}` WHERE qq='{$qq}' AND zid='{$userrow['zid']}' LIMIT 1");
	if($qqrow) {
		$DB->exec("UPDATE `{$qq_table}` SET `pwd`='{$pwd}', `uptime`= NOW() WHERE qq='{$qqrow['qq']}' AND zid='{$userrow['zid']}'");
	}
	return true;
}

function check_free_experience($qq, $cid, $login) {
	global $DB, $userrow;
	
	if(intval($login['free']) <= 0) return true;
	
	$old = $DB->getRow("SELECT * FROM `pre_old_qq` WHERE qq='{$qq}' AND zid='".$userrow['zid']."'");
	if($old) {
		$cidarr = explode('-', $old['cid'] ?? '');
		if(in_array(strval($cid), $cidarr)) {
			return false;
		}
	}
	return true;
}

function update_free_experience($qq, $cid, $login) {
	global $DB, $userrow;
	
	if(intval($login['free']) <= 0) return;
	
	$old = $DB->getRow("SELECT * FROM `pre_old_qq` WHERE qq='{$qq}' AND zid='".$userrow['zid']."'");
	if($old) {
		$cidarr = explode('-', $old['cid'] ?? '');
		if(!in_array(strval($cid), $cidarr)) {
			$new_cid = $old['cid'] . '-' . strval($cid);
			$DB->exec("UPDATE `pre_old_qq` SET cid='{$new_cid}' WHERE qq='{$qq}' AND zid='".$userrow['zid']."'");
		}
	} else {
		$DB->exec("INSERT INTO pre_old_qq (`zid`, `cid`, `qq`, `addtime`) VALUES ('".$userrow['zid']."','".strval($cid)."', '{$qq}', NOW())");
	}
}

function add_free_time($endtime_arr, $cid, $free_days) {
	if(!isset($endtime_arr[$cid]) || strtotime($endtime_arr[$cid]) < time()) {
		$endtime_arr[$cid] = date('Y-m-d H:i:s', strtotime('+' . intval($free_days) . ' days'));
	}
	return $endtime_arr;
}

function get_login_config_by_id($id) {
	global $DB, $biz;
	$id_str = strval($id);
	if (strpos($id_str, 'link_') === 0 && function_exists('nodeLinkGetLoginConfig')) {
		$nodeLinkId = intval(substr($id_str, 5));
		$login = nodeLinkGetLoginConfig($nodeLinkId);
		if (isset($login['error'])) {
			return $login;
		}
		if ($login) {
			$login['free'] = 0;
		}
		return $login;
	}
	return $DB->getRow("SELECT a.*,b.free FROM `pre_loginconfig` a LEFT JOIN `pre_login_class` b ON a.cids=b.id AND b.biz='{$biz}' WHERE a.status='1' AND a.biz='{$biz}' AND a.id='{$id}' LIMIT 1");
}

function get_login_config_by_qq($qq) {
	global $DB, $qq_table, $biz;

	// 与 submit_ticket 一致：优先会话中的 login_id（密码/验证码流程中途可能尚未写入 cityid，尤其是 link_ 对接节点）
	$loginid = isset($_SESSION['login_id_'.$qq]) ? $_SESSION['login_id_'.$qq] : 0;
	if (!is_empty_login_ref($loginid)) {
		$login = get_login_config_by_id($loginid);
		if (isset($login['error'])) {
			return $login;
		}
		if ($login) {
			return $login;
		}
		$login = $DB->getRow("SELECT a.*,b.free FROM `pre_loginconfig` a LEFT JOIN `pre_login_class` b ON a.cids=b.id AND b.biz='{$biz}' WHERE a.status='1' AND a.biz='{$biz}' AND a.id='{$loginid}' LIMIT 1");
		if ($login) {
			return $login;
		}
		// 会话 id 可能已失效，继续走订单 / QQ 表
	}

	$order_no = $_SESSION['login_order_'.$qq] ?? '';
	if($order_no){
		$order = $DB->getRow("SELECT * FROM `pre_login_order` WHERE `order_no`='{$order_no}' LIMIT 1");
		if($order && $order['status'] == 0){
			$loginid = $order['apiid'];
			$loginid_str = strval($loginid);
			if (strpos($loginid_str, 'link_') === 0 && function_exists('nodeLinkGetLoginConfig')) {
				$nodeLinkId = intval(substr($loginid_str, 5));
				$login = nodeLinkGetLoginConfig($nodeLinkId);
				if (isset($login['error'])) {
					return $login;
				}
				if ($login) {
					$login['free'] = 0;
					return $login;
				}
			} else {
				$login = $DB->getRow("SELECT a.*,b.free FROM `pre_loginconfig` a LEFT JOIN `pre_login_class` b ON a.cids=b.id AND b.biz='{$biz}' WHERE a.status='1' AND a.biz='{$biz}' AND a.id='{$loginid}' LIMIT 1");
				if($login) return $login;
			}
		}
	}
	
	$qqrow = $DB->getRow("SELECT * FROM `{$qq_table}` WHERE qq='{$qq}' LIMIT 1");
	$loginid = $qqrow['cityid'] ?? 0;
	
	if (is_empty_login_ref($loginid)) {
		$login = $DB->getRow("SELECT a.*,b.free FROM `pre_loginconfig` a LEFT JOIN `pre_login_class` b ON a.cids=b.id AND b.biz='{$biz}' WHERE a.status='1' AND a.biz='{$biz}' ORDER BY a.id LIMIT 1");
	}else{
		$loginid_str = strval($loginid);
		if (strpos($loginid_str, 'link_') === 0 && function_exists('nodeLinkGetLoginConfig')) {
			$nodeLinkId = intval(substr($loginid_str, 5));
			$login = nodeLinkGetLoginConfig($nodeLinkId);
			if (isset($login['error'])) {
				return $login;
			}
			if ($login) {
				$login['free'] = 0;
				return $login;
			}
			return false;
		}
		$login = $DB->getRow("SELECT a.*,b.free FROM `pre_loginconfig` a LEFT JOIN `pre_login_class` b ON a.cids=b.id AND b.biz='{$biz}' WHERE a.status='1' AND a.biz='{$biz}' AND a.id='{$loginid}' LIMIT 1");
	}
	
	return $login;
}

function generate_order_no() {
	return date('YmdHis') . sprintf('%04d', mt_rand(0, 9999)) . sprintf('%04d', mt_rand(0, 9999));
}

function create_login_order($qq, $pwd, $apiid, $cid, $protocol) {
	global $DB, $userrow;
	
	$order_no = generate_order_no();
	$DB->exec("INSERT INTO `pre_login_order` (`order_no`, `zid`, `qq`, `pwd`, `apiid`, `cid`, `protocol`, `status`, `addtime`) VALUES ('{$order_no}', '".$userrow['zid']."', '{$qq}', '{$pwd}', '{$apiid}', '{$cid}', '{$protocol}', 0, NOW())");
	
	return $order_no;
}

function update_login_order($order_no, $status, $msg = '') {
	global $DB;
	
	$DB->exec("UPDATE `pre_login_order` SET `status`='{$status}', `msg`='{$msg}', `endtime`=NOW() WHERE `order_no`='{$order_no}'");
}

function clean_old_orders() {
	global $DB;
	
	$DB->exec("DELETE FROM `pre_login_order` WHERE `addtime` < DATE_SUB(NOW(), INTERVAL 2 DAY)");
}

function handle_login_success($qq, $login, $cid, $protocol = '1') {
	global $DB, $userrow, $conf, $qq_table;

	// 对接节点登录配置（nodeLinkGetLoginConfig）里会带 biz=cloud/dg。
	// 之前强依赖请求参数决定写入 pre_qq / pre_dg_qq，容易造成“登录成功但 qqlist 不显示/二次登录下线定位不到”的错表问题。
	$target_biz = isset($login['biz']) ? strtolower(trim((string)$login['biz'])) : '';
	$target_biz = $target_biz === 'dg' ? 'dg' : 'cloud';
	$target_qq_table = ($target_biz === 'dg') ? 'pre_dg_qq' : $qq_table;
	// 如果 biz 没有传递过来（本地接口），target_qq_table 退回使用原来的 qq_table。
	if ($target_biz === 'cloud' && (!isset($login['biz']) || $login['biz'] === '')) {
		$target_qq_table = $qq_table;
	}

	// 同一个 qq 可能因为 biz 参数传递问题落在不同表；先在候选表里按 qq+zid 找到已存在的那条再更新。
	$qq_tables_to_try = array_values(array_unique([$qq_table, $target_qq_table]));
	$qqrow = null;
	$real_qq_table = $qq_table;
	foreach ($qq_tables_to_try as $t) {
		$tmp = $DB->getRow("SELECT * FROM `{$t}` WHERE qq='{$qq}' AND zid='{$userrow['zid']}' LIMIT 1");
		if ($tmp) {
			$qqrow = $tmp;
			$real_qq_table = $t;
			break;
		}
	}

	// 保存密码到数据库
	if(isset($_SESSION['qq_pwd_'.$qq])){
		$save_pwd = $_SESSION['qq_pwd_'.$qq];
		save_qq_pwd($qq, $save_pwd);
	}

	if($qqrow){
		$end = json_decode($qqrow['endtime_arr'],true);
		if(intval($login['free']) >= 1){
			$end = add_free_time($end, $cid, $login['free']);
		}
		$end = json_encode($end);
		
		// 更新时包含密码字段
		if(!empty($save_pwd)){
			$DB->exec("UPDATE `{$real_qq_table}` SET endtime_arr='{$end}',`login_zt`='1',`cityid`='{$login['id']}',`protocol`='{$protocol}',`uptime`= NOW(),`pwd`='{$save_pwd}' WHERE qq='{$qqrow['qq']}' AND zid='{$userrow['zid']}'");
		}else{
			$DB->exec("UPDATE `{$real_qq_table}` SET endtime_arr='{$end}',`login_zt`='1',`cityid`='{$login['id']}',`protocol`='{$protocol}',`uptime`= NOW() WHERE qq='{$qqrow['qq']}' AND zid='{$userrow['zid']}'");
		}
	}else{
		$endtime_arr = [];
		if(intval($login['free']) >= 1){
			$endtime_arr[$cid] = date('Y-m-d H:i:s',strtotime('+'.intval($login['free']).' days'));
		}else{
			$endtime_arr[$cid] = date('Y-m-d H:i:s',strtotime('+1 day'));
		}
		
		// 插入时包含密码字段
		$pwd_value = $save_pwd ?? '';
		// 如果候选表里没有找到记录，按当前站点对应的 qq_table 插入（确保 ajax.php?act=login/qqlist 读到）。
		$DB->exec("INSERT INTO `{$qq_table}` (`pwd`,`dropline`,`login_zt`,`zid`,`qq`,`cityid`,`protocol`,`addtime`,`endtime_arr`) VALUES ('{$pwd_value}', '0', '1', '".$userrow['zid']."', '{$qq}', '{$login['id']}', '{$protocol}', NOW(), '".json_encode($endtime_arr)."')");
	}

	update_free_experience($qq, $cid, $login);
	$order_no = $_SESSION['login_order_'.$qq] ?? '';
	if($order_no){
		$DB->exec("DELETE FROM `pre_login_order` WHERE `order_no`='{$order_no}'");
		unset($_SESSION['login_order_'.$qq]);
	}
	clean_old_orders();
	
	$qqconf = $DB->getColumn("SELECT count(*) FROM `pre_frame_qqconf` WHERE qq='{$qq}'");
	if($qqconf==0){
		$DB->exec("INSERT INTO `pre_frame_qqconf` (`zid`,`qq`,`massmsg_open`,`massmsg_delay`,`addtime`) VALUES('".$userrow['zid']."','{$qq}','1','2000',NOW())");
	}
	
	unset($_SESSION['qr_login_params']);
	unset($_SESSION['login_protocol_'.$qq]);
	unset($_SESSION['login_id_'.$qq]);
	
	json_success('登录成功', ['qq' => $qq]);
}

// ============================================
// 业务逻辑优化函数
// ============================================
function validate_login_permission($qq, $login, $userrow, $qqrow = null) {
	global $DB, $conf, $conf_frame, $biz;
	
	if (isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	
	$cid = intval($login['cids']);
	
	// 检查黑名单
	check_blacklist($qq);
	
	// 检查接口是否存在
	if (!$login) {
		json_error(ERROR_API_NOT_FOUND, '接口不存在');
	}
	
	// 检查接口人数上限
	// 按接口返回/同步的人数字段 online_census 判定，不查询 pre_qq 表
	$maxUsers = intval($login['max']);
	if ($maxUsers != 0) {
		$onlineCount = intval($login['online_census']);
		if ($onlineCount >= $maxUsers) {
			// login_api_is=0: 仅允许“本节点老用户”继续登录；新用户或跨节点老用户禁止
			// login_api_is=1: 新老用户都禁止
			$allowOldUserOnSameNode = ($qqrow && strval($qqrow['cityid']) === strval($login['id']));
			if (intval($conf['login_api_is']) == 1 || !$allowOldUserOnSameNode) {
				json_error(ERROR_API_MAX_USERS, '该接口人数已上限，请换一个接口！');
			}
		}
	}
	
	// 检查接口绑定
	if ($conf_frame['login_bangding'] == '1' && $qqrow) {
		$qc = strval($qqrow['cityid']);
		if ($qc !== '0' && $qc !== '' && $qc !== strval($login['id'])) {
			$old_login = null;
			if (strpos($qc, 'link_') === 0 && function_exists('nodeLinkGetLoginConfig')) {
				$tmp = nodeLinkGetLoginConfig(intval(substr($qc, 5)));
				if ($tmp && !isset($tmp['error'])) {
					$old_login = $tmp;
				}
			}
			if (!$old_login) {
				$old_login = $DB->getRow("SELECT * FROM `pre_loginconfig` WHERE id='{$qqrow['cityid']}' AND biz='{$biz}'");
			}
			if ($old_login) {
				json_error(ERROR_API_BINDING, "您的账号只能在以下节点登录哦<br>{$old_login['citybz']}<br>可联系管理员进行更换登录节点");
			} else {
				json_error(ERROR_API_BINDING, '原登录接口已被删除，请联系管理员进行更换登录节点');
			}
		}
	}
	
	// 检查接口密码 - 如果有密码则跳过免费体验检查（保持原有逻辑）
	if ($login['apipwd'] == '') {
		// 检查账号权限
		if ($qqrow) {
			// 检查账号归属
			if ($qqrow['zid'] != '0' && $userrow['zid'] != $qqrow['zid']) {
				json_error(ERROR_NO_PERMISSION, '该账号不在您名下，找回后在操作哦', ['qq' => $qq]);
			}
			
			// 检查分类权限
			if (!check_category_permission($qq, $cid, $userrow['zid'])) {
				json_error(ERROR_NO_CATEGORY, '您没有购买该分类，请先购买代挂时长', ['qq' => $qq]);
			}
			
			// 检查是否过期
			$is_end = is_end($qqrow['endtime_arr'], $login);
			if ($is_end) {
				if (intval($login['free']) > 0) {
					if (!check_free_experience($qq, $cid, $login)) {
						json_error(ERROR_FREE_EXPIRED, '该账号已免费体验过了<br>请购买代挂时长后在登录哦', ['qq' => $qq]);
					}
				} else {
					json_error(ERROR_EXPIRED, '账号已过期<br>请购买代挂时长后在登录哦', ['qq' => $qq]);
				}
			}
		} else {
			// 新账号检查免费体验
			if (intval($login['free']) > 0) {
				if (!check_free_experience($qq, $cid, $login)) {
					json_error(ERROR_FREE_EXPIRED, '该账号已免费体验过了<br>请购买代挂时长后在登录哦', ['qq' => $qq]);
				}
			} else {
				json_error(ERROR_NO_CATEGORY, '购买代挂时长后在登录', ['qq' => $qq]);
			}
		}
	} else {
		// 有接口密码的情况，检查密码是否正确（密码验证在调用处处理）
		if ($login['apipwd'] != '0') {
			// 接口密码验证在调用处处理
			return true;
		}
	}
	
	return true;
}

function handle_frame_switch($qq, $biz, $old_cityid, $new_cityid, $old_protocol, $new_protocol) {
	global $DB, $conf_frame;
	
	if ($old_cityid != $new_cityid || $old_protocol != $new_protocol) {
		$old_cityid_str = strval($old_cityid);
		if (strpos($old_cityid_str, 'sync_') === 0) {
			return;
		}
		if (strpos($old_cityid_str, 'link_') === 0 && function_exists('nodeLinkGetLoginConfig')) {
			$nodeLinkId = intval(substr($old_cityid_str, 5));
			$oldlogin = nodeLinkGetLoginConfig($nodeLinkId);
			if ($oldlogin && !isset($oldlogin['error'])) {
				$del_frame_qq = isset($conf_frame['del_frame_qq']) ? $conf_frame['del_frame_qq'] : '0';
				if ($del_frame_qq === '1') {
					delete_bot($oldlogin, $qq);
				} elseif ($del_frame_qq === '0') {
					outqq($oldlogin, $qq);
				}
			}
			return;
		}
		$oldlogin = $DB->getRow("SELECT * FROM `pre_loginconfig` WHERE id='{$old_cityid}' AND biz='{$biz}' LIMIT 1");
		if ($oldlogin) {
			$del_frame_qq = isset($conf_frame['del_frame_qq']) ? $conf_frame['del_frame_qq'] : '0';
			if ($del_frame_qq === '1') {
				delete_bot($oldlogin, $qq);
			} elseif ($del_frame_qq === '0') {
				outqq($oldlogin, $qq);
			}
		}
	}
}

switch($act){
case 'bot':
	$type = daddslashes($_GET['type']);
	$id = validate_api_id($_POST['apiid']);
	$cid = intval($_POST['cid']);
	$protocol = daddslashes($_POST['protocol']);
	$qq = validate_qq(str_replace(array("\r\n", "\r", "\n"), "", daddslashes($_POST['qq'])));
	$pwd = daddslashes($_POST['pwd']);
	$apipwd = daddslashes($_POST['apipwd']);
	
	$qqrow = $DB->getRow("SELECT * FROM `{$qq_table}` WHERE qq='{$qq}' LIMIT 1");
	$login = get_login_config_by_id($id);
	if (isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	if (!$login) {
		$login = $DB->getRow("SELECT a.*,b.free FROM `pre_loginconfig` a LEFT JOIN `pre_login_class` b ON a.cids=b.id AND b.biz='{$biz}' WHERE a.status='1' AND a.biz='{$biz}' AND a.id='{$id}' LIMIT 1");
	}
	
	// 验证权限
	validate_login_permission($qq, $login, $userrow, $qqrow);
	
	// 检查接口密码
	if ($login['apipwd'] != '' && $login['apipwd'] != '0' && $login['apipwd'] != $apipwd) {
		json_error(ERROR_API_PASSWORD, '接口密码不正确！');
	}
	
	// dr、myqq 仅支持扫码登录
	if ($type == 'pwd') {
		$frame_type = $login['framework_type'] ?? $login['type'] ?? '';
		if (in_array($frame_type, ['myqq', 'myqqa', 'dr'])) {
			json_error(ERROR_PARAM_EMPTY, '该节点仅支持扫码登录');
		}
	}
	
	$cid = intval($login['cids']);

	// 处理框架切换
	if ($qqrow) {
		handle_frame_switch($qq, $biz, $qqrow['cityid'], $id, $qqrow['protocol'], $protocol);
	}
	
	if($type == 'pwd'){
		$protocol_val = $protocol;
		if($protocol_val == 'null' || empty($protocol_val)){
			$protocol_val = '0';
		}
		$save_pwd = $pwd;
		$order_no = create_login_order($qq, $save_pwd, $id, $cid, $protocol_val);
		$_SESSION['login_order_'.$qq] = $order_no;
		$_SESSION['qq_pwd_'.$qq] = $save_pwd;
		$_SESSION['login_protocol_'.$qq] = $protocol_val;
		$_SESSION['login_id_'.$qq] = $id;

		// 可选：密码登录时在“添加QQ”之前删除目标节点上的该QQ（默认否）
		if (!empty($conf_frame['login_del_before']) && strval($conf_frame['login_del_before']) === '1') {
			@delete_bot($login, $qq);
		}

		$ret = addqq($login, $qq, $pwd, $protocol_val);
		$bool = $ret['bool'] ?? false;
		$retcode = $ret['retcode'] ?? -1;
		if(!is_array($ret) || !($bool === true || $retcode == 200)){
			$errMsg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '服务器连接失败，请重试';
			update_login_order($order_no, 2, $errMsg);
			json_error(ERROR_PARAM_EMPTY, $errMsg);
		}
		$ret = loginqq($login, $qq, $pwd);
		
		$frame_code = $ret['code'] ?? -1;
		$ticket_url = $ret['ticket_url'] ?? '';
		$retcode = $ret['retcode'] ?? -1;
		$bool = $ret['bool'] ?? false;
		
		if($frame_code == 114514){
			$sid = '0';
			$aid = '2090581062';
			
			if(!empty($ticket_url) && strpos($ticket_url, '?') !== false){
				$url_parts = parse_url($ticket_url);
				if(isset($url_parts['query'])){
					parse_str($url_parts['query'], $params);
					$sid = $params['sid'] ?? $sid;
					$aid = $params['aid'] ?? $aid;
				}
			}
			
			json_error(114514, '需要进行身份验证', [
				'qq' => $qq,
				'sid' => $sid,
				'aid' => $aid,
				'hkurl' => $ticket_url,
				'hktype' => 2
			]);
		}
		
		if($frame_code == 2 && !empty($ticket_url)){
			$sid = '0';
			$aid = '16';
			$uin = $qq;
			
			if(strpos($ticket_url, '?') !== false){
				$url_parts = parse_url($ticket_url);
				if(isset($url_parts['query'])){
					parse_str($url_parts['query'], $params);
					$sid = $params['sid'] ?? $sid;
					$aid = $params['aid'] ?? $aid;
					$uin = $params['uin'] ?? $uin;
				}
			}
			
			json_error(20, '需要执行滑块验证', [
				'qq' => $qq,
				'sid' => $sid,
				'aid' => $aid,
				'hkurl' => $ticket_url,
				'hktype' => 1
			]);
		}
		
		if($frame_code == 239 || $frame_code == 2){
			// xlz 由框架侧发验证码，不需要再调发送接口
			$skip_send_sms = (($login['type'] ?? '') === 'xlz');
			json_error(10, '需要手机验证码', [
				'qq' => $qq,
				'skip_send_sms' => $skip_send_sms
			]);
		}
		// dulu 的 retcode:200 仅表示请求成功，不是登录成功；只有 frame_code==0 或 bool===true 才算登录成功
		$frame_type = $login['type'] ?? 'dulu';
		$login_success = is_login_success_result($ret, $frame_type);

		if($login_success){
			if($qqrow){
				$end = json_decode($qqrow['endtime_arr'],true);
				if(intval($login['free']) >= 1){
					$end = add_free_time($end, $cid, $login['free']);
				}
				$end = json_encode($end);

				if(!empty($save_pwd)){
					$DB->exec("UPDATE `{$qq_table}` SET endtime_arr='{$end}',`login_zt`='1',`cityid`='{$id}',`protocol`='{$protocol}',`uptime`= NOW(),`pwd`='{$save_pwd}' WHERE qq='{$qqrow['qq']}'");
				}else{
					$DB->exec("UPDATE `{$qq_table}` SET endtime_arr='{$end}',`login_zt`='1',`cityid`='{$id}',`protocol`='{$protocol}',`uptime`= NOW() WHERE qq='{$qqrow['qq']}'");
				}
			}else{
				$endtime_arr = [];
				if(intval($login['free']) >= 1){
					$endtime_arr[$cid] = date('Y-m-d H:i:s',strtotime('+'.intval($login['free']).' days'));
				}else{
					$endtime_arr[$cid] = date('Y-m-d H:i:s',strtotime('+30 days'));
				}
				$DB->exec("INSERT INTO `{$qq_table}` (`pwd`,`dropline`,`login_zt`,`zid`,`qq`,`cityid`,`protocol`,`addtime`,`endtime_arr`) VALUES ('{$save_pwd}', '".intval($conf['dropline_user'])."', '1', '".$userrow['zid']."', '{$qq}', '{$id}', '{$protocol}', NOW(), '".json_encode($endtime_arr)."')");
			}

			update_free_experience($qq, $cid, $login);
			$DB->exec("DELETE FROM `pre_login_order` WHERE `order_no`='{$order_no}'");
			clean_old_orders();
			
			$qqconf = $DB->getColumn("SELECT count(*) FROM `pre_frame_qqconf` WHERE qq='{$qq}'");
			if($qqconf==0){
				$DB->exec("INSERT INTO `pre_frame_qqconf` (`zid`,`qq`,`massmsg_open`,`massmsg_delay`,`addtime`) VALUES('".$userrow['zid']."','{$qq}','1','2000',NOW())");
			}
			
			json_success('登录成功', ['qq' => $qq]);
		}
		
		if($frame_code == 1 && $retcode != 200){
			update_login_order($order_no, 2, '请检查 QQ 密码是否正确');
			$errMsg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '请检查 QQ 密码是否正确';
			json_error(ERROR_PARAM_EMPTY, $errMsg);
		}
		// xlz 禁止登录/密码泄露等返回 retcode:200 且 code:-1，此处统一把框架 msg 返回给前端
		$errMsg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '连接服务器失败，可能软件掉线';
		update_login_order($order_no, 2, $errMsg);
		json_error(ERROR_PARAM_EMPTY, $errMsg);
	}elseif($type == 'qr'){
		$qqrow = $DB->getRow("SELECT * FROM `{$qq_table}` WHERE qq='{$qq}' LIMIT 1");
		$is_free_node = ($login['apipwd'] === '0' || $login['apipwd'] === 0 || ($login['apipwd'] && $login['apipwd'] !== ''));
		if($qqrow){
			if($userrow){
				if($userrow['zid'] != $qqrow['zid']){
					json_error(ERROR_NO_PERMISSION, '该账号不在您名下，找回后在操作哦', ['qq' => $qq]);
				}
			}
			if(!$is_free_node && !check_category_permission($qq, $cid, $userrow['zid'])){
				json_error(ERROR_NO_CATEGORY, '您没有购买该分类，请先购买代挂时长', ['qq' => $qq]);
			}
		}else{
			if($is_free_node){
			}elseif(intval($login['free'])>0){
				if(!check_free_experience($qq, $cid, $login)){
					json_error(ERROR_FREE_EXPIRED, '该账号已免费体验过了<br>请购买代挂时长后在登录哦', ['qq' => $qq]);
				}
			}else{
				json_error(ERROR_NO_CATEGORY, '购买代挂时长后在登录', ['qq' => $qq]);
			}
		}
				// 可选：密码登录时在“添加QQ”之前删除目标节点上的该QQ（默认否）
		if (!empty($conf_frame['login_del_before']) && strval($conf_frame['login_del_before']) === '1') {
			@delete_bot($login, $qq);
		}
		$order_no = create_login_order($qq, '', $id, $cid, $protocol);
		$_SESSION['login_order_'.$qq] = $order_no;
		$ret = get_login_qr($login, $qq, $protocol);
		$ok = is_array($ret) && (($ret['code'] ?? -1) == 1 || ($ret['retcode'] ?? -1) == 200) && isset($ret['qrid']) && (isset($ret['base64']) || isset($ret['qrcode']));
		if(!$ok){
			update_login_order($order_no, 2, $ret['msg'] ?? '获取二维码失败');
			json_error(ERROR_PARAM_EMPTY, $ret['msg'] ?? '获取二维码失败');
		}
		$qrid = $ret['qrid'] ?? $ret['qr_id'] ?? '';
		$base64 = $ret['base64'] ?? $ret['qrcode'] ?? '';
		$_SESSION['qr_login_params'] = ['id' => $id, 'cid' => $cid, 'qq' => $qq, 'protocol' => $protocol, 'qrid' => $qrid];
		json_success('获取成功', ['qrid' => $qrid, 'base64' => $base64]);
	}else{
		json_error(ERROR_PARAM_EMPTY, '类型错误');
	}
break;

case 'check_qr':
case 'get_qr_zt':
	$qrid = $_POST['qrid'] ?? $_GET['qrid'] ?? $_POST['qq'] ?? $_GET['qq'] ?? '';
	$qrid = $qrid === null || $qrid === '' ? '' : (is_string($qrid) ? trim($qrid) : (string)$qrid);
	if($qrid === '')json_error(ERROR_PARAM_EMPTY, '参数不能为空');
	
	if(isset($_SESSION['qr_login_params'])){
		$params = $_SESSION['qr_login_params'];
		$qq = $params['qq'] ?? '';
		if(!empty($qq)){
			$login = get_login_config_by_qq($qq);
		}else{
			$login = $DB->getRow("SELECT * FROM `pre_loginconfig` WHERE status='1' AND biz='{$biz}' ORDER BY id LIMIT 1");
		}
	}else{
		$login = $DB->getRow("SELECT * FROM `pre_loginconfig` WHERE status='1' AND biz='{$biz}' ORDER BY id LIMIT 1");
	}
	if (is_array($login) && isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	if(!$login)json_error(ERROR_API_NOT_FOUND, '未找到可用的登录接口');
	$qq = $_SESSION['qr_login_params']['qq'] ?? '';
	$ret = get_login_qr_zt($login, $qq, $qrid);
	if (($ret['code'] ?? -1) == 1) {
		if(!isset($_SESSION['qr_login_params'])){
			json_error(-1, '登录参数丢失，请重新扫码');
		}
		$params = $_SESSION['qr_login_params'];
		$id = $params['id'];
		$expected_qq = $params['qq'] ?? $qq ?? '';
		$actual_qq = $ret['qq'] ?? $ret['uin'] ?? $ret['bot'] ?? $expected_qq;
		if($expected_qq && $actual_qq && strval($expected_qq) !== strval($actual_qq)){
			delete_bot($login, $actual_qq);
			json_error(-1, '登录qq不一致');
		}
		$qq = $expected_qq ?: $actual_qq;
		$protocol = $params['protocol'] ?? '0';
		
		$login = get_login_config_by_id($id);
		if (isset($login['error'])) {
			json_error(ERROR_API_NOT_FOUND, $login['error']);
		}
		if(!$login) {
			$login = $DB->getRow("SELECT a.*,b.free FROM `pre_loginconfig` a LEFT JOIN `pre_login_class` b ON a.cids=b.id AND b.biz='{$biz}' WHERE a.status='1' AND a.biz='{$biz}' AND a.id='{$id}' LIMIT 1");
		}
		if(!$login)json_error(ERROR_API_NOT_FOUND, '接口不存在');
		
		$cid = intval($login['cids']);
		
		$qqrow = $DB->getRow("SELECT * FROM `{$qq_table}` WHERE qq='{$qq}' LIMIT 1");
		if(isset($_SESSION['qq_pwd_'.$qq])){
			save_qq_pwd($qq, $_SESSION['qq_pwd_'.$qq]);
		}
		$is_free_node = ($login['apipwd'] === '0' || $login['apipwd'] === 0);
		if($qqrow){
			// 扫码登录换节点时也按 del_frame_qq 处理原框架上的该QQ
			if(strval($qqrow['cityid']) !== strval($id) || $qqrow['protocol'] != $protocol){
				$oc = strval($qqrow['cityid']);
				$oldlogin = null;
				if (strpos($oc, 'link_') === 0 && function_exists('nodeLinkGetLoginConfig')) {
					$tmp = nodeLinkGetLoginConfig(intval(substr($oc, 5)));
					if ($tmp && !isset($tmp['error'])) {
						$oldlogin = $tmp;
					}
				}
				if (!$oldlogin) {
					$oldlogin = $DB->getRow("SELECT * FROM `pre_loginconfig` WHERE id='{$qqrow['cityid']}' AND biz='{$biz}' LIMIT 1");
				}
				if($oldlogin){
					$del_frame_qq = isset($conf_frame['del_frame_qq']) ? $conf_frame['del_frame_qq'] : '0';
					if($del_frame_qq === '1'){
						delete_bot($oldlogin, $qq);
					}elseif($del_frame_qq === '0'){
						outqq($oldlogin, $qq);
					}
				}
			}
			if(!$is_free_node && !check_category_permission($qq, $cid, $userrow['zid'])){
				exit(json_encode(['code'=>-200,'qq'=>$qq,'msg'=>'您没有购买该分类，请先购买代挂时长'], JSON_UNESCAPED_UNICODE));
			}

			$end = json_decode($qqrow['endtime_arr'],true);
			if(intval($login['free']) >= 1){
				$end = add_free_time($end, $cid, $login['free']);
			}
			$end = json_encode($end);
			$DB->exec("UPDATE `{$qq_table}` SET endtime_arr='{$end}',`login_zt`='1',`cityid`='{$id}',`protocol`='{$protocol}',`uptime`= NOW() WHERE qq='{$qqrow['qq']}'");
		}else{
			$endtime_arr = [];
			if(intval($login['free']) >= 1){
				$endtime_arr[$cid] = date('Y-m-d H:i:s',strtotime('+'.intval($login['free']).' days'));
			}else{
				$endtime_arr[$cid] = date('Y-m-d H:i:s',strtotime('+30 days'));
			}
			$DB->exec("INSERT INTO `{$qq_table}` (`dropline`,`login_zt`,`zid`,`qq`,`cityid`,`protocol`,`addtime`,`endtime_arr`) VALUES ('".intval($conf['dropline_user'])."', '1', '".$userrow['zid']."', '{$qq}', '{$id}', '{$protocol}', NOW(), '".json_encode($endtime_arr)."')");
		}

		update_free_experience($qq, $cid, $login);
		$order_no = $_SESSION['login_order_'.$qq] ?? '';
		if($order_no){
			$DB->exec("DELETE FROM `pre_login_order` WHERE `order_no`='{$order_no}'");
			unset($_SESSION['login_order_'.$qq]);
		}
		clean_old_orders();

		$qqconf = $DB->getColumn("SELECT count(*) FROM `pre_frame_qqconf` WHERE qq='{$qq}'");
		if($qqconf==0){
			$DB->exec("INSERT INTO `pre_frame_qqconf` (`zid`,`qq`,`massmsg_open`,`massmsg_delay`,`addtime`) VALUES('".$userrow['zid']."','{$qq}','1','2000',NOW())");
		}
		
		unset($_SESSION['qr_login_params']);
		json_success('登录成功', ['qq' => $qq]);
	}
	$code = $ret['code'] ?? -1;
	$msg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '';
	if ($code == 0) {
		exit(json_encode(['code'=>0,'msg'=>$msg], JSON_UNESCAPED_UNICODE));
	}
	if ($code == -1) {
		$order_no = isset($_SESSION['qr_login_params']['qq']) ? ($_SESSION['login_order_'.$_SESSION['qr_login_params']['qq']] ?? '') : '';
		if ($order_no) update_login_order($order_no, 2, $msg);
		json_error(-1, $msg);
	}
	exit(json_encode(['code'=>0,'msg'=>$msg], JSON_UNESCAPED_UNICODE));
break;

case 'submit_ticket':
	$qq = daddslashes($_POST['qq'] ?? $_GET['qq'] ?? '');
	$ticket = daddslashes($_POST['ticket'] ?? $_GET['ticket'] ?? '');
	$randstr = daddslashes($_POST['randstr'] ?? $_GET['randstr'] ?? '');

	if(!$qq || !$ticket)json_error(ERROR_PARAM_EMPTY, '参数不能为空');

	$login = get_login_config_by_qq($qq);
	if (is_array($login) && isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	if(!$login)json_error(ERROR_API_NOT_FOUND, '未找到可用的登录接口');
	
	$cid = intval($login['cids']);
	
	$ret = submit_ticket($login, $qq, $ticket, $randstr);
	
	$frame_code = $ret['code'] ?? -1;
	$retcode = $ret['retcode'] ?? -1;
	$ticket_url = $ret['ticket_url'] ?? '';
	
	if($frame_code == 114514){
		$sid = '0';
		$aid = '2090581062';
		
		if(!empty($ticket_url) && strpos($ticket_url, '?') !== false){
			$url_parts = parse_url($ticket_url);
			if(isset($url_parts['query'])){
				parse_str($url_parts['query'], $params);
				$sid = $params['sid'] ?? $sid;
				$aid = $params['aid'] ?? $aid;
			}
		}
		
		exit(json_encode([
			'code' => 114514,
			'msg' => '需要进行身份验证',
			'qq' => $qq,
			'sid' => $sid,
			'aid' => $aid,
			'hkurl' => $ticket_url,
			'hktype' => 2
		]));
	}
	
	if($frame_code == 2 && !empty($ticket_url)){
		$sid = '0';
		$aid = '16';
		$uin = $qq;
		
		if(strpos($ticket_url, '?') !== false){
			$url_parts = parse_url($ticket_url);
			if(isset($url_parts['query'])){
				parse_str($url_parts['query'], $params);
				$sid = $params['sid'] ?? $sid;
				$aid = $params['aid'] ?? $aid;
				$uin = $params['uin'] ?? $uin;
			}
		}
		
		exit(json_encode([
			'code' => 20,
			'msg' => '需要执行滑块验证',
			'qq' => $qq,
			'sid' => $sid,
			'aid' => $aid,
			'hkurl' => $ticket_url,
			'hktype' => 1
		]));
	}
	
	if($frame_code == 239 || $frame_code == 2){
		$skip_send_sms = (($login['type'] ?? '') === 'xlz');
		exit(json_encode([
			'code' => 10,
			'msg' => '需要手机验证码',
			'qq' => $qq,
			'skip_send_sms' => $skip_send_sms
		]));
	}
	$frame_type = $login['type'] ?? 'dulu';
	$bool = $ret['bool'] ?? false;
	$success = ($frame_type == 'xlz') ? ($retcode == 200 && ($frame_code == 1 || $frame_code == 0)) : ($frame_code == 0 || $bool === true);
	
	if($success){
		$protocol = $_SESSION['login_protocol_'.$qq] ?? '1';
		handle_login_success($qq, $login, $cid, $protocol);
	}
	// dulu 密码错误等会返回 code:1, retcode:200 但无实际登录成功，必须统一返回 code:-1 和明确文案
	$errMsg = $ret['msg'] ?? $ret['data']['retmsg'] ?? $ret['echo'] ?? '';
	if ($errMsg === '' && $frame_type === 'dulu' && $frame_code == 1 && $retcode == 200) {
		$errMsg = '请检查 QQ 密码是否正确';
	}
	if ($errMsg === '') {
		$errMsg = '登录失败';
	}
	exit(json_encode(['code' => -1, 'msg' => $errMsg], JSON_UNESCAPED_UNICODE));
break;

case 'submit_verify_1':
	$qq = daddslashes($_POST['qq']);
	$ticket = daddslashes($_POST['ticket']);
	$randstr = daddslashes($_POST['randstr']);
	
	if(!$qq || !$ticket)json_error(ERROR_PARAM_EMPTY, '参数不能为空');
	
	$login = get_login_config_by_qq($qq);
	if (is_array($login) && isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	if(!$login)json_error(ERROR_API_NOT_FOUND, '未找到可用的登录接口');
	
	$ret = submit_verify_step1($login, $qq, $ticket, $randstr);
	
	$frame_code = $ret['code'] ?? -1;
	$retcode = $ret['retcode'] ?? -1;
	$frame_type = $login['type'] ?? 'dulu';
	
	if($frame_code == 239 || ($retcode == 239) || $frame_code == 2 || ($retcode == 2)){
		$skip_send_sms = ($frame_type === 'xlz');
		exit(json_encode([
			'code' => 10,
			'msg' => '需要手机验证码',
			'qq' => $qq,
			'skip_send_sms' => $skip_send_sms
		]));
	}
	// dulu 的 retcode:200 仅请求成功，只有 frame_code==0 或 bool 才算成功
	$bool = $ret['bool'] ?? false;
	$ok = ($frame_type == 'xlz') ? ($retcode == 200 && ($frame_code == 1 || $frame_code == 0)) : ($frame_code == 0 || $bool === true);
	if($ok){
		exit(json_encode([
			'code' => 1,
			'msg' => '验证成功',
			'qq' => $qq,
			'areaCode' => $ret['areaCode'] ?? '+86',
			'phoneNum' => $ret['phoneNum'] ?? ''
		], JSON_UNESCAPED_UNICODE));
	}
	$errMsg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '验证失败';
	exit(json_encode(['code' => -1, 'msg' => $errMsg], JSON_UNESCAPED_UNICODE));
break;

case 'submit_verify_2':
	$qq = daddslashes($_POST['qq']);
	$areaCode = daddslashes($_POST['areaCode']);
	$phoneNum = daddslashes($_POST['phoneNum']);
	$mobile = daddslashes($_POST['mobile']);
	
	if(!$qq || !$mobile)json_error(ERROR_PARAM_EMPTY, '参数不能为空');
	
	$login = get_login_config_by_qq($qq);
	if (is_array($login) && isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	if(!$login)json_error(ERROR_API_NOT_FOUND, '未找到可用的登录接口');
	
	$ret = submit_verify_step2($login, $qq, $areaCode, $phoneNum, $mobile);
	
	$frame_code = $ret['code'] ?? -1;
	$retcode = $ret['retcode'] ?? -1;
	$sms = $ret['sms'] ?? '';
	
	if(($retcode == 200) && !empty($sms)){
		exit(json_encode([
			'code' => 1,
			'msg' => '验证成功',
			'qq' => $qq,
			'sms' => $sms,
			'sendTo' => $ret['sendTo'] ?? ''
		], JSON_UNESCAPED_UNICODE));
	}
	$errMsg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '身份验证失败，请重试';
	exit(json_encode(['code' => -1, 'msg' => $errMsg], JSON_UNESCAPED_UNICODE));
break;

case 'success_sms':
	$qq = daddslashes($_POST['qq']);
	
	if(!$qq)json_error(ERROR_PARAM_EMPTY, 'QQ号不能为空');
	
	$login = get_login_config_by_qq($qq);
	if (is_array($login) && isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	if(!$login)json_error(ERROR_API_NOT_FOUND, '未找到可用的登录接口');
	
	$ret = confirm_sms_success($login, $qq);
	$r = $ret['retcode'] ?? -1;
	$c = $ret['code'] ?? -1;
	$ok = ($login['type'] ?? 'dulu') == 'xlz' ? ($r == 200 && ($c == 1 || $c == 0)) : ($r == 200 || $c == 1);
	if($ok){
		exit(json_encode(['code' => 1, 'msg' => '确认成功'], JSON_UNESCAPED_UNICODE));
	}
	// xlz 未收到短信等返回 retcode:300，必须把框架的 msg/data.retmsg 原样返回给前端
	$errMsg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '';
	if ($errMsg === '') $errMsg = '确认失败';
	exit(json_encode(['code' => -1, 'msg' => $errMsg], JSON_UNESCAPED_UNICODE));
break;

case 'send_phone_code':
	$qq = daddslashes($_POST['qq']);
	if(!$qq)json_error(ERROR_PARAM_EMPTY, 'QQ号不能为空');
	
	$login = get_login_config_by_qq($qq);
	if (is_array($login) && isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	if(!$login)json_error(ERROR_API_NOT_FOUND, '未找到可用的登录接口');
	
	$ret = send_sms_code($login, $qq);
	$r = $ret['retcode'] ?? -1;
	$c = $ret['code'] ?? -1;
	$b = $ret['bool'] ?? false;
	$ok = ($login['type'] ?? 'dulu') == 'xlz' ? ($r == 200 && ($c == 1 || $c == 0)) : ($r == 200 || $c == 1 || $b === true);
	if($ok){
		exit(json_encode(['code' => 1, 'msg' => '验证码发送成功，请查收']));
	}
	$msg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '';
	exit(json_encode(['code' => -1, 'msg' => '发送验证码失败' . $msg]));
break;

case 'submit_phone_code':
	$qq = daddslashes($_POST['qq']);
	$code = daddslashes($_POST['code']);
	if(!$qq || !$code)json_error(ERROR_PARAM_EMPTY, '参数不能为空');

	$login = get_login_config_by_qq($qq);
	if (is_array($login) && isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	if(!$login)json_error(ERROR_API_NOT_FOUND, '未找到可用的登录接口');
	
	$ret = submit_sms_code($login, $qq, $code);
	
	$frame_type = $login['type'] ?? 'dulu';
	$frame_code = $ret['code'] ?? -1;
	$frame_retcode = $ret['retcode'] ?? -1;
	$bool = $ret['bool'] ?? false;
	$success = ($frame_type == 'xlz') ? ($frame_retcode == 200 && ($frame_code == 1 || $frame_code == 0)) : ($frame_code == 0 || $bool === true);
	
	if($success){
		$cid = intval($login['cids']);
		$protocol = $_SESSION['login_protocol_'.$qq] ?? '1';
		handle_login_success($qq, $login, $cid, $protocol);
		exit(json_encode(['code' => 1, 'msg' => '验证成功']));
	}
	
	$msg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '验证失败';
	exit(json_encode(['code' => -1, 'msg' => $msg]));
break;

case 'login_qq':
	$qq = daddslashes($_POST['qq'] ?? $_GET['qq'] ?? '');
	$pwd = daddslashes($_POST['pwd'] ?? '');
	
	if(!$qq)json_error(ERROR_PARAM_EMPTY, 'QQ号不能为空');
	
	$login = get_login_config_by_qq($qq);
	if (is_array($login) && isset($login['error'])) {
		json_error(ERROR_API_NOT_FOUND, $login['error']);
	}
	if(!$login)json_error(ERROR_API_NOT_FOUND, '未找到可用的登录接口');
	
	$cid = intval($login['cids']);
	
	if(!empty($pwd)){
		$_SESSION['qq_pwd_'.$qq] = $pwd;
	}
	
	$ret = loginqq($login, $qq, $pwd);
	
	$frame_code = $ret['code'] ?? -1;
	$ticket_url = $ret['ticket_url'] ?? '';
	
	if($frame_code == 2 && !empty($ticket_url)){
		$sid = '0';
		$aid = '16';
		$uin = $qq;
		
		if(strpos($ticket_url, '?') !== false){
			$url_parts = parse_url($ticket_url);
			if(isset($url_parts['query'])){
				parse_str($url_parts['query'], $params);
				$sid = $params['sid'] ?? $sid;
				$aid = $params['aid'] ?? $aid;
				$uin = $params['uin'] ?? $uin;
			}
		}
		
		exit(json_encode([
			'code' => 20,
			'msg' => '需要执行滑块验证',
			'qq' => $qq,
			'sid' => $sid,
			'aid' => $aid,
			'hkurl' => $ticket_url,
			'hktype' => 1
		]));
	}
	
	if($frame_code == 239 || $frame_code == 2){
		$skip_send_sms = (($login['type'] ?? '') === 'xlz');
		exit(json_encode([
			'code' => 10,
			'msg' => '需要手机验证码',
			'qq' => $qq,
			'skip_send_sms' => $skip_send_sms
		]));
	}
	
	if(is_login_success_result($ret, $login['type'] ?? 'dulu')){
		$frame_type = $login['type'] ?? 'dulu';
		$ret_msg = $ret['msg'] ?? $ret['echo'] ?? '';
		if ($frame_type === 'dulu' && !empty($ret_msg) && strpos($ret_msg, '错误') !== false) {
			$msg = $ret_msg;
			exit(json_encode(['code' => -1, 'msg' => $msg]));
		}
		$protocol = $_SESSION['login_protocol_'.$qq] ?? '1';
		handle_login_success($qq, $login, $cid, $protocol);
	}
	
	$msg = $ret['msg'] ?? $ret['data']['retmsg'] ?? '登录失败';
	exit(json_encode(['code' => -1, 'msg' => $msg]));
break;

case 'loading_pwd':
	$qq = daddslashes($_POST['qq']);
	$row = $DB->getRow("SELECT pwd FROM `{$qq_table}` WHERE qq='{$qq}' AND zid='{$userrow['zid']}' LIMIT 1");
	if(!$row)json_error(-1, $qq.'<br>账户数据不存在');
	if(!empty($row['pwd'])){
		exit(json_encode(['code'=>1,'msg'=>'历史密码 成功载入','pwd'=>$row['pwd']], JSON_UNESCAPED_UNICODE));
	}
	json_error(-1, '没有历史密码哦！');
break;

default:
	json_error(-1, '未知操作');
break;
}
?>
