# 第三方系統 API 對接手冊 Star ERP 系統提供外部整合 API (Integration API) 供電商前台、POS 機或其他第三方系統串接。 所有的整合 API 均受到 Laravel Sanctum Token 與多租戶 (Multi-tenant) Middleware 保護。 ## 基礎連線資訊 - **API Base URL**: `https://[租戶網域]/api/v1/integration` (依實際部署網址為準,單機開發為 `http://localhost/api/v1/integration`) - **Headers 要求**: - `Accept: application/json` - `Content-Type: application/json` - `Authorization: Bearer {YOUR_API_TOKEN}` (由 ERP 系統管理員核發的 Sanctum Token) - **速率限制**:每位使用者每分鐘最多 60 次請求。超過時會回傳 `429 Too Many Requests`。 --- ## 1. 產品資料同步 (Upsert Product) 此 API 用於將第三方系統(如 POS)的產品資料單向同步至 ERP。採用 Upsert 邏輯:若 `external_pos_id` 存在則更新資料,不存在則新增產品。 - **Endpoint**: `/products/upsert` - **Method**: `POST` ### Request Body (JSON) | 欄位名稱 | 類型 | 必填 | 說明 | | :--- | :--- | :---: | :--- | | `external_pos_id` | String | **是** | 在 POS 系統中的唯一商品 ID (Primary Key) | | `name` | String | **是** | 商品名稱 (最大 255 字元) | | `price` | Decimal | 否 | 商品售價 (預設 0) | | `barcode` | String | 否 | 商品條碼 (最大 100 字元) | | `category` | String | 否 | 商品分類名稱。若系統中不存在,會自動建立 (最大 100 字元) | | `unit` | String | 否 | 商品單位 (例如:個、杯、件)。若不存在會自動建立 (最大 100 字元) | | `brand` | String | 否 | 商品品牌名稱 (最大 100 字元) | | `specification` | String | 否 | 商品規格描述 (最大 255 字元) | | `cost_price` | Decimal | 否 | 成本價 (預設 0) | | `member_price` | Decimal | 否 | 會員價 (預設 0) | | `wholesale_price` | Decimal | 否 | 批發價 (預設 0) | | `is_active` | Boolean| 否 | 是否上架/啟用 (預設 true) | | `updated_at` | String | 否 | POS 端的最後更新時間 (格式: YYYY-MM-DD HH:mm:ss) | **請求範例:** ```json { "external_pos_id": "POS-PROD-9001", "name": "特級冷壓初榨橄欖油 500ml", "price": 380.00, "barcode": "4711234567890", "category": "調味料", "unit": "瓶", "brand": "健康王", "specification": "500ml / 玻璃瓶裝", "cost_price": 250.00, "member_price": 350.00, "wholesale_price": 300.00, "is_active": true, "updated_at": "2024-03-15 14:30:00" } ``` ### Response **Success (HTTP 200)** ```json { "message": "Product synced successfully", "data": { "id": 15, "external_pos_id": "POS-ITEM-001" } } ``` --- ## 2. 訂單資料寫入與扣庫 (Create Order) 此 API 用於讓第三方系統(如 POS 結帳後)將「已成交」的訂單推送到 ERP。 **重要提醒**:寫入訂單的同時,ERP 會自動且**強制**扣除對應倉庫的庫存(允許扣至負數,以利後續盤點或補單)。 - **Endpoint**: `/orders` - **Method**: `POST` ### Request Body (JSON) | 欄位名稱 | 型態 | 必填 | 說明 | | :--- | :--- | :---: | :--- | | `external_order_id` | String | **是** | 第三方系統中的唯一訂單編號,不可重複 (Unique) | | `warehouse_id` | Integer | 否 | 指定出貨倉庫的系統 ID (若已知) | | `warehouse` | String | 否 | 指定出貨倉庫名稱。若 `warehouse_id` 與此欄皆未傳,系統將預設寫入並建立「銷售倉庫」 | | `payment_method` | String | 否 | 付款方式,僅接受:`cash`, `credit_card`, `line_pay`, `ecpay`, `transfer`, `other`。預設為 `cash` | | `sold_at` | String(Date) | 否 | 交易發生時間,預設為當下時間 (格式: YYYY-MM-DD HH:mm:ss) | | `items` | Array | **是** | 訂單明細陣列,至少需包含一筆商品 | #### `items` 陣列欄位說明: | 欄位名稱 | 型態 | 必填 | 說明 | | :--- | :--- | :---: | :--- | | `pos_product_id` | String | **是** | 對應產品的 `external_pos_id`。**注意:商品必須先透過產品同步 API 建立至 ERP 中。** | | `qty` | Number | **是** | 銷售數量 (必須 > 0) | | `price` | Number | **是** | 銷售單價 | **請求範例:** ```json { "external_order_id": "ORD-20231026-0001", "warehouse": "台北大安門市", "payment_method": "credit_card", "sold_at": "2023-10-26 14:30:00", "items": [ { "pos_product_id": "POS-ITEM-001", "qty": 2, "price": 450 }, { "pos_product_id": "POS-ITEM-005", "qty": 1, "price": 120 } ] } ``` ### Response **Success (HTTP 201)** ```json { "message": "Order synced and stock deducted successfully", "order_id": 42 } ``` **Error: Product Not Found (HTTP 400)** 若 `items` 內傳入了未曾同步過的 `pos_product_id`,會導致寫入失敗。 ```json { "message": "Sync failed: Product not found for POS ID: POS-ITEM-999. Please sync product first." } ``` #### 錯誤回應 (HTTP 422 Unprocessable Entity - 驗證失敗) 當傳入資料格式有誤、商品編號不存在,或是該訂單正在處理中被系統鎖定時返回。 - **`message`** (字串): 錯誤摘要。 - **`errors`** (物件): 具體的錯誤明細列表,能一次性回報多個商品不存在或其它欄位錯誤。 ```json { "message": "Validation failed", "errors": { "items": [ "The following products are not found: POS-999, POS-888. Please sync products first." ], "external_order_id": [ "The order ORD-01 is currently being processed by another transaction. Please try again later." ] } } ``` #### 錯誤回應 (HTTP 500 Internal Server Error - 伺服器異常) 當系統發生預期外的錯誤(如資料庫連線失敗)時返回。 ```json { "message": "Sync failed: An unexpected error occurred." } ``` --- ## 幂等性說明 (Idempotency) 訂單 API 支援幂等性處理:若傳入已存在的 `external_order_id`,系統不會報錯,而是回傳該訂單的資訊: ```json { "message": "Order already exists", "order_id": 42 } ``` 這讓第三方系統在網路問題導致重送時,不會產生重複訂單或重複扣庫。 --- ## 常見問題與除錯 (FAQ) 1. **收到 `401 Unauthorized` 錯誤?** - 請檢查請求標頭 (Header) 是否有正確攜帶 `Authorization: Bearer {Token}`。 - 確認該 Token 尚未過期或被撤銷。 2. **收到 `422 Unprocessable Entity` 錯誤?** - 代表傳送的 JSON 欄位不符合格式要求,例如必填欄位遺漏、數量為負數、或 `payment_method` 不在允許的值中。Laravel 會在回應的 `errors` 物件中詳細說明哪個欄位驗證失敗。 3. **收到 `429 Too Many Requests` 錯誤?** - 代表已超過速率限制(每分鐘 60 次),請稍後再試。 4. **庫存扣除邏輯** - POS 訂單寫入視為「已發生之事實」,系統會無條件扣除庫存。若該產品在指定倉庫原先庫存為 0,訂單寫入後庫存將變為負數,提醒門市人員需進行調撥補貨。