PLATFORM OVERVIEW
平台概览
RECENT SESSIONS
最近录制
| 会话 | 项目 | 订单 | 状态 | 时间 |
|---|
INTEGRITY CHAIN
证据链状态
- SDK 离线可恢复已实现
- 清单数字签名检查中
- WORM 对象锁定检查中
- 可信时间戳检查中
| 会话 ID | 项目 | 订单/手机号 | 时长 | 事件 | 保存状态 | 录制时间 |
|---|
每个项目独立管理来源策略和服务端凭证;多域名商户可以关闭域名白名单。
商户是平台的数据隔离边界,项目、会话和成员账号均归属于商户。
| 商户名称 | 唯一标识 | 项目数 | 管理员 | 保留/月配额 | 状态 | 创建时间 |
|---|
按角色控制查看、验证、导出和管理权限;新账号首次登录必须修改密码。
| 账号 | 显示名称 | 角色 | MFA | 状态 | 最后登录 |
|---|
按下面顺序完成服务端与网页接入;项目服务端凭证只能放在商户后端,不能写进 H5、App 或小程序代码。
打开录制沙箱 ↗INTEGRATION OVERVIEW
先理解三个核心标识
RUNNABLE EXAMPLES
下载完整示例,运行接入自检
选择商户后端语言,解压后按包内 README 启动。示例会实际检查凭证、页面来源、图片内容归档、原会话续期、订单与号码绑定,以及最终存证结果;每一步显示中文建议和请求编号。
默认本机运行、使用合成数据和调试项目。项目凭证只填写后端 .env;正式测试需要后端配置和页面双重确认。调试通过只表示本地链路通过,腾讯云存证须以最终状态与实际完整性核验为准。
END-TO-END FLOW
完整对接流程
- 01创建项目并生成凭证配置允许域名;如果只保留有效业务,开启“仅在商户确认后永久保存”。
- 02商户后端申请录制 Token页面进入业务流程时调用,保存返回的 traceSessionId,并把录制 Token 返回当前网页。
- 03网页启动并结束录制使用 traceSessionId 和 recordingToken 初始化 SDK;业务页面结束时调用 stop/finish。
- 04统一提交业务结果订单号或手机号生成后,通过一次commit请求完成绑定和确认;字段按需传入,重复提交幂等。
- 05检查最终结果普通模式结束后直接封存;确认模式在确认且录制结束后转存腾讯云,可通过 Webhook 或后台任务查看。
PERSISTENCE MODES
两种保存模式
全部永久保存
项目开关关闭。录制分块直接写入腾讯云,网页结束录制后签名封存。
不需要调用确认接口确认后永久保存
项目开关开启。录制先进入待确认区,商户确认后才转存腾讯云并锁定。
72小时未确认自动删除判断依据必须使用申请 Token 响应中的 persistence.confirmationRequired,不要只依赖商户本地配置。项目开关只影响新签发的会话。
DEBUG / PRODUCTION
先调试,再切换正式环境
在“录制项目 → 编辑”选择调试环境。只影响之后新签发的会话,SDK会自动识别,不需要商户修改初始化代码。
录制分块、图片/样式/字体、Manifest和详细日志都进入独立本地目录,绝不上传腾讯云;默认7天,可设置1~30天。
SDK自动保存console、页面运行错误、Promise异常、SDK诊断和接口上下文;也可调用KHSRecorder.log(level,message,detail)追加业务日志。
输入、订单号、手机号等业务内容会保留用于联调;密码、Cookie、Authorization、项目凭证和录制Token始终强制脱敏。
调试会话可在后台回放和查看日志,但不生成官网核验码,也不能导出正式PDF、ZIP或MP4,超过期限自动删除。
选择正式环境后,新会话恢复腾讯云长期保存流程。旧调试会话仍留在本地并按期删除,不会因切换而补传云端。
Token响应中的 environment.mode、environment.localOnly 和 environment.expiresAt 是该会话的最终环境快照;不要用项目当前开关反推历史会话。
STEP 1 · BACKEND
申请 Token 并保存 traceSessionId
// 这段代码只能运行在商户后端
// KHS_PROJECT_CREDENTIAL=cred_xxx.secret(不要填写 Bearer)
const khs = KhsClient.fromEnv();
await khs.checkCredential(); // GET /api/v1/credential-status
// 下行方法对应 POST /api/v1/recording-tokens
const tokenResult = await khs.issueRecordingToken({
origin: "https://h5.customer.com",
userRef: "USER-10001", // 可选:商户自己的用户标识
flowRef: "FLOW-20260827", // 可选:跨页面业务流程标识
idempotencyKey: await getOrCreateEntryKey() // 同一次重试必须复用
});
// 必须把 traceSessionId 保存到商户数据库
await saveTraceSession({
traceSessionId: tokenResult.traceSessionId,
confirmationRequired:
tokenResult.persistence.confirmationRequired,
confirmationDeadline:
tokenResult.persistence.confirmationDeadline,
environment: tokenResult.environment // debug/production会话快照
});
// 只把下面两个字段返回当前业务网页
return {
traceSessionId: tokenResult.traceSessionId,
recordingToken: tokenResult.recordingToken
};
origin 必须是实际 H5 来源;开启域名白名单时要与项目允许域名一致。凭证只在后端通过 KHS_PROJECT_CREDENTIAL 配置一次,不要包含Bearer或返回前端。STEP 2 · H5
网页启动与结束录制
<script
src="https://khs.szshuqi.com/sdk/recorder.min.js"
crossorigin="anonymous" defer></script>
<script>
window.addEventListener("DOMContentLoaded", async () => {
KHSRecorder.error(error => {
console.log("error", error);
showRecordingStatus(`${error.code}: ${error.message}`);
});
const tokenProvider = async ({ reason, traceSessionId, origin, signal }) => {
const response = await fetch(
reason === "initial"
? "/business/recording-token"
: "/business/recording-token/renew",
{
method: "POST", credentials: "same-origin",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ traceSessionId, origin }), signal
}
);
const data = await response.json();
if (!response.ok) throw Object.assign(new Error(data.message), data);
return data;
};
const recording = await KHSRecorder.init({
endpoint: "https://khs.szshuqi.com",
tokenProvider,
pagehideStrategy: "flush"
});
await saveCurrentTraceSessionId(recording.traceSessionId);
});
// 页面业务完成或离开前,由业务代码显式调用并等待成功
async function finishRecording() {
await KHSRecorder.stop();
}
</script>
tokenProvider;调试日志遇到401也会自动续期,无法续期时暂停重复请求。DEBUG & ERROR
调试模式与统一错误监听
SDK脚本加载完成后、调用init()/resume()之前注册KHSRecorder.error(),初始化错误才能被收到。
包含code、message、stage、status、requestId、retryable、待传分块和安全的actual/expected Origin。
将当前页window.location.origin交给商户后端签发Token;不要关闭Origin安全校验。
配置tokenProvider后由SDK自动提前续期并对401单飞恢复;返回旧Token会熔断,不再形成循环请求。
debug()/getDiagnostics()只输出安全诊断;项目“调试环境”会额外把console及业务敏感上下文保存到后台,并自动脱敏认证秘密。
sealed后清理traceSessionId,新录制重新签发;error()/debug()返回的取消函数应在组件销毁时调用。
window.addEventListener("DOMContentLoaded", async () => {
const cancelError = KHSRecorder.error(error => {
console.log("error", error);
if (error.code === "ORIGIN_MISMATCH") {
showRecordingStatus(
`页面来源 ${error.actualOrigin} 与 Token 来源 ${error.expectedOrigin} 不一致`
);
}
if (error.code.startsWith("TOKEN_") || error.code === "INVALID_RECORDING_TOKEN") {
showRecordingStatus("自动续期未完成,请检查商户后端Token接口和requestId");
}
if (error.code === "SESSION_ALREADY_SEALED") {
showRecordingStatus("请清理已封存traceSessionId并申请新会话");
}
});
const cancelDebug = new URLSearchParams(location.search).get("khs_debug") === "1"
? KHSRecorder.debug(info => console.debug("KHS debug", info))
: null;
// 也可以主动查看当前脱敏诊断信息
console.log(KHSRecorder.getDiagnostics());
// SPA组件销毁时执行:
// cancelError();
// cancelDebug?.();
});
KHSRecorder.error()不会代替Promise错误处理;init()、stop()等调用仍要使用try/catch。自动续期失败会返回TOKEN_NOT_RENEWED、TOKEN_PROVIDER_INVALID_TOKEN或商户后端错误码。调试信息虽然已脱敏,生产页面仍不建议长期打开控制台日志。禁止打印recordingToken、项目服务端凭证或把完整错误对象上传到不受控的第三方日志平台。
WEAK NETWORK & RECOVERY
弱网、断网与中断恢复
SDK 4.3.3 会监听网络切换并结合真实上传RTT、吞吐量和重试动态调整;不要因为一次超时重新创建 traceSessionId。
事件先写入 IndexedDB,恢复联网后自动继续上传。页面应提示“本机已暂存”,不要让用户重复提交业务。
4.3.3保持150~250ms草稿并监听freeze;强杀仍是尽力保存。恢复时使用原traceSessionId;真正结束必须等待stop。
SDK通过tokenProvider自动续期、校验新Token并恢复上传;错误监听只负责展示失败信息。
同页最终离开前必须等待 stop() 成功;跨域多页面使用 handoff(),不要依赖 pagehide 完成网络请求。
IndexedDB按需读取当前上传分块,不在内存堆积。durable=false表示内存降级;khs:local-cache-full会停止采集,必须提示恢复网络并封存。
window.addEventListener("khs:offline", () =>
showRecordingStatus("网络已断开,录制数据已暂存在本机"));
window.addEventListener("khs:retry", event =>
showRecordingStatus(`网络不稳定,${event.detail.delay}ms 后重试`));
window.addEventListener("khs:network-profile-changed", event =>
showRecordingStatus(`网络传输档位已调整为 ${event.detail.to}`));
window.addEventListener("khs:recovered", () =>
showRecordingStatus("正在续传上次未完成的数据"));
window.addEventListener("khs:local-cache-full", () =>
showRecordingStatus("本机待传数据已满,录制暂停,请恢复网络"));
window.addEventListener("khs:sealed", () =>
showRecordingStatus("录制已封存"));
window.addEventListener("khs:finish-waiting-network", event =>
showRecordingStatus(`等待网络继续封存,剩余 ${event.detail.pendingChunks} 个分块`));
async function finishBeforeNavigation(nextUrl) {
try {
await KHSRecorder.stop();
location.assign(nextUrl);
} catch (error) {
showRecordingStatus(["NETWORK_OFFLINE", "FINISH_DEFERRED"].includes(error.code)
? `数据已暂存,剩余 ${KHSRecorder.getStatus().pendingChunks} 个分块,请恢复网络后重试`
: "尚未封存,请检查错误后重试");
throw error;
}
}
刷新续传必须配置pagehideStrategy:"flush"并使用原 traceSessionId;默认finish保持旧接入兼容。pagehide只负责尽力落盘,真正业务结束仍必须显式等待stop()。
STEP 3 · BACKEND
一次提交订单、手机号和保存确认
// 推荐:官方服务端SDK自动添加Bearer并复用同一凭证
await khs.commitSession(traceSessionId, {
businessId: "ORDER-20260827-001", // 可选
mobile: "13800138000", // 可选
confirmed: true // 可选
});
// 对应原始接口
POST /api/v1/sessions/{traceSessionId}/commit
Authorization: Bearer cred_xxx.secret
Content-Type: application/json
三个字段按需传入,至少一项。订单生成较晚时可以只传手机号,之后再用同一接口补订单和确认。
必须由持有项目服务端凭证的商户后端发送,不能由 H5 直接调用。
确认请求成功只表示已接受。录制结束后等待 recording.persisted Webhook,或在“质量与任务”查看“确认后转存腾讯云”任务完成。
相同订单、手机号和确认均为幂等;项目无需确认时传confirmed:true也会直接返回成功,不需要分支判断。
旧版独立接口(继续兼容)
POST /bindings绑定订单,POST /mobile-bindings绑定手机号,POST /confirm发送确认。新接入优先使用统一commit,避免三套请求头配置不一致。
ERROR HANDLING
上线前检查与常见错误
- 统一使用KHS_PROJECT_CREDENTIAL且不含Bearer
- 启动时调用credential-status检查凭证
- 每次申请 Token 后立即保存 traceSessionId
- H5实际origin与Token请求参数一致
- 配置tokenProvider自动单飞续期
- 业务结束统一调用commit
- 跳转前显式等待stop成功
- 开启Webhook并按投递编号做幂等
| 状态码 | 常见原因 | 处理方式 |
|---|---|---|
| 401 | 服务端凭证读取或请求头拼接错误 | 用credential-status检查;不要重复或遗漏Bearer |
| 403 | 项目、凭证停用或来源域名不允许 | 检查项目状态与域名策略 |
| 409 | 项目无需确认、订单冲突或会话状态不允许 | 按错误 code 判断,不要盲目换 sessionId |
| 410 | 超过72小时确认期限 | 该会话已不能永久保存,不要继续重试 |
| 426 | SDK 版本低于项目最低要求 | 升级固定版本 SDK,不要修改旧版本文件 |
| 429 | 请求频率过高、会话或存储配额不足 | 读取错误 code,按 Retry-After 退避或联系平台 |
| 网络异常 | 离线、超时或移动网络切换 | 保留 traceSessionId,恢复网络后重试 stop/resume |
| 时间 | 操作 | 操作人 | 资源 | 记录哈希 |
|---|
SECURITY EVENTS
安全事件
| 时间 | 风险 | 事件 | 账号 | IP |
|---|
监控已接收会话的完整率、恢复与上传异常;任务失败可重试,导出完成后可下载(保留 7 天)。
近 30 天正式环境录制质量
| 分组 | 总会话 | 完整封存/已启动 | 录制中 | 中断 | 上传错误/重复/恢复 | 存储 |
|---|
客户用量
| 客户 | 月会话/配额 | 累计存储/配额 |
|---|
验证、导出与通知任务
| 任务 | 类型 | 状态 | 尝试 | 时间 | 结果/操作 |
|---|