开发文档

设备标识服务对外开放。客户端采集后换取 token,业务后端用 token 换取设备标识;原始特征不经过业务系统。

快速开始

一次完整的接入分为三段:客户端取 token,前端把 token 交给自家后端,后端带签名换取标识。

1. 引入 SDK

<script src="https://fp.mima-code.com/sdk/core.js"></script>

2. 初始化并获取 token

const app = AppSDK.init({ appKey: '<APP_KEY>', server: 'https://fp.mima-code.com', timeout: 6000, }); const { code, token } = await app.getTokenAsync(); if (code === 200 || code === 201) { await post('/api/device-token', { token }); // 交给自家后端 }

3. 服务端换取标识

POST /sdk/v1/check { "app_id": "<APP_ID>", "timestamp": 1730000000000, "nonce": "<32 位随机串>", "version": "1.0", "sign": "<md5>", "token": "<客户端 token>" }
返回的 device_token 可直接放进业务请求头,格式与现有 fp 头一致。

初始化

初始化只使用公开的应用标识,不携带任何密钥。真正的鉴权在服务端由来源白名单与配额承担。

AppSDK.init({ appKey: '<APP_KEY>', // 必填,公开标识 server: 'https://fp.mima-code.com', // 可选,默认公网地址 timeout: 6000, // 可选,采集上报超时(毫秒) callback(code, msg) {} // 可选,初始化回调 })
code含义
200初始化完成
109重复初始化,沿用已有实例
199应用标识无效或已停用

获取 token

同步接口返回当前状态;异步接口每次都会重新采集并上报,属于耗时操作,不要在页面高频调用。

// 同步 const { code, token } = app.getToken(); // 异步 app.getTokenAsync().then((result) => { if (result.code === 200 || result.code === 201) { // result.token 交给业务后端 } });
code状态处理
200正常模式,数据已上报,token 长度固定直接送检
201离线模式,上报失败,token 为本地加密载荷同样送检,效果一致
202获取异常,token 为空串本次不送检,稍后重试
同步调用时若初始化回调尚未完成,会返回 202。需要稳定结果请使用异步接口。

token 形态

服务端对两种 token 的处理方式不同,接入方不需要区分。

形态触发长度服务端处理
短 token上报成功固定 40 字符从缓存读取计算结果
长 token上报失败4–8KB解密后现场计算

短 token 建议在 30 分钟内送检,超时后返回 5512。离线 token 内含采集数据,传输与存储都应按敏感数据处理。

检测接口

POST https://fp.mima-code.com/sdk/v1/check Content-Type: application/json

公共参数与业务参数放在同一个 JSON 请求体里。

参数必填说明
app_id是接入方标识
timestamp是13 位毫秒时间戳,超过 5 分钟拒绝
nonce是32 位随机串,服务端去重防重放
version是接口版本,当前为 1.0
sign是签名,见下节
token是客户端获取的凭证
account否业务方用户 ID
ip否用户 IP,缺省取请求来源

签名规则

所有参数(不含 sign)按参数名 ASCII 升序排序,依次拼接键与值,末尾追加 app_secret,整体做 MD5,取 32 位小写十六进制。

function sign(params, secret) { const keys = Object.keys(params).filter(k => k !== 'sign').sort(); let raw = ''; for (const k of keys) raw += k + params[k]; raw += secret; return md5(raw).toLowerCase(); }
空值不要省略成 null,统一传空字符串,否则前后端签名会不一致。

返回字段

{ "code": 200, "msg": "ok", "data": { "device_id": "RZBW7ZSRJ7ID3SCVY2PIICNKEF654JUB", "device_token": "RZBW7ZSRJ7ID3SCVY2PIICNKEF654JUB|v1|<md5>", "risk_level": 0, "hit_infos": [], "coverage": 100, "pending": false, "first_seen": false, "task_id": "trace-id", "cached": true } }
字段说明
device_id32 位 Base32 设备标识;pending 时为空串
device_token可直接放入业务请求头的完整串
risk_level0 正常 / 1 低 / 2 中 / 3 高 / 4 可信
coverage核心特征覆盖率,100 表示采集完整
pending为 true 时应保留本地已有标识,不要覆盖
cached同一 token 重复送检时为 true

返回码

code含义处理建议
200正常—
400请求参数不合法检查必填字段与类型
411请求频率过高降频后重试
5501时间戳过期校准服务器时间
5502参数缺失或格式错误对照参数表检查
5505nonce 格式错误或重复每次请求生成新的 32 位随机串
5506应用标识无效确认 app_id
5507token 为空检查客户端是否成功获取 token
5508签名错误核对排序与拼接规则
5509应用已停用联系管理员
5510配额或调用次数超限联系管理员调整配额
5511重复请求本服务默认返回 cached=true,不报错
5512token 非法或过期重新获取 token 后重试一次
5514处理超时可按退避策略重试
5515处理失败重试仍失败请携带 task_id 反馈
5521可重试失败稍后重试

业务侧约定

  • 返回的 device_token 按现有方式加密存储,请求时解密放入请求头;存储层无需改动。
  • pending=true 时保留本地已有标识,不要覆盖。
  • token 获取失败(202)时本次不送检,不影响业务主流程。
  • 服务不可用时沿用本地已有标识,避免阻塞下单、登录等主链路。
存量标识与旧值不同时,切换初期会出现同一设备换 ID 的情况,建议先在单一端灰度。