适用场景:对公结算、商户代付、企业批量打款时自动补齐 12 位联行号(CNAPS),以及表单自动带出开户行、风控核验辅助。 接口文档:https://www.du21.cc/api_v1.html 官方主站:https://www.du21.cc/
在跨行对公转账、批量代付、商户结算这类业务里,除了收款人的账号和户名,银行通常还需要收款账户的 12 位联行号(CNAPS Code),才能精确路由到开户的那家支行。财务手工录入几十上百条对公账户、逐条核对开户行,既慢又容易出错。
银行卡开户行 / 联行号查询 API 解决的就是这个问题:你只需传一个银行卡号,接口就返回该卡所属银行、卡类型(借记卡 / 信用卡)、开户分行名称,以及对应的 12 位联行号。
典型应用场景
重要说明:本接口是信息查询类接口,只负责返回银行卡的归属与开户行信息,不具备资金划转能力。真正的批量代付、批量转账必须通过持牌银行或合规支付机构的对公渠道完成,联行号查询在其中仅作为「补齐收款信息」的一个前置步骤。请勿用于搭建任何未经许可的资金流转通道。
项目 | 说明 |
|---|---|
请求地址 |
|
请求方式 | POST(必须为 POST) |
请求参数格式 |
|
返回格式 | JSON |
参数名 | 类型 | 必填 | 说明 |
|---|---|---|---|
| string | 是 | 用户的 API Key,登录主站后在「我的 API」中获取 |
| string | 是 | 银行卡号,单次仅查询一张卡(12–25 位数字) |
参数名 | 类型 | 说明 |
|---|---|---|
| int | 状态码, |
| string | 提示信息 |
| object | 查询结果(成功时返回) |
| string | 卡类型,如:借记卡 |
| string | 开户分行名称 |
| string | 开户行 12 位联行号 |
成功响应
{
"code": 1,
"msg": "成功",
"data": {
"cardType": "借记卡",
"name": "中国建设银行股份有限公司张家口分行",
"cnaps": "105138000014"
}
}失败响应
{
"code": 0,
"msg": "余额不足"
}以下代码均为可直接运行的最小可用示例,请把 您的API_KEY 替换成你在主站后台获取的真实密钥。
curl -X POST https://www.du21.cc/index/api/v1 \
-d "key=您的API_KEY" \
-d "bankcard=6217000170006318989"import requests
url = "https://www.du21.cc/index/api/v1"
data = {
"key": "您的API_KEY",
"bankcard": "6217000170006318989",
}
resp = requests.post(url, data=data, timeout=10)
resp.raise_for_status()
result = resp.json()
if result.get("code") == 1:
d = result["data"]
print(f"卡类型: {d['cardType']}")
print(f"开户分行: {d['name']}")
print(f"联行号: {d['cnaps']}")
else:
print(f"查询失败: {result.get('msg')}")<?php
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => 'https://www.du21.cc/index/api/v1',
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'key' => '您的API_KEY',
'bankcard' => '6217000170006318989',
]),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 10,
]);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
if (($result['code'] ?? 0) === 1) {
echo $result['data']['name'], PHP_EOL;
echo $result['data']['cnaps'], PHP_EOL;
} else {
echo '查询失败: ', $result['msg'] ?? '未知错误', PHP_EOL;
}const data = new URLSearchParams({
key: "您的API_KEY",
bankcard: "6217000170006318989",
});
const resp = await fetch("https://www.du21.cc/index/api/v1", {
method: "POST",
headers: { "Content-Type": "application/x-www-form-urlencoded" },
body: data,
});
const result = await resp.json();
if (result.code === 1) {
console.log(`开户分行: ${result.data.name}`);
console.log(`联行号: ${result.data.cnaps}`);
} else {
console.log(`查询失败: ${result.msg}`);
}银行卡号一般符合 Luhn 算法,调用接口前先做本地校验,能拦截大量明显非法的输入,减少无效计费调用:
def luhn_check(card_no: str) -> bool:
if not card_no.isdigit() or not (12 <= len(card_no) <= 25):
return False
total = 0
reverse = card_no[::-1]
for i, ch in enumerate(reverse):
n = int(ch)
if i % 2 == 1:
n *= 2
if n > 9:
n -= 9
total += n
return total % 10 == 0code == 0 时不要盲目重试,先看 msg。余额不足 等属于账户层面的问题,重试无意义,应告警并充值。timeout、连接失败 等网络异常可做有限次退避重试(如 3 次,间隔 1s / 2s / 4s),并记录日志。最常见的落地形态是「批量导入对公账户 → 自动补齐开户行与联行号 → 导出」。下面给出一份可运行的 Python 脚本思路:
import csv
import time
import requests
API_URL = "https://www.du21.cc/index/api/v1"
API_KEY = "您的API_KEY"
def query_bankcard(card_no: str):
try:
resp = requests.post(
API_URL,
data={"key": API_KEY, "bankcard": card_no},
timeout=10,
)
result = resp.json()
if result.get("code") == 1:
d = result["data"]
return {
"card_no": card_no,
"card_type": d["cardType"],
"bank_name": d["name"],
"cnaps": d["cnaps"],
"status": "success",
}
return {"card_no": card_no, "status": "failed", "msg": result.get("msg")}
except Exception as e:
return {"card_no": card_no, "status": "error", "msg": str(e)}
# 从输入文件读取卡号
with open("input_cards.txt", "r") as f:
cards = [line.strip() for line in f if line.strip()]
# 逐张查询(可自行改为线程池并发,注意控制速率)
results = []
for c in cards:
results.append(query_bankcard(c))
time.sleep(0.2) # 适当限速,避免触发风控
# 写回 CSV,供对公代付系统使用
with open("output_cnaps.csv", "w", newline="", encoding="utf-8-sig") as f:
writer = csv.DictWriter(f, fieldnames=["card_no", "card_type", "bank_name", "cnaps", "status", "msg"])
writer.writeheader()
for row in results:
writer.writerow({k: row.get(k, "") for k in writer.fieldnames})
print(f"完成,共 {len(results)} 条")提示:批量场景建议把「查询结果」落库并做卡号去重;对外提供查询服务时再加一层缓存与限流。
Q1:只传银行卡号,为什么有时需要人工确认开户行?
银行卡号一般只能定位到所属分行,一个分行下可能有多个支行,每个支行都有独立的 12 位联行号。接口返回的是该分行下的候选信息,前端需要结合用户填写或系统已有资料确认到具体支行。
Q2:个人银行卡转账,也需要调用这个接口吗?
一般不需要。个人跨行转账大多不用填联行号;这个接口主要面向对公结算、商户代付、企业批量打款这类对公场景,跨行对公支付时联行号才是必填项。
Q3:为什么会返回「余额不足」?
该接口按查询次数计费,每次查询会扣除账户余额。余额不足时返回 code = 0, msg = 余额不足,需要到主站充值后再继续调用。
Q4:单次能传多个卡号批量查询吗?
当前文档规定单次请求只能查询一个卡号。批量场景需在业务侧循环调用,或采用并发 + 限速的方式自行封装成批量服务。
Q5:测试时如何不扣费?
文档提供测试卡号 000000000000000,查询该卡号不扣费,可用于联调。
银行卡开户行 / 联行号查询 API 是打通对公结算、批量代付「最后一公里」的高频工具:通过一次 POST 请求补齐 12 位联行号,能把财务人工核对从几十上百条手工操作,压缩成一段可复用、可缓存、可审计的代码流程。接入时务必遵守 POST 请求、单卡查询、密钥服务端保管、批量限速、结果落库缓存 等工程规范,并始终在合法合规的对公场景中使用。
相关资源
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。