2.102 · 星益欣 POS 權益操作、自動扣點、票券查詢
commit 與 release 以 holdId 本身為冪等鍵,
不需要 Idempotency-Key;重送會回放原本的結果。
| 情境 | 怎麼做 | 預期 |
|---|---|---|
| 快樂路徑 | 查會員 → 加點數 → 預扣 → 核銷 | 回 committed;重查一次餘額真的少了 |
| 顧客放棄 | 預扣 → 改按 release | 回 released;額度立刻回來 |
| 什麼都不做 | 預扣後放著 5 分鐘 → 核銷 | HOLD_EXPIRED;額度自己恢復 |
| 重複核銷 | 核銷成功後,同一個 holdId 再送一次 | 回放同一份結果,不會扣第二次 |
| 冪等鍵 | 同一把 Idempotency-Key 連送兩次預扣 | 回同一張預扣單,不會鎖兩次額度 |
| 同鍵不同內容 | 用同一把鍵,但改掉金額再送 | IDEMPOTENCY_KEY_CONFLICT |
| 三種混折 | 點數 + 票券 + 寄杯序號一起預扣 → 核銷 | 三種都動到;寄杯回應會按堂票分組並帶「有價/無價」 |
| 全有全無 | 一張正常的券 + 一張已使用的券,一起預扣 | 整包回絕,連正常那張也沒被鎖;逐筆原因在畫面上 |
| 搶單 | 同一張券,用兩把不同的鍵各預扣一次 | 第二次被擋,原因 HELD |
| 拿錯碼 | 把查詢結果的 discountCode 當票券碼預扣 |
NOT_FOUND —— 折扣碼不唯一,不能拿來核銷 |
| 餘額不足 | 預扣一個大於餘額的點數 | 整包回絕,訊息會講出「其中 N 點正在門市結帳中」 |
預扣只活 5 分鐘。逾時自動失效、額度恢復,不需要清理動作。
核銷一律用 code,不可用折扣碼。
票券用「票券唯一碼」、寄杯用「序號」。discountCode 不唯一
(同一張券發給 500 人就有 500 張共用同一個),只供 POS 對應自己的優惠規則 ——
拿它來預扣會回 NOT_FOUND。
一個序號 = 一堂。要折兩杯就帶兩個序號。
commit 失敗 = 什麼都沒發生。 5 分鐘內重送同一個 holdId,或換新的 Idempotency-Key 重走 hold,兩者都安全。
唯一的例外:訊息裡出現
「點數已扣除」(COMMIT_IN_PROGRESS /
COMMIT_FAILED)。那是資料庫在提交瞬間故障才會出現的罕見狀況,點數真的扣掉了 ——
此時絕對不要重新結帳。
balanceAfter 與 shopPointKey 會是 null。
實際從哪幾個錢包扣了多少,要看回應的 details[] —— 那才是逐筆的事實。
| 情境 | 怎麼做 | 預期 |
|---|---|---|
| 基本扣點 | 填會員、金額、產生一把鍵 → 送出 | 回實際扣掉的金額與扣後餘額 |
| 冪等 | 原封不動再按一次送出 | 回應一模一樣,餘額不會再少 |
| 到期順序 | 會員有多個錢包時扣一筆大額 | details[] 依到期由近到遠扣;頂層 balanceAfter 會是 null |
| 餘額不足 | 扣一個大於總餘額的金額 | 失敗,而且一點都沒扣 |
| 與星益欣互不干擾 | 先在星益欣分頁預扣一筆點數(不要核銷),再回來自動扣點 | 可用餘額已經少掉被預扣的部分 —— 兩條路走的是同一份額度 |
| 情境 | 怎麼做 | 預期 |
|---|---|---|
| 看有哪些規則 | type 選 coupon → 列表 |
回這家店的使用券規則 |
| 類型篩選 | 切 exchange 再查一次,再切 all |
三種結果的筆數不同;all 最多 |
| 名稱模糊查詢 | name 填一個片段(不用完整名稱) | 只回名稱含該片段的 |
| 筆數對照 | 同樣條件下分別按 count 與列表 | 列表撈滿 limit 時,count 才看得出真正的總數 |
| 翻頁 | limit 設 5,start 改成 0 / 5 / 10 | 每次回不同的五筆,不重複 |
| 查單筆 | 列表按「複製 ID」→ 切 findOne → 送出 | 多出使用須知、兌換連結、所屬店家等列表沒有的欄位 |
| 查不存在的 | findOne 填一個隨便的 UUID | 查無,而不是 500 |