SCGA Pay · 收款核對 API · 資金直接入你嘅收款戶口,平台唔經手資金
API key 喺後台「API」分頁建立(只顯示一次);換屆時可以撤銷再建新嘅。
curl -X POST https://api.pay.scga.hk/api/v1/payments \
-H "Content-Type: application/json" \
-H "X-API-Key: hkpay_xxxxxxxx" \
-d '{
"amount_hkd": 200,
"method": "fps",
"reference": "BNI-KLN-2026-11-G37",
"description": "嘉賓登記費",
"expires_in_minutes": 1440
}'{
"payment_id": "7bf929192a673bc0",
"reference": "BNI-KLN-2026-11-G37",
"method": "fps",
"amount_hkd": 200,
"status": "pending",
"payment_code": "792826",
"pay_payload": {
"qr_data_url": "data:image/png;base64,iVBOR...",
"qr_text": "00020101021226320012hk.com.hkicl...",
"instructions": "請用銀行 App 掃描 QR 付款。金額 HK$200.00,付款備註請輸入 792826"
},
"payout": { "merchant_name": "SZE C** C*** G***", "fps_mobile": "****1111" }
}欄位:amount_hkd(必要,> 0)、method(both = FPS + PayMe 同時出,客人邊個通就用邊個;亦可指定 fps / payme)、reference(必要,你嘅單號,同一商戶內唯一)、description、expires_in_minutes、payout_account_id、payout(inline)。
⚠️ 每個收款身份都要填收款人全名(同銀行戶口一樣,例如 SZE CHI CHUNG GARY); 填遮罩(SZE C** C*** G***)或簡稱會被拒 —— 因為核對截圖時要靠個名對得上。
優先次序:inline payout(API 即時傳)→ payout_account_id(後台已存)→ 帳號預設。 每張單都會記錄當時用邊個收款身份(payout),換屆後查舊單仍然準確。
# 收款身份由 API 即時傳入(需後台開啟 allow_inline_payout)
curl -X POST https://api.pay.scga.hk/api/v1/payments \
-H "Content-Type: application/json" \
-H "X-API-Key: hkpay_xxxxxxxx" \
-d '{
"amount_hkd": 200,
"method": "fps",
"reference": "BNI-KLN-2027-G01",
"payout": { "fps_mobile": "+85291111111", "merchant_name": "CHAN T** M***" }
}'# 客戶付款後上載截圖(唔使 API key) curl -X POST https://api.pay.scga.hk/api/v1/payments/7bf929192a673bc0/proof \ -F "file=@receipt.jpg"
核對規則:
・金額必須相等・付款方式係 fps/payme/both 時必須對上 6 位付款碼
・收款人姓名:單上顯示嘅收款人(可以係銀行遮罩版,例如 SZE C** C*** G***、SZEC** C***、陳*文,或夾咗 (Wechat Gary) 別名)會同你設定嘅收款人全名比對;對唔上轉人手,線索太少(例如 ***)亦轉人手
・自己轉自己:如果單上「付款人」都係你(例如自己由一個戶口轉去另一個戶口),一律轉人手 —— 唔會當客人付款
・交易狀態「失敗/取消」→ 拒絕;「處理中/指示已提交」→ 唔會當已收款
・收款人姓名(mask 感知)唔對、截圖早過建單 24 小時、同金額撞單 → 轉人手覆核
・每張單最多上載 5 次
喺後台「Webhook」分頁填 https 網址,我哋會 POST JSON 去你嘅系統;唔使自己輪詢。
payment.paid 客人付款已確認(AI 自動或人手) payment.pending_review 已收到截圖但要人手覆核 payment.refunded 已記錄退款(可部分) payment.cancelled 商戶取消咗張單 payment.expired 過期未付款 ping 後台「送測試 ping」用
POST https://your-system.example.com/hkpay/webhook Content-Type: application/json X-HKPay-Event: payment.paid X-HKPay-Delivery: 8f3c... X-HKPay-Timestamp: 1793016296 X-HKPay-Signature: t=1793016296,v1=4f2c9a...
import crypto from "node:crypto";
// rawBody 一定要用「未 parse 嘅原始字串」
const [tPart, vPart] = req.headers["x-hkpay-signature"].split(",");
const ts = tPart.split("=")[1];
const sig = vPart.split("=")[1];
if (Math.abs(Date.now() / 1000 - Number(ts)) > 300) throw new Error("stale");
const expect = crypto
.createHmac("sha256", process.env.HKPAY_WEBHOOK_SECRET)
.update(ts + "." + rawBody)
.digest("hex");
if (!crypto.timingSafeEqual(Buffer.from(expect), Buffer.from(sig))) {
throw new Error("bad signature");
}失敗會自動重試(30 秒 → 2 分 → 10 分 → 1 小時 → 6 小時 → 24 小時 ×3);後台可以睇最近 20 次派送結果。
平台唔經手資金:退款只係記錄,實際退錢你要自己用銀行/PayMe 做。 已退款金額會由收款淨額扣除,所以唔會再收服務費;全額退嘅單狀態轉 refunded,部分退保持 paid 並累加 refunded_amount。
curl -X POST https://api.pay.scga.hk/api/v1/dashboard/payments/7bf929192a673bc0/refund \
-H "Authorization: Bearer <session-token>" -H "Content-Type: application/json" \
-d '{"amount_hkd": 50, "reason": "客人取消"}'| 項目 | 值 |
|---|---|
| 截圖 | 客人唔需要理大小:上載後系統自動縮到長邊 1600px、JPEG q82 才送核對(硬上限 10MB 只係防濫用,正常唔會撞到) |
| 每單上載次數 | 5 次,超過轉人手 |
| 人手覆核門檻 | HK$5,000(可設定);以下金額只要金額、付款碼、收款人姓名全對就自動確認 |
| 付款碼 | 6 位數字,同一商戶內不重複 |
| 截圖時效 | 早過建單 24 小時或遲過 7 日 → 人手 |
| 資料保留 | 截圖不長期保存;AI 抽取結果 180 日後清空 |
| Method | Path | 用途 | 認證 |
|---|---|---|---|
| POST | /api/v1/payments | 建立收款單(fps / payme) | API key |
| GET | /api/v1/payments/{id} | 查收款單狀態(客戶端用) | 開放 |
| POST | /api/v1/payments/{id}/proof | 上載付款截圖 → AI 核對 | 開放 |
| GET | /api/v1/payments/by-reference/{ref} | 用自己單號查 | API key |
| POST | /api/v1/payments/{id}/cancel | 取消未付款嘅單 | API key |
| GET | /api/v1/payout-accounts | 列出收款身份 | API key / 登入 |
| POST | /api/v1/payout-accounts | 新增收款身份 | API key / 登入 |
| PATCH | /api/v1/payout-accounts/{id} | 改收款身份(設預設/停用) | API key / 登入 |
| GET | /api/v1/reconciliation | 對賬(JSON,已扣退款) | API key |
| GET | /api/v1/reconciliation.csv | 對賬(CSV,開 Excel) | API key |
| POST | /api/v1/dashboard/payments/{id}/refund | 退款(可部分退,只記錄) | 登入 owner/admin |
| GET | /api/v1/dashboard/payments/{id}/refunds | 退款紀錄 | 登入 |
| POST | /api/v1/dashboard/payments/{id}/review | 人手確認/拒絕 | 登入 |
| GET/PATCH | /api/v1/dashboard/webhook | 讀/設 webhook URL | 登入 admin |
| POST | /api/v1/dashboard/webhook/test | 送測試 ping(附簽名) | 登入 admin |
| POST | /api/v1/dashboard/webhook/rotate | 換 webhook 簽名密鑰 | 登入 admin |
| GET | /api/v1/dashboard/invoices/{id}/pay | 月結服務費繳費 QR | 登入 |
| GET | /api/v1/version | 平台版本/啟用方法/門檻 | 開放 |
| GET | /openapi.json | OpenAPI 3.1 規格 | 開放 |
| POST | /api/v1/webhooks/{provider} | 支付機構回調(預留) | API key |
| GET | /health | 健康檢查 | 開放 |
| HTTP | 意思 |
|---|---|
| 400 | 參數錯(金額 ≤ 0、方法唔支援、已取消嘅單再取消) |
| 401 | 冇 X-API-Key,或者 key 無效 |
| 403 | 帳號停用,或者唔夠權限(例如 staff 想改收款身份) |
| 404 | 搵唔到收款單 |
| 409 | 用戶名重複(開戶/加成員) |
| 413 | 超過硬上限 10MB(自動縮圖後正常唔會撞到) |
| 415 | 圖片格式唔支援(只收 png/jpeg/webp/gif) |
| 422 | 業務驗證唔過(例如未設定收款身份、退款超過餘額) |
| 429 | 同一張單上載截圖次數過多(預設 5 次) |
錯誤回應格式:{ "detail": "說明" }