Android SDK 0.1.4
接入文档
SDK 提供登录、设备风险采集和事件上报,负责会话缓存与上报重试。广告、提现和页面行为由宿主处理。
能力与入参
左侧查看开放能力,右侧看接入时的数据流向。点击条目查看具体用法。
-
登录与会话
ensureSession· 缓存复用、并发合并、加密持久化返回
userId / token / riskTolerance;可刷新、读取或观察会话 -
设备风控
自动采集 Root、ADB、模拟器、Hook、无障碍、VPN 等
业务无需实现检测;独立检测 / 扫描 API 可按需使用
-
事件上报
ReportQueue.report· 业务在真实事件发生时调用SDK 负责签名、持久化队列、断网 / 限流重试与会话恢复
-
初始化必填
context·baseUrl·bundleId·appSecretloginParameters回调提供deviceId、country -
调用时必填
登录:
scope登录态分组;上报:identityScope同一分组 +EventType创建队列:
RiskClient+ 应用级CoroutineScope -
可选覆盖
设备字段 ·
gaid / adid / network归因字段riskStatExtras追加业务字段;日志 / tag、会话通知等按需配置
scope / identityScope 是业务必传的登录态分组名,没有默认值;同一身份的登录与上报传同一个值。
CoroutineScope 则是队列运行的协程作用域。查看分组示例。
广告屏蔽、提现限制和页面提示由业务根据返回结果执行。
UNKNOWN 的处理见 版本说明。
业务传入
- 初始化
- Context · 域名
bundleId · 应用密钥 - 登录
- deviceId · country
scope 登录态分组 - 上报
- 同一分组 · EventType
Risk Control
登录与会话 · 设备检测 · 事件上报
签名 · 持久化 · 队列重试
业务获得
- 登录态
userId / token- 风控结果
riskTolerance- 通知
- 会话回调 / 状态流
上报回执:确认或失败
广告、提现和页面提示由业务处理。
Play Integrity · 按需独立调用
Context + Cloud 项目编号 → 加密 Token
业务提交后端验证,不自动接入登录。
添加依赖
在 App 模块添加依赖,并配置下方的 GitHub Packages 仓库。
dependencies {
implementation("com.remax:risk-control:0.1.4")
}
仓库凭据
在用户目录的
~/.gradle/gradle.properties 配置拥有该仓库 /
包读取权限、包含 read:packages 的 GitHub 令牌;CI
可用同名用途的环境变量。以下均为占位符。
gpr.user=YOUR_GITHUB_USERNAME
gpr.key=YOUR_GITHUB_PACKAGES_TOKEN
Maven 仓库
合并到宿主现有的
dependencyResolutionManagement。仓库凭据只参与 Gradle
下载;SDK 的 appSecret 是另一项业务配置。
dependencyResolutionManagement {
repositories {
google()
mavenCentral()
exclusiveContent {
forRepository {
maven {
url = uri("https://maven.pkg.github.com/toukaremax/risk-control")
credentials {
username = providers.gradleProperty("gpr.user")
.orElse(providers.environmentVariable("GITHUB_ACTOR")).orNull
password = providers.gradleProperty("gpr.key")
.orElse(providers.environmentVariable("GITHUB_TOKEN")).orNull
}
}
}
filter { includeModule("com.remax", "risk-control") }
}
}
}
传递依赖、权限与混淆
| 依赖 | 声明版本 | 用途 |
|---|---|---|
| kotlinx-coroutines-core | 1.10.2 | 挂起函数、StateFlow 和队列 |
| okhttp | 4.12.0 | HTTP 请求 |
| play:integrity | 1.6.0 | 可选 Play Integrity API |
| play-services-tasks | 18.2.0 | Play Integrity 的 Task 返回类型 |
以上依赖通过 Maven 元数据自动传递,最终版本由宿主 Gradle
冲突解析确定。AAR 合并 INTERNET、ACCESS_NETWORK_STATE
普通权限,无运行时授权弹窗。登录和事件上报无需接入内容签名插件或
Play Integrity。
SDK 发布 AAR 不预混淆,随宿主 Release 的 R8 一起处理;目前无需额外添加 SDK keep 规则。HTTP 明文地址是否允许由宿主网络安全配置决定。
最简接入
只需提供 Application Context、接口域名、BundleId、应用密钥、稳定设备 ID 和国家。 在 Application 或业务单例中创建一次,后续复用。
import com.remax.riskcontrol.sdk.client.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
val riskClient = RiskClient(
context = applicationContext,
config = RiskClientConfig(
baseUrl = apiBaseUrl,
bundleId = backendBundleId,
appSecret = backendAppSecret,
),
loginParameters = { scope ->
// 本例用国家代码作为登录态分组,因此 country 取 scope。
LoginParameters(deviceId = stableDeviceId, country = scope)
},
)
val applicationScope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
val reports = ReportQueue(riskClient, applicationScope)
型号、系统版本、运营商、UA、应用版本和 RiskStat 由 SDK 默认采集;登录态和事件队列默认持久化。
gaid / adid / network 由业务按需提供,不传则省略。
0.1.2 已默认将 UNKNOWN 按未发现上报,无需额外兼容回调。 见 RiskStat 的版本说明。
// 登录态分组名,由业务必传;本例按国家分组,设备身份固定。
val identityScope = "USA"
// 在业务协程中获取登录态,有缓存时直接复用。
val session = riskClient.ensureSession(identityScope)
// session.userId / session.token 供业务接口使用;使用前检查 canLogin 和凭据。
// 在真实事件发生时调用;SDK 自动登录、持久化和重试,无需等待回执。
reports.report(identityScope, ReportEventType.CONTENT_START)
reports.report(identityScope, ReportEventType.OPEN_PAYOUT_PAGE)
按需覆盖:业务已有的设备或归因值可直接传入 LoginParameters;
日志、会话通知、风险策略和网络配置均为可选项,见 配置参考。
登录态分组:登录参数叫 scope,上报参数叫 identityScope,含义相同。
同组复用登录态,不同组隔离;分组名是 SDK 内部标识,不作为接口字段发送。
单一身份可固定传 "default",此时 loginParameters 应独立提供真实的国家代码,不能把 default 当作 country。
按国家区分时可用 "USA" / "BRA" / "IDN";多账号还需包含账号标识。
分组名必须稳定、非空,切换身份时换组,并让 loginParameters(scope) 能根据分组返回对应的设备 ID 和国家,包括积压事件的旧分组。
创建 RiskClient 本身不登录;队列恢复积压事件时可能触发登录。队列使用 Application 生命周期。
登录态与风控
ensureSession 表示确保有可复用结果;有缓存时不会重新请求登录。
先查找内存会话;未命中时尝试恢复磁盘缓存,仍未命中才请求登录。恢复缓存或取得新登录结果后,触发
onSession。
| 公开函数 | 返回值 | 行为 |
|---|---|---|
state(scope: String) |
StateFlow<SessionState> | 观察 LoggedOut / LoggingIn / Authenticated(session) / Restricted(riskTolerance) / Failed(reason)。 |
currentSession(scope: String) |
RiskSession? | 仅读内存;不登录、不恢复磁盘。 |
suspend ensureSession(scope: String) |
RiskSession | 同一登录态分组的并发调用合并;优先内存,再恢复磁盘,最后登录。 |
suspend invalidateSession(scope: String, expected:
RiskSession)
|
Unit | 仅清除与 expected 相同实例的当前会话,同时清磁盘;旧请求不会误删较新的会话。 |
suspend refreshSession(scope: String) |
RiskSession | 主动清除缓存,再获取新登录结果。 |
RiskSession 返回值
| 字段 | 含义 |
|---|---|
scope: String |
对应的登录态分组名,由业务传入;与上报的 identityScope 使用同一个值。 |
userId: Long / token: String |
业务接口所用登录凭据。等级 3 可能缺少凭据,不能拿空凭据调用业务接口。 |
riskTolerance: Int |
原样保留服务端等级,见下表。 |
canLogin: Boolean |
riskTolerance 在 0..2 时为 true。 |
canWithdraw: Boolean |
riskTolerance 为 0 时为 true。 |
isRestored: Boolean |
true 表示从磁盘恢复,是旧决策,不是刚取得的服务端结果。 |
| 等级 | SDK 语义 | 短剧目前采用的业务策略 |
|---|---|---|
| 0 | 正常 | 允许广告和提现,清除旧限制。 |
| 1 | 限制提现 | 提现入口提示,不限制广告。 |
| 2 | 限制广告和提现 | 调用广告屏蔽 API,提现入口提示。 |
| 3 | 本次不可登录;canLogin=false | 短剧同样屏蔽广告和提现,SDK 仍保留等级 3。 |
SDK 不调用广告库、不弹 Toast、不关闭应用,也不代替业务判断提现。是否上报以是否有完整凭据为准;等级 1 / 2 仍可上报。等级 3 无 Token 时失败结束,不循环登录。
业务接口如何无感刷新
SDK 自动处理自己的 report 会话失效。提现等宿主接口继续由现有拦截逻辑识别失效,并调用以下公共函数:
// failedSession 必须是这次失败请求实际使用的会话对象。
riskClient.invalidateSession(identityScope, failedSession)
val refreshed = riskClient.ensureSession(identityScope)
// 由业务决定是否使用 refreshed 重发该业务请求,并限制恢复次数。
// 不要将所有业务错误都当成 Token 失效。
SDK 的会话失效兼容条件为 Result=201 / 406 或
HTTP 401。单独 HTTP 406
不算;这是当前客户端兼容规则。
缓存隔离与持久化细节
默认以 Android Keystore AES-GCM 加密 Token、UserId、RiskTolerance 等会话数据,存入私有 SharedPreferences。按宿主包名、规范化 baseUrl(含路径)、bundleId、appSecret 和 scope 隔离,恢复时校验 DeviceId / Country。加密不可用时只用内存,不降级明文。
SDK 不猜测 Token 有效期;久未使用的缓存可先复用,服务端返回失效后再刷新。等级 3 不保存成可恢复会话,但进程内保留决策,防止循环重登。新登录时才能拿到新风控结果。
业务广告 / 提现策略的持久化由宿主维护。短剧会单独保存限制;磁盘恢复的旧会话不会覆盖更新的业务限制。新登录结果为 0 时清除限制,失败 / 离线时不自动放行。
事件上报
普通业务全部使用 ReportQueue。SDK 负责登录、签名、持久化、串行发送和失败重试。
// scope 是应用级 CoroutineScope,store 通常省略。
val reports = ReportQueue(client = riskClient, scope = applicationScope)
val receipt: ReportReceipt = reports.report(
identityScope = identityScope, // 必填:登录态分组,与 ensureSession 的 scope 一致
type = ReportEventType.AD_COMPLETE,
value = revenue, // Double;默认 0.0,必须非负且有限
)
// receipt.id 是本地事件 ID;不会作为幂等键发送给后端。
// 在协程中 receipt.await() 等待确认或失败;取消等待不取消事件。
| 枚举 | EventType | 业务调用位置 / Value |
|---|---|---|
NOTHING |
0 | 空事件,按服务端用途使用。 |
CONTENT_COMPLETE |
1 | 内容完成的既有业务回调,通常 Value=0。 |
AD_COMPLETE |
2 | 短剧沿用广告收益回调,Value=收益,单位沿用服务端约定;不是广告关闭回调。 |
CONTENT_START |
4 | 播放器实际开始播放的回调;宿主避免缓冲 / 暂停恢复重复计数。 |
OPEN_PAYOUT_PAGE |
5 | 进入提现页面后,Value=0;入口被拦截未进页面不报。 |
当前不提供广告开始
AD_START / 3。开发工具可以直接调用相同公共队列,模拟内容开始、提现页打开等事件。
{
"EventType": 5,
"Value": 0,
"Timestamp": 1793318400,
"Retry": 0
}
Timestamp 是入队时记录的事件 UTC Unix
秒,重试保持原值。Retry 首次即传
0;同一事件重发递增。每次请求头 Timestamp / Nonce / Sign
会重新生成。仅登录阶段失败时,尚未发出 report,不增加该事件的
Retry。
单次调用:reportOnce
riskClient.reportOnce(
scope = identityScope,
type = ReportEventType.CONTENT_START,
value = 0.0,
timestampSeconds = occurredAtUtcSeconds, // 可省略,默认当前 UTC 秒
)
挂起函数,返回 Unit;不持久化,不做网络 / 429 定时重试,仅支持一次失效会话恢复重发。常规业务和短剧开发工具均应使用 ReportQueue。
队列与重试
同一队列按入队顺序发送。网络恢复由定时尝试发现,没有主动注册网络恢复监听。
- 第一次重试:等待 30 秒。
- 第二次重试:等待 2 分钟。
- 第三次重试:等待 5 分钟。
- 之后每 30 分钟重试一次。
前三档最多追加 20% 随机延迟;之后每 30 分钟一次。与服务端
Retry-After 取较长时间。网络失败与 HTTP 429
共用退避次数。
| 结果 / 情况 | 队列处理 |
|---|---|
| 断网、连接失败、读写超时、HTTP 429 | 保留事件、持久化下次尝试时间;队首等待期间,后续事件排队。 |
| report 会话过期 | 清除失效会话、重新登录,原事件最多立即恢复重试一次;网络 / 限流重试不重置该次数。 |
| 服务端成功 | 移除持久化记录,完成回执并记录 ack;不另外保存成功历史。 |
| 业务错误、其他 HTTP 错误(含普通 5xx)、无效 JSON、明确证书 / 主机名校验失败 | 完成失败并移出队列,继续后续事件。 |
| 风控拒绝且缺少凭据 | 失败结束,不自动循环登录。 |
| App 进程退出 | 下次初始化队列恢复;上次仍标记发送中的事件按不确定尝试保留,增加 Retry 并退避。 |
| 持久化读写失败 | 停止本轮发送并通知当前等待方,不盲目继续发请求。 |
成功口径、重复发送和生命周期边界
- 当前成功判断是 HTTP 2xx + 可解析 JSON + 解析后的 Result=0。兼容解析中缺失 / 非数字 Result 会按 0 处理,并非只接受显式 HTTP 200 / Result=0。
- 本地删除发生在成功响应后;终止类错误也会删除,但回执失败、日志为 failed。调用 report 返回回执不等于已经成功,也不等于已写盘。
- 超时可能发生在服务端已接收之后;目前后端没有事件幂等键,因此重发有重复计数可能。receipt.id 只用于本地跟踪。
- 重试由循环和挂起 delay 实现,不递归增加调用栈。没有队列容量上限或自动过期清理,长期离线持续入队会增加存储占用。
- 进程存活时按计时器重试,进程结束后等待下次启动;不创建系统后台任务。重启 / 新事件不会重置已经持久化的退避时间。
- 默认 SharedPreferences 存储按宿主包名、baseUrl(含路径)、bundleId 隔离;密钥轮换不会切换事件队列。每份存储使用一个队列实例。
RiskStat
SDK 默认自动采集并拼接 RiskStat,业务无需实现检测或手动调用采集函数。 原始检测结果区分 DETECTED、NOT_DETECTED 和 UNKNOWN。
自定义策略可通过 deviceRisk 返回调整后的结果;明确状态会按业务值上报。
显式传 deviceRisk = null 或回调返回 null,则省略整个 RiskStat。
追加业务字段:riskStatExtras(0.1.3 起)
新增可选 riskStatExtras: suspend (scope: String) -> Map<String, Any?>。
业务可直接返回缓存,也可挂起等待结果;每次真实登录在 IO 调用,并等返回后再合并、签名和发送。
等待时长及失败时是否继续登录由业务决定。同组并发登录共用本次等待,内存或磁盘会话命中时不调用。
// 添加到 RiskClient(...) 参数中;awaitPlayResult 是业务函数。
// PlayInstall 仅为示例字段名,须与后端约定。
riskStatExtras = { scope ->
val result = kotlinx.coroutines.withTimeoutOrNull(1_000) {
awaitPlayResult(scope)
}
mapOf("PlayInstall" to result)
},
不需要等待时直接读取业务缓存即可。支持字符串、布尔及有限的基本数值类型;null 字段省略,空 Map 保留默认字段。 内置字段仍通过 deviceRisk 调整;冲突键、空白键及不支持的值会使本次登录失败。 回调异常和取消向外传播,需要继续登录时由业务处理并返回空 Map。 显式省略整个 RiskStat 时也跳过扩展回调。SDK 不因此自动执行 Play Integrity,字段值由业务提供。
仅 0.1.1 需要:UNKNOWN 按未发现处理
在 RiskClient 构造参数中补充以下回调。升级到 0.1.2 后可省略。
// Status 来自 com.remax.riskcontrol.sdk.Status。
// 添加到 RiskClient(...) 的参数中:
deviceRisk = {
val observed = collectDeviceRisk(applicationContext)
fun resolve(value: Status) =
if (value == Status.UNKNOWN) Status.NOT_DETECTED else value
observed.copy(
root = resolve(observed.root), adb = resolve(observed.adb),
emulator = resolve(observed.emulator), hook = resolve(observed.hook),
accessibility = resolve(observed.accessibility), vpn = resolve(observed.vpn),
)
}
| DeviceRisk 字段 | RiskStat 字段 | 含义 |
|---|---|---|
| networkType / timezone / locale | NetworkType / Timezone / Locale | 当前网络类型、时区、系统语言标记。 |
| root | Milan | Root 检测。 |
| adb | Como | ADB 开关;与调试器检测分开。 |
| emulator | Lazio | 模拟器检测。 |
| hook | Roma | Hook 检测。 |
| accessibility | Genoa | 无障碍服务检测。 |
| vpn | Verona | 默认网络 VPN;不把单纯代理当 VPN。 |
collectDeviceRisk(context: Context): DeviceRisk
是挂起函数,内部切换 IO。DeviceRisk.toJson(): JSONObject
将 DETECTED 编码为 0、NOT_DETECTED 编码为 1;UNKNOWN 按上方版本说明处理。
采集只包含登录需要的设备项,不进行完整 APK
扫描,也不请求 Play Integrity Token。
需要独立检测时可用
RiskScanner.scan() 或直接检测函数,详见
设备检测与可选插件指南 ↗。这部分是 SDK 的独立能力。
调试日志
所有 login / report 请求及响应、RiskStat 明细和队列状态,统一使用 RiskClient 的 debug 配置。
从 0.1.4 起,RiskStat 和 EventType 的释义直接拼在请求日志的 JSON 值中, 不再另外输出释义段。字段名不变,原始 UNKNOWN 会注明“未知,按未发现上报”。 业务追加的 RiskStat 字段保留原样。
带释义的字符串仅用于 debug 日志;实际 HTTP 仍发送原协议值和类型,签名不变。例如日志中的 EventType 为“4(CONTENT_START,内容开始)”,实际发送的仍是数字 4。
RiskClientConfig(
baseUrl = baseUrl,
bundleId = bundleId,
appSecret = appSecret,
debug = RiskDebugConfig(enabled = BuildConfig.DEBUG, tag = "CoreModule"),
)
// 可选:传给 RiskClient 的 diagnostics 参数。
val diagnostics = RiskDiagnostics { tag, message ->
android.util.Log.d(tag, "MultiCountryPayout: " + message)
}
request /user/login headers=
{ ... } body=
{
"DeviceId": "example-device",
"Country": "USA",
"RiskStat": {
"NetworkType": "wifi(网络类型)",
"Timezone": "Asia/Shanghai(时区)",
"Locale": "en-US(系统语言)",
"Milan": "1(Root,未发现)",
"Como": "0(ADB 调试,已检测到)",
"Lazio": "1(模拟器,未发现)",
"Roma": "1(Hook,未知,按未发现上报)",
"Genoa": "1(无障碍服务,未发现)",
"Verona": "0(VPN,已检测到)"
}
}
request /user/report headers=
{ ... } body=
{
"EventType": "4(CONTENT_START,内容开始)",
"Value": 0,
"Timestamp": 1793318400,
"Retry": 0
}
response /user/report http=200 result=0 body=
{
"Result": 0
}
report_queue ack type=CONTENT_START retry=0
report_queue retry type=CONTENT_START reason=network login_only=false delay_ms=32000
默认 enabled=false,不传 tag 时为
RiskControl。开启后完整打印请求头 / 正文 /
响应,包括 Token、DeviceId、UserId、Sign 等,不脱敏;RiskStat 和 EventType 的日志值附带释义。JSON
两空格缩进,长消息分段编号;不改变实际请求正文和签名。appSecret
本身不是请求字段,不单独输出。
| 操作 | 线程行为 |
|---|---|
| HTTP、默认采集、会话与队列磁盘 IO | SDK 内部在 IO 执行,report 可由主线程触发。 |
| 参数校验、读内存、事件时间记录 | 在调用线程执行。 |
| loginParameters / deviceRisk | IO 上执行。 |
| onSession | 调用协程的上下文,不保证 Main;UI 更新自行切主线程或观察 StateFlow。 |
| RiskDiagnostics.log | 可能后台调用;日志回调异常不会破坏业务。 |
| 独立 checkRoot 等同步检测函数 | 调用方负责放后台;RiskScanner 使用内部工作线程。 |
配置参考
可选参数省略时使用默认实现;只覆盖业务已经维护的字段。
RiskClientConfig
| 参数 | 默认值 / 要求 | 作用 |
|---|---|---|
baseUrl: String |
必填 | 后端根地址,拼接 /user/login 和 /user/report;支持根地址包含路径。 |
bundleId: String |
必填 | 服务端应用标识并参与签名,可与开发 APK 的包名不同。 |
appSecret: String |
必填 | login 签名密钥,不是 GitHub Packages 令牌。 |
debug: RiskDebugConfig |
enabled=false tag="RiskControl" |
统一控制 login、report、队列日志,可覆盖 tag。 |
persistSession: Boolean |
true | 加密保存登录态;false 时只使用内存,不影响事件持久化。 |
RiskClient 构造参数
| 参数 | 默认 / 类型 | 调用时机与用途 |
|---|---|---|
config |
必填 · RiskClientConfig | 服务配置。 |
context |
必填 · Context | 内部仅保留 applicationContext,用于设备默认值、采集、持久化。 |
loginParameters |
必填 · suspend (String) → LoginParameters | 接收登录态分组名 scope,向业务获取该组的设备 ID、国家和其他登录字段。IO 上执行;首次校验磁盘缓存及每次真实登录调用,内存命中不调用。 |
deviceRisk |
可选 · suspend () → DeviceRisk? | 默认 collectDeviceRisk(context),真实登录时在 IO 采集。可覆盖采集或映射策略;UNKNOWN 处理见 RiskStat 的版本说明。 显式传 null 或返回 null 省略 RiskStat。 |
riskStatExtras |
可选 · 0.1.3 起 | 挂起回调,根据 scope 追加 RiskStat 字段;真实登录在 IO 等待返回,超时与降级由业务决定。见 RiskStat 章节。 |
client |
可选 · OkHttpClient | 默认 connectTimeout=15 秒、readTimeout=30 秒。report 使用派生 client,关闭自动连接重试和重定向;login 保留传入配置。 |
nowEpochSeconds |
可选 · () → Long | 默认系统 Unix 秒。请求签名、Retry-After 计算、reportOnce 默认时间使用它。队列事件时间独立在入队时采集。 |
nonceSource |
可选 · () → String | 默认 UUID;每次带会话的请求产生新 Nonce。login 不使用 Nonce。 |
diagnostics |
可选 · RiskDiagnostics | 默认 Android Log.d;debug 开启时收到 tag 和文本,可接宿主日志系统。 |
onSession |
可选 · (RiskSession) → Unit | 默认空函数。恢复磁盘或新登录结果写入内存 / 状态后通知业务,包括等级 3;内存命中、登录失败不通知。 |
LoginParameters
| 参数 → 协议字段 | 默认行为 | 覆盖规则 |
|---|---|---|
deviceId → DeviceId |
必填非空 | 沿用宿主稳定设备 / 用户身份。 |
country → Country |
必填非空 | 服务端约定的地区代码。 |
deviceType → DeviceType |
厂商 + 型号 | null 使用默认值;非 null 使用传入值。 |
deviceVersion → DeviceVersion |
Android OS 版本 / API / Build | 同上。 |
isp → Isp |
系统运营商名(尽力获取) | null 尝试默认值;空串省略字段。 |
userAgent → UserAgent |
WebSettings 默认 UA / http.agent | null 尝试默认值;空串省略字段。 |
version → Version |
宿主 versionName | null 使用默认值;非 null 使用传入值。 |
gaid → Gaidadid → Adidnetwork → Network
|
不自动采集归因信息 | 由业务提供,null / 空串省略。 |
Network 是业务归因渠道,RiskStat.NetworkType
是当前设备网络类型,两者含义不同。
辅助 API
标准接入省略 store 即可。仅兼容旧队列或有独立存储需求时覆盖。
ReportStore.preferences(...) 可指定持久化名称并迁移旧 scope;
ReportStore(read, write, legacyScope) 可对接业务存储。
显式传入无参数的 ReportStore() 会使用纯内存,普通接入应省略 store。
| 辅助 API / 类型 | 用途 |
|---|---|
RiskProtocol.sign(content: String, key: String):
String
|
HMAC-SHA256,输出小写十六进制;供确需自行适配业务签名的宿主使用,login/report 已自动签名。 |
riskRetryAfterMillis(value: String?, nowMillis: Long):
Long?
|
解析 Retry-After 秒数或 HTTP 日期,返回等待毫秒;无效 / 不支持返回 null。 |
RiskServiceException |
提供 httpCode、result、serverMessage、retryAfterMillis、requestPath,以及 isExpiredSession()。 |
RiskRestrictedException |
提供 riskTolerance,表示缺少可用凭据的风控结果。 |
ReportReceipt |
id: String;suspend await(): Unit。成功确认时完成,终止失败抛异常;只是服务确认,不代表业务收益到账。 |
RiskDiagnostics |
函数接口 log(tag: String, message: String)。 |
ReportStore(read, write, legacyScope) |
read: () → String?;write: (String) → Unit;legacyScope: (String?) → String?。省略三者为纯内存存储。 |
普通 IOException、参数校验异常也可能返回给调用方;协程取消继续传播。SDK 没有对外提供手动 flush、成功历史查询、重试次数配置或队列清空函数。
更新记录
0.1.4 · 已发布
RiskStat 和 EventType 释义合并到请求日志 JSON 中,移除独立释义段。保留业务扩展字段、debug 开关和自定义 tag;实际 HTTP 请求、协议类型及签名不变。
0.1.3 · 已发布
新增 riskStatExtras 挂起回调,可在默认 RiskStat 中追加业务字段,由业务决定是否等待结果及超时策略;保留原构造函数。report 调试日志补充 EventType 中文释义。能力与入参增加接入示意图。
0.1.2 · 已发布
UNKNOWN 默认按未发现上报,保留原始检测状态和业务自定义能力;login 日志增加 RiskStat 字段释义。接入文档补充最简示例、能力导图和登录态分组说明。
0.1.1 · 已发布
- 统一 HTTP 日志:login / report 的请求、响应和 RiskStat 明细;JSON 格式化,长日志分段。
- 修复主线程发请求:开发工具由 Main 触发事件时,队列显式调度至 IO。
- 持久化网络重试:断网 / 超时保留事件,使用 30 秒 → 2 分钟 → 5 分钟 → 30 分钟退避。
- 恢复未确认事件:重启保留事件时间、Retry 和退避进度,继续尝试未确认的发送。