从 curl 到工程封装:综合风控评分 API 集成实战
2026/7/23 14:40:55 网站建设 项目流程

适用场景与问题背景

在准备、登录、下单、领券等核心业务环节,黑产团伙常利用虚拟运营商号段、代理IP、临时邮箱进行批量养号或薅羊毛。传统做法是人工维护黑名单或自建规则引擎,但维护维护复杂度高、响应慢。综合风控评分 API 提供三个维度的信号(手机号、IP、邮箱),返回 0~100 风险分以及明确的决策建议:放行(pass)、二次验证(challenge)、拦截(reject),让业务方无需自建复杂模型即可快速接入反欺诈能力。

接口能力边界

  • 单次调用可同时检测三项:mobile(手机号/物联网卡号)、ip(IPv4/IPv6)、email(邮箱)。各项为可选参数,可按需传入。
  • 支持多场景:通过scene参数区分registerloginordercoupon,API 内部会自适应阈值权重。
  • 结果包含信号层明细:不仅给出总分,还给出每条数据源的具体风险标签(如MOBILE_MVNOIP_DATACENTEREMAIL_DISPOSABLE)及权重,方便业务侧二次加工。
  • QPS 限制:2 次/秒,适合在线实时决策。超出限制会返回 429。

鉴权与请求参数

Header 鉴权

接口使用Authorization头部传递 API Key(从控制台获取),格式为Bearer <your_api_key>或使用X-API-Key(curl 示例中使用的就是后者)。实际生产中建议统一使用Authorization: Bearer <key>更规范。

请求体(JSON)

字段类型必填说明
mobilestring11 位手机号或 13 位物联网卡号。传此字段会检查是否属于虚拟运营商/物联网卡号段
ipstringIPv4/IPv6 地址。传self可自动获取调用者出口 IP
emailstring邮箱地址。检测是否为临时邮箱、MX 记录是否异常
scenestring业务场景,默认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} ] } }

返回字段深度解读

字段路径类型含义
codeint业务状态码,0 表示成功
msgstring对应文字信息
request_idstring唯一请求标识,可用于问题排查
data.risk_scoreint综合风险分 0-100,越高越危险
data.risk_levelstring等级:safe/low/medium/high/critical
data.decisionstring业务决策:pass/challenge/reject
data.hit_rules[]array命中规则列表,每条含codedescweight(权重 1-100,总和 100)
data.signalsobject各信号的详细检测结果,见下方子表

signals 子字段说明

mobile
字段类型含义
checkedbool是否检测了手机号
input_maskstring脱敏手机号(中间四位隐藏)
validbool号码格式是否有效
number_typestringnormal/mvno/iot
carrierstring运营商名称
riskstringlow/medium/high
ip
字段类型含义
checkedbool是否检测 IP
ipstring脱敏后的 IP(部分隐藏)
validboolIP 格式是否有效
ispstring所属运营商/云厂商
is_datacenterbool是否为机房 IP
is_proxybool是否为代理/VPN IP
is_privatebool是否为内网 IP
riskstring风险等级
email
字段类型含义
checkedbool是否检测邮箱
emailstring完整邮箱(原样返回)
valid_formatbool格式是否合法
has_mxbool是否有 MX 记录
is_disposablebool是否为临时/一次性邮箱
is_trustedbool是否属于可信域名库
riskstring风险等级

常见错误处理

HTTP状态码业务codemsg原因处理方式
4011001认证失败API Key 无效或未传检查 Header 中的 Authorization/X-API-Key
4002001参数校验失败请求体 JSON 格式错误或未传任何检测字段确保至少填一个字段,且 JSON 合法
4002002场景值不在允许范围内scene 字段值非法仅传register/login/order/coupon
4293001请求频率过高超过 2 QPS 限制限流降级,等待后重试
5004001服务内部错误服务端异常重试,若持续则联系技术支持

注意:所有错误响应也包含codemsg,以及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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询