From 8f008ffb615e7535a0fbb4b31599978012dcea85 Mon Sep 17 00:00:00 2001 From: sky121113 Date: Mon, 13 Apr 2026 17:04:52 +0800 Subject: [PATCH] =?UTF-8?q?[FEAT]=20=E5=AF=A6=E4=BD=9C=20B014=20=E6=A9=9F?= =?UTF-8?q?=E5=8F=B0=E5=8F=83=E6=95=B8=E4=B8=8B=E8=BC=89=20API=20=E8=88=87?= =?UTF-8?q?=20B000=20=E7=99=BB=E5=85=A5=E8=AA=8D=E8=AD=89=E5=BC=B7?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 1. 強化 B000 登入接口:驗證成功後回傳 Sanctum Token 供後續初始化使用。 2. 實作 B014 (getSettings) API:整合機台、金流與發票設定,並映射至 Android App 預期欄位。 3. 強化安全性:B014 API 掛載 auth:sanctum 並執行 RBAC 權限檢查。 4. 更新 API 說明文件 (iot-spec.md, api-docs.php) 及技術規範 (SKILL.md)。 --- .agents/skills/api-technical-specs/SKILL.md | 46 +++++++- .../Api/V1/App/MachineAuthController.php | 3 +- .../Api/V1/App/MachineController.php | 82 +++++++++++++ config/api-docs.php | 109 ++++++++++++++++++ docs/api/iot-spec.md | 61 ++++++++++ routes/api.php | 3 + 6 files changed, 301 insertions(+), 3 deletions(-) diff --git a/.agents/skills/api-technical-specs/SKILL.md b/.agents/skills/api-technical-specs/SKILL.md index e0e2738..a920ef0 100644 --- a/.agents/skills/api-technical-specs/SKILL.md +++ b/.agents/skills/api-technical-specs/SKILL.md @@ -12,8 +12,18 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 - **類型嚴格**:文件定義的類型 (Integer, Float, String) 必須在後端 Model 與前端文件中心嚴格遵守。 ## 2. 身份認證 (Authentication) -- **Bearer Token**:所有 API 必須在 Header 帶入 Authorization: Bearer 。 -- **身分綁定**:後端透過 Token 自動識別 machine_id,禁止在 Body 帶入 machine 或 key 欄位。 +本系統採用兩階段認證模式: + +### 2.1 維運人員認證 (User Authentication) +- **核發端點**:B000 (登入)。 +- **使用端點**:B014 (參數下載)。 +- **方式**:使用 Laravel Sanctum 核發之 **User Token**。 +- **Header**:`Authorization: Bearer `。 + +### 2.2 機台通訊認證 (Machine Authentication) +- **適用 API**:B010, B012, B013, B600 等後續通訊。 +- **方式**:使用機台專屬之 **api_token**。 +- **Header**:`Authorization: Bearer `。 --- @@ -40,6 +50,7 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 | 參數 | 類型 | 說明 | 範例 | | :--- | :--- | :--- | :--- | | message | String | 驗證結果 (Success 或 Failed) | Success | +| token | String | **臨時身份認證 Token** (用於 B014) | 1|abcdefg... | --- @@ -216,3 +227,34 @@ description: 本技能規範定義了 Star Cloud 系統中所有機台 (IoT) 與 | **0415** | Pickup door error | error | 取貨門異常 | | **5402** | Pickup door not closed | warning | **取貨門未關** (警告) | | **5403** | Elevator failure | error | 昇降系統故障 | + +--- + +### 3.7 B014: 機台參數與金鑰下載 (Config Download) +用於機台引導階段 (Provisioning),向雲端請求支付金鑰、發票設定及機台正式 API Token。 + +- **URL**: POST /api/v1/app/machine/setting/B014 +- **Authentication**: **User Token** (Sanctum Header) +- **Request Body:** + +| 參數 | 類型 | 必填 | 說明 | 範例 | +| :--- | :--- | :--- | :--- | :--- | +| machine | String | 是 | 機台編號 (serial_no) | M-001 | + +- **Response Body (Success 200):** + +| 欄位 (Key) | 說明 | 備註 | +| :--- | :--- | :--- | +| **t050v01** | 機台序號 | 即 machine_id | +| **api_token** | **機台正式 Token** | 初始化後應存於本地,後續 API 認證用 | +| **t050v41** | 玉山特店編號 | ESUN Merchant ID | +| **t050v42** | 玉山終端編號 | ESUN Terminal ID | +| **t050v43** | 玉山 Hash Key | ESUN Hash | +| **t050v34** | 發票特店 ID | Invoice Merchant ID | +| **t050v35** | 發票 Hash Key | Invoice Key | +| **t050v36** | 發票 Hash IV | Invoice IV | +| **TP_APP_ID** | 趨勢支付 AppID | TrendPay ID | +| **TP_APP_KEY** | 趨勢支付 Key | TrendPay Key | + +> [!CAUTION] +> **安全性規範**:B014 會回傳敏感金鑰與正式 Token,背景必須強制進行 RBAC 校驗。只有當前登入的人員具備該機台管理權限時,後端才允許發放資料。 diff --git a/app/Http/Controllers/Api/V1/App/MachineAuthController.php b/app/Http/Controllers/Api/V1/App/MachineAuthController.php index 8b38da9..26231fa 100644 --- a/app/Http/Controllers/Api/V1/App/MachineAuthController.php +++ b/app/Http/Controllers/Api/V1/App/MachineAuthController.php @@ -112,7 +112,8 @@ class MachineAuthController extends Controller ); return response()->json([ - 'message' => 'Success' + 'message' => 'Success', + 'token' => $user->createToken('technician-setup')->plainTextToken ]); } } diff --git a/app/Http/Controllers/Api/V1/App/MachineController.php b/app/Http/Controllers/Api/V1/App/MachineController.php index 6b20d0f..29ea080 100644 --- a/app/Http/Controllers/Api/V1/App/MachineController.php +++ b/app/Http/Controllers/Api/V1/App/MachineController.php @@ -456,4 +456,86 @@ class MachineController extends Controller 'message' => 'Error report accepted', ], 202); // 202 Accepted } + + /** + * B014: Download Machine Settings & Config (Synchronous, Requires User Auth) + * 用於機台引導階段,同步金流、發票與機台專屬 API Token。 + */ + public function getSettings(Request $request) + { + $serialNo = $request->input('machine'); + $user = $request->user(); + + // 1. 查找機台 (忽略全局範圍以進行認領) + $machine = Machine::withoutGlobalScopes() + ->with(['paymentConfig', 'company']) + ->where('serial_no', $serialNo) + ->first(); + + if (!$machine) { + return response()->json([ + 'success' => false, + 'code' => 404, + 'message' => 'Machine not found' + ], 404); + } + + // 2. 權限加強驗證 (RBAC) + $isAuthorized = false; + if ($user->isSystemAdmin()) { + $isAuthorized = true; + } elseif ($machine->company_id === $user->company_id) { + // 公司管理員或已授權員工才能存取 + if ($user->is_admin || $user->machines()->where('machine_id', $machine->id)->exists()) { + $isAuthorized = true; + } + } + + if (!$isAuthorized) { + return response()->json([ + 'success' => false, + 'code' => 403, + 'message' => 'Forbidden: You do not have permission to configure this machine' + ], 403); + } + + // 3. 獲取關聯設定 + $paymentSettings = $machine->paymentConfig->settings ?? []; + $companySettings = $machine->company->settings ?? []; + + // 4. 映射 App 預期欄位 (嚴格遵守 HttpAPI.java 結構) + $data = [ + 't050v01' => $machine->serial_no, + 'api_token' => $machine->api_token, // 向 App 核發正式通訊 Token + + // 玉山支付 + 't050v41' => $paymentSettings['esun_store_id'] ?? '', + 't050v42' => $paymentSettings['esun_term_id'] ?? '', + 't050v43' => $paymentSettings['esun_hash'] ?? '', + + // 電子發票 (綠界) + 't050v34' => $companySettings['invoice_merchant_id'] ?? '', + 't050v35' => $companySettings['invoice_hash_key'] ?? '', + 't050v36' => $companySettings['invoice_hash_iv'] ?? '', + 't050v38' => $companySettings['invoice_email'] ?? '', + + // 趨勢支付 (TrendPay/Greenpay) + 'TP_APP_ID' => $paymentSettings['tp_app_id'] ?? '', + 'TP_APP_KEY' => $paymentSettings['tp_app_key'] ?? '', + 'TP_PARTNER_KEY' => $paymentSettings['tp_partner_key'] ?? '', + + // 各類行動支付特店 ID + 'TP_LINE_MERCHANT_ID' => $paymentSettings['tp_line_merchant_id'] ?? '', + 'TP_PS_MERCHANT_ID' => $paymentSettings['tp_ps_merchant_id'] ?? '', + 'TP_EASY_MERCHANT_ID' => $paymentSettings['tp_easy_merchant_id'] ?? '', + 'TP_PI_MERCHANT_ID' => $paymentSettings['tp_pi_merchant_id'] ?? '', + 'TP_JKO_MERCHANT_ID' => $paymentSettings['tp_jko_merchant_id'] ?? '', + ]; + + return response()->json([ + 'success' => true, + 'code' => 200, + 'data' => [$data] // App 預期的是包含單一物件的陣列 + ]); + } } diff --git a/config/api-docs.php b/config/api-docs.php index 564dc41..98dae36 100644 --- a/config/api-docs.php +++ b/config/api-docs.php @@ -8,6 +8,115 @@ return [ [ 'name' => '機台核心通訊 (IoT Core)', 'apis' => [ + [ + 'name' => 'B000: 維運人員登入認證 (Technician Login)', + 'slug' => 'b000-tech-login', + 'method' => 'POST', + 'path' => '/api/v1/app/admin/login/B000', + 'description' => '機台啟動引導的第一步。維運人員輸入個人帳密與機台編號進行認證,成功後核發臨時 Sanctum Token 供後續 B014 下載敏感設定使用。', + 'headers' => [ + 'Content-Type' => 'application/json', + ], + 'parameters' => [ + 'username' => [ + 'type' => 'string', + 'required' => true, + 'description' => '維運人員帳號', + 'example' => 'admin_test' + ], + 'password' => [ + 'type' => 'string', + 'required' => true, + 'description' => '維運人員密碼', + 'example' => 'password123' + ], + 'machine' => [ + 'type' => 'string', + 'required' => true, + 'description' => '機台序號 (Serial No)', + 'example' => 'SN202604130001' + ], + ], + 'response_parameters' => [ + 'message' => [ + 'type' => 'string', + 'description' => '回應訊息', + 'example' => 'Success' + ], + 'token' => [ + 'type' => 'string', + 'description' => '臨時身份認證 Token (Sanctum)', + 'example' => '1|abcdefg...' + ], + ], + 'request' => [ + 'username' => 'admin_test', + 'password' => 'password123', + 'machine' => 'SN202604130001' + ], + 'response' => [ + 'message' => 'Success', + 'token' => '1|abcdefg...' + ], + ], + [ + 'name' => 'B014: 機台參數與金鑰下載 (Config Download)', + 'slug' => 'b014-config-download', + 'method' => 'POST', + 'path' => '/api/v1/app/machine/setting/B014', + 'description' => '機台引導階段的第二步。在人員登入後,透過此介面下載金流金鑰、電子發票設定與機台專屬通訊 Token。', + 'headers' => [ + 'Authorization' => 'Bearer ', + 'Content-Type' => 'application/json', + ], + 'parameters' => [ + 'machine' => [ + 'type' => 'string', + 'required' => true, + 'description' => '機台序號', + 'example' => 'SN202604130001' + ], + ], + 'response_parameters' => [ + 'success' => [ + 'type' => 'boolean', + 'description' => '是否成功', + 'example' => true + ], + 'data' => [ + 'type' => 'array', + 'description' => '配置物件陣列。包含:t050v01 (序號), api_token (通訊 Token), t050v41~43 (玉山設定), t050v34~38 (發票設定), TP_... (趨勢/手機支付設定)', + 'example' => [ + [ + 't050v01' => 'SN202604130001', + 'api_token' => 'mac_token_...', + 't050v41' => '80812345', + 't050v34' => '2000132', + 'TP_APP_ID' => 'GP_001' + ] + ] + ], + ], + 'request' => [ + 'machine' => 'SN202604130001' + ], + 'response' => [ + 'success' => true, + 'code' => 200, + 'data' => [ + [ + 't050v01' => 'SN202604130001', + 'api_token' => 'mac_token_...', + 't050v41' => '80812345', + 't050v42' => '9001', + 't050v43' => 'hash_key', + 't050v34' => '2000132', + 'TP_APP_ID' => 'GP_001' + ] + ] + ], + 'notes' => '此 API 受 auth:sanctum 保護,必須在 Header 帶上從 B000 取得的 Token。' + ], [ 'name' => 'B005: 廣告清單同步 (Ad Sync)', 'slug' => 'b005-ad-sync', diff --git a/docs/api/iot-spec.md b/docs/api/iot-spec.md index 544051f..3c3088e 100644 --- a/docs/api/iot-spec.md +++ b/docs/api/iot-spec.md @@ -4,6 +4,67 @@ --- +## 🔐 B000: 維運人員登入認證 (Technician Login) +機台引導階段 (Provisioning) 的第一步,用於核發臨時身份 Token 以便後續下載敏感設定。 + +### 1. API 資訊 +- **Endpoint**: `POST /api/v1/app/admin/login/B000` +- **認證方式**: 無 (需傳入 `username`, `password`, `machine`) +- **回應內容**: `token` (Sanctum Token) + +### 2. 回應範例 +```json +{ + "message": "Success", + "token": "3|abcdef1234567890..." +} +``` + +--- + +## 🔑 B014: 機台參數與金鑰下載 (Config Download) +下載機台運作所需的支付金鑰、電子發票設定與正式通訊 Token。 + +### 1. API 資訊 +- **Endpoint**: `POST /api/v1/app/machine/setting/B014` +- **認證方式**: **Bearer Token** (需帶上 B000 取得的 Token) +- **Header**: `Authorization: Bearer {token}` + +### 2. 請求參數 +- `machine`: 機台序號 (Serial No) + +### 3. 回應規格 (欄位映射) +| 欄位 | 說明 | 來源範例 | +| :--- | :--- | :--- | +| `t050v01` | 機台序號 | `SN2026041301` | +| `api_token` | **機台正式 Token** | 後續 B010/B600 認證用 | +| `t050v41` | 玉山特店編號 | `ESUN_STORE_ID` | +| `t050v43` | 玉山 Hash Key | `ESUN_HASH` | +| `t050v34` | 發票特店 ID | `INV_MID` | +| `TP_APP_ID` | 趨勢支付 AppID | `TP_APP_ID` | + +### 4. 回應範例 (JSON) +```json +{ + "success": true, + "code": 200, + "data": [ + { + "t050v01": "SN2026041301", + "api_token": "mac_token_...", + "t050v41": "8081234567", + "t050v42": "9001", + "t050v43": "password123", + "t050v34": "2000132", + "TP_APP_ID": "GREEN_001", + "...": "..." + } + ] +} +``` + +--- + ## 🟢 B010: 心跳上報與狀態同步 (Heartbeat & Status) 機台定時(建議每 5-10 秒)上送,用於確認連線狀態、溫度及門禁狀態。 diff --git a/routes/api.php b/routes/api.php index e066d5f..757a846 100644 --- a/routes/api.php +++ b/routes/api.php @@ -51,6 +51,9 @@ Route::prefix('v1')->middleware(['throttle:api'])->group(function () { // 機台管理員 B000 登入驗證 (由於此階段機台未帶 Token 無法通過 iot.auth) Route::prefix('app')->group(function () { Route::post('admin/login/B000', [\App\Http\Controllers\Api\V1\App\MachineAuthController::class, 'loginB000'])->middleware('throttle:30,1'); + + // 機台啟動引導與參數下載 (需人員登入 Token) + Route::middleware('auth:sanctum')->post('machine/setting/B014', [App\Http\Controllers\Api\V1\App\MachineController::class, 'getSettings']); }); Route::prefix('app')->middleware(['iot.auth', 'throttle:100,1'])->group(function () {