企业信息模糊查询 API 实战:名称、注册号、统一社会信用代码、企业类型与法人一次查全
开票系统里最让人头疼的一步,是让用户把企业名称和税号填对------手打全称容易漏字,复制来的名字带空格,税号抄错一位整张票就得重开。CRM 建档、供应商资质核验、风控 KYC 也是同一个问题:手里只有「重庆可乐家装饰」这么一个模糊的名称片段,却要拿到完整工商登记信息。本文介绍一个企业信息模糊查询接口:一个关键词进去,企业名称、工商注册号、统一社会信用代码、企业类型、成立日期、法定代表人一次返回,并且查不到结果不收费。
api.xujian.tech- V
xujian_cq
一、为什么企业信息查询值得单独做成接口
自己抓数据或写规则匹配,通常会卡在这几个地方:
| 难点 | 具体表现 |
|---|---|
| 关键词不完整 | 用户只记得「可乐家装饰」几个字,缺地域前缀、缺「有限公司」后缀 |
| 入口不统一 | 有的场景只有企业名,有的只有注册号,有的只有 18 位统一社会信用代码 |
| 字段口径乱 | 「企业类型」在不同数据源里编码不同,业务侧还要自己翻译 |
| 税号不确定 | 三证合一前成立的企业,纳税人识别号与统一社会信用代码可能不一致 |
| 批量成本高 | 存量数据几万条,脏关键词占了很大比例,按调用次数付费时很心疼 |
把这一步收敛成一个接口,价值在于:调用方只需要维护一个 X-API-Key 和一个关键词,字段口径由接口统一,脏数据不产生费用。
二、接口能力概览
2.1 接口基础信息
| 项目 | 说明 |
|---|---|
| 接口地址 | https://api.xujian.tech/openapi/enterprise/query |
| 接口编码 | enterprise.query |
| 请求方式 | GET(keyword 放 Query String) |
| 鉴权方式 | 请求头 X-API-Key,不做签名、时间戳或加密 |
| 返回格式 | JSON,Content-Type: application/json;charset=UTF-8 |
| 单次费用 | 0.01 元/次 |
| 关键词长度 | 2 ~ 50 个字符(建议 4 个字符以上) |
| 最多返回 | 20 条(可用 limit 收敛) |
| 典型耗时 | 百毫秒 ~ 1 秒级(响应体 costMs 为本次真实耗时) |
2.2 请求参数
请求头:
| 参数名 | 必填 | 说明 |
|---|---|---|
X-API-Key |
是 | 开发者 API Key,缺失或无效直接返回失败 |
业务参数:
| 参数名 | 必填 | 类型 | 示例 | 说明 |
|---|---|---|---|---|
keyword |
是 | String | 重庆可乐家装饰 | 查询关键词,可以是企业名称片段、工商注册号或统一社会信用代码;长度 2 ~ 50 字符 |
limit |
否 | Integer | 10 | 期望返回条数,实际取 limit 与系统上限(20)的较小值 |
2.3 计费上比较实在的一点
接口是先预鉴权、查到结果后再扣费 的两段式流程。下面这些情况直接返回失败,不扣费、不写扣费流水、不累加调用次数:
keyword为空、少于 2 个字符或超过 50 个字符;- 企业信息查询服务暂时不可用(上游超时或网络异常);
- 一条都没查到。
也就是说,只有真正返回了至少一条企业信息才计一次费用。做存量数据清洗时,那些拼错的、已经注销的关键词不会白白吃掉预算。
三、返回字段详解
3.1 顶层字段
| 字段 | 类型 | 说明 |
|---|---|---|
code |
int | 0 成功,非 0 失败(常见为 500) |
msg |
String | 结果描述,成功为 success,失败为具体原因 |
data |
Object | 业务数据,失败时为 null |
3.2 data 字段
| 字段 | 类型 | 示例 | 说明 |
|---|---|---|---|
keyword |
String | 重庆可乐家装饰 | 本次实际使用的查询关键词(已去除首尾空格) |
total |
int | 1 | 本次返回的企业条数 |
list |
Array | ... | 企业列表,按匹配度排序 |
apiCode |
String | enterprise.query | 接口编码 |
apiName |
String | 企业信息模糊查询 | 接口名称 |
chargeType |
String | PER_CALL | 计费类型 |
balance |
BigDecimal | 99.9900 | 调用完成后(已扣费)的账户余额(元) |
costMs |
Long | 260 | 本次调用耗时(毫秒) |
3.3 list\[\] 企业对象字段
| 字段 | 类型 | 示例 | 说明 |
|---|---|---|---|
name |
String | 重庆可乐家装饰工程有限公司 | 企业名称(工商登记全称) |
regNo |
String | 500113014353471 | 工商注册号 |
creditNo |
String | 91500113MAABRA7D0H | 统一社会信用代码(18 位),开票场景通常作为纳税人识别号使用 |
type |
String | 0 | 企业类型编码 |
typeName |
String | 企业 | 企业类型中文名:0 企业 / 4 社团 / 5 律师事务所 / 6 香港公司,未覆盖的编码返回「其他」 |
startDate |
String | 2021-06-02 | 成立日期,格式 YYYY-MM-DD |
operName |
String | 李伦智 | 法定代表人姓名 |
两个字段设计上的细节 :一是未取到的字段一律返回空字符串而不是
null,调用方不必到处判空;二是type与typeName同时返回,既能做程序判断又能直接展示,不用自己维护一张编码字典。
四、调用示例
4.1 curl
bash
curl -s -G "https://api.xujian.tech/openapi/enterprise/query" \
--data-urlencode "keyword=重庆可乐家装饰" \
-H "X-API-Key: 你的APIKey"
只想要 5 条结果:
bash
curl -s -G "https://api.xujian.tech/openapi/enterprise/query" \
--data-urlencode "keyword=重庆可乐家装饰" \
--data-urlencode "limit=5" \
-H "X-API-Key: 你的APIKey"
4.2 Java(Hutool)
java
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
public class EnterpriseQueryClient {
private static final String API_URL = "https://api.xujian.tech/openapi/enterprise/query";
/**
* 模糊查询企业信息
*
* @param apiKey 开发者 API Key
* @param keyword 企业名称片段 / 注册号 / 统一社会信用代码,2 ~ 50 字符
* @return 企业列表;查询失败(含查不到)返回 null,且不扣费
*/
public static java.util.List<JSONObject> query(String apiKey, String keyword) {
String body = HttpRequest.get(API_URL)
.form("keyword", keyword)
.header("X-API-Key", apiKey)
.timeout(10000)
.execute()
.body();
JSONObject json = JSONUtil.parseObj(body);
Integer code = json.getInt("code");
if (code == null || code != 0) {
System.out.println("查询失败(不收费):" + json.getStr("msg"));
return null;
}
return json.getJSONObject("data").getJSONArray("list")
.toList(JSONObject.class);
}
public static void main(String[] args) {
var list = query("你的APIKey", "重庆可乐家装饰");
if (list == null) {
return;
}
for (JSONObject ent : list) {
System.out.printf("%s | %s | %s | %s%n",
ent.getStr("name"), ent.getStr("creditNo"),
ent.getStr("typeName"), ent.getStr("operName"));
}
}
}
如果项目里没有 Hutool,用 JDK 11+ 自带的 HttpClient 也一样:
java
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.xujian.tech/openapi/enterprise/query?keyword="
+ URLEncoder.encode("重庆可乐家装饰", StandardCharsets.UTF_8)))
.header("X-API-Key", apiKey)
.timeout(Duration.ofSeconds(15))
.GET()
.build();
String body = HttpClient.newHttpClient()
.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8))
.body();
4.3 Python
python
import requests
def query_enterprise(api_key: str, keyword: str, limit: int = 20):
"""
模糊查询企业信息
Args:
api_key: 开发者 API Key
keyword: 企业名称片段 / 注册号 / 统一社会信用代码
limit: 期望返回条数,最大 20
Returns:
list: 成功返回企业列表;失败(含查不到)返回 None,且不扣费
"""
resp = requests.get(
"https://api.xujian.tech/openapi/enterprise/query",
params={"keyword": keyword, "limit": limit},
headers={"X-API-Key": api_key},
timeout=15,
)
result = resp.json()
if result.get("code") != 0:
print("查询失败(不收费):", result.get("msg"))
return None
return result["data"]["list"]
if __name__ == "__main__":
for ent in query_enterprise("你的APIKey", "重庆可乐家装饰") or []:
print(ent["name"], ent["creditNo"], ent["startDate"], ent["operName"])
4.4 JavaScript(浏览器 / Node 18+)
javascript
const resp = await fetch(
"https://api.xujian.tech/openapi/enterprise/query?keyword=" + encodeURIComponent("重庆可乐家装饰"),
{ headers: { "X-API-Key": API_KEY } }
);
const { code, msg, data } = await resp.json();
if (code === 0) {
data.list.forEach((ent) => console.log(ent.name, ent.creditNo, ent.operName));
} else {
console.warn("查询失败(不收费):", msg);
}
五、返回示例
5.1 按企业名称片段查询(单条命中)
json
{
"code": 0,
"msg": "success",
"data": {
"keyword": "重庆可乐家装饰",
"total": 1,
"list": [
{
"name": "重庆可乐家装饰工程有限公司",
"regNo": "500113014353471",
"creditNo": "91500113MAABRA7D0H",
"type": "0",
"typeName": "企业",
"startDate": "2021-06-02",
"operName": "李伦智"
}
],
"apiCode": "enterprise.query",
"apiName": "企业信息模糊查询",
"chargeType": "PER_CALL",
"balance": 99.9900,
"costMs": 260
}
}
5.2 按统一社会信用代码查询(多条命中)
json
{
"code": 0,
"msg": "success",
"data": {
"keyword": "91500113MAABRA7D0H",
"total": 2,
"list": [
{
"name": "重庆可乐家装饰工程有限公司",
"regNo": "500113014353471",
"creditNo": "91500113MAABRA7D0H",
"type": "0",
"typeName": "企业",
"startDate": "2021-06-02",
"operName": "李伦智"
},
{
"name": "重庆某某科技有限公司",
"regNo": "500113014353472",
"creditNo": "91500113MAABRA7D1X",
"type": "0",
"typeName": "企业",
"startDate": "2019-11-20",
"operName": "王某某"
}
],
"apiCode": "enterprise.query",
"apiName": "企业信息模糊查询",
"chargeType": "PER_CALL",
"balance": 99.9800,
"costMs": 310
}
}
5.3 查不到结果(不收费)
json
{
"code": 500,
"msg": "未查询到匹配的企业信息,请更换更完整的企业名称 / 注册号 / 统一社会信用代码后重试;本次调用不计费",
"data": null
}
六、典型应用场景
6.1 开票信息自动补全
用户在开票表单里输入几个字,前端实时调用接口、下拉展示候选,选中后自动填全称和税号:
javascript
async function fillInvoiceForm(keyword) {
const resp = await fetch(
"https://api.xujian.tech/openapi/enterprise/query?keyword=" + encodeURIComponent(keyword),
{ headers: { "X-API-Key": API_KEY } }
);
const { code, data } = await resp.json();
if (code !== 0 || !data.list.length) return []; // 查不到不收费,让用户手填
return data.list.map((ent) => ({
label: ent.name,
taxNo: ent.creditNo,
legalPerson: ent.operName,
startDate: ent.startDate,
}));
}
交互上建议:只做「预填 + 让用户点一下确认」。企业名称相似的情况客观存在,最终选择权留给用户,能避免填错抬头带来的退票。
6.2 存量客户档案批量清洗
几万条客户名录里,企业名称往往是不完整的。建议「本地缓存 + 并发控制 + 查不到即跳过」:
python
import json
import os
from concurrent.futures import ThreadPoolExecutor, as_completed
from threading import Lock
CACHE_FILE = "enterprise_cache.json"
cache, lock = {}, Lock()
def load_cache():
global cache
if os.path.exists(CACHE_FILE):
with open(CACHE_FILE, encoding="utf-8") as f:
cache = json.load(f)
def clean_batch(api_key: str, keywords: list[str], workers: int = 4):
"""批量清洗企业名称:命中缓存直接返回,未命中才调用接口"""
load_cache()
todo = [k for k in keywords if k not in cache]
print(f"共 {len(keywords)} 条,需调用接口 {len(todo)} 条")
with ThreadPoolExecutor(max_workers=workers) as pool:
futures = {pool.submit(query_enterprise, api_key, k): k for k in todo}
for fu in as_completed(futures):
k = futures[fu]
with lock:
cache[k] = fu.result() or [] # 查不到记为空,下次不再重复调用
with lock, open(CACHE_FILE, "w", encoding="utf-8") as f:
json.dump(cache, f, ensure_ascii=False)
return {k: cache.get(k) for k in keywords}
由于「查不到不收费」,拼错的关键词不会额外增加成本;加上缓存之后,1 万条名录按 30% 需真实调用估算,费用在几十元量级。
6.3 供应商资质核验与风控 KYC
合作前快速核对统一社会信用代码是否真实、法定代表人是否与工商登记一致,把人工核对的时间从几分钟压到一次请求:
python
def verify_supplier(api_key: str, name: str, credit_no: str, legal_person: str) -> dict:
"""核验供应商三要素:名称片段、信用代码、法人姓名"""
for ent in query_enterprise(api_key, name) or []:
if ent["creditNo"] == credit_no:
return {
"match": True,
"name": ent["name"],
"creditNo": ent["creditNo"],
"legalPersonMatch": ent["operName"] == legal_person,
"startDate": ent["startDate"],
"typeName": ent["typeName"],
}
return {"match": False}
type 字段还能直接做主体筛选,例如只保留 type=0(企业)或单独处理 5(律师事务所)这类特殊主体。
6.4 CRM 客户建档补全
销售只录入了客户简称,建档时用接口把全称、信用代码、成立日期、法人补全,后续的对账、开票、合同主体校验都有了统一口径,不用再人工去公开渠道一条条查。
七、提升命中率的几条实践建议
- 关键词尽量 4 个字符以上。太短会返回大量不相关结果,例如「科技」不如「重庆 科技」或完整名称片段。
- 能加地域前缀就加。同名企业很多,「北京 腾讯」这类组合比单独一个词精准得多。
- 优先用信用代码精确匹配 。手里已经有 18 位统一社会信用代码时,直接把它当
keyword传,命中率最高。 - 本地做缓存。工商数据变化不频繁,缓存 24 小时以上可以显著降低调用量。
- 税号做一次人工核验。三证合一前成立的部分企业,纳税人识别号与统一社会信用代码可能不一致,首次开票前建议确认一次。
- 结果入库保留原文 。同时保存原始关键词与返回的
name、creditNo,便于后续回溯和重新核对。
八、错误码与排查
| code | msg(示例) | 处理建议 |
|---|---|---|
| 0 | success | 调用成功 |
| 500 | 缺少请求头 X-API-Key | 在请求头补充 X-API-Key |
| 500 | API Key 无效 / API Key 已停用 | 检查 Key 是否正确,或在控制台重新启用 |
| 500 | 客户不存在或已停用 | 联系平台确认账号状态 |
| 500 | 接口不存在或已停用 | 确认 enterprise.query 当前是否维护中 |
| 500 | 余额不足,请先充值 | 按次计费接口调用前校验余额,余额不足不扣费,充值后重试 |
| 500 | keyword 不能为空 | 补充 keyword 参数,不计费 |
| 500 | keyword 至少需要 2 个字符(建议 4 个字符以上以提高匹配率) | 使用更完整的企业名称片段,不计费 |
| 500 | keyword 长度不能超过 50 个字符 | 缩短关键词,不计费 |
| 500 | 未查询到匹配的企业信息...... | 换用更准确的关键词或信用代码,不计费 |
| 500 | 企业信息查询服务暂时不可用(请求上游超时或网络异常) | 稍后重试,不计费 |
九、计费与接入
| 项目 | 说明 |
|---|---|
| 单次费用 | 0.01 元/次 |
| 计费方式 | 按次计费,调用前校验余额,查询到结果后才扣费 |
| 不计费场景 | 关键词为空 / 超长、服务暂时不可用、未查询到任何匹配企业 |
| 最多返回 | 20 条,可用 limit 收敛 |
| 关键词长度 | 2 ~ 50 个字符 |
接入流程 :注册开发者账号 → 控制台创建 API Key → 请求头带上 X-API-Key 即可调用,无需签名或加密。控制台可查看调用量、扣费流水与余额。
十、总结
企业信息查询这类需求,自己维护数据源成本高、更新慢,交给一个专门的接口更划算:一个关键词覆盖企业名称、注册号、统一社会信用代码三种入口,返回的字段口径统一(含企业类型编码与中文名),调用侧只要一个 X-API-Key。
几个关键取舍值得留意:
- 查得计费:只有真正返回了至少一条企业信息才扣费,脏关键词不吃预算;
- 不返回 null:未取到的字段统一空字符串,调用方少写一堆判空;
- 类型双字段 :
type+typeName同时返回,程序判断与界面展示都能直接用; - 接口极简 :只有一个必填参数
keyword、一个X-API-Key请求头,GET 即可调用。