Wixtar Member Transactions Composite
Description
Wixtar 全通路會員中介平台 - 複合式交易 API。提供外部系統結帳主入口,一次整合:交易紀錄寫入、累點(選填 bonus_points)、扣點(選填 redeem_points)及票券核銷(選填 vouchers)功能 (POST /v1/public/members/transactions/composite)。
業務與運算邏輯
- 單一交易處理鎖:同一會員同時間僅能有一筆交易/操作進行中。
- 選填項目執行判斷:
bonus_points:數值 > 0 才執行加點作業。
redeem_points:數值 > 0 才執行扣點作業。
vouchers:陣列非空時執行票券核銷。
- 品牌篩選 (brand_id):未帶或空字串時自動取
token_brand_id 帶入。
Resource
POST /v1/member/wixtar/transactions/composite
Authorization
採用 OAuth 2.0 Bearer Token(全通路 Token),並支援以下兩種 Wixtar 認證模式(兩者擇一提供):
* 模式 1 (裝置端自管 Token,推薦):於 Header 帶入 X-Member-Center-Token(由 Wixtar Member Token 取得),此時 X-Client-Id 與 X-Shop-Id 為選填。
* 模式 2 (後端代管 Token,向後相容):未帶入 X-Member-Center-Token 時,必須在 Header 提供 X-Client-Id 與 X-Shop-Id,全通路將自動依後台設定與 Redis 快取代管換發 Token。
認證模式二擇一:若提供 X-Member-Center-Token,則 X-Client-Id 與 X-Shop-Id 為選填;若未提供 X-Member-Center-Token,則 X-Client-Id 與 X-Shop-Id 為必填。
| Name |
Type |
Description |
| X-Member-Center-Token |
string |
(optional) 裝置端自管之 Wixtar Access Token (由 POST /v1/member/wixtar/token 取得)。若有提供則優先以此 Token 轉發 Wixtar |
| X-Client-Id |
string |
(optional/條件必填) POS 機或呼叫端設備代碼。若未提供 X-Member-Center-Token 則為必填 |
| X-Shop-Id |
string |
(optional/條件必填) 門市代碼。若未提供 X-Member-Center-Token 則為必填 |
Request Body Parameters
| Name |
Type |
Description |
| request_id |
string |
冪等識別碼 (UUID 格式) |
| sale_id |
string |
交易單號 (長度 1..40) |
| vip_id |
string |
會員編號 (長度 1..20) |
| sale_date |
string |
銷售日期時間 (YYYY-MM-DD HH:MM:SS) |
| tot_sales |
number |
銷售金額 (≥ 0) |
| tot_pcs |
number |
銷售數量 (≥ 0) |
| tot_tips |
number |
服務費 (≥ 0) |
| tot_extra |
number |
溢收額 (≥ 0) |
| tot_discharge |
number |
(optional) 尾數折讓金額 (折讓額 ≤ 0) |
| brand_id |
string |
(optional) 品牌編號 (未帶時自動取 token_brand_id 或集團範圍) |
| products |
Products[] |
(optional) 商品銷售明細清單 |
| tastes |
Tastes[] |
(optional) 商品加值銷售明細清單 |
| promotions |
Promotions[] |
(optional) 促銷銷售明細清單 |
| bonus_points |
integer |
(optional) 累積點數 (> 0 才執行加點) |
| redeem_points |
integer |
(optional) 扣除點數 (> 0 才執行扣點) |
| vouchers |
Vouchers[] |
(optional) 票券核銷清單 (陣列非空才執行核銷) |
| card_no |
string |
(optional) 會員卡號 |
| sale_desc |
string |
(optional) 交易摘要說明 |
| remark |
string |
(optional) 備註說明 |
Request Body Parameters - Products
| Name |
Type |
Description |
| item_no |
integer |
品項序號 |
| prod_id |
string |
商品編號 |
| prod_name |
string |
商品名稱 |
| dep_id |
string |
類別編號 |
| dep_name |
string |
類別名稱 |
| tot_pcs |
number |
銷售數量 (≥ 0) |
| tot_sales |
number |
銷售金額 (≥ 0) |
| tot_disc |
number |
(optional) 折扣金額 |
Request Body Parameters - Tastes
| Name |
Type |
Description |
| item_no |
integer |
品項序號 |
| taste_id |
integer |
加值類別代碼 |
| taste_name |
string |
加值類別名稱 |
| taste_item_no |
integer |
加值項目代碼 |
| taste_item_name |
string |
加值項目名稱 |
| tot_pcs |
number |
銷售數量 (≥ 0) |
| tot_sales |
number |
銷售金額 (≥ 0) |
Request Body Parameters - Promotions
| Name |
Type |
Description |
| prom_id |
string |
促銷活動編號 |
| prom_name |
string |
促銷活動名稱 |
| tot_pcs |
number |
促銷數量 (≥ 0) |
| tot_sales |
number |
促銷金額 (≥ 0) |
| tot_disc |
number |
(optional) 促銷折抵金額 |
| prom_scope |
string |
(必填) 促銷範圍:1=整單促銷;2=商品促銷 |
Request Body Parameters - Vouchers
| Name |
Type |
Description |
| tk_no |
string |
欲核銷之票券號碼 |
Request Example
{
"request_id": "550e8400-e29b-41d4-a716-446655440020",
"sale_id": "SALE20260601001",
"vip_id": "CM00000001",
"sale_date": "2026-06-01 12:00:00",
"tot_sales": 1000,
"tot_pcs": 2,
"tot_tips": 100,
"tot_extra": 0,
"bonus_points": 100
}
Response Body Parameters
| Name |
Type |
Description |
| status |
integer |
HTTP 狀態碼 (例如: 200) |
| code |
string |
業務回應代碼 (成功為 "000000") |
| message |
string |
回應訊息 (例如: "Success") |
| data |
Data |
主要業務資料內容 |
Response Body Parameters - Data
| Name |
Type |
Description |
| sale_id |
string |
交易單號 |
| vip_id |
string |
會員編號 |
| remaining_total_points |
integer |
交易後可用點數 |
| bonus_points |
integer |
實際累積點數 |
| redeem_points |
integer |
實際兌換點數 |
| vouchers |
Vouchers[] |
票券核銷/反核銷結果清單 |
Response Body Parameters - Vouchers
| Name |
Type |
Description |
| tk_no |
string |
票券號碼 |
| status |
string |
核銷後狀態(2=兌回) |
Response Example - Http Code = 200
{
"status": 200,
"code": "000000",
"message": "Success",
"data": {
"sale_id": "SALE20260624001",
"vip_id": "CM00000001",
"remaining_total_points": 385,
"bonus_points": 15,
"redeem_points": 0,
"vouchers": [
{
"tk_no": "TK00000001",
"status": "2"
}
]
}
}
Response Example 錯誤回應 - 400 Pydantic參數驗證(必填欄位缺漏)
{
"status": 200,
"code": "400",
"message": "缺少必填欄位:request_id(欄位代號:request_id);缺少必填欄位:sale_id(欄位代號:sale_id);缺少必填欄位:vip_id(欄位代號:vip_id);缺少必填欄位:sale_date(欄位代號:sale_date);缺少必填欄位:tot_sales(欄位代號:tot_sales);缺少必填欄位:tot_pcs(欄位代號:tot_pcs);缺少必填欄位:tot_tips(欄位代號:tot_tips);缺少必填欄位:tot_extra(欄位代號:tot_extra)",
"data": {
"errors_zh": [
"缺少必填欄位:request_id(欄位代號:request_id)",
"缺少必填欄位:sale_id(欄位代號:sale_id)",
"缺少必填欄位:vip_id(欄位代號:vip_id)",
"缺少必填欄位:sale_date(欄位代號:sale_date)",
"缺少必填欄位:tot_sales(欄位代號:tot_sales)",
"缺少必填欄位:tot_pcs(欄位代號:tot_pcs)",
"缺少必填欄位:tot_tips(欄位代號:tot_tips)",
"缺少必填欄位:tot_extra(欄位代號:tot_extra)"
],
"errors": [
{
"type": "missing",
"loc": [
"body",
"request_id"
],
"msg": "Field required",
"input": {}
},
{
"type": "missing",
"loc": [
"body",
"sale_id"
],
"msg": "Field required",
"input": {}
},
{
"type": "missing",
"loc": [
"body",
"vip_id"
],
"msg": "Field required",
"input": {}
},
{
"type": "missing",
"loc": [
"body",
"sale_date"
],
"msg": "Field required",
"input": {}
},
{
"type": "missing",
"loc": [
"body",
"tot_sales"
],
"msg": "Field required",
"input": {}
},
{
"type": "missing",
"loc": [
"body",
"tot_pcs"
],
"msg": "Field required",
"input": {}
},
{
"type": "missing",
"loc": [
"body",
"tot_tips"
],
"msg": "Field required",
"input": {}
},
{
"type": "missing",
"loc": [
"body",
"tot_extra"
],
"msg": "Field required",
"input": {}
}
]
}
}
Response Example 錯誤回應 - 4091 request_id重複但內容不一致
{
"status": 200,
"code": "4091",
"message": "request_id 重複但請求內容不一致"
}
Response Example 錯誤回應 - 400 request_id快取損毀
{
"status": 200,
"code": "400",
"message": "request_id 已完成但快取損毀,請確認後重試"
}
Response Example 錯誤回應 - 400 request_id處理中
{
"status": 200,
"code": "400",
"message": "相同 request_id 處理中,請稍後查詢"
}
Response Example 錯誤回應 - 404 查無對應會員
{
"status": 200,
"code": "404",
"message": "查無對應會員"
}
Response Example 錯誤回應 - 400 會員交易處理中
{
"status": 200,
"code": "400",
"message": "會員交易處理中,請稍後再試"
}
Response Example 錯誤回應 - 4092 交易單號已存在
{
"status": 200,
"code": "4092",
"message": "交易單號 SALE20260624001 已存在"
}
Response Example 錯誤回應 - 500 查詢票券失敗
{
"status": 200,
"code": "500",
"message": "查詢票券失敗"
}
Response Example 錯誤回應 - 400 票券不屬於此會員/品牌或查無此票券
{
"status": 200,
"code": "400",
"message": "票券不屬於此會員或查無此票券:TK00000099"
}
Response Example 錯誤回應 - 400 票券狀態不可核銷
{
"status": 200,
"code": "400",
"message": "票券狀態不可核銷:TK00000001"
}
Response Example 錯誤回應 - 400 票券已過期
{
"status": 200,
"code": "400",
"message": "票券已過期:TK00000001"
}
Response Example 錯誤回應 - 400 票券尚未到有效起日
{
"status": 200,
"code": "400",
"message": "票券尚未到有效起日:TK00000001"
}
Response Example 錯誤回應 - 400 交易寫入業務錯誤(動態訊息)
{
"status": 200,
"code": "400",
"message": "商品明細金額加總與 tot_sales 不符"
}
Response Example 錯誤回應 - 500 交易寫入失敗
{
"status": 200,
"code": "500",
"message": "交易寫入失敗"
}
Response Example 錯誤回應 - 500 查詢點數摘要失敗
{
"status": 200,
"code": "500",
"message": "查詢點數摘要失敗"
}