Xác thực
InfraIO Pay có hai surface API với mô hình auth khác nhau. Chọn cái khớp với người gọi:
| Surface | Path prefix | Đối tượng | Auth |
|---|---|---|---|
| B2B Merchant | /b2b/v1/* | Server của bạn | Ký request HMAC-SHA256 |
| Dashboard | Dùng bởi dashboard merchant | Session trình duyệt cho dashboard merchant | Bearer JWT |
Trang này cover surface B2B, cái bạn gọi từ server với một cặp API key. Surface dashboard được dùng bởi dashboard merchant của InfraIO Pay và không phải là surface tích hợp công khai.
Luôn gửi path đầy đủ gồm prefix /b2b, và ký chính path đó (xem
bên dưới).
Endpoints
| Môi trường | Base URL |
|---|---|
| Test | https://api-dev.infraio.xyz |
| Live | https://api.infraio.xyz |
Cùng một pattern URL — môi trường được điều khiển bởi prefix của
key (pk_test_… vs pk_live_…), không phải URL.
Cặp key
Bạn nhận được hai giá trị từ merchant dashboard (Developers → API keys → + Add key):
- Publishable key (
pk_test_…hoặcpk_live_…) — nhận diện tài khoản của bạn. Gửi dưới dạngX-Client-ID. An toàn để nhúng trong bundle trình duyệt của bạn (SDK đã làm điều này). - Secret key (
sk_test_…hoặcsk_live_…) — khóa ký HMAC. Chỉ phía server. Đối xử với nó như password database.
Nếu một secret key bao giờ lọt vào bundle trình duyệt, git repo, dòng log, hay chat chia sẻ — revoke ngay lập tức từ dashboard. Revoke có hiệu lực tức thời, không có cửa sổ overlap. Phát hành key mới và redeploy.
Ký một request
Mọi lệnh gọi đến /b2b/v1/* mang ba header:
X-Client-ID: pk_live_70d0becbd7a53047b0dfe88a960d10ad
X-Timestamp: 1715990400
X-Signature: 9a8b7c6d… (hex HMAC-SHA256)Chữ ký được tính trên một chuỗi canonical:
METHOD + "\n" + PATH + "\n" + TIMESTAMP + "\n" + BODYMETHOD— HTTP verb viết hoa (POST,GET, …).PATH— path của request kèm prefix/b2b, không có host và không có query string (ví dụ/b2b/v1/checkout-sessions/quick). Prefix phải có mặt. Query parameter không được ký — vớiGET …?cursor=…&limit=20, chỉ ký path, không phải phần?….TIMESTAMP— unix seconds, dưới dạng chuỗi decimal (ví dụ"1715990400"), khớp chính xác vớiX-Timestamp.BODY— raw bytes của body request. Chuỗi rỗng choGET/DELETE.
Ký bằng HMAC-SHA256 với khóa secret, xuất hex:
Node / TS
import { createHmac } from "node:crypto";
function sign({ method, path, body, secret }: {
method: string; path: string; body: string; secret: string;
}) {
const timestamp = Math.floor(Date.now() / 1000).toString();
const input = [method.toUpperCase(), path, timestamp, body].join("\n");
const signature = createHmac("sha256", secret).update(input).digest("hex");
return { timestamp, signature };
}Vì sao HMAC, không Bearer?
Một API Bearer-token thuần ship secret duy nhất qua dây trên mọi request. Bất kỳ ai bắt được một log của proxy TLS-terminated đều có chìa khóa tài khoản của bạn. Ký HMAC nghĩa là secret không bao giờ di chuyển — chỉ chữ ký được dẫn xuất, là single-use (gắn vào đúng request đó + đúng phút đó).
Đánh đổi: bạn phải tính chữ ký cho mỗi lệnh gọi. Hiện chưa có SDK server, nhưng helper ở trên chỉ khoảng 15 dòng theo từng ngôn ngữ.
Tolerance timestamp
Tolerance là ±5 phút (300 giây). Một request nằm ngoài cửa sổ
đó sẽ bị từ chối với 401 invalid_signature. Hai hệ quả:
- Đồng bộ đồng hồ server với NTP. Một cron chạy dài hạn với đồng hồ trôi sẽ fail không đều.
- Đừng pre-compute và xếp hàng đợi chữ ký. Nếu một request nằm trong queue retry >5 phút, chữ ký của nó hết hạn.
Scope của key
Secret key mang một hoặc nhiều bundle scope sau:
| Scope | Use case dự kiến |
|---|---|
read | List/đọc orders, sessions, refunds |
write_order | Tạo checkout sessions, orders |
write_refund | Phát hành refund, mint token refund-request |
webhook_manage | Tạo/cập nhật/xóa webhook endpoint |
Dashboard phát hành key “full access” mặc định (cả bốn scope). Bạn có thể phát hành key scope hạn chế từ Developers → API keys → + Add key và chỉ tick các scope mà tích hợp cần.
Scope chưa được enforce. Scope được ghi trên key và hiển thị
trong dashboard, nhưng bất kỳ key sk_… hợp lệ nào đều có thể gọi
mọi endpoint /b2b/v1/* cho merchant của bạn. Đừng dựa vào scope
như ranh giới bảo mật. Rotate hoặc revoke key để hạn chế truy cập.
Xác thực thất bại
Nếu chữ ký, X-Client-ID, hoặc timestamp không hợp lệ, request bị từ
chối với 401 INVALID_SIGNATURE trước khi đến API. Chỉ các request
/b2b/v1/* được ký theo cách này. Webhook dùng một scheme riêng (xem
bên dưới).
Tiếp theo
- Lỗi — hình dáng response trên 4xx/5xx.
- Bảo mật → API keys — rotate, revoke, làm gì nếu secret bị lộ.
- Webhooks → Xác thực chữ ký
— dùng một scheme HMAC khác (header
X-Signature: sha256=…, kýX-Timestamp + "." + raw_body, cộng thêmX-Signature-Prevtùy chọn trong cửa sổ grace 24 giờ khi rotate). Đừng nhầm hai scheme — chúng dùng chung thuật toán hash nhưng bytes được ký và họ secret (whsec_…vssk_…) là khác nhau.