付款流程
當一張訂單有應收(outstandingTwd > 0),你向客人收款。收款是金流商無關的——流程一致,ECPay 等只是底層付款管道。
本篇說明收款的生命週期、redirect 與 webhook 怎麼運作,以及租戶如何設定自己的 ECPay。
收款的生命週期
一筆收款會經過三個階段,反映在訂單的 intents 與 transactions 上:
| 階段 | 是什麼 | 在訂單上 |
|---|---|---|
| 收款 intent | 「打算收的一筆錢」(還不是收到) | order.intents[] |
| 付款嘗試 | 一次實際付款(redirect / 手動) | — |
| 現金紀錄 | 真正收到 / 退出的現金——報表基準 | order.transactions[] |
注意
只有 transactions 是現金真相。intent 是「打算收」、嘗試是「進行中」,都不能當收款證明。intent 成功後即終態;下一筆收款(例如尾款、補款)會是一筆新的 intent。
Hosted redirect 流程
線上刷卡 / 轉帳最常見的是把客人導去金流商頁面付款:
- 付款結果以 webhook 為準(return URL 只是把客人導回)。
- webhook 經驗章與金額核對才認列;重送同一筆不會重複入帳(冪等)。
- 認列後訂單的
paymentState/outstandingTwd即時更新。
ATM 虛擬帳號(延遲付款)
ATM 轉帳是兩步:先取號、客人去繳費、入帳才算收到:
取號還沒有現金——拿到虛擬帳號只代表等待繳費。要等入帳 webhook 才會記一筆現金紀錄、才更新訂單狀態。
設定 ECPay(per-tenant)
ECPay 憑證是每個租戶各自設定的,不是平台共用:
- 租戶在後台付款設定填入自己的特店 ID、HashKey、HashIV(也可經 settings API)。
- HashKey / HashIV 加密保存,讀回只回遮罩值(write-only)。
- 上線後若未設定憑證,收款會被擋下(不會用平台預設)。
說明
重送同一筆付款時,ECPay 每次會用新的交易編號(重送同號會被 ECPay 退件)。你的整合不需要自己管這個——cairn 重建付款時會處理。
測試模式
開發 / 測試可切到 mock 付款,不實際打 ECPay:
| 設定 | 行為 |
|---|---|
付款商 = test | mock:直接把訂單標為已付,方便端到端測試 |
付款商 = ecpay + staging | 真打 ECPay sandbox |
付款商 = ecpay + production | 正式收款 |
請款、退款、出款(別混)
| 概念 | 方向 | API |
|---|---|---|
| 跟客人收款 | 收進來 | 訂單收款(上述流程) |
| 退客人錢 | 退出去 | /orders/{id}/refunds |
| 對供應商 / 嚮導 / 佣金出款 | 出去(非客戶退款) | payouts |
| 請款單核簽流程 | — | payment-requests |
退客人錢一律走訂單的退款流程(會反映在 refundState);對外付款走 payouts,兩者不混用。
下一步
- 訂單與金流模型:應收、現金、三軸狀態的全貌。
- 總覽:認證、權限、模組。
- payments API · payment-requests API。