JavaScript / 瀏覽器 SDK
@lartech/infraio-checkout-js 是我們目前唯一發佈的 SDK。它在瀏覽器中
執行並開啟我們託管的結帳頁。後端 SDK(Node、Go、Python)在路線圖上;
在那之前,請直接呼叫 gateway — 參考 Quickstart
中的 HMAC 簽章輔助函式。
- 目前版本:
0.1.1-beta.17(pre-1.0;可能有 minor break) - 格式:ESM(
index.js)、CJS(index.cjs)、IIFE(index.global.js) - 內建型別(
index.d.ts) - 無 runtime peer 相依 — 不需要 React、jQuery 或其他套件
沒有伺服端入口。Webhook 簽章驗證輔助函式並未打包進來 — 請以
crypto 自行實作(簽章驗證頁面
有 4 種語言的可直接複製貼上的程式碼)。
安裝
npm
npm install @lartech/infraio-checkout-jsloadInfraIo(publicKey, options?)
回傳 Promise<InfraIoInstance>。
import { loadInfraIo } from "@lartech/infraio-checkout-js";
const sdk = await loadInfraIo("pk_live_yourkeyhere", {
// 選填。僅在指向非 production 環境時覆寫。
checkoutUrl: "https://checkout-dev.infraio.xyz",
});| 參數 | 型別 | 必填 | 說明 |
|---|---|---|---|
publicKey | string | ✓ | 必須符合 pk_(live|test)_… |
options.checkoutUrl | string | — | 覆寫結帳基礎 URL。預設:https://checkout.infraio.xyz。對應的 gateway URL 由結帳頁面在 runtime 自行判定 — 每個 checkout(-dev).infraio.xyz 部署都帶有其編譯期的 NEXT_PUBLIC_API_URL,所以這裡選對 hostname 就會自動選到對的後端。沒有獨立的 gatewayUrl 選項。 |
sdk.checkout({ … })
開啟託管結帳頁。回傳 void(以 callback 處理狀態)。
| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
sessionId | string | ✓ | POST /b2b/v1/checkout-sessions/quick 回傳的 session_key |
checkoutUrl | string | — | 同一 endpoint 回傳的完整 URL。若省略,SDK 會以 loadInfraIo() 的 checkoutUrl(或預設值)+ sessionId 組合 |
mode | "popup" | "redirect" | "embed" | — | 預設 "popup" |
container | string | HTMLElement | 僅 embed | iframe 要掛載到的 CSS 選擇器或 DOM 元素 |
width | number | — | 僅 popup。預設 560。範圍夾在 [320, 1280] |
height | number | — | 僅 popup。預設 780。範圍夾在 [400, 1000] |
timeoutMs | number | — | 僅 popup。Iframe 載入逾時。預設 30000。傳 0 可停用 |
locale | string | — | BCP-47 標籤,以 ?locale= 傳給結帳頁(en、ja、zh-CN、zh-TW) |
hideSummary | boolean | — | 隱藏訂單摘要欄。預設 false |
hideHeader | boolean | — | 隱藏 InfraIO header 與內建的錢包連線按鈕。預設 false。搭配 walletAddress 可達成完整白牌 |
walletAddress | string | — | 預先連接買家錢包。需要搭配 onSignRequest |
walletChainId | number | — | 預連接錢包的 EVM chain ID |
onReady | () => void | — | 當 iframe 變成可互動時觸發。僅 popup/embed |
onSignRequest | (req: { method: string; params: unknown[] }) => Promise<string> | 設定 walletAddress 時必填 | SDK 把錢包 RPC 代理給你的 handler;回傳已簽章的 hex |
onSuccess | ({ sessionId }) => void | — | 付款成功時觸發。並非權威 — webhook 才是 |
onCancel | () => void | — | 買家在未付款的情況下關閉 popup/embed 時觸發 |
onError | (err: InfraIoError) => void | — | 在 iframe 載入失敗時觸發(popup + embed 模式)。參數無效會同步 throw,不會透過此處傳遞。Redirect 模式沒有 runtime error 介面 — 失敗會在重導後的頁面中觀察到。 |
onSuccess 不是權威訊號。即使 webhook 之後判定付款失敗
(testnet 重組、買家端時序問題),它仍可能觸發。請僅用於 UX
(顯示「謝謝!」、轉址)。履約前一定要透過 webhook 確認。
sdk.close()
以程式方式關閉已開啟的 popup 或 embed。redirect 模式下為 no-op。
sdk.checkout({ sessionId, mode: "popup", /* … */ });
// 之後,例如當使用者離開頁面時
sdk.close();sdk.openRefundRequest({ … })
開啟託管的退款申請表單,使用你的後端透過
POST /b2b/v1/merchants/{merchant_id}/refund-requests 鑄造的一次性
token。買家在我們的頁面填入退款目的地位址 + 原因 +(選填)metadata;
你的頁面只負責處理開啟/關閉生命週期。回傳一個 close() 函式 —
呼叫它可以程式化關閉 popup 或卸載 embed iframe。在 redirect 模式下
回傳的函式為 no-op。
表單位於 https://checkout.infraio.xyz/refund-request/:token。此方法
只是把該 URL 包裝成 popup / redirect / embed,讓買家不必離開你的網域
(popup / embed),或讓他自動返回(redirect)。後端用來鑄造 token 的
endpoint 是 POST /b2b/v1/merchants/{merchant_id}/refund-requests —
以你的 secret key 做 HMAC 簽章,跟其他 B2B 接口使用相同的驗證機制。
請參考概念 → 退款。
import { loadInfraIo } from "@lartech/infraio-checkout-js";
const sdk = await loadInfraIo("pk_live_yourkeyhere");
// 在伺服端鑄造 token,再交給瀏覽器端的 SDK。
const { token } = await fetch("/api/mint-refund-token", { method: "POST" }).then(r => r.json());
const close = sdk.openRefundRequest({
token,
mode: "popup",
onSuccess: ({ linkToken, refundId }) => {
// 買家送出表單。
// linkToken → /r/:linkToken 狀態頁面(分享給買家)。
// refundId → 搭配 B2B API 來核准 / 駁回。
window.location.href = `/r/${linkToken}`;
},
onCancel: () => { /* 買家未送出就關閉 */ },
});
// 之後如有需要可程式化關閉 popup:
// close();| 欄位 | 型別 | 必填 | 說明 |
|---|---|---|---|
token | string | ✓ | POST /b2b/v1/merchants/{merchant_id}/refund-requests 回傳的 rfqt_… token |
mode | "popup" | "redirect" | "embed" | — | 預設 "popup"。介面語意與 sdk.checkout() 相同 — 參見模式說明 |
container | string | HTMLElement | 僅 embed | iframe 要掛載到的 CSS 選擇器或 DOM 元素 |
locale | string | — | BCP-47 標籤,以 ?locale= 傳遞(en、ja、zh-CN、zh-TW) |
hideHeader | boolean | — | 隱藏 iframe 內的 InfraIO header。popup/embed 中 SDK 會自繪 modal 外觀,頁面 header 通常是雜訊。預設 false |
hideSummary | boolean | — | 隱藏「訂單摘要」欄,僅顯示退款表單。預設 false |
walletAddress | string | — | 預填目的地錢包欄位(?wallet_address=)。讓已知道買家錢包的商家可跳過手動輸入 |
onSuccess | (data: { linkToken: string; refundId: string }) => void | — | 買家送出表單後觸發。linkToken → /r/:linkToken 狀態頁,可分享給買家。refundId → 用於 B2B API 核准 / 駁回 |
onCancel | () => void | — | 買家未送出就關閉 popup/embed 時觸發 |
onError | (err: InfraIoError) => void | — | iframe 載入失敗或參數無效時觸發。Token 過期 / 取消由託管頁面處理,不會透過 onError 通知 |
透過 onError 暴露的 Token 狀態
若買家開啟一個已過期的 token,頁面本身會處理顯示(渲染「已過期 —
申請新連結」提示等),SDK 不會為這些情境觸發 onError — 買家
正在表單流程中,你的程式碼不需要反應。onError 只在你的程式碼
可以採取行動時觸發(錯誤參數、載入 iframe 的網路失敗)。
openRefundRequest 記錄退款意圖 — 它不會移動資金。onSuccess
之後,退款列為 PENDING(或若你的商家設定為自動核准客戶退款,則為
APPROVED)。你仍需用你的商家錢包簽章並廣播鏈上轉帳,然後將
tx hash 送到 POST /b2b/v1/refunds/:id/submit-tx。完整生命週期請見
概念 → 退款。
Error class
import { InfraIoError } from "@lartech/infraio-checkout-js";
sdk.checkout({
sessionId,
onError: (err: InfraIoError) => {
switch (err.code) {
case "invalid_request_error": /* sessionId / 參數錯誤 */ break;
case "iframe_load_error": /* iframe 載入失敗 */ break;
case "iframe_timeout_error": /* 超過 timeoutMs */ break;
case "already_open_error": /* 已有另一個結帳處於開啟狀態 */ break;
case "network_error": /* 與結帳 origin 通訊時的短暫網路問題 */ break;
case "api_error": /* SDK 發起的呼叫,後端回了非 2xx */ break;
}
},
});sdk.openRefundRequest() 只會同步丟出 invalid_request_error(token /
參數遺失或無效)。iframe_load_error(退款申請 iframe 載入失敗)是
透過 onError 非同步傳遞,不會被 throw。它不會發出
iframe_timeout_error 或 already_open_error — 退款申請 popup 沒有
載入逾時,並允許多個並行 popup。
Mode notes
Popup
- 置中疊加層,搭配深色半透明背景
z-index: 2147483647(int32 最大值)— 位於所有元素之上- 開啟時鎖定 body 捲動;關閉時還原
- 關閉按鈕取得初始焦點;Tab 鍵被限制在 popup 內
- 可由以下方式關閉:關閉按鈕、Escape、點擊外部、
sdk.close()。 全部都會呼叫onCancel - 結帳頁可透過
postMessage要求 resize — SDK 會將其夾在width/height限制範圍內
Redirect
- 透過
window.location.href做硬轉址 - 自動附加
?return_url=<current-page>,讓買家回到他原本的位置。 若 session 上的success_url/cancel_url已涵蓋此情境, 往返流程會忽略return_url
Embed
- iframe 帶
allow="payment; clipboard-write"(HTML5 Feature Policy 指令 — 不是sandbox屬性)。Iframe 由結帳 origin 提供,因此買家 端的錢包 popup 與剪貼簿寫入無需額外 opt-in 即可運作。 - 容器寬度為 100%;高度透過
INFRAIO_RESIZEpostMessage 自動調整, 夾在[200, 2000]px範圍 - 除 iframe 邊界以外不做 CSS 隔離 — 你的父頁面樣式不會滲透進來
- 請務必接上
onReady,以便在結帳變成可互動時隱藏你自己的載入狀態
TypeScript
所有型別都已打包。最常用的匯出:
import type {
CheckoutOptions,
RefundRequestOptions,
LoadOptions,
InfraIoInstance,
InfraIoErrorCode,
} from "@lartech/infraio-checkout-js";
import { loadInfraIo, InfraIoError, VERSION } from "@lartech/infraio-checkout-js";VERSION 是 SDK 自身的版本字串 — 在 bug 回報時很有用。
下一步
- React / Vue 框架封裝 — 計畫在 vanilla JS 介面於試辦商家間穩定
後的 post-launch 迭代中推出。Vanilla SDK 在 React 中今天就能正常
運作;封裝只是省下手動
useRef+ 生命週期管線。 - 跨分頁的 session 續傳 — 在分頁 A 開啟結帳,在分頁 B 完成。 在買家於流程中途點開 magic-link 的情境下很有用。已列入下一個 minor release。
- 透過 CSS 變數做主題化 — 在 iframe 上開放一小組設計 token (圓角、強調色),讓商家不用 fork 頁面就能匹配品牌。
- 伺服端輔助 — 一個小型的
@lartech/infraio-server套件,匯出verifyWebhook()+signedRequest(),讓後端不必複製 HMAC 流程。 在它出貨前,簽章驗證頁 列出 TypeScript、Go、Python 與 Ruby 的可直接套用實作。