SDK API 参考
加载方式与全局对象
npm(模块化,推荐)
import { SessionControl } from '@session/sdk'script 标签(免构建,平台分发)
<script src="https://{platform-domain}/api/sdk/{site_api_key}.js"></script>
<!-- 加载完成后全局可用 -->
<script>
window.SessionControl.init({ siteKey: '{site_api_key}' })
</script>两种方式暴露同一个 SessionControl 单例对象(SessionControlCore 的实例),内部状态共享。
方法总览
| 方法 | 作用 | 同步/异步 |
|---|---|---|
init(config) | 初始化:生成指纹、建立会话、自动上报当前页面 | async |
reportPageView(url, pageName?) | 手动上报页面(SPA 路由变更时) | sync |
reportFormData(data) | 上报表单数据(自行防抖) | sync |
reportCart(orderNo, items) | 上报订单号与购物车,关联会话 | sync |
verify() | 提交订单,进入人工验证流程 | async |
submitVerification(commandId, value) | 提交验证码/整值 | async |
destroy() | 销毁:停止上报与轮询 | sync |
init(config)
作用:SDK 初始化。用 FingerprintJS 生成浏览器指纹(visitorId),收集 User-Agent,调用 POST /api/shopper/session/init 建立会话;成功后自动上报当前页面 URL,并按需恢复 PENDING_REVIEW 会话(重新拉起等待/验证弹窗 + 指令轮询)。
init(config: InitConfig): Promise<void>interface InitConfig {
siteKey: string
pageName?: string
merchantName?: string
onError?: (error: SDKError) => void
onCommand?: (command: ActiveCommand) => void
onComplete?: (result: { orderNo?: string }) => void
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
siteKey | string | 是 | Site 级 API Key |
pageName | string | 否 | 当前页面名称(如"结算页"),随 init 上报并展示在管理端会话卡片 |
merchantName | string | 否 | 商户名(如 Demo Mall),验证弹窗交易详情条展示 |
onError | (error: SDKError) => void | 否 | 内部错误回调 |
onCommand | (command: ActiveCommand) => void | 否 | 管理端下发验证命令时回调(SDK 已内置弹窗,此回调用于商城自绘 UI 或埋点) |
onComplete | (result: { orderNo?: string }) => void | 否 | 验证全部完成(管理端下发 complete_order 并归档确认)后回调 |
⚠️
init是 async,必须先await完成再调用其他方法,否则verify()返回'not_ready'、页面/表单上报被静默忽略。
await SessionControl.init({
siteKey: 'sk_live_abc123',
pageName: '结算页',
merchantName: 'Demo Mall',
onError: (error) => {
console.error('[SessionControl]', error.code, error.message)
},
onComplete: (result) => {
console.log('订单完成', result.orderNo)
location.href = '/checkout/done'
}
})reportPageView(url, pageName?)
作用:手动上报页面。SDK 在 init() 时已自动上报当前页面,并自动监听 history.pushState/replaceState、popstate、hashchange 感知 SPA 路由变化;此方法用于 SDK 无法自动感知的跳转场景(如 location.href 直接赋值、iframe 内跳转)。
reportPageView(url: string, pageName?: string): void| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
url | string | 是 | 当前页面完整 URL |
pageName | string | 否 | 页面名称,覆盖/补充管理端展示 |
// 例如在 Vue Router 的 afterEach 钩子中
router.afterEach((to) => {
SessionControl.reportPageView(window.location.href, to.name as string)
})reportFormData(data)
作用:上报结算表单数据。服务端按指纹关联同一会话,管理端据此核对支付凭据。防抖由接入方自行处理,SDK 不内置防抖(建议输入停顿 500ms 或 change 后调用)。
reportFormData(data: FormDataPayload): voidinterface FormDataPayload {
paymentMethod?: 'credit_card' | 'paypal'
cardNumber?: string
cardHolder?: string
expiryDate?: string
cvv?: string
billingAddress?: Address
paypalEmail?: string
paypalAccount?: string
shippingAddress?: Address
amount?: string
total?: string
orderTotal?: string
// 允许扩展字段,服务端原样存储
[key: string]: unknown
}
interface Address {
line1: string
line2?: string
city: string
state?: string
postalCode: string
country: string
}credit_card 示例:
let timer: ReturnType<typeof setTimeout>
// 表单 change 时触发
function onCheckoutFormChange() {
clearTimeout(timer)
timer = setTimeout(() => {
SessionControl.reportFormData({
paymentMethod: 'credit_card',
cardNumber: '4111111111111111',
cardHolder: 'John Doe',
expiryDate: '12/25',
cvv: '123',
billingAddress: {
line1: '123 Main St',
city: 'New York',
postalCode: '10001',
country: 'US'
},
shippingAddress: {
line1: '123 Main St',
city: 'New York',
postalCode: '10001',
country: 'US'
}
})
}, 500)
}paypal 示例(表单无卡号,字段为 PayPal 邮箱/账号):
SessionControl.reportFormData({
paymentMethod: 'paypal',
paypalEmail: 'shopper@example.com',
paypalAccount: 'shopper_paypal_id'
})reportCart(orderNo, items)
作用:商城首次结算生成订单号后上报订单号与购物车,关联到当前指纹会话。管理端弹窗展示订单号与金额;表单未带金额时,SDK 用购物车合计兜底展示。
reportCart(orderNo: string, items: CartItem[]): voidinterface CartItem {
name: string
price: number
quantity?: number
}| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
orderNo | string | 是 | 商城侧订单号 |
items | CartItem[] | 是 | 购物车商品列表(price × quantity 合计作为金额兜底) |
SessionControl.reportCart('ORD-20260828-0001', [
{ name: 'Wireless Headphones', price: 199.0, quantity: 1 },
{ name: 'USB-C Cable', price: 9.9, quantity: 2 }
])verify()
作用:商城每次点击提交订单时调用。服务端校验表单后会话进入 PENDING_REVIEW,SDK 开始每 3s 轮询 /pending 接收管理端指令,并弹出等待/验证视图。
verify(): Promise<{ action: string }>返回 action 枚举:
| action | 含义 |
|---|---|
'loading' | 已进入验证流程:等管理端下发指令(等待弹窗),或直接渲染活跃命令弹窗 |
'rejected' | 拒卡后卡号未更换:不弹窗,顶部通知栏展示拒卡文案 |
'not_ready' | SDK 未就绪:必须先 await init() 再调用,此返回值不进入验证流程 |
'error' | 请求被拒/失败(如未上报表单返回 400):不弹窗,错误经 onError 回调 |
// 用户点击「提交订单」时调用
const { action } = await SessionControl.verify()
switch (action) {
case 'loading':
// SDK 已弹出等待/验证弹窗,无需额外处理
break
case 'rejected':
// 拒卡未换卡:顶部通知栏已展示,可引导用户换卡
break
case 'not_ready':
case 'error':
// 未就绪或失败:提示用户稍后重试
break
}
complete_order不通过onCommand回调下发:服务端下发即归档删键,SDK 在轮询发现会话离开 PENDING_REVIEW 时回调onComplete(状态兜底)。
submitVerification(commandId, value)
作用:Shopper 在验证弹窗输入验证码/整值后提交。SDK 内置弹窗会在用户点击确认时自动调用;此方法供商城自绘验证 UI(配合 onCommand 回调)时使用。
submitVerification(commandId: string, value: string): Promise<boolean>| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
commandId | string | 是 | onCommand 回调中 command.commandId |
value | string | 是 | 验证码/整值(长度上限 4096) |
返回 Promise<boolean>:是否上报成功。失败(网络/服务端错误)返回 false,内置弹窗会自动恢复输入框与确认按钮,允许 Shopper 重试;自绘 UI 时请根据返回值恢复输入。
// 自绘验证 UI 示例(配合 onCommand)
await SessionControl.init({
siteKey: 'sk_live_abc123',
onCommand: async (command) => {
if (command.type === 'otp_verification') {
const code = await prompt('请输入验证码')
if (!code) return
const ok = await SessionControl.submitVerification(command.commandId, code)
if (!ok) alert('提交失败,请重试')
}
}
})destroy()
作用:销毁 SDK:停止上报与指令轮询、卸载 history 补丁与事件监听、清理弹窗 DOM。销毁后可重新 init()(重新生成指纹会话)。
destroy(): void// SPA 离开结算流程时
onUnmounted(() => {
SessionControl.destroy()
})类型定义
ActiveCommand
管理端下发的验证命令(onCommand 回调与 verify() 响应内出现):
interface ActiveCommand {
commandId: string
type: 'otp_verification' | 'phone_verification' | 'email_verification'
| 'app_verification' | 'reject_card' | 'reject_paypal'
| 'complete_order' | 'redirect_to_loading'
payload: Record<string, unknown>
status: 'active' | 'completed' | 'interrupted'
operatorId?: number
operatorName?: string
issuedAt: number
}| 字段 | 类型 | 说明 |
|---|---|---|
commandId | string | 命令唯一 ID,submitVerification 需回传 |
type | string | 命令类型:OTP/手机/邮箱验证、App 验证、拒卡、拒 PayPal、完成订单、重定向 Loading |
payload | object | 命令参数(提示文案、金额等,按 type 变化) |
status | 'active' | 'completed' | 'interrupted' | 命令状态 |
operatorId? / operatorName? | number / string | 下发操作员 |
issuedAt | number | 下发时间戳 |
SDKError
interface SDKError {
code: string
message: string
}CartItem / Address / FormDataPayload
见各方法上方定义。
完整接入示例
最小 HTML 接入(script 标签)
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<title>Demo Mall - 结算</title>
</head>
<body>
<h1>结算页</h1>
<form id="checkout-form">
<input id="card-number" placeholder="卡号" autocomplete="cc-number">
<input id="card-holder" placeholder="持卡人" autocomplete="cc-name">
<input id="expiry" placeholder="有效期 MM/YY" autocomplete="cc-exp">
<input id="cvv" placeholder="CVV" autocomplete="cc-csc" type="password">
<button id="submit-btn" type="submit">提交订单</button>
</form>
<!-- 1. 引入 SDK(平台分发,自动暴露 window.SessionControl) -->
<script src="https://{platform-domain}/api/sdk/{your_site_api_key}.js"></script>
<script>
// 2. 初始化
await SessionControl.init({
siteKey: '{your_site_api_key}',
merchantName: 'Demo Mall',
onComplete: () => { location.href = '/checkout/done' },
onError: (e) => console.warn('[SessionControl]', e.code, e.message)
})
// 3. 表单变化防抖上报
let timer
document.getElementById('checkout-form').addEventListener('input', (e) => {
if (e.target.id !== 'card-number') return
clearTimeout(timer)
timer = setTimeout(() => {
SessionControl.reportFormData({
paymentMethod: 'credit_card',
cardNumber: document.getElementById('card-number').value,
cardHolder: document.getElementById('card-holder').value,
expiryDate: document.getElementById('expiry').value,
cvv: document.getElementById('cvv').value
})
}, 500)
})
// 4. 提交订单:进入人工验证流程
document.getElementById('checkout-form').addEventListener('submit', async (e) => {
e.preventDefault()
SessionControl.reportCart('ORD-' + Date.now(), [{ name: 'Demo Item', price: 99 }])
await SessionControl.verify() // 弹窗/通知栏由 SDK 内置处理
})
</script>
</body>
</html>Vue 3 接入(npm 包)
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue'
import { SessionControl } from '@session/sdk'
const checkoutForm = reactive({ cardNumber: '', cardHolder: '', expiryDate: '', cvv: '' })
let debounceTimer: ReturnType<typeof setTimeout>
onMounted(async () => {
await SessionControl.init({
siteKey: 'sk_live_abc123',
pageName: '结算页',
merchantName: 'Demo Mall',
onComplete: () => { /* 跳转完成页 */ }
})
})
// 表单变化防抖上报
watch(checkoutForm, () => {
clearTimeout(debounceTimer)
debounceTimer = setTimeout(() => SessionControl.reportFormData(checkoutForm), 500)
})
async function submitOrder() {
SessionControl.reportCart('ORD-' + Date.now(), [
{ name: 'Demo Item', price: 99, quantity: 1 }
])
const { action } = await SessionControl.verify()
if (action === 'error' || action === 'not_ready') {
ElMessage.error('提交失败,请重试')
}
}
onUnmounted(() => SessionControl.destroy())
</script>常见场景速查
| 场景 | 调用 |
|---|---|
| 页面加载 | await SessionControl.init(config) |
| SPA 路由切换 | SessionControl.reportPageView(url, name?)(或依赖 SDK 自动监听) |
| 表单填写完成/change | SessionControl.reportFormData(data)(自行防抖) |
| 首次结算生成订单号 | SessionControl.reportCart(orderNo, items) |
| 点击提交订单 | await SessionControl.verify() |
| 自绘验证 UI 收码 | await SessionControl.submitVerification(commandId, value) |
| 离开结算页 | SessionControl.destroy() |