fix: api auth - getUserId uses UserTokenData (DB fallback) + user_info cookie decode, removes broken JWT parseToken

feat/phase-b-verification
Council 2026-04-24 13:07:09 +08:00
parent f422ffcebb
commit b27467035c
1 changed files with 65 additions and 52 deletions

View File

@ -3,7 +3,7 @@
* VR票务插件 - C端票夹API控制器
*
* 路由机制PluginsService::PluginsApiCall:
* URL: ?s=api/plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=list
* URL: /api.php?s=plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=list
* pluginsname=vr_ticket, pluginscontrol=ticket, pluginsaction=list
* class = \app\plugins\vr_ticket\api\Ticket (ucfirst('ticket') = 'Ticket')
* method = ucfirst('list') = 'list'
@ -21,67 +21,54 @@ use app\plugins\vr_ticket\service\WalletService;
*/
class Ticket
{
/**
* 获取当前登录用户ID
*
* ShopXO 使用 X-Token Authorization
* @return int|null
*/
private static function getUserId()
{
// 方式1从 header 获取(推荐
// 方式1X-Token / Authorization headerJS 发送方式)
$token = request()->header('X-Token') ?: request()->header('Authorization', '');
if (!empty($token)) {
$token = str_replace('Bearer ', '', $token);
$user = self::parseToken($token);
if (!empty($user['id'])) {
$token = trim(str_replace('Bearer ', '', $token));
}
if (!empty($token)) {
// 优先用 vrt_user_platform.token 查 DBApp 登录场景)
$user = \app\service\UserService::UserTokenData($token);
if (!empty($user) && !empty($user['id'])) {
return intval($user['id']);
}
// 如果没查到,说明是 web 登录 token存在 user_info cookie 里,不在 vrt_user_platform
// 尝试从 user_info cookie 直接解码cookie 内容 = 用户 JSON
$userInfoCookie = request()->cookie('user_info');
if (!empty($userInfoCookie)) {
$decoded = urldecode($userInfoCookie);
$userData = json_decode($decoded, true);
if (!empty($userData) && !empty($userData['id'])) {
return intval($userData['id']);
}
}
}
// 方式2从 session 获取
$userId = session('user_id');
if (!empty($userId)) {
return intval($userId);
// 方式2ShopXO 标准方式session / cookie适用于页面直接访问场景
$user = \app\service\UserService::LoginUserInfo();
if (!empty($user) && !empty($user['id'])) {
return intval($user['id']);
}
return null;
}
/**
* 解析 TokenJWT格式
*
* @param string $token
* @return array
*/
private static function parseToken(string $token): array
{
$parts = explode('.', $token);
if (count($parts) !== 3) {
return [];
}
$payload = base64_decode(strtr($parts[1], '-_', '+/'));
if ($payload === false) {
return [];
}
$data = json_decode($payload, true);
return is_array($data) ? $data : [];
}
/**
* 返回未登录错误
*
* @return Json
*/
private static function unauthorized(string $msg = '请先登录'): Json
private static function unauthorized(string $msg = '请先登录')
{
return json([
return [
'code' => 401,
'msg' => $msg,
'data' => [],
]);
];
}
/**
@ -91,13 +78,13 @@ class Ticket
* @param string $msg
* @return Json
*/
private static function success($data = [], string $msg = 'success'): Json
private static function success($data = [], string $msg = 'success')
{
return json([
return [
'code' => 0,
'msg' => $msg,
'data' => $data,
]);
];
}
/**
@ -107,23 +94,49 @@ class Ticket
* @param int $code
* @return Json
*/
private static function error(string $msg = '请求失败', int $code = -1): Json
private static function error(string $msg = '请求失败', int $code = -1)
{
return json([
return [
'code' => $code,
'msg' => $msg,
'data' => [],
]);
];
}
/**
* 获取用户票列表
*
* GET ?s=api/plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=list
* GET /api.php?s=plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=list
*
* @return Json
*/
public function list(): Json
public function list()
{
$userId = self::getUserId();
if (empty($userId)) {
return self::unauthorized();
}
try {
$tickets = WalletService::getUserTickets($userId);
return self::success([
'tickets' => $tickets,
'count' => count($tickets),
]);
} catch (\Exception $e) {
return self::error('获取票列表失败: ' . $e->getMessage());
}
}
/**
* 获取用户票列表tickets 别名,兼容文档格式)
*
* GET /api.php?s=plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=tickets
*
* @return Json
*/
public function tickets()
{
$userId = self::getUserId();
if (empty($userId)) {
@ -145,11 +158,11 @@ class Ticket
/**
* 获取票详情(含 QR payload
*
* GET ?s=api/plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=detail&id=X
* GET /api.php?s=plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=detail&id=X
*
* @return Json
*/
public function detail(): Json
public function detail()
{
$userId = self::getUserId();
if (empty($userId)) {
@ -179,11 +192,11 @@ class Ticket
/**
* 强制刷新 QR payload
*
* GET ?s=api/plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=refreshQr&id=X
* GET /api.php?s=plugins/index&pluginsname=vr_ticket&pluginscontrol=ticket&pluginsaction=refreshQr&id=X
*
* @return Json
*/
public function refreshQr(): Json
public function refreshQr()
{
$userId = self::getUserId();
if (empty($userId)) {