适用场景与问题背景
在准备、登录、下单、领券等核心业务环节,黑产团伙常利用虚拟运营商号段、代理IP、临时邮箱进行批量养号或薅羊毛。传统做法是人工维护黑名单或自建规则引擎,但维护维护复杂度高、响应慢。综合风控评分 API 提供三个维度的信号(手机号、IP、邮箱),返回 0~100 风险分以及明确的决策建议:放行(pass)、二次验证(challenge)、拦截(reject),让业务方无需自建复杂模型即可快速接入反欺诈能力。
接口能力边界
- 单次调用可同时检测三项:mobile(手机号/物联网卡号)、ip(IPv4/IPv6)、email(邮箱)。各项为可选参数,可按需传入。
- 支持多场景:通过
scene参数区分register、login、order、coupon,API 内部会自适应阈值权重。 - 结果包含信号层明细:不仅给出总分,还给出每条数据源的具体风险标签(如
MOBILE_MVNO、IP_DATACENTER、EMAIL_DISPOSABLE)及权重,方便业务侧二次加工。 - QPS 限制:2 次/秒,适合在线实时决策。超出限制会返回 429。
鉴权与请求参数
Header 鉴权
接口使用Authorization头部传递 API Key(从控制台获取),格式为Bearer <your_api_key>或使用X-API-Key(curl 示例中使用的就是后者)。实际生产中建议统一使用Authorization: Bearer <key>更规范。
请求体(JSON)
| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
mobile | string | 否 | 11 位手机号或 13 位物联网卡号。传此字段会检查是否属于虚拟运营商/物联网卡号段 |
ip | string | 否 | IPv4/IPv6 地址。传self可自动获取调用者出口 IP |
email | string | 否 | 邮箱地址。检测是否为临时邮箱、MX 记录是否异常 |
scene | string | 否 | 业务场景,默认register。取值register/login/order/coupon |
至少应传一个检测维度,否则接口会返回参数校验错误。
curl 可复现实例
假设已设置环境变量API_KEY,以下命令检测一个高风险场景(虚拟运营商号段 + 机房IP + 临时邮箱):
curl -sS -X POST \ -H "X-API-Key: $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "mobile": "17012345678", "ip": "47.88.1.1", "email": "abc@guerrillamail.com", "scene": "register" }' \ "https://v1.apizero.cn/api/risk-score"响应示例(已格式化):
{ "code": 0, "msg": "成功", "request_id": "k9x2p4mabc12", "data": { "risk_score": 88, "risk_level": "critical", "decision": "reject", "scene": "register", "checked": { "mobile": true, "ip": true, "email": true }, "signals": { "mobile": { "checked": true, "input_mask": "170****5678", "valid": true, "number_type": "mvno", "carrier": "虚拟运营商", "risk": "high" }, "ip": { "checked": true, "ip": "47.88.x.x", "valid": true, "isp": "阿里云", "is_datacenter": true, "is_proxy": false, "is_private": false, "risk": "medium", "province": "" }, "email": { "checked": true, "email": "abc@guerrillamail.com", "valid_format": true, "has_mx": true, "is_disposable": true, "is_trusted": false, "risk": "high" } }, "hit_rules": [ {"code": "MOBILE_MVNO", "desc": "虚拟运营商号段(170),实名宽松,薅羊毛高发", "weight": 35}, {"code": "EMAIL_DISPOSABLE", "desc": "一次性/临时邮箱域名,典型用于注册套利", "weight": 35}, {"code": "IP_DATACENTER", "desc": "机房/IDC IP(非真实用户网络,脚本批量常用)", "weight": 30} ] } }返回字段深度解读
| 字段路径 | 类型 | 含义 |
|---|---|---|
code | int | 业务状态码,0 表示成功 |
msg | string | 对应文字信息 |
request_id | string | 唯一请求标识,可用于问题排查 |
data.risk_score | int | 综合风险分 0-100,越高越危险 |
data.risk_level | string | 等级:safe/low/medium/high/critical |
data.decision | string | 业务决策:pass/challenge/reject |
data.hit_rules[] | array | 命中规则列表,每条含code、desc、weight(权重 1-100,总和 100) |
data.signals | object | 各信号的详细检测结果,见下方子表 |
signals 子字段说明
mobile
| 字段 | 类型 | 含义 |
|---|---|---|
checked | bool | 是否检测了手机号 |
input_mask | string | 脱敏手机号(中间四位隐藏) |
valid | bool | 号码格式是否有效 |
number_type | string | normal/mvno/iot |
carrier | string | 运营商名称 |
risk | string | low/medium/high |
ip
| 字段 | 类型 | 含义 |
|---|---|---|
checked | bool | 是否检测 IP |
ip | string | 脱敏后的 IP(部分隐藏) |
valid | bool | IP 格式是否有效 |
isp | string | 所属运营商/云厂商 |
is_datacenter | bool | 是否为机房 IP |
is_proxy | bool | 是否为代理/VPN IP |
is_private | bool | 是否为内网 IP |
risk | string | 风险等级 |
| 字段 | 类型 | 含义 |
|---|---|---|
checked | bool | 是否检测邮箱 |
email | string | 完整邮箱(原样返回) |
valid_format | bool | 格式是否合法 |
has_mx | bool | 是否有 MX 记录 |
is_disposable | bool | 是否为临时/一次性邮箱 |
is_trusted | bool | 是否属于可信域名库 |
risk | string | 风险等级 |
常见错误处理
| HTTP状态码 | 业务code | msg | 原因 | 处理方式 |
|---|---|---|---|---|
| 401 | 1001 | 认证失败 | API Key 无效或未传 | 检查 Header 中的 Authorization/X-API-Key |
| 400 | 2001 | 参数校验失败 | 请求体 JSON 格式错误或未传任何检测字段 | 确保至少填一个字段,且 JSON 合法 |
| 400 | 2002 | 场景值不在允许范围内 | scene 字段值非法 | 仅传register/login/order/coupon |
| 429 | 3001 | 请求频率过高 | 超过 2 QPS 限制 | 限流降级,等待后重试 |
| 500 | 4001 | 服务内部错误 | 服务端异常 | 重试,若持续则联系技术支持 |
注意:所有错误响应也包含
code和msg,以及request_id,便于日志追踪。
工程化封装注意事项
1. 网络层:超时与重试
API 要求在 500ms 以内(通常几十 ms),但网络波动可能引起超时。建议设置连接超时 3s、读超时 5s。对于 429 和 5xx 错误实施指数退避重试(最多 3 次,间隔 1s/2s/4s)。
2. 限流保护
单实例 QPS 上限为 2,多实例部署时要确保总请求不超过限制。可使用令牌桶或信号量控制本地频率,或借助网关集中限流。
3. 缓存策略
同一手机号/IP/邮箱的短时间重复查询(如 1 分钟内),可以缓存上次结果(但注意风险会随时间变化,缓存不宜过长)。对于 blacklist 级别的拦截,可以缓存 15-30 分钟。
4. 降级预案
当 API 不可用(如超时或 5xx)时,建议采取保守策略:对风险较高的场景(准备)默认拦截 + 人工审核,对低风险场景(如登录)可放行。
5. 工程代码示例(Python)
import requests import time import logging logger = logging.getLogger(__name__) class RiskScoreClient: def __init__(self, api_key: str, base_url: str = "https://v1.apizero.cn/api/risk-score"): self.headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } self.url = base_url self.max_retries = 3 self.retry_delays = [1, 2, 4] def query(self, mobile: str = None, ip: str = None, email: str = None, scene: str = "register") -> dict: payload = {k: v for k, v in [("mobile", mobile), ("ip", ip), ("email", email), ("scene", scene)] if v is not None} for attempt in range(self.max_retries): try: resp = requests.post(self.url, json=payload, headers=self.headers, timeout=(3, 5)) if resp.status_code == 429: logger.warning("Rate limited, retrying after %ss", self.retry_delays[attempt]) time.sleep(self.retry_delays[attempt]) continue resp.raise_for_status() data = resp.json() if data.get("code") != 0: logger.error("API error: %s", data.get("msg")) return data except requests.exceptions.Timeout: logger.warning("Timeout on attempt %d", attempt+1) if attempt < self.max_retries - 1: time.sleep(self.retry_delays[attempt]) else: raise except requests.exceptions.RequestException as e: logger.error("Request failed: %s", e) if attempt < self.max_retries - 1: time.sleep(self.retry_delays[attempt]) else: raise # 降级:返回默认拒绝决策 return { "code": -1, "msg": "service unavailable", "data": {"decision": "reject", "risk_score": 100} }6. Java 代码片段(使用 HttpClient)
import java.net.URI; import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; public class RiskScoreClient { private static final String URL = "https://v1.apizero.cn/api/risk-score"; private final String apiKey; private final HttpClient client; public RiskScoreClient(String apiKey) { this.apiKey = apiKey; this.client = HttpClient.newBuilder() .connectTimeout(Duration.ofSeconds(3)) .build(); } public String query(String mobile, String ip, String email, String scene) throws Exception { // 构建 JSON 请求体(使用 Jackson 等库序列化) String body = String.format( "{\"mobile\":\"%s\",\"ip\":\"%s\",\"email\":\"%s\",\"scene\":\"%s\"}", mobile != null ? mobile : "", ip != null ? ip : "", email != null ? email : "", scene != null ? scene : "register"); HttpRequest request = HttpRequest.newBuilder() .uri(URI.create(URL)) .header("Authorization", "Bearer " + apiKey) .header("Content-Type", "application/json") .POST(HttpRequest.BodyPublishers.ofString(body)) .timeout(Duration.ofSeconds(5)) .build(); HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString()); return response.body(); } }总结
综合风控评分 API 通过一次调用即可整合三大风险信号,配合工程化封装(重试、限流、降级)能稳定支撑在线业务。建议在接入前先使用 curl 验证 Key 和参数,再逐步替换为客户端 SDK 或自行封装的工具类。
参考文档
- 原始文档:https://apizero.cn/aidocs/risk-score/raw.md
- 接口文档页:https://apizero.cn/aidocs/risk-score