diff --git a/app/api/controller/v1/Playx.php b/app/api/controller/v1/Playx.php index 7320448..1205266 100644 --- a/app/api/controller/v1/Playx.php +++ b/app/api/controller/v1/Playx.php @@ -393,7 +393,7 @@ class Playx extends Api /** * Token 验证 - POST /api/v1/playx/verify-token - * 配置 playx.verify_token_local_only=true 时仅本地校验 token(不请求 PlayX)。 + * 配置 playx.verify_token_local_only=true 时:不向 PlayX 请求,且不校验传入 token(联调占位)。 */ public function verifyToken(Request $request): Response { @@ -402,15 +402,15 @@ class Playx extends Api return $response; } + if (config('playx.verify_token_local_only', false)) { + return $this->verifyTokenLocalOpen(); + } + $token = strval($request->post('token', $request->post('session', $request->get('token', '')))); if ($token === '') { return $this->error(__('Token expiration'), null, 0, ['statusCode' => 401]); } - if (config('playx.verify_token_local_only', false)) { - return $this->verifyTokenLocal($token); - } - $baseUrl = config('playx.api.base_url', ''); $verifyUrl = config('playx.api.token_verify_url', '/api/v1/auth/verify-token'); if ($baseUrl === '') { @@ -470,128 +470,32 @@ class Playx extends Api } /** - * 联调:合作方 JWT payload 的 base64url 解码(不验签),仅用于 dev_verify_token_exact 命中后的 session 字段。 - * - * @return array{sub?: string, user_fullname?: string, exp?: int}|null + * 本地联调:不校验 token,按配置默认用户签发新 mall_session(待 PlayX 远程校验就绪后关闭 verify_token_local_only)。 */ - private function parsePartnerJwtPayloadForDev(string $jwt): ?array + private function verifyTokenLocalOpen(): Response { - $parts = explode('.', $jwt); - if (count($parts) < 2) { - return null; - } - $payload = $parts[1]; - $b64 = strtr($payload, '-_', '+/'); - $pad = strlen($b64) % 4; - if ($pad > 0) { - $b64 .= str_repeat('=', 4 - $pad); - } - $raw = base64_decode($b64, true); - if ($raw === false || $raw === '') { - return null; - } - $decoded = json_decode($raw, true); - if (!is_array($decoded)) { - return null; - } - - return $decoded; - } - - /** - * 本地校验 temLogin 等写入的商城 token(类型 muser),写入 mall_session - */ - private function verifyTokenLocal(string $token): Response - { - $devExact = strval(config('playx.dev_verify_token_exact', '')); - if ($devExact !== '' && hash_equals($devExact, $token)) { - $payload = $this->parsePartnerJwtPayloadForDev($token); - if ($payload === null) { - return $this->error(__('Token expiration'), null, 0, ['statusCode' => 401]); - } - if (isset($payload['exp'])) { - $exp = intval($payload['exp']); - if ($exp > 0 && $exp <= time()) { - return $this->error(__('Token expiration'), null, 0, ['statusCode' => 401]); - } - } - - $overrideUserId = strval(config('playx.dev_verify_session_user_id', '')); - $playxUserId = $overrideUserId; - if ($playxUserId === '' && isset($payload['sub']) && is_string($payload['sub'])) { - $playxUserId = $payload['sub']; - } - if ($playxUserId === '') { - return $this->error(__('Token expiration'), null, 0, ['statusCode' => 401]); - } - - $overrideUsername = strval(config('playx.dev_verify_session_username', '')); - $username = $overrideUsername; - if ($username === '') { - if (isset($payload['user_fullname']) && is_string($payload['user_fullname']) && $payload['user_fullname'] !== '') { - $username = $payload['user_fullname']; - } elseif (isset($payload['sub']) && is_string($payload['sub'])) { - $username = $payload['sub']; - } - } - - $expireAt = time() + intval(config('playx.session_expire_seconds', 3600)); - $sessionId = bin2hex(random_bytes(16)); - MallSession::create([ - 'session_id' => $sessionId, - 'user_id' => $playxUserId, - 'username' => $username, - 'expire_time' => $expireAt, - 'create_time' => time(), - 'update_time' => time(), - ]); - - return $this->success('', [ - 'session_id' => $sessionId, - 'user_id' => $playxUserId, - 'username' => $username, - 'token_expire_at' => date('c', $expireAt), - ]); - } - - $tokenData = Token::get($token); - if (empty($tokenData) || (isset($tokenData['expire_time']) && intval($tokenData['expire_time']) <= time())) { - return $this->error(__('Token expiration'), null, 0, ['statusCode' => 401]); - } - $tokenType = strval($tokenData['type'] ?? ''); - if ($tokenType !== UserAuth::TOKEN_TYPE_MALL_USER) { - return $this->error(__('Token expiration'), null, 0, ['statusCode' => 401]); - } - $assetId = intval($tokenData['user_id'] ?? 0); - if ($assetId <= 0) { - return $this->error(__('Token expiration'), null, 0, ['statusCode' => 401]); - } - - $asset = MallUserAsset::where('id', $assetId)->find(); - if (!$asset) { - return $this->error(__('Token expiration'), null, 0, ['statusCode' => 401]); - } - - $playxUserId = strval($asset->playx_user_id ?? ''); + $playxUserId = strval(config('playx.verify_token_local_default_user_id', 'testmyr')); + $username = strval(config('playx.verify_token_local_default_username', 'yangyang123')); if ($playxUserId === '') { - $playxUserId = strval($assetId); + return $this->error(__('PlayX API not configured')); } $expireAt = time() + intval(config('playx.session_expire_seconds', 3600)); $sessionId = bin2hex(random_bytes(16)); + $now = time(); MallSession::create([ 'session_id' => $sessionId, 'user_id' => $playxUserId, - 'username' => strval($asset->username ?? ''), + 'username' => $username, 'expire_time' => $expireAt, - 'create_time' => time(), - 'update_time' => time(), + 'create_time' => $now, + 'update_time' => $now, ]); - return $this->success('', [ + return $this->success('Success', [ 'session_id' => $sessionId, 'user_id' => $playxUserId, - 'username' => strval($asset->username ?? ''), + 'username' => $username, 'token_expire_at' => date('c', $expireAt), ]); } diff --git a/config/playx.php b/config/playx.php index 4fee1ab..132c41f 100644 --- a/config/playx.php +++ b/config/playx.php @@ -20,23 +20,14 @@ return [ // token 会话缓存过期时间(秒) 'session_expire_seconds' => intval(env('PLAYX_SESSION_EXPIRE_SECONDS', '3600')), /** - * 为 true 时:/api/v1/playx/verify-token 仅本地校验(查 token 表 + mall_playx_user_asset),不请求 PlayX。 - * 联调/无 PlayX 环境可开;上线对接 PlayX 后请设为 false 并配置 api.base_url。 + * 为 true 时:verifyToken 不向 PlayX 请求;当前实现为联调占位——不校验请求中的 token, + * 每次签发新 session,用户标识见 verify_token_local_default_*(待对方提供校验接口后请设为 false 并走远程校验)。 */ 'verify_token_local_only' => filter_var(env('PLAYX_VERIFY_TOKEN_LOCAL_ONLY', '1'), FILTER_VALIDATE_BOOLEAN), - /** - * 联调占位(待对方提供 token 校验接口后删除或清空):verify_token_local_only 为 true 时, - * 若请求中的 token 与此字符串完全一致则视为有效合作方 JWT,并写入 mall_session。 - * 生产环境务必置空或通过环境变量覆盖为空。 - */ - 'dev_verify_token_exact' => strval(env( - 'PLAYX_DEV_VERIFY_TOKEN_EXACT', - 'eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJ0ZXN0bXlyIiwiYXV0aCI6IlJPTEVfTUVNQkVSIiwibWVyY2hhbnQiOiJwbHgiLCJ1c2VyX2Z1bGxuYW1lIjoiQW5uYSIsImN1cnJlbmN5IjoiTVlSIiwibGFuZ3VhZ2UiOiJ6aC1DTiIsInZpcCI6ZmFsc2UsImV4cCI6MTc3NjkzODI4N30.XVvNcnBcAEqdxqoNRmygkl826bLUfwH2xyBE8wiSTOSeJjv99DHKJOAgsE4ukJ-M_t1hPbraz9GO4qvOszOeDg' - )), - /** 命中 dev_verify_token_exact 时写入 session 的展示用户名(空则取 JWT user_fullname 或 sub) */ - 'dev_verify_session_username' => strval(env('PLAYX_DEV_VERIFY_SESSION_USERNAME', 'yangyang123')), - /** 命中 dev_verify_token_exact 时写入 session 的 user_id(空则取 JWT sub) */ - 'dev_verify_session_user_id' => strval(env('PLAYX_DEV_VERIFY_SESSION_USER_ID', '')), + /** verify_token_local_only 为 true 时写入 mall_session 的 playx 用户标识 */ + 'verify_token_local_default_user_id' => strval(env('PLAYX_VERIFY_TOKEN_LOCAL_DEFAULT_USER_ID', 'testmyr')), + /** verify_token_local_only 为 true 时写入 mall_session 的展示用户名 */ + 'verify_token_local_default_username' => strval(env('PLAYX_VERIFY_TOKEN_LOCAL_DEFAULT_USERNAME', 'yangyang123')), // PlayX API 配置(商城调用 PlayX 时使用) 'api' => [ 'base_url' => strval(env('PLAYX_API_BASE_URL', '')),