1.对接平台接口新增api-key参数
This commit is contained in:
23
API对接文档.md
23
API对接文档.md
@@ -49,10 +49,10 @@
|
||||
|
||||
## 2. 鉴权与对接流程(平台侧 /api/v1)
|
||||
|
||||
平台侧接口分两步:
|
||||
平台侧接口需统一携带请求头 **`api-key`**(与服务端 `.env` 中 `API_KEY` 一致),业务接口另需 **`auth-token`**。
|
||||
|
||||
1. **获取 `auth-token`**
|
||||
2. **携带 `auth-token` 调用 `/api/v1/*` 业务接口**
|
||||
1. **获取 `auth-token`**(同时携带 `api-key`)
|
||||
2. **携带 `api-key` + `auth-token` 调用 `/api/v1/*` 业务接口**
|
||||
|
||||
### 2.1 获取 auth-token
|
||||
|
||||
@@ -100,11 +100,22 @@ signature = md5(agent_id + secret + time)
|
||||
- 密钥错误/签名错误/时间戳无效:`code=403`
|
||||
- 服务端未配置密钥或生成失败:`code=500`
|
||||
|
||||
### 2.2 调用 v1 业务接口(携带 auth-token)
|
||||
### 2.2 平台 api-key(所有 /api/v1/* 必填)
|
||||
|
||||
除 `/api/v1/authToken` 外,其余 `/api/v1/*` 接口需要在请求头携带:
|
||||
- **取值**:与服务端环境变量 `API_KEY` 完全一致(部署在 `server/.env`)
|
||||
- **适用范围**:所有 `/api/v1/*` 接口(含 `/api/v1/authToken` 与业务接口)
|
||||
- **携带方式**(任选其一,按优先级读取,先命中即采用):
|
||||
1. 请求头 `api-key: <API_KEY>`(**推荐**)
|
||||
2. URL 查询参数 `api_key=<API_KEY>`(或 `api-key=<API_KEY>`)
|
||||
3. body 表单/JSON 字段 `api_key`(或 `api-key`)
|
||||
- **未携带或错误**:`401` / `403`
|
||||
|
||||
- `auth-token: <authtoken>`
|
||||
### 2.3 调用 v1 业务接口(携带 auth-token)
|
||||
|
||||
除 `/api/v1/authToken` 外,其余 `/api/v1/*` 接口需要携带:
|
||||
|
||||
- `api-key: <与 API_KEY 一致>`(请求头 / query / body 任选其一,参见 2.2)
|
||||
- `auth-token: <authtoken>`(仅支持请求头)
|
||||
|
||||
当 `auth-token` 过期或失效,返回 `code=402`,需要重新调用 `/api/v1/authToken` 获取新 token。
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_NAME=dafuweng-v3
|
||||
DB_USER=dafuweng-v3
|
||||
DB_PASSWORD=tA6rciKLKxpFNGAm
|
||||
DB_PASSWORD=123456
|
||||
DB_PREFIX=
|
||||
DB_POOL_MAX=32
|
||||
DB_POOL_MIN=4
|
||||
@@ -28,14 +28,16 @@ WEBMAN_CHANNEL_LISTEN_HOST=0.0.0.0
|
||||
GAME_URL=dice-v3-game.h55555game.top
|
||||
|
||||
# API 鉴权与用户(可选,不填则用默认值)
|
||||
# 平台对接 /api/v1/* 请求头 api-key(必填,与对接方约定)
|
||||
API_KEY=
|
||||
# authToken 签名密钥(必填,与客户端约定,用于 signature 校验)
|
||||
API_AUTH_TOKEN_SECRET=xF75oK91TQj13s0UmNIr1NBWMWGfflNO
|
||||
API_AUTH_TOKEN_SECRET=
|
||||
# authToken 时间戳允许误差秒数,防重放,默认 300
|
||||
API_AUTH_TOKEN_TIME_TOLERANCE=300
|
||||
API_AUTH_TOKEN_EXP=86400
|
||||
# API_USER_TOKEN_EXP=604800
|
||||
API_USER_CACHE_EXPIRE=86400
|
||||
API_USER_ENCRYPT_KEY=Wj818SK8dhKBKNOY3PUTmZfhQDMCXEZi
|
||||
API_USER_ENCRYPT_KEY=
|
||||
|
||||
# 验证码配置,支持cache|session
|
||||
CAPTCHA_MODE=cache
|
||||
|
||||
@@ -48,6 +48,9 @@ return [
|
||||
'没有原因' => 'Unknown reason',
|
||||
'缺少参数:agent_id、secret、time、signature 不能为空' => 'Missing parameters: agent_id, secret, time, signature are required',
|
||||
'服务端未配置 API_AUTH_TOKEN_SECRET' => 'API_AUTH_TOKEN_SECRET is not configured',
|
||||
'服务端未配置 API_KEY' => 'API_KEY is not configured',
|
||||
'请携带 api-key' => 'Please provide api-key',
|
||||
'api-key 无效' => 'Invalid api-key',
|
||||
'密钥错误' => 'Invalid secret',
|
||||
'时间戳已过期或无效,请同步时间' => 'Timestamp expired or invalid, please sync time',
|
||||
'签名验证失败' => 'Signature verification failed',
|
||||
|
||||
@@ -20,6 +20,7 @@ class ApiAccessLogMiddleware implements MiddlewareInterface
|
||||
|
||||
/** 请求头名称(小写) */
|
||||
private const SENSITIVE_HEADER_NAMES = [
|
||||
'api-key',
|
||||
'auth-token',
|
||||
'token',
|
||||
'authorization',
|
||||
@@ -32,6 +33,8 @@ class ApiAccessLogMiddleware implements MiddlewareInterface
|
||||
'secret',
|
||||
'signature',
|
||||
'token',
|
||||
'api-key',
|
||||
'api_key',
|
||||
'auth-token',
|
||||
'auth_token',
|
||||
'old_token',
|
||||
|
||||
64
server/app/api/middleware/ApiKeyMiddleware.php
Normal file
64
server/app/api/middleware/ApiKeyMiddleware.php
Normal file
@@ -0,0 +1,64 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace app\api\middleware;
|
||||
|
||||
use app\api\util\ReturnCode;
|
||||
use plugin\saiadmin\exception\ApiException;
|
||||
use Webman\Http\Request;
|
||||
use Webman\Http\Response;
|
||||
use Webman\MiddlewareInterface;
|
||||
|
||||
/**
|
||||
* 校验对接平台 api-key(与 .env 中 API_KEY 一致)
|
||||
* 仅用于 /api/v1/* 平台对接接口
|
||||
*
|
||||
* 取值优先级(按顺序读取,首个非空即采用):
|
||||
* 1. 请求头 api-key(推荐)
|
||||
* 2. 查询参数 api_key / api-key
|
||||
* 3. body 表单/JSON api_key / api-key
|
||||
*/
|
||||
class ApiKeyMiddleware implements MiddlewareInterface
|
||||
{
|
||||
public function process(Request $request, callable $handler): Response
|
||||
{
|
||||
$expected = (string) config('api.platform_api_key', '');
|
||||
if ($expected === '') {
|
||||
throw new ApiException('API_KEY is not configured', ReturnCode::SERVER_ERROR);
|
||||
}
|
||||
|
||||
$apiKey = $this->resolveApiKey($request);
|
||||
if ($apiKey === '') {
|
||||
throw new ApiException('Please provide api-key', ReturnCode::UNAUTHORIZED);
|
||||
}
|
||||
if (!hash_equals($expected, $apiKey)) {
|
||||
throw new ApiException('Invalid api-key', ReturnCode::FORBIDDEN);
|
||||
}
|
||||
|
||||
return $handler($request);
|
||||
}
|
||||
|
||||
private function resolveApiKey(Request $request): string
|
||||
{
|
||||
$headerValue = $request->header('api-key');
|
||||
if ($headerValue !== null && trim((string) $headerValue) !== '') {
|
||||
return trim((string) $headerValue);
|
||||
}
|
||||
|
||||
foreach (['api_key', 'api-key'] as $key) {
|
||||
$val = $request->get($key);
|
||||
if ($val !== null && trim((string) $val) !== '') {
|
||||
return trim((string) $val);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['api_key', 'api-key'] as $key) {
|
||||
$val = $request->post($key);
|
||||
if ($val !== null && trim((string) $val) !== '') {
|
||||
return trim((string) $val);
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
@@ -11,6 +11,8 @@ return [
|
||||
'session_username_prefix' => env('API_SESSION_USERNAME_PREFIX', 'api:user:session:'),
|
||||
// 登录会话过期时间(秒),默认 7 天
|
||||
'session_expire' => (int) env('API_SESSION_EXPIRE', 604800),
|
||||
// 平台对接请求头 api-key(/api/v1/* 必填,与客户端请求头 api-key 一致)
|
||||
'platform_api_key' => env('API_KEY', ''),
|
||||
// auth-token 签名密钥(与客户端约定,用于 /api/authToken 的 signature 校验,必填)
|
||||
'auth_token_secret' => env('API_AUTH_TOKEN_SECRET', ''),
|
||||
// auth-token 时间戳允许误差(秒),防重放,默认 300 秒
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
use Webman\Route;
|
||||
use app\api\middleware\ApiAccessLogMiddleware;
|
||||
use app\api\middleware\ApiKeyMiddleware;
|
||||
use app\api\middleware\AuthTokenMiddleware;
|
||||
use app\api\middleware\TokenMiddleware;
|
||||
|
||||
@@ -22,9 +23,10 @@ Route::group('/api/v1', function () {
|
||||
Route::any('/authToken', [app\api\controller\v1\AuthTokenController::class, 'index']);
|
||||
})->middleware([
|
||||
ApiAccessLogMiddleware::class,
|
||||
ApiKeyMiddleware::class,
|
||||
]);
|
||||
|
||||
// 平台 v1 接口:需在请求头携带 auth-token
|
||||
// 平台 v1 接口:需在请求头携带 api-key、auth-token
|
||||
Route::group('/api/v1', function () {
|
||||
Route::any('/getGameList', [app\api\controller\v1\GameController::class, 'getGameList']);
|
||||
Route::any('/getGameHall', [app\api\controller\v1\GameController::class, 'getGameHall']);
|
||||
@@ -36,6 +38,7 @@ Route::group('/api/v1', function () {
|
||||
Route::any('/setPlayerWallet', [app\api\controller\v1\GameController::class, 'setPlayerWallet']);
|
||||
})->middleware([
|
||||
ApiAccessLogMiddleware::class,
|
||||
ApiKeyMiddleware::class,
|
||||
AuthTokenMiddleware::class,
|
||||
]);
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ declare(strict_types=1);
|
||||
return [
|
||||
'ACCOUNT_DISABLED' => 'Account is disabled and cannot log in',
|
||||
'API_AUTH_TOKEN_SECRET is not configured' => 'API_AUTH_TOKEN_SECRET is not configured',
|
||||
'API_KEY is not configured' => 'API_KEY is not configured',
|
||||
'Please provide api-key' => 'Please provide api-key',
|
||||
'Invalid api-key' => 'Invalid api-key',
|
||||
'AUTH_TOKEN_EXPIRED' => 'auth-token expired',
|
||||
'AUTH_TOKEN_FORMAT_INVALID' => 'auth-token format invalid',
|
||||
'AUTH_TOKEN_INVALID' => 'auth-token invalid',
|
||||
|
||||
@@ -4,6 +4,9 @@ declare(strict_types=1);
|
||||
return [
|
||||
'ACCOUNT_DISABLED' => '账号已被禁用,无法登录',
|
||||
'API_AUTH_TOKEN_SECRET is not configured' => '服务端未配置 API_AUTH_TOKEN_SECRET',
|
||||
'API_KEY is not configured' => '服务端未配置 API_KEY',
|
||||
'Please provide api-key' => '请携带 api-key',
|
||||
'Invalid api-key' => 'api-key 无效',
|
||||
'AUTH_TOKEN_EXPIRED' => 'auth-token 已过期',
|
||||
'AUTH_TOKEN_FORMAT_INVALID' => 'auth-token 格式无效',
|
||||
'AUTH_TOKEN_INVALID' => 'auth-token 无效',
|
||||
|
||||
@@ -11,7 +11,7 @@ declare(strict_types=1);
|
||||
|
||||
$options = getopt('', ['agent_id:', 'secret:', 'time::']);
|
||||
|
||||
$agentId = $options['agent_id'] ?? '5ef059938ba799aaa845e1c2e8a762bd';
|
||||
$agentId = $options['agent_id'] ?? '202cb962ac59075b964b07152d234b70';
|
||||
$secret = $options['secret'] ?? 'xF75oK91TQj13s0UmNIr1NBWMWGfflNO';
|
||||
$time = $options['time'] ?? (string) time();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user