Files
star-erp/resources/markdown/manual/api-integration.md
sky121113 904132e460
All checks were successful
Koori-ERP-Deploy-System / deploy-demo (push) Has been skipped
Koori-ERP-Deploy-System / deploy-production (push) Successful in 1m14s
feat(integration): 擴充產品同步 API 欄位與驗證強化
1. ProductSync API 新增防護機制,為既有欄位加上字串長度與金額上限限制
2. 開放並接收 ERP Product Model 實用欄位(品牌、規格、成本價、會員價、批發價)
3. 更新 ProductService 寫入邏輯以支援新增的可選欄位
4. 同步更新 api-integration.md 手冊,加入新欄位說明與 JSON 範例
2026-02-23 11:02:25 +08:00

174 lines
6.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 第三方系統 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."
}
```
---
## 幂等性說明 (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訂單寫入後庫存將變為負數提醒門市人員需進行調撥補貨。