> >

极验设备指纹 GeeGuard 面向开发者快速集成指南

本文用于让开发者在不跳转多份文档的情况下完成极验设备指纹(GeeGuard)的标准接入。除非需要自定义风险策略、账号画像字段、私有化域名或特殊端能力,按本文即可完成客户端采集、业务提交、服务端查询、风险处置、异常排查和联调验收。

参考来源:

1. 接入目标

GeeGuard 适合保护这些高风险动作:

  • 登录、注册、找回密码
  • 下单、支付、提现、领券、参与活动
  • 内容发布、评论、点赞、关注
  • 账号绑定、实名、设备绑定
  • 后台敏感操作和接口防刷

推荐原则:

  • 客户端负责初始化 SDK / JS / 小程序插件,并在业务动作发生前生成 gee_tokenrespondedGeeToken
  • 客户端把 gee_token 随业务参数提交给业务服务端。
  • 服务端必须调用极验 token_query 查询风险结果。
  • 服务端结合 risk_levelrisk_codeip_type 和业务自身策略做处置。
  • 高风险业务建议按 reject 拒绝、review 二次校验、pass 放行处理。
  • 设备指纹接口异常时,官方示例倾向“通常直接放过,不做任何风险封禁操作”。实际生产可按业务风险等级决定失败放行、二次验证或人工审核。

不能只做客户端采集。gee_token 本身不是最终风险结论,最终可信判断必须由服务端调用极验查询接口完成。

2. 标准交互流程

sequenceDiagram
participant U as User
participant C as Client
participant B as Business Server
participant G as GeeTest RiskCT

C->>C: 应用启动/页面加载时注册 app_id
U->>C: 触发登录、注册、下单等业务动作
C->>C: 使用业务流水号生成 GeeGuardReceipt
C-->>B: 提交业务参数 + gee_token/respondedGeeToken
B->>B: 使用 private_key 生成 sign_token
B->>G: POST /g2/api/v1.1/token_query
G-->>B: 返回 risk_level/risk_code/root_id/ip_type
B->>B: 按风险策略放行、复核或拒绝
B-->>C: 返回业务结果

3. 必要参数

3.1 控制台参数

参数 来源 所在端 用途
app_id / appId 极验后台 客户端、服务端 设备指纹应用 ID,客户端初始化和服务端查询都需要
private_key 极验后台 仅服务端 生成 sign_token,严禁下发到客户端

3.2 客户端提交给服务端的参数

参数 必填 说明
gee_token 客户端 SDK / JS / 插件采集生成的数据,有效期 10 分钟
business_id 强烈建议 唯一标记本次业务的流水号或凭证,用于防止 GeeToken 与业务场景剥离
业务字段 按需 登录账号、订单号、活动 ID 等业务数据

说明:

  • Android、iOS、HarmonyOS 既可提交 receipt.geeToken,也可优先提交 receipt.respondedGeeToken
  • respondedGeeToken 获取失败时,如果 SDK 同时返回了 geeToken,可降级提交 geeToken 查询。
  • Web / H5 和小程序通常直接返回 gee_token

3.3 服务端提交给极验的参数

参数 必填 说明
app_id 极验后台创建应用后生成的应用 ID
gen_time 秒级时间戳,用于签名
gee_token 客户端提交的 gee_tokenrespondedGeeToken
sign_token private_keyapp_id + gen_time 做 HMAC-SHA256 后得到
scene loginsign_upactivity,默认 activity
attr.user_ip 用户 IP,支持 IPv4 和 IPv6;ip_type 当前只支持国内 IPv4
attr.op_timestamp 条件必填 需要账号画像标签时必填,C 端用户发起业务操作的秒级时间戳
attr.user_id 条件必填 需要账号画像标签时必填,按 user_id_type 传入账号标识
attr.user_id_type 条件必填 2 手机号、102 MD5 手机号、103 SHA256 手机号、3 QQOpenID、4 WechatOpenID

sign_token 生成规则:

gen_time = 当前秒级时间戳
sign_token = HMAC_SHA256_HEX(key = private_key, message = app_id + gen_time)

4. 服务端快速接入

4.1 GeeToken 查询接口

接口地址 https://riskct.geetest.com/g2/api/v1.1/token_query
请求方式 POST
Content-Type application/json
返回格式 json

请求体:

{
"app_id": "你的 app_id",
"gen_time": 1710000000,
"sign_token": "HMAC-SHA256 签名",
"scene": "login",
"gee_token": "客户端提交的 gee_token",
"attr": {
"user_ip": "127.0.0.1",
"op_timestamp": 1710000000,
"user_id": "13888888888",
"user_id_type": 2
}
}

成功响应:

{
"status": "success",
"code": 0,
"data": {
"local_id": "247A8CCF15054743B781759621570060",
"root_id": "GEE4-01-xxxx",
"risk_code": [10001, 20400, 20501],
"risk_level": "review",
"ip_type": 4,
"sign": "业务数据签名",
"ts": 1666772160860,
"client_ts": 1655369276590
}
}

核心字段处理:

  • risk_level = pass:无明显恶意,通常直接放行。
  • risk_level = review:结合业务策略处理,可要求短信、人机验证、人工审核或限额。
  • risk_level = reject:高风险,建议拒绝、封禁或冻结相关动作。
  • risk_level = null:未取到有效建议,结合 risk_code 和业务策略兜底。
  • risk_code:命中的设备、IP、账号风险码,用于解释和细分处置。
  • root_id:服务端生成的设备指纹,可用于设备维度风控、黑白名单和关联分析。

4.2 Node.js 服务端模板

import { createHmac } from "node:crypto";

const GEEGUARD_APP_ID = process.env.GEEGUARD_APP_ID;
const GEEGUARD_PRIVATE_KEY = process.env.GEEGUARD_PRIVATE_KEY;

function buildGeeGuardSignToken(appId, privateKey, genTime) {
return createHmac("sha256", privateKey)
.update(`${appId}${genTime}`)
.digest("hex");
}

function normalizeRiskDecision(gt) {
if (gt.status !== "success" || gt.code !== 0 || !gt.data) {
return { action: "review", reason: gt.msg || "geeguard query failed" };
}

const level = gt.data.risk_level;
if (level === "reject") return { action: "reject", reason: "device risk reject" };
if (level === "review" || level == null) return { action: "review", reason: "device risk review" };
return { action: "pass", reason: "device risk pass" };
}

async function queryGeeGuard({ geeToken, scene, userIp, userId, userIdType }) {
const genTime = Math.floor(Date.now() / 1000);
const body = {
app_id: GEEGUARD_APP_ID,
gen_time: genTime,
sign_token: buildGeeGuardSignToken(GEEGUARD_APP_ID, GEEGUARD_PRIVATE_KEY, genTime),
scene: scene || "activity",
gee_token: geeToken,
attr: {
user_ip: userIp,
op_timestamp: genTime
}
};

if (userId && userIdType) {
body.attr.user_id = userId;
body.attr.user_id_type = userIdType;
}

const response = await fetch("https://riskct.geetest.com/g2/api/v1.1/token_query", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
signal: AbortSignal.timeout(3000)
});

if (!response.ok) {
throw new Error(`geeguard http ${response.status}`);
}

return response.json();
}

app.post("/api/protected-action", async (req, res) => {
try {
if (!req.body.gee_token) {
return res.status(400).json({ result: "fail", reason: "missing gee_token" });
}

const gt = await queryGeeGuard({
geeToken: req.body.gee_token,
scene: "login",
userIp: req.ip,
userId: req.body.phone,
userIdType: req.body.phone ? 2 : undefined
});

const decision = normalizeRiskDecision(gt);
if (decision.action === "reject") {
return res.status(403).json({ result: "fail", reason: decision.reason, risk: gt.data });
}
if (decision.action === "review") {
return res.status(202).json({ result: "review", reason: decision.reason, risk: gt.data });
}

// 执行业务动作。
return res.json({ result: "success", risk: gt.data });
} catch (error) {
// 设备指纹异常时不要直接做风险封禁;按业务风险等级决定放行或二次验证。
return res.status(202).json({
result: "review",
reason: "geeguard unavailable"
});
}
});

4.3 风险处置建议

结果 默认动作 适用场景
risk_level=pass 放行并记录 root_id 普通登录、浏览、低价值动作
risk_level=review 二次验证、限频、限额或人工审核 注册、领奖、下单、提现
risk_level=reject 拒绝、封禁、冻结或拦截 批量注册、薅羊毛、接口攻击
查询失败 / 超时 不建议直接封禁;进入 review 或按低风险放行 极验接口异常、网络抖动

5. 全客户端快捷部署

5.1 Web / H5

适用:PC Web、移动 H5、内嵌 WebView。

步骤:

  1. 引入线上 JS:
<script src="https://static.geetest.com/g5/gd.js"></script>
  1. 页面加载或业务动作前调用 initGeeGuard
  2. 配置 appId,必要时传入 customInfo 绑定业务流水号。
  3. 成功回调中读取 data.data.gee_token
  4. gee_token 随业务参数提交服务端。
  5. 服务端调用 token_query 查询风险结果。

核心代码:

<script src="https://static.geetest.com/g5/gd.js"></script>
<script>
function getGeeToken(businessId) {
return new Promise((resolve, reject) => {
initGeeGuard(
{
appId: "你的 appId",
protocol: "https://",
networkTimeout: 10000,
customInfo: businessId
},
function (data) {
if (data.status === "success" && data.data && data.data.gee_token) {
resolve(data.data.gee_token);
} else {
reject(data.data || data);
}
}
);
});
}
</script>

注意:

  • appId 必填。
  • offlineapiServersstaticServers 等配置除非明确需要,不要随意设置。
  • 本地或混合开发环境可能取到 file: 协议,建议显式设置 protocol: "https://"
  • customInfo 建议传唯一业务流水号,防止 gee_token 被挪用到其他业务场景。

5.2 Android 原生

环境要求:

  • Android 5.0+,minSdk 21。
  • Android Studio 2022.2.1+,AGP 8+。
  • SDK 无第三方依赖。

步骤:

  1. 从极验后台下载 Android SDK。
  2. geetest_geeguard_android_vx.y.z_date.aar 放入 libs
  3. repositories 添加 flatDir { dirs 'libs' }
  4. 添加依赖 implementation(name: 'geetest_geeguard_android_vx.y.z_date', ext: 'aar')
  5. 添加 INTERNET 权限;如需日志分析,可按需申请存储权限。
  6. 添加混淆规则:
-dontwarn com.geetest.geeguard.**
-keep class com.geetest.geeguard.**{*;}
  1. 应用启动后立即注册 GeeGuard.register(context, appId)
  2. 业务动作发生时调用 GeeGuard.fetchReceipt(context, data)GeeGuard.submitReceipt(context, data, callback)
  3. receipt.respondedGeeTokenreceipt.geeToken 提交服务端。

Kotlin 核心代码:

class APP : Application() {
override fun onCreate() {
super.onCreate()
GeeGuard.register(this, "你的 appId")
}
}

fun getGeeToken(context: Context, businessId: String) {
val receipt = GeeGuard.fetchReceipt(context, businessId)
if (receipt != null) {
submitBusiness(geeToken = receipt.geeToken)
}
}

fun getRespondedGeeToken(context: Context, businessId: String) {
GeeGuard.submitReceipt(context, businessId) { status, receipt ->
when (status) {
200 -> submitBusiness(geeToken = receipt.respondedGeeToken)
-300, -500, -501 -> submitBusiness(geeToken = receipt.geeToken)
-200 -> showError("GeeGuard 未注册 appId")
}
}
}

5.3 iOS 原生

环境要求:

  • iOS 9+。
  • Xcode 13+。
  • SDK 无第三方依赖。

步骤:

  1. 从极验后台下载 GeeGuardSDK.xcframeworkGeeGuardSDK.framework
  2. 将 SDK 添加到工程 Linked Frameworks and Libraries
  3. 建议在 Capabilities 中添加 Access WiFi Information
  4. 按合规要求处理隐私清单,涉及磁盘空间和文件时间戳等 Required Reason API 类别。
  5. 应用启动后调用 [GeeGuard registerWithAppID:APPID]
  6. 业务动作发生时调用 fetchReceiptWithSignData:submitReceiptWithSignData:completion:
  7. respondedGeeTokengeeToken 提交服务端。

Objective-C 核心代码:

#import <GeeGuardSDK/GeeGuardSDK.h>

#define APPID @"你的 appId"

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeeGuard registerWithAppID:APPID];
return YES;
}

- (void)getGeeTokenWithBusinessId:(NSString *)businessId {
NSData *data = [businessId dataUsingEncoding:NSUTF8StringEncoding];
GeeGuardReceipt *receipt = [GeeGuard fetchReceiptWithSignData:data];
if (receipt) {
// 提交 receipt.geeToken 到业务服务端。
}
}

- (void)getRespondedGeeTokenWithBusinessId:(NSString *)businessId {
NSData *data = [businessId dataUsingEncoding:NSUTF8StringEncoding];
[GeeGuard submitReceiptWithSignData:data completion:^(GeeGuardReceipt * _Nullable receipt, NSError * _Nullable error) {
if (!error) {
// 提交 receipt.respondedGeeToken 到业务服务端。
} else if (error.code == -300 || error.code == -500 || error.code == -501) {
// 可降级提交 receipt.geeToken。
}
}];
}

5.4 HarmonyOS Next

环境要求:

  • HarmonyOS Next OS。
  • DevEco Studio 6.0.1。
  • API Version 20,minAPI 12。
  • SDK 无第三方依赖。

步骤:

  1. 从极验后台下载 HarmonyOS SDK。
  2. geetest_geeguard_harmonyos_vx.y.z_date.har 放入 libs
  3. oh-package.json5 添加本地依赖。
  4. 添加权限:INTERNETSTORE_PERSISTENT_DATAGET_NETWORK_INFOAPP_TRACKING_CONSENT 为可选动态权限。
  5. 应用启动后调用 GeeGuard.register(context, appId)
  6. 业务动作发生时调用 GeeGuard.fetchReceipt(context, data)GeeGuard.submitReceipt(context, data, callback)
  7. respondedGeeTokengeeToken 提交服务端。

核心代码:

export default class MainAbilityStage extends AbilityStage {
private static readonly GEEGUARD_APP_ID = "你的 appId";

onCreate() {
GeeGuard.register(this.context, MainAbilityStage.GEEGUARD_APP_ID);
}
}

async function getGeeToken(context: Context, businessId: string) {
const receipt = await GeeGuard.fetchReceipt(context, businessId);
if (!receipt || !receipt.geeToken) return;
// 提交 receipt.geeToken 到业务服务端。
}

function getRespondedGeeToken(context: Context, businessId: string) {
GeeGuard.submitReceipt(context, businessId, {
onCompletion: (status: number, receipt: GeeGuardReceipt | undefined) => {
if (status === 200 && receipt?.respondedGeeToken) {
// 提交 receipt.respondedGeeToken 到业务服务端。
} else if (receipt?.geeToken) {
// 可降级提交 receipt.geeToken。
}
}
});
}

5.5 微信小程序

前置要求:

  • 先完成服务端部署。
  • 在小程序后台“设置 - 第三方服务 - 插件管理”添加设备验插件。
  • 插件 provider:wx47cb3e96a69c25ef

步骤:

  1. app.json 中声明插件:
{
"plugins": {
"guard": {
"version": "1.0.4",
"provider": "wx47cb3e96a69c25ef"
}
}
}
  1. 在页面 JSON 中注册组件:
{
"usingComponents": {
"guard": "plugin://guard/guard"
}
}
  1. 在 WXML 中引入:
<guard></guard>
  1. 调用插件获取 gee_token
const guard = requirePlugin("guard");

guard
.load({ appId: "你的 appId" })
.then((data) => {
wx.request({
url: "https://你的域名/api/protected-action",
method: "POST",
data: {
gee_token: data.gee_token,
businessField: "value"
}
});
})
.catch((e) => {
// 采集失败时按业务策略放行、复核或提示重试。
});

5.6 微信小游戏

官方导航中提供微信小游戏入口。接入原则与小程序一致:

  1. 使用极验提供的小游戏插件或资源。
  2. 初始化时传入 appId
  3. 获取 gee_token 后提交业务服务端。
  4. 服务端统一调用 token_query

6. 必要错误码与处理办法

6.1 服务端错误码

错误码 含义 处理办法
-50001 参数解析错误 检查 JSON Body 是否正确,Content-Type 是否为 application/json
-50002 参数缺失或格式错误 检查 app_idgen_timegee_tokensign_tokenattr.user_ip
-50101 app_id 不存在 检查极验后台应用 ID,确认环境未混用
-50102 签名校验失败 检查 private_key、签名消息 app_id + gen_time、秒级时间戳
-50201 GeeToken 解析错误 重新采集 gee_token;仍失败联系极验支持
-50000 运行时错误 记录上下文,稍后重试或联系极验支持

6.2 客户端 SDK 错误码

Android、iOS、HarmonyOS 异步提交 submitReceipt / submitReceiptWithSignData 可能返回:

错误码 含义 处理办法
-200 未注册 AppID 确认应用启动后已调用注册方法,且 appId 非空
-300 网络错误 记录日志;可降级提交 receipt.geeToken
-500 服务响应格式异常 查看 receipt.originalResponse;可降级提交 receipt.geeToken
-501 服务响应失败 查看 receipt.originalResponse;可降级提交 receipt.geeToken

6.3 Web 常见错误

现象 / 错误 优先检查 处理办法
status=errorcode=-50101 / msg=not app_id 初始化 appId 是否为空 补充正确 appId
无法加载 gd.js 网络、CSP、静态资源域名 放行 static.geetest.com,使用 HTTPS
gee_token 为空 初始化回调、appId、网络 不提交业务或进入复核策略
本地 WebView 取到 file: 协议 protocol 配置 显式设置 protocol: "https://"

6.4 关键风险码与处理建议

风险码 含义 建议动作
10001 包名篡改或重打包 高风险业务拒绝或强二次验证
10002 GeeToken 过期或重复使用,有效期 10 分钟 要求重新采集 gee_token
20100 传统模拟器风险 注册、领券、提现场景至少二次验证
20101 云手机或 ARM 服务器风险 高风险业务拒绝或人工审核
20200 / 20210 多开环境风险 限制批量注册、邀请、领券
20201 / 20211 改机工具风险 拒绝高风险业务或提升验证强度
20202 / 20212 群控或自动化工具风险 拒绝批量行为,记录设备
20203 / 20213 逆向或篡改工具风险 拒绝敏感业务
20400 / 20401 调试风险 开发环境白名单,生产高风险复核
20500 / 20501 VPN 或代理风险 登录可复核,支付/提现建议拒绝或限额
20600 iOS 越狱 高风险业务拒绝或强复核
20601 Android Root 高风险业务拒绝或强复核
20604 ~ 20606 Web Cookie 不可用、伪造浏览器、隐私模式 Web 业务要求重试或二次验证
21000 未插 SIM 卡 移动端业务结合场景复核
40003 设备指纹黑名单 拒绝或封禁
60113 设备指纹白名单 可降低验证强度
40002 / 40204 IP 黑名单或疑似代理 IP 结合 ip_type 限制或复核
40001 / 60111 账号黑名单 / 白名单 按账号黑白名单策略处理
90101 ~ 90405 账号画像风险 注册、营销活动、支付提现重点使用

7. 联调清单

客户端检查:

  • 是否已在应用启动或页面加载时注册 / 初始化 appId
  • 客户端代码中是否没有 private_key
  • 是否在业务动作发生时获取新的 gee_token,不复用旧 token。
  • 是否传入唯一业务流水号作为签名数据或 customInfo
  • gee_tokenrespondedGeeToken 是否随业务参数提交到服务端。
  • Android / iOS / HarmonyOS 异步失败时是否能降级提交 geeToken
  • Web 是否成功加载 https://static.geetest.com/g5/gd.js
  • 小程序插件 provider 和版本是否配置正确。

服务端检查:

  • private_key 是否只存在服务端。
  • gen_time 是否为秒级时间戳。
  • sign_token 是否用 private_keyapp_id + gen_time 做 HMAC-SHA256。
  • 请求地址是否为 https://riskct.geetest.com/g2/api/v1.1/token_query
  • 请求体是否为 JSON。
  • attr.user_ip 是否正确获取真实用户 IP。
  • 是否处理 risk_level=pass/review/reject/null
  • 是否记录 root_idlocal_idrisk_coderisk_levelip_type

上线检查:

  • 已完成隐私政策、合规指南、SDK 权限和 App Store / 应用市场合规要求。
  • 生产环境关闭不必要调试日志。
  • 日志不记录 private_key、完整敏感账号信息或敏感业务数据。
  • 已制定 reviewreject 的业务处置策略。
  • 已准备极验接口异常时的降级策略。

8. 常见异常处理

现象 优先检查 解决办法
服务端返回 -50102 签名算法和时间戳 使用 private_keyapp_id + gen_time 签名,gen_time 为秒级
服务端返回 -50201 gee_token 是否过期、重复、截断 重新采集并提交完整 gee_token
客户端返回 -200 是否注册 AppID 应用启动后立即注册
客户端返回 -300 网络状态 记录日志,可降级提交 geeToken
Web 返回 not app_id 初始化参数 补充正确 appId
风险结果为 review 命中中风险或信息不足 触发短信、人机验证、限频或人工审核
风险结果为 reject 高风险设备、IP 或账号 拒绝业务并记录风险上下文
risk_levelnull 未取到有效建议 结合 risk_code 和业务策略兜底