整合指南
一次成功的結帳:拿到 orderId 與 checkoutUrl,付款後訂單變成 paid。
App 金鑰或 Bearer可由後端帶 App 金鑰呼叫,或由終端用戶帶 access token 呼叫。
GET /v1/pay/orders/{id} 的 status 變成 paid,且 items 帶回你買的商品。
本篇大綱(9 節)
這篇會帶你做到什麼
一條最短的收款路線:建立商品 → 查價格 → 結帳 → 付款 → 看訂單變成 paid。 先用 stub(本機測試用的假金流)通道跑完,不需要任何真實金鑰、也不會真的扣款。
先打這 3 支就好
| 順序 | 端點 | 做什麼 |
|---|---|---|
| 1 | GET /v1/pay/prices | 前端顯示價格(不用自己寫定價邏輯) |
| 2 | POST /v1/pay/checkout | 建立訂單+收款意圖,回 checkoutUrl |
| 3 | GET /v1/pay/orders/{id} | 確認履約狀態(paid/shipped/fulfilled) |
另外兩支只在測試與退款時用:POST /v1/pay/hosted/{intentId}/stub-pay(假付款)、POST /v1/pay/intents/{id}/refund(退款)。
前置:兩個名詞
- 產品(product):你要賣的東西,在控制台建立,會有
productId。 - 價格(price):同一個產品可以有月付、年付等多個價格,各自有
lookupKey。
這兩個都在開發者控制台的金流服務裡建。文件站不幫你建商品。
第 1 步:看得到價格(5 分鐘)
curl -s "https://api.hsystem.halphastech.com/v1/pay/prices?keys=basic,pro" \
-H "Authorization: Bearer $HS_ACCESS_TOKEN"
回傳只會包含 active=true 的價格。前端拿到 amountCents、currency 就能直接顯示,不要在前端自己算金額。
需要憑證:終端用戶的 access_token(Bearer)或 App 金鑰都可以。
第 2 步:建立結帳(10 分鐘)
curl -s -X POST https://api.hsystem.halphastech.com/v1/pay/checkout \
-H "Authorization: Bearer $HS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"items": [{ "productId": "prd_demo", "quantity": 1 }],
"providerId": "stub",
"region": "TW"
}'
成功的回應長這樣(重點欄位):
{
"orderId": "ord_demo_123",
"intentId": "pi_demo_123",
"status": "requires_payment",
"provider": "stub",
"amountCents": 12000,
"currency": "TWD",
"checkoutUrl": "https://pay.example.test/checkout/pi_demo_123"
}
下一步只有一個動作:把使用者導去 checkoutUrl。付款流程、信用卡表單、3D 驗證都由那一頁負責,你的前端不需要碰卡號。
providerId 不帶也可以(會走控制台設定的預設帳號);測試階段請明確帶 "stub",避免不小心接到真的金流。
第 3 步:把測試付款完成(5 分鐘)
stub 通道的意圖可以用公開端點直接標記付款成功:
curl -s -X POST https://api.hsystem.halphastech.com/v1/pay/hosted/pi_demo_123/stub-pay
這支不需要任何憑證,而且只對 stub 通道有效;其他通道一律 404,所以它不可能變成繞過金流的後門。正式環境請把這段從程式裡拿掉。
第 4 步:確認結果
curl -s https://api.hsystem.halphastech.com/v1/pay/orders/ord_demo_123 \
-H "Authorization: Bearer $HS_ACCESS_TOKEN"
看到 "status": "paid" 就代表整條路通了。之後出貨可以 PATCH /v1/pay/orders/{id} 改成 shipped(帶 trackingNo),履約完成改 fulfilled。
上線前必須做的三件事
- 接 webhook:付款成功是
pay.intent.succeeded,退款是pay.intent.partially_refunded。不要只靠前端輪詢當作「已付款」的依據。 - 冪等:重複送出結帳時帶
Idempotency-Key,避免使用者連點產生兩張訂單。 - 退款:
POST /v1/pay/intents/{id}/refund,amountCents省略就是退掉剩下的可退餘額;多次部分退款會累計。需要 App 金鑰。
常見錯誤
providerId打錯:stub只在測試環境存在;正式環境要先在控制台把金流通道的金鑰填好,否則checkout會回缺少金鑰的錯誤。- 前端自己算金額:一律用
prices回傳的amountCents,避免與後台定價不一致。 - 把 App 金鑰放前端:
checkout可以用終端用戶 token;只有退款、改訂單這類管理動作才需要 App 金鑰。 - 只做前端導轉、沒接 webhook:使用者關掉分頁就收不到結果,訂單狀態會永遠停在
requires_payment。
這篇用到的接口
參數、回應與錯誤碼看文件;想先看回應長什麼樣,直接開 Playground 的模擬模式。

