feat: 新增备货单公共 API 接口(PI 号/VIN 号列表)
- 新增 ApiKeyAuth 中间件(hash_equals 防时序攻击) - 新增 PublicApiController(piList/vinList 两个只读接口) - 仅返回已审批通过(approval_status=2)的数据,支持分页和模糊搜索 - LIKE 通配符已转义,异常信息不暴露内部细节 - 附对接文档 docs/public-stock-api.md Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
# Public Stock Order API Design
|
||||
|
||||
## Goal
|
||||
|
||||
Provide two read-only public APIs for internal systems to query approved stock order PI numbers and VIN numbers, with API Key authentication.
|
||||
|
||||
## Data Model
|
||||
|
||||
- `stock_orders.approval_status = 2` means approved
|
||||
- `stock_orders.pi_no` — PI number (string)
|
||||
- `stock_order_items.vin` — VIN/chassis number (string)
|
||||
- `stock_order_items.model_snapshot` — car model name (plain string)
|
||||
- `stock_order_items.order_id` → `stock_orders.id`
|
||||
|
||||
## Authentication
|
||||
|
||||
New middleware `ApiKeyAuth`:
|
||||
|
||||
- Read `Fdesk-Api-Key` header
|
||||
- Compare against key stored in `.env` (`API_KEY`) or `config/app.php`
|
||||
- Reject with 401 on mismatch or missing key
|
||||
- Bypass both `AuthCheck` (JWT) and `BasicData` middleware
|
||||
|
||||
## Endpoints
|
||||
|
||||
### A. PI Number List
|
||||
|
||||
```
|
||||
GET /common/public/pi/list
|
||||
Headers: Fdesk-Api-Key: <key>
|
||||
Query: page, page_size, pi_no (optional filter)
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"code": 200,
|
||||
"data": {
|
||||
"total": 150,
|
||||
"per_page": 20,
|
||||
"current_page": 1,
|
||||
"data": [
|
||||
{
|
||||
"pi_no": "PI20250601001",
|
||||
"vins": ["LSVAU2A39N2123456", "LSVAU2A39N2123457"],
|
||||
"model_names": ["Model Y", "Model 3"]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Logic:
|
||||
1. Query `stock_orders` where `approval_status = 2` and `pi_no IS NOT NULL` and `pi_no != ''`
|
||||
2. Optional filter by `pi_no` (LIKE match)
|
||||
3. Paginate
|
||||
4. For each order, eager-load `items` → collect `vin` and `model_snapshot`
|
||||
5. Return aggregated result
|
||||
|
||||
### B. VIN Number List
|
||||
|
||||
```
|
||||
GET /common/public/vin/list
|
||||
Headers: Fdesk-Api-Key: <key>
|
||||
Query: page, page_size, vin (optional filter)
|
||||
```
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"status": "success",
|
||||
"code": 200,
|
||||
"data": {
|
||||
"total": 500,
|
||||
"per_page": 20,
|
||||
"current_page": 1,
|
||||
"data": [
|
||||
{
|
||||
"vin": "LSVAU2A39N2123456",
|
||||
"model_name": "Model Y"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Logic:
|
||||
1. Query `stock_order_items` via `stock_orders` where `approval_status = 2`
|
||||
2. Optional filter by `vin` (LIKE match)
|
||||
3. Paginate
|
||||
4. Return `vin` + `model_snapshot` per item
|
||||
|
||||
## File Changes
|
||||
|
||||
| Action | File | Description |
|
||||
|--------|------|-------------|
|
||||
| New | `app/middleware/ApiKeyAuth.php` | API Key auth middleware |
|
||||
| New | `app/common/controller/PublicApiController.php` | Two endpoints |
|
||||
| Modify | `config/route.php` | Add `/common/public/*` route group with ApiKeyAuth |
|
||||
|
||||
## Constraints
|
||||
|
||||
- Read-only, no write operations
|
||||
- Only `approval_status = 2` records
|
||||
- Pagination required (default page_size = 20)
|
||||
- No JWT / BasicData middleware for these routes
|
||||
Reference in New Issue
Block a user