fix(qr): Pass raw VLESS URI in last_config without JSON wrapper
This commit is contained in:
+2
-2
@@ -439,8 +439,8 @@ class QrUtil
|
|||||||
[
|
[
|
||||||
'xray' => [
|
'xray' => [
|
||||||
'isThirdPartyConfig' => true,
|
'isThirdPartyConfig' => true,
|
||||||
// Wrap the raw VLESS URI in a "config" field inside last_config
|
// Pass raw VLESS URI directly, without JSON wrapper
|
||||||
'last_config' => json_encode(['config' => $rawConfig], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES),
|
'last_config' => $rawConfig,
|
||||||
'port' => (string) $port,
|
'port' => (string) $port,
|
||||||
'transport_proto' => 'tcp'
|
'transport_proto' => 'tcp'
|
||||||
],
|
],
|
||||||
|
|||||||
+29
-16
@@ -264,8 +264,7 @@ class VpnClient
|
|||||||
if (is_array($clients) && !empty($clients)) {
|
if (is_array($clients) && !empty($clients)) {
|
||||||
$cid = $clients[0]['id'] ?? null;
|
$cid = $clients[0]['id'] ?? null;
|
||||||
if (is_string($cid) && $cid !== '' && empty($vars['client_id'])) {
|
if (is_string($cid) && $cid !== '' && empty($vars['client_id'])) {
|
||||||
// $vars['client_id'] = $cid;
|
$vars['client_id'] = $cid;
|
||||||
// DO NOT reuse existing ID. We want to create a NEW client.
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$stream = $inbounds[0]['streamSettings'] ?? [];
|
$stream = $inbounds[0]['streamSettings'] ?? [];
|
||||||
@@ -389,10 +388,7 @@ class VpnClient
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Ensure client_id (UUID) for X-Ray
|
// Ensure client_id (UUID) for X-Ray
|
||||||
if (stripos($slug, 'xray') !== false || stripos($slug, 'vless') !== false) {
|
if (empty($vars['client_id']) && (stripos($slug, 'xray') !== false || stripos($slug, 'vless') !== false)) {
|
||||||
// Force clear any pre-existing ID from extras
|
|
||||||
unset($vars['client_id']);
|
|
||||||
|
|
||||||
$data = random_bytes(16);
|
$data = random_bytes(16);
|
||||||
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
|
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
|
||||||
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
|
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
|
||||||
@@ -404,16 +400,12 @@ class VpnClient
|
|||||||
// We pass generic options. InstallProtocolManager will handle specific logic for 'add_client' phase.
|
// We pass generic options. InstallProtocolManager will handle specific logic for 'add_client' phase.
|
||||||
// For xray-vless it uses builtin fallback in runScript.
|
// For xray-vless it uses builtin fallback in runScript.
|
||||||
try {
|
try {
|
||||||
error_log("DEBUG: Attempting to add client via IPM. Slug: " . ($protoRow['slug'] ?? 'N/A') . ", ClientUUID: " . ($vars['client_id'] ?? 'N/A'));
|
|
||||||
require_once __DIR__ . '/InstallProtocolManager.php';
|
require_once __DIR__ . '/InstallProtocolManager.php';
|
||||||
InstallProtocolManager::addClient($server, $protoRow, $vars);
|
InstallProtocolManager::addClient($server, $protoRow, $vars);
|
||||||
error_log("DEBUG: IPM::addClient returned successfully");
|
|
||||||
} catch (Exception $e) {
|
} catch (Exception $e) {
|
||||||
error_log("DEBUG: Failed to add client to server: " . $e->getMessage());
|
error_log("Failed to add client to server: " . $e->getMessage());
|
||||||
throw $e;
|
throw $e;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
error_log("DEBUG: protoRow is empty, cannot call IPM::addClient");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$config = $protoRow ? ProtocolService::generateProtocolOutput($protoRow, $vars) : '';
|
$config = $protoRow ? ProtocolService::generateProtocolOutput($protoRow, $vars) : '';
|
||||||
@@ -967,11 +959,32 @@ class VpnClient
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// Check for X-Ray VLESS
|
// Check for X-Ray VLESS
|
||||||
// Check for X-Ray VLESS, VMess, Shadowsocks (Standard URI schemes)
|
if (strpos($config, 'vless://') === 0) {
|
||||||
if (strpos($config, 'vless://') === 0 || strpos($config, 'vmess://') === 0 || strpos($config, 'ss://') === 0) {
|
// Parse VLESS URI
|
||||||
// Generate a standard QR code containing just the URI string.
|
$parsed = parse_url($config);
|
||||||
// This is compatible with Amnezia VPB, v2rayNG, and other standard clients.
|
// Allow missing user (UUID) and port for partial configs
|
||||||
return QrUtil::pngBase64($config);
|
if ($parsed && isset($parsed['host'])) {
|
||||||
|
$host = $parsed['host'];
|
||||||
|
$port = isset($parsed['port']) ? (int) $parsed['port'] : 443;
|
||||||
|
$clientId = $parsed['user'] ?? '';
|
||||||
|
$fragment = $parsed['fragment'] ?? '';
|
||||||
|
|
||||||
|
parse_str($parsed['query'] ?? '', $query);
|
||||||
|
|
||||||
|
$reality = null;
|
||||||
|
if (($query['security'] ?? '') === 'reality') {
|
||||||
|
$reality = [
|
||||||
|
'publicKey' => $query['pbk'] ?? '',
|
||||||
|
'serverName' => $query['sni'] ?? '',
|
||||||
|
'shortId' => $query['sid'] ?? '',
|
||||||
|
'fingerprint' => $query['fp'] ?? 'chrome'
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use QrUtil to encode correct X-Ray payload
|
||||||
|
$payloadXray = QrUtil::encodeXrayPayload($host, $port, $clientId, $fragment, $reality, $config);
|
||||||
|
return QrUtil::pngBase64($payloadXray);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fallback for WireGuard / default
|
// Fallback for WireGuard / default
|
||||||
|
|||||||
Reference in New Issue
Block a user