diff --git a/.env-example b/.env-example index f34c445..8f4e169 100644 --- a/.env-example +++ b/.env-example @@ -27,7 +27,7 @@ PLAYX_UNLOCK_RATIO=0.1 # Daily Push 签名校验密钥(HMAC,建议从部署系统注入,避免写入代码/仓库) PLAYX_DAILY_PUSH_SECRET= # 合作方回调 JWT 验签密钥(HS256,与对端私发密钥一致;与上一项可同时配置,则两种均需通过) -PLAYX_PARTNER_JWT_SECRET=5590a339502b133f4d0c545c3cdad159a4827dfccb3f51bb110c56f9b96568ca +PLAYX_PARTNER_JWT_SECRET= # Agent authtoken(/api/v1/authToken)JWT 签名密钥;留空则使用下方 buildadmin.token.key AGENT_AUTH_JWT_SECRET= # token 会话缓存过期时间(秒) diff --git a/app/api/controller/v1/Playx.php b/app/api/controller/v1/Playx.php index c207e5d..86fc050 100644 --- a/app/api/controller/v1/Playx.php +++ b/app/api/controller/v1/Playx.php @@ -14,7 +14,6 @@ use app\common\model\MallPlayxDailyPush; use app\common\model\MallPlayxSession; use app\common\model\MallPlayxOrder; use app\common\model\MallPlayxUserAsset; -use app\common\library\PlayxInboundJwt; use support\think\Db; use Webman\Http\Request; use support\Response; @@ -157,14 +156,6 @@ class Playx extends Api return $response; } - $partnerJwtSecret = strval(config('playx.partner_jwt_secret', '')); - if ($partnerJwtSecret !== '') { - $authHeader = strval($request->header('authorization', '')); - if (!PlayxInboundJwt::verifyBearer($authHeader, $partnerJwtSecret)) { - return $this->error(__('Invalid or missing JWT'), null, 0, ['statusCode' => 401]); - } - } - $body = $request->post(); if (empty($body)) { $raw = $request->rawBody(); @@ -179,12 +170,12 @@ class Playx extends Api $ts = $request->header('X-Timestamp', ''); $rid = $request->header('X-Request-Id', ''); if ($sig === '' || $ts === '' || $rid === '') { - return $this->error(__('Invalid signature'), null, 0, ['statusCode' => 401]); + return $this->error(__('Daily push signature missing or incomplete'), null, 0, ['statusCode' => 401]); } $canonical = $ts . "\n" . $rid . "\nPOST\n/api/v1/playx/daily-push\n" . hash('sha256', json_encode($body)); $expected = hash_hmac('sha256', $canonical, $secret); if (!hash_equals($expected, $sig)) { - return $this->error(__('Invalid signature'), null, 0, ['statusCode' => 401]); + return $this->error(__('Daily push signature verification failed'), null, 0, ['statusCode' => 401]); } } @@ -259,7 +250,7 @@ class Playx extends Api $asset = $this->ensureAssetForPlayx($playxUserId, $username); if (!$asset) { - throw new \RuntimeException(__('Failed to map playx user to mall user')); + throw new \RuntimeException(__('Failed to ensure PlayX user asset')); } if ($asset->today_limit_date !== $date) { @@ -345,7 +336,7 @@ class Playx extends Api $asset = $this->ensureAssetForPlayx($playxUserId, strval($body['username'] ?? '')); if (!$asset) { - throw new \RuntimeException(__('Failed to map playx user to mall user')); + throw new \RuntimeException(__('Failed to ensure PlayX user asset')); } if ($asset->today_limit_date !== $date) { diff --git a/app/api/lang/en.php b/app/api/lang/en.php index 5b61696..bd6dc3c 100644 --- a/app/api/lang/en.php +++ b/app/api/lang/en.php @@ -35,6 +35,11 @@ return [ 'Ok' => 'OK', 'Failed to map playx user to mall user' => 'Failed to map PlayX user to mall user', 'Missing required fields: request_id, date, user_id' => 'Missing required fields: request_id, date, user_id', + 'Missing required fields: report_date, member' => 'Missing required fields: report_date, member', + 'Missing required fields: member_id' => 'Missing required fields: member_id', + 'Daily push signature missing or incomplete' => 'Daily push signature missing or incomplete', + 'Daily push signature verification failed' => 'Daily push signature verification failed', + 'Failed to ensure PlayX user asset' => 'Failed to ensure PlayX user asset', 'claim_request_id and user_id/session_id required' => 'claim_request_id and user_id/session_id/token are required', 'User asset not found' => 'User asset not found', 'No points to claim or limit reached' => 'No points to claim or daily limit reached', diff --git a/app/api/lang/zh-cn.php b/app/api/lang/zh-cn.php index 2d6410f..3599b01 100644 --- a/app/api/lang/zh-cn.php +++ b/app/api/lang/zh-cn.php @@ -67,6 +67,11 @@ return [ 'Ok' => '成功', 'Failed to map playx user to mall user' => '无法将 PlayX 用户关联到商城用户', 'Missing required fields: request_id, date, user_id' => '缺少必填字段:request_id、date、user_id', + 'Missing required fields: report_date, member' => '缺少必填字段:report_date、member', + 'Missing required fields: member_id' => '缺少必填字段:member_id', + 'Daily push signature missing or incomplete' => '签名缺失或不完整', + 'Daily push signature verification failed' => '签名校验失败', + 'Failed to ensure PlayX user asset' => '创建/映射用户资产失败', 'claim_request_id and user_id/session_id required' => '缺少 claim_request_id,或未提供有效的 user_id/session_id/token', 'User asset not found' => '未找到用户资产', 'No points to claim or limit reached' => '暂无可领取积分或已达今日上限', diff --git a/app/common/middleware/AllowCrossDomain.php b/app/common/middleware/AllowCrossDomain.php index 842e724..1207115 100644 --- a/app/common/middleware/AllowCrossDomain.php +++ b/app/common/middleware/AllowCrossDomain.php @@ -30,7 +30,7 @@ class AllowCrossDomain implements MiddlewareInterface 'Access-Control-Allow-Credentials' => 'true', 'Access-Control-Max-Age' => '1800', 'Access-Control-Allow-Methods' => 'GET, POST, PUT, DELETE, PATCH, OPTIONS', - 'Access-Control-Allow-Headers' => 'Content-Type, Authorization, batoken, ba-user-token, think-lang, server', + 'Access-Control-Allow-Headers' => 'Content-Type, Authorization, batoken, ba-user-token, think-lang, lang, server', ]; $origin = $request->header('origin'); if (is_array($origin)) { diff --git a/docs/PlayX-接口文档.md b/docs/PlayX-接口文档.md index ef0f74d..4fcc601 100644 --- a/docs/PlayX-接口文档.md +++ b/docs/PlayX-接口文档.md @@ -15,8 +15,11 @@ * 方法:`POST` * 路径:`/api/v1/playx/daily-push` -#### Header(签名校验:可选) -当 `playx.daily_push_secret` 配置非空时,需要携带: +#### Header(多语言,可选) +- `lang`: `zh`/`zh-cn` 返回中文(默认);`en` 返回英文 + +#### Header(签名校验:HMAC 必填) +当 `playx.daily_push_secret` 配置非空时,需要携带(HMAC): - `X-Request-Id`:请求 ID - `X-Timestamp`:时间戳 - `X-Signature`:签名(HMAC_SHA256) @@ -26,6 +29,9 @@ - `expected = hash_hmac('sha256', canonical, daily_push_secret)` - 校验:`hash_equals(expected, X-Signature)` +说明: +- 本项目对接方案为 **仅启用 HMAC**,不使用 `Authorization` 头做校验。 + #### Body | 字段 | 类型 | 必填 | 说明 | |------|------|------|------|