跳至主要内容

OneWarehouse × OMS 串接 API

版本:v1.2(2026-07-20)— 契約更新:帳號僅置於 HTTP header,body 不再攜帶 account_no 狀態:7 支 endpoint 已全數實測通過(含冪等重送),正式開放 UAT


1. 連線資訊

項目
Base URLhttps://oms.licodes.net/example/onewarehouse/v1
Method一律 POST
Content-Typeapplication/json
帳號(HTTP header account-no)oms_example_wh01
shared_secret由 LifeCOM 窗口另行提供
warehouse_tpw_idOW_UAT_TPW(UAT 暫定值,正式對接時更換)

1.1 UAT tenant 對映與現成測試資料

以 header 帳號 oms_example_wh01 + body warehouse_tpw_id=OW_UAT_TPW 呼叫時,單據會由伺服器自動對映落到:

項目說明
倉別翔丰倉(warehouse_no=2)進出庫單據落此倉。payload 不需要也不能指定倉別,由 tenant 對映決定
賣場Upload 型測試賣場(markets_no=13)出庫訂單掛此賣場,不會觸發任何真實電商平台同步

現成測試資料(可直接用,不必從零建):

資料用途
測試 SKUUAT-SKU-001(效期 2027-12-31)已建檔且有庫存 100 pcs,可直接測 stock/query、outbound/create

也可以自建:用 product/sync 建自己的 SKU(建議前綴 UAT- 便於識別清理)→ inbound/create 進庫存 → 再測出庫。

⚠️ 這是 UAT 測試環境:資料會定期清理,請勿放正式資料;出庫單會走到「待轉倉」狀態為止,不會真實出貨。


2. 鑑權(每個請求都要)

2.1 HTTP Header(3 個,缺一即 401)

Header說明
account-no帳號。必須用連字號 account-no,不可用底線 account_no
timestampUnix 秒(10 位)。與伺服器時間差必須在 ±300 秒
sign簽章,計算方式見下

2.2 簽章計算

sign = HMAC-SHA256( <raw request body 字串> + <timestamp> , shared_secret )
  • body 與 timestamp 直接字串串接,中間無分隔符
  • 輸出 hex 小寫
  • body 必須與實際送出的 raw bytes 完全一致(注意 JSON 序列化差異)

範例(bash):

SECRET="<由 LifeCOM 窗口取得的 shared_secret>"
BODY='{"sku_ids":["SKU-001"]}'
TS=$(date +%s)
SIGN=$(printf '%s%s' "$BODY" "$TS" | openssl dgst -sha256 -hmac "$SECRET" -hex | sed 's/^.*= //')

curl -X POST "https://<host>/onewarehouse/v1/stock/query" \
-H "Content-Type: application/json" \
-H "account-no: oms_example_wh01" \
-H "timestamp: $TS" \
-H "sign: $SIGN" \
-d "$BODY"

範例(PHP):

$sign = hash_hmac('sha256', $rawBody . $timestamp, $secret);

2.3 tenant 識別(body 內)

除鑑權 header 外,inbound/createinbound/returnoutbound/createbody 必須帶:

欄位
warehouse_tpw_idOW_UAT_TPW

伺服器以 warehouse_tpw_id + 鑑權 header 中驗簽通過的帳號 解析對映到內部倉別/賣場;未對映 → PARAM_INVALID

帳號只需要放在 HTTP header(account-no)一個地方,body 不需要(也無法)攜帶帳號——伺服器一律以驗簽通過的 header 帳號為準。


3. 回應格式與狀態碼

統一回應封套:

{
"code": "LST-TPW-2000",
"trace_id": "uuid(每請求唯一,回報問題時請附上)",
"message": "success",
"success": true,
"data": { }
}
HTTPcode意義
200LST-TPW-2000成功
400LST-TPW-2001重複單(冪等:同單號重送)。非錯誤,代表原單已受理
400PARAM_INVALID參數缺漏/格式錯/tenant 未對映/庫存不足,詳見 message
401LST-TPW-4001鑑權失敗:缺 header / 簽章不符 / timestamp 超窗 / 帳號未註冊
503LST-TPW-5030整合功能未開通

4. API 一覽

#Endpoint功能冪等
F-1/product/sync商品主檔同步(upsert)同 sku_id 重呼=update
F-2/inbound/create進貨入庫單建立同 inbound_short_id 重送 → 2001
F-3/inbound/return退貨入庫單建立同單重送 → 2001
F-4/inbound/cancel進貨單批次取消(≤100)每筆回獨立狀態
F-5/outbound/create出庫(訂單)建立同 outbound_short_id 重送=回原單
F-6/outbound/cancel出庫單批次取消(≤100)每筆回獨立狀態
F-7/stock/query庫存批次查詢(建議 ≤1000)唯讀

5. 各 API 詳細

F-1 POST /product/sync — 商品主檔同步

必填:sku_idsku_namestorage_type(1=常溫 2=空調 3=冷凍 4=冷藏)

{
"sku_id": "SKU-001",
"sku_name": "測試商品001",
"length": 10, "width": 8, "height": 5, "weight": 200,
"storage_type": 1
}
  • sku_images(選填,URL 陣列):僅做格式驗證(array、最多 5 張),OMS 不儲存圖片內容——傳了也不會落地,商品圖請勿依賴此欄位。超過 5 張回 PARAM_INVALID
  • sku_id 重複呼叫為更新(無副作用)
  • 成功 data:{"success":true,"products_id":<內部id>}
  • ⚠️ 商品必須先經此 API 建立,後續進出庫的 sku_id 才查得到

F-2 POST /inbound/create — 進貨入庫

必填:inbound_short_idwarehouse_tpw_iddetails[](每筆:sku_id + expires[] 非空)

{
"inbound_short_id": "IN-20260717-001",
"warehouse_tpw_id": "OW_UAT_TPW",
"estimated_arrival_time": 1784448000000,
"details": [
{
"sku_id": "SKU-001",
"expires": [
{ "expire_date": "2027-12-31", "qty": 100 }
]
}
]
}
  • 數量放在 expires[].qty(每個效期一筆,qty 必須 >0);detail 層 qty 可不帶,若帶則必須等於該 detail 所有 expires qty 加總,不符回 PARAM_INVALID
  • estimated_arrival_time:毫秒 timestamp,可不帶
  • 成功 data:{"success":true,"stock_in_no":"si_...","stock_in_sn":"<你的inbound_short_id>","warehouse_no":"..."}
  • 冪等:同 inbound_short_id 重送 → 400 LST-TPW-2001

F-3 POST /inbound/return — 退貨入庫

必填:inbound_short_idoutbound_short_id(原出庫單號)、warehouse_tpw_iddetails[](結構同 F-2)

{
"inbound_short_id": "RET-20260717-001",
"outbound_short_id": "OUT-20260717-001",
"warehouse_tpw_id": "OW_UAT_TPW",
"details": [
{
"sku_id": "SKU-001",
"expires": [ { "expire_date": "2027-12-31", "qty": 5 } ]
}
]
}
  • outbound_short_id 關聯原出庫單;查無對應退貨單時仍受理(靜默略過關聯)
  • 冪等:同單重送 → 400 LST-TPW-2001

F-4 POST /inbound/cancel — 進貨批次取消

{ "inbound_short_ids": ["IN-20260717-001", "IN-20260717-002"] }
  • 上限 100 筆
  • data.results 每筆獨立回狀態,例:[{"stock_in_sn":"IN-...","status":"not_found"}](查無單回 not_found,不視為整批失敗)

F-5 POST /outbound/create — 出庫(訂單)建立

必填:outbound_short_idwarehouse_tpw_idconsignee_country(目前僅支援 "TW")、logistics_typeexpress_typedetails[](每筆 sku_id + qty>0)

{
"outbound_short_id": "OUT-20260717-001",
"warehouse_tpw_id": "OW_UAT_TPW",
"consignee_name": "王小明",
"consignee_phone": "0912345678",
"consignee_address": "台北市信義區信義路五段7號",
"consignee_country": "TW",
"consignee_zip": "110",
"logistics_type": "home",
"express_type": "tcat",
"details": [ { "sku_id": "SKU-001", "qty": 2 } ]
}
  • 物流對照(logistics_type::express_type),目前支援:
logistics_typeexpress_type說明
hometcat宅配-黑貓
homehct宅配-新竹物流
homepost宅配-郵局
csvspcsc超商-7-11
csvsfamily超商-全家
csvshilife超商-萊爾富
  • 查無對照 → PARAM_INVALID unknown ship_method mapping
  • 庫存檢查:qty 超過可售量 → PARAM_INVALID sku X available=N < requested=M
  • consignee_country 非 TW → PARAM_INVALID
  • 成功 data:{"success":true,"orders_id":"ow_<outbound_short_id>_xxxx","idempotent":false}
  • 冪等:同 outbound_short_id 重送 → 200 且 idempotent:true(回原單,不重建)

F-6 POST /outbound/cancel — 出庫批次取消

{ "outbound_short_ids": ["OUT-20260717-001"] }
  • 上限 100 筆;data.results 每筆獨立狀態(查無回 not_found)
  • 已進倉/揀貨後不可取消:該筆回 status:"cannot_cancel_after_picking" + code:"LST-TPW-6001"(HTTP 仍 200,批次其他筆不受影響)

F-7 POST /stock/query — 庫存批次查詢

{ "sku_ids": ["SKU-001", "SKU-002"] }
  • 建議單次 ≤1000;空陣列 → PARAM_INVALID
  • 回應 data:
{
"stock_details": [
{
"sku_id": "SKU-001",
"status": "ok",
"stock_type": "good",
"batch_id": "",
"expire_date": "2027-12-31",
"qty": 100,
"qty_lock": 0,
"qty_available": 100
},
{ "sku_id": "SKU-002", "status": "not_found", "qty": 0, "qty_lock": 0, "qty_available": 0 }
]
}
  • stock_type:good=良品 / bad=不良品;qty=在庫量、qty_lock=已配鎖定量、qty_available=可售量
  • 已建檔但目前無庫存的 sku:回 status:"ok" 且 qty/qty_available=0(與 not_found 區分:not_found=商品未建檔)
  • 查無 sku 每筆回 status:"not_found"(200,不報錯)

6. 建議測試順序(資料相依)

1. product/sync 建商品(沒建商品,後面全部 sku_id not found)
2. inbound/create 進貨建庫存
3. stock/query 確認庫存入帳
4. outbound/create 出庫(需有可售量)
5. inbound/return 退貨(引用步驟4的 outbound_short_id)
6. inbound/cancel / outbound/cancel 取消流程
7. 冪等驗證 同單號重送,F-2/F-3 應回 2001、F-5 應回 idempotent:true

7. 常見錯誤速查

現象原因處理
一律 401header 用了底線 account_no改連字號 account-no
401timestamp 超出 ±300s校時,用當下 Unix 秒
401sign 不符確認 body 原始字串+timestamp 直接串接、hex 小寫、secret 正確
PARAM_INVALID unknown tenantbody 的 warehouse_tpw_id 錯或 header 帳號未註冊body 用 OW_UAT_TPW,header 用 oms_example_wh01
PARAM_INVALID sku_id not found商品未同步先呼 product/sync
PARAM_INVALID available < requested可售量不足先 inbound/create 建庫存
400 LST-TPW-2001同單號重送(冪等)非錯誤;原單已受理,換新單號即可
503 LST-TPW-5030功能未開通聯繫 OMS 端確認環境設定

回報問題時請附:呼叫的 endpoint、完整 request(header+body)、回應內容、trace_id


8. 注意事項

  • UAT 期間 warehouse_tpw_id=OW_UAT_TPW 為暫定值,正式對接時由雙方確認真實值後更換,屆時本文件同步改版
  • outbound_short_id / inbound_short_id 請保證全域唯一(它們直接作為 OMS 內部單號與冪等鍵)
  • 出庫單建立成功後由 OMS 既有排程推送 WMS,實際出貨狀態回拋(webhook callback)屬後續階段,UAT 範圍先以 API 受理成功為準