JavaScript / 浏览器 SDK
@lartech/infraio-checkout-js 是我们目前发布的唯一 SDK。它运行在浏览器中,
并打开我们的托管结账页。后端 SDK(Node、Go、Python)在路线图上;
在此之前请直接调用 gateway —
HMAC 签名 helper 请参见 快速开始。
- 当前版本:
0.1.1-beta.17(1.0 之前;可能有小幅破坏性变更) - 格式:ESM (
index.js)、CJS (index.cjs)、IIFE (index.global.js) - 已打包类型定义 (
index.d.ts) - 零运行时对等依赖 — 不依赖 React、jQuery 或其他库
没有服务端入口。Webhook 签名验证 helper 未打包 —
请用 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", {
// 可选。仅当指向非生产环境时才覆盖。
checkoutUrl: "https://checkout-dev.infraio.xyz",
});| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
publicKey | string | ✓ | 必须匹配 pk_(live|test)_… |
options.checkoutUrl | string | — | 覆盖结账基础 URL。默认:https://checkout.infraio.xyz。对应的 gateway URL 在运行时由结账页决定 — 每个 checkout(-dev).infraio.xyz 部署携带自身编译期的 NEXT_PUBLIC_API_URL,所以在这里选对主机名就会自动选对后端。没有单独的 gatewayUrl 选项。 |
sdk.checkout({ … })
打开托管结账页。返回 void(状态通过回调获取)。
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
sessionId | string | ✓ | 由 POST /b2b/v1/checkout-sessions/quick 返回的 session_key |
checkoutUrl | string | — | 同一端点返回的完整 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 页头与内建的钱包连接按钮。默认 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;返回已签名的十六进制 |
onSuccess | ({ sessionId }) => void | — | 支付成功时触发。非权威 — Webhook 才是 |
onCancel | () => void | — | 买家未支付就关闭弹窗/嵌入时触发 |
onError | (err: InfraIoError) => void | — | iframe 加载失败时触发(popup + embed 模式)。参数非法会同步抛出,不会通过这里传递。Redirect 模式没有运行时错误表面 — 失败在跳转后的页面里观察。 |
onSuccess 不是权威。即便 Webhook 后续判定支付失败(测试网重组、
买家侧时序问题),它也可能触发。仅将其用于 UX(显示”感谢!”、
跳转)。履约前请始终通过 Webhook 确认。
sdk.close()
通过代码关闭已打开的 popup 或 embed。redirect 模式下为空操作。
sdk.checkout({ sessionId, mode: "popup", /* … */ });
// 之后,例如用户导航离开时
sdk.close();sdk.openRefundRequest({ … })
为你的后端通过 POST /b2b/v1/merchants/{merchant_id}/refund-requests
铸造的一次性 token 打开托管退款申请表单。买家在我们页面填写退款
目标地址 + 原因 +(可选)元数据;你的页面只处理打开/关闭生命周期。
返回一个 close() 函数 — 调用它可通过代码关闭弹窗或卸载嵌入的
iframe。redirect 模式下返回的函数为空操作。
表单位于 https://checkout.infraio.xyz/refund-request/:token。
此方法只是把该 URL 包装成 popup / redirect / embed,这样买家就不会
离开你的域名(popup / embed)或自动返回(redirect)。后端用来铸造
token 的端点是 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: () => { /* 买家未提交就关闭了 */ },
});
// 后续如需通过代码关闭弹窗:
// 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 页头。在 popup/embed 中 SDK 自行绘制模态框架,所以页头通常是噪音。默认 false |
hideSummary | boolean | — | 隐藏订单摘要列,仅显示退款表单。默认 false |
walletAddress | string | — | 预填目标钱包字段 (?wallet_address=)。当商户已知买家钱包时,免去手动重新输入 |
onSuccess | (data: { linkToken: string; refundId: string }) => void | — | 买家提交表单后触发。linkToken → /r/:linkToken 状态页,可分享给买家。refundId → 用于 B2B API 审批 / 驳回 |
onCancel | () => void | — | 买家未提交就关闭弹窗/嵌入时触发 |
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 类
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": /* 已有一个 checkout 打开中 */ break;
case "network_error": /* 与结账 origin 通信的短时网络问题 */ break;
case "api_error": /* SDK 发起的调用上后端返回非 2xx */ break;
}
},
});sdk.openRefundRequest() 只会同步抛出 invalid_request_error(缺少
或无效的 token / 参数)。iframe_load_error(退款申请 iframe 加载失败)
会异步通过 onError 传递,而不是被抛出。它不会触发
iframe_timeout_error 或 already_open_error — 退款申请弹窗没有加载
超时,并允许多个并发弹窗。
模式说明
Popup
- 居中覆盖层,背后为半透明深色蒙版
z-index: 2147483647(int32 最大值)— 位于其他一切之上- 打开时锁定 body 滚动;关闭后恢复
- 关闭按钮获得初始焦点;Tab 被困在弹窗内
- 关闭方式:关闭按钮、Escape、点击外部、
sdk.close()。以上方式都会触发onCancel - 结账页可通过
postMessage请求调整大小 — SDK 在width/height范围内夹紧
Redirect
- 通过
window.location.href硬跳转 - 自动追加
?return_url=<current-page>,这样买家会回到出发处。如果 会话上的success_url/cancel_url已覆盖这点,往返会忽略return_url
Embed
- iframe 带
allow="payment; clipboard-write"(HTML5 Feature Policy 指令 — 不是sandbox属性)。iframe 由结账 origin 提供,所以 买家侧的钱包弹窗与剪贴板写入无需进一步授权即可工作。 - 容器宽度为 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 表面随首批试点商户稳定后,
将作为发布后迭代的一部分推出。Vanilla SDK 今天在 React 中也能用;
封装只是免去手写
useRef+ 生命周期连接。 - 跨标签会话恢复 — 在 A 标签打开结账,在 B 标签完成。当买家在 流程中跟随魔法链接时很有用。已列入下一次小版本。
- 通过 CSS 变量做主题化 — 在 iframe 上暴露一小套设计 token(圆角、 强调色),这样商户无需 fork 页面就能匹配品牌。
- 服务端 helper — 一个微小的
@lartech/infraio-server包,暴露verifyWebhook()+signedRequest(),后端代码就不必复制 HMAC 套路。 在发布之前,签名验证页 列出了 TypeScript、Go、Python、Ruby 的可直接采用实现。