DeviceTrust 接入手册
先在工作台创建应用,再连接 Android SDK 与业务服务。应用密钥只保存在业务服务端。
01 / 接入准备
| 入口 | 地址 |
|---|---|
| 工作台 | https://devicetrust-console.lingzidev.com |
| 业务与上报 API | https://devicetrust-sdk-api.lingzidev.com |
| 版本 | Android SDK 0.4.1 / Android 7.0+ / 四种 ABI |
- 在“应用管理”创建应用,包名填写 Android applicationId。
- 保存创建时展示的应用 ID 与应用密钥,后者只展示一次。
- “接入保护”默认开启签名上报。硬件证明需要配置 APK 证书 SHA-256,再开启并进行目标机型验收。
- 策略先使用观察模式评估风险;确认业务处置已接入后切换执行模式。
02 / Android SDK
下载 SDK 包,将 sdk-0.4.1.aar 和 sdk-secure-0.4.1.aar 放入 app/libs。可选模块独立引入;安全模块包含已经混淆的原生库。
// app/build.gradle
dependencies {
implementation files('libs/sdk-0.4.1.aar')
implementation files('libs/sdk-secure-0.4.1.aar')
// 可选:sdk-environment、sdk-rootbeer
// RootBeer 适配还需 com.scottyab:rootbeer-lib:0.1.2
}在用户同意采集后,于后台线程调用。challenge 由你的业务服务创建后返回 App,businessToken 是业务登录会话;完整在线体验代码在 SDK 包 examples 中。
String api = "https://devicetrust-sdk-api.lingzidev.com";
String[] pins = {"AU7LGDAFJUgs4HkcpRf1O7/6OU9avVMvle6wTsAK5m4="};
String keyId = SecureReporter.keyId(context, appId);
// 将 keyId 提交给业务服务,取得绑定本次业务的 challenge。
JSONObject report = DeviceTrust.collect(context,
new DeviceTrust.Options(appId, false), true);
JSONObject result = SecureReporter.upload(
context, api, pins, challenge, report);
String reportId = result.getString("reportId");
// reportId 回传业务服务进行事件评估与执行授权。导入 com.device.trust.DeviceTrust 与 com.device.trust.secure.SecureReporter。SDK 会生成 Keystore 密钥、注册证明并提交二进制帧。密钥注册过期时,服务端下发新注册挑战。pin 为 API 证书 SPKI 的 SHA-256/Base64,证书公钥轮换需先发布包含新旧 pin 的 SDK 配置。
03 / 业务服务端
所有业务接口使用 Authorization: Bearer <应用密钥>。账号、订单和金额来自业务服务,不采用客户端自报值。eventId 在应用内唯一,并持久保存以支持重试。
POST /v1/challenges
Content-Type: application/json
Authorization: Bearer <APP_KEY>
{
"appId": "APP_ID",
"eventId": "registration-20261111-001",
"accountId": "ACCOUNT_ID",
"type": "register",
"clientIp": "203.0.113.10",
"context": {},
"keyId": ""
}首次 keyId 为空,其后填写 SDK 返回的 keyId。挑战有效期 3 分钟,将响应原样交给 SDK。得到 reportId 后,使用原挑战的账号、类型、IP 与上下文提交:
POST /v1/events
Authorization: Bearer <APP_KEY>
{
"appId": "APP_ID",
"eventId": "registration-20261111-001",
"reportId": "REPORT_ID",
"accountId": "ACCOUNT_ID",
"type": "register",
"clientIp": "203.0.113.10",
"context": {}
}type 为 register、reward、payment 或业务自定义事件类型。营销 context 使用 campaignId、recipientId;支付使用 orderId、paymentMethodId、amountMinor、currency。金额按最小货币单位。支付工具和收款对象使用业务侧去标识化代号,不上传完整卡号。响应包含 score、action、mode、reasons 与策略版本;action 为 observe、verify、hold。
04 / 连接实际处置
执行模式下,核验或暂缓事件须先取得批准。业务服务应在完成真实核验后提交结果,或交由工作台审批。
POST /v1/decisions/resolve
{"appId":"APP_ID","eventId":"EVENT_ID",
"resolutionId":"VERIFY_RESULT_ID","status":"approved"}
POST /v1/decisions/claim
{"appId":"APP_ID","eventId":"EVENT_ID",
"operationId":"BUSINESS_OPERATION_ID"}
POST /v1/executions
{"appId":"APP_ID","eventId":"EVENT_ID",
"operationId":"BUSINESS_OPERATION_ID","token":"CLAIM_TOKEN",
"receiptId":"RECEIPT_ID","status":"succeeded",
"reference":"BUSINESS_REFERENCE"}上述请求都需要应用密钥。claim 的 token 与 expiresAt 是执行凭据,首次领取限事件或批准后 5 分钟内;业务必须检查到期时间,在自己的数据库按 operationId 原子幂等提交。相同授权重试用于恢复回执,不启动第二次业务效果。支付真实回调通过 /v1/outcomes 进行结果回流,字段见下载包 integration.md 与 business-risk.md。
05 / 签名与设备真实性
TLS 校验证书链、主机名和 SPKI;设备报告使用 DTP4 二进制帧、P-256 ECDH、HKDF-SHA256、AES-256-GCM 和 SHA256withECDSA。签名覆盖头与密文,服务端将挑战绑定到账号和业务。NDK 编排密码调用,Keystore 私钥不导出,四架构原生库经 xollvm 混淆。
signature_only 表示持钥签名;tee/strongbox 表示通过硬件证明。硬件证明校验可信根、撤销状态、挑战、启动锁定、包名和 APK 签名。证明反映注册时状态,不保证其后所有信号真实。设备被完全控制时,混淆与固定证书也不能保证绝对不可抓包。完整帧格式与约束见 SDK 包 secure-protocol.md。
06 / 在线体验
- 下载并安装体验 APK,默认服务已配置,无需 USB 端口转发。
- 用管理员提供的体验密码登录,账号填写自选测试名称;同意采集后尝试注册、奖励或支付。
- 进入工作台查看事件。遇到等待核验/审核,在事件详情处理,再回 App 点“查询并继续”。
07 / 排查与重试
| 状态 | 处理 |
|---|---|
| 401 | 检查业务应用密钥或登录会话。 |
| 403 | 查看原始 error:证明、业务绑定、停用密钥或审批状态不满足。 |
| 409 | 同一 ID 已用于不同内容,修正幂等数据,不能覆盖旧记录。 |
| 410 | 挑战、注册或授权过期,按对应流程重新发起。 |
| TLS / pin mismatch | 核对服务域名、证书链与 SPKI,不能关闭证书验证。 |
服务端原始错误会保留。记录 eventId、reportId、发生时间和完整错误,排查时避免附带应用密钥或用户敏感信息。