技术博客
银行卡归属地查询的 cardNum 与 needBin 怎么传:什么时候才需要 BIN 与 Luhn 效验

银行卡归属地查询的 cardNum 与 needBin 怎么传:什么时候才需要 BIN 与 Luhn 效验

作者: 万维易源
2026-09-15
银行卡归属地查询参数说明needBinisLuhnLuhn效验
# 银行卡归属地查询的 cardNum 与 needBin 怎么传:什么时候才需要 BIN 与 Luhn 效验 > 接口:银行卡归属地查询(apiCode=30)· 接入点:`30-7` · 计费:按次计费,5 厘/次,查询失败不计费 · 请求方式:GET / POST · 适用人群:已接入、准备调优参数的开发者 · 阅读时间:约 7 分钟 > 最后实测核对:2026-09-15 一句话结论:银行卡归属地查询接口只有两个业务参数,`cardNum` 必填,`needBin` 决定要不要多拿 BIN 码与银联 Luhn 效验结果——不开就少四个字段、响应更快,开就多四个字段、耗时略增。 ## 参数表 | 参数 | 类型 | 必填 | 示例值 | 作用 | |------|------|------|--------|------| | `cardNum` | String | 是 | `6228480402564890018` | 要查询的银行卡号 | | `needBin` | String | 否 | `1` | 是否需要返回银行卡 BIN 码信息和银联 Luhn 效验。`1` 需要,`0` 不需要,不传默认不返回 | POST 表单场景下还有个 Header 参数: | Header | 类型 | 必填 | 示例值 | |------|------|------|--------| | `content-type` | String | 否 | `application/x-www-form-urlencoded` | 鉴权参数 `appKey` 走 query,不在这两个业务参数里。 ## cardNum 怎么传 `cardNum` 传卡号本身,不含空格和分隔符。2026-09-15 实测传 `6228480402564890018`(19 位)能正常返回,返回体里的 `cardNum` 与入参一致。 位数不是硬门槛,但查不到就没有结果。实测传一个 10 位数字 `1234567890`,返回: ```json { "showapi_res_code": 0, "showapi_fee_num": 0, "showapi_res_body": { "remark": "找不到此卡号信息", "ret_code": -1 } } ``` `ret_code` 为 `-1`,`showapi_fee_num` 为 `0`。这次调用不计费,业务侧按「未查到」处理即可。 必须传。不传 `cardNum` 时请求不会被受理,返回的是外层错误: ```json { "showapi_res_error": "must input cardNum field", "showapi_res_code": -1, "showapi_fee_num": 0, "showapi_res_body": {} } ``` 注意这时 `showapi_res_body` 是空对象,里面没有 `ret_code`。所以判定逻辑得先看外层,具体写法见[银行卡归属地查询排错:三种失败形态怎么区分](https://www.showapi.com/guides/bank-card-attribution-error-codes-30)。 ## needBin 怎么传 `needBin` 控制四个字段是否返回:`card_bin`、`bin_digits`、`card_digits`、`isLuhn`。 传 `1` 时,四个字段都出现: ```json { "card_bin": "622848", "bin_digits": "6", "card_digits": "19", "isLuhn": "1" } ``` 传 `0` 或不传时,四个字段整体不出现。2026-09-15 实测对比:同一张卡,不传 `needBin` 的返回体里完全没有这四个键;传 `needBin=1` 才出现。计费口径不变,两次都是 `showapi_fee_num: 1`。 接口文档对 `needBin=1` 的说明是「返回这些信息将使得查询更加耗时」。也就是说这四项是有代价的,不值得每次调用都开。 BIN 未收录时字段仍存在、值为空字符串: ```json { "card_bin": "", "bin_digits": "", "card_digits": "19", "isLuhn": "0" } ``` ## isLuhn 的三个取值 `isLuhn` 不是布尔量,它有三个取值: | 取值 | 含义 | |------|------| | `1` | 能通过中国银联 Luhn 效验 | | `0` | 不能通过 | | 空字符串 | 不支持效验 | 做卡号形态初筛时,只有 `1` 和 `0` 能给出明确判断;空字符串代表本卡号不参与这项校验,不能当成「不合法」处理。 ## 什么场景该开 needBin | 你要做的事 | 建议 | |------|------| | 只展示银行名、归属地、卡种、客服电话 | 不传 `needBin` | | 绑卡时做卡号形态初筛(位数、BIN 段、Luhn) | 传 `needBin=1` | | 批量核对存量卡号的开户行 | 不传 `needBin`,减少响应耗时 | | 风控侧要拿卡号长度做异常识别 | 传 `needBin=1` | 一句话:`needBin` 只在「需要判断这张卡号本身是否形态合法」时才开。 ## 三语言调用示例 Python: ```python import requests APPKEY = "YOUR_APPKEY" API_URL = "https://route.showapi.com/30-7" def query_bank_card(card_num: str, need_bin: bool = False, timeout: int = 30) -> dict: params = {"appKey": APPKEY, "cardNum": card_num} if need_bin: params["needBin"] = "1" resp = requests.post(API_URL, data=params, timeout=timeout, headers={"content-type": "application/x-www-form-urlencoded"}) resp.raise_for_status() data = resp.json() if data.get("showapi_res_code") != 0: raise RuntimeError(f'请求失败:{data.get("showapi_res_error")}') body = data.get("showapi_res_body") or {} if str(body.get("ret_code")) != "0": return {"ok": False, "reason": body.get("remark") or "未查到归属地", "raw": body} return { "ok": True, "area": body.get("area", ""), "bank": body.get("formatBankName") or body.get("bankName", ""), "brand": body.get("brand", ""), "card_type": body.get("cardType", ""), # 只有 needBin=1 时才有值,其余情况走默认值 "card_bin": body.get("card_bin", ""), "is_luhn": body.get("isLuhn", ""), } ``` cURL(POST 表单): ```bash curl -s -X POST "https://route.showapi.com/30-7?appKey=YOUR_APPKEY" \ -H "content-type: application/x-www-form-urlencoded" \ -d "cardNum=6228480402564890018&needBin=1" \ --max-time 30 ``` Node.js: ```javascript const APPKEY = "YOUR_APPKEY"; const API_URL = "https://route.showapi.com/30-7"; async function queryBankCard(cardNum, needBin = false) { const body = new URLSearchParams({ cardNum }); if (needBin) body.set("needBin", "1"); const controller = new AbortController(); const timer = setTimeout(() => controller.abort(), 30000); try { const res = await fetch(`${API_URL}?appKey=${encodeURIComponent(APPKEY)}`, { method: "POST", headers: { "content-type": "application/x-www-form-urlencoded" }, body, signal: controller.signal, }); const data = await res.json(); if (data.showapi_res_code !== 0) throw new Error(`请求失败:${data.showapi_res_error}`); const b = data.showapi_res_body || {}; if (String(b.ret_code) !== "0") return { ok: false, reason: b.remark || "未查到归属地" }; return { ok: true, area: b.area || "", bank: b.formatBankName || b.bankName || "", brand: b.brand || "", cardType: b.cardType || "", cardBin: b.card_bin || "", isLuhn: b.isLuhn || "", }; } finally { clearTimeout(timer); } } ``` ## FAQ **Q1:`needBin` 会不会影响结果里其他字段?** 不会。2026-09-15 实测对比同一张卡号的两次调用,`area`、`bankName`、`formatBankName`、`brand`、`cardType`、`tel`、`url`、`logo`、`simpleCode` 的取值完全一致,只有 BIN 相关的四个字段出现与否不同,计费次数也都是 `1`。 **Q2:`needBin` 传 `0` 和完全不传有区别吗?** 没有区别,两种写法都不返回那四个字段。文档对 `needBin` 的说明是「`1` 表示需要,`0` 表示不需要,默认不会返回这些信息」。 **Q3:卡号里带空格或「-」能查吗?** 接口按传入的字符串处理,建议在调用前先去空格、去分隔符,只传纯数字串。 **Q4:`cardNum` 位数不对会返回什么?** 看具体情况:位数明显不足且 BIN 无法识别的,会走「卡号未收录」这条路,返回 `ret_code: -1` 与 `remark`;这种失败不计费。 **Q5:POST 和 GET 用哪个?** 两者都支持。参数只有两个,GET 更省事;如果你不想让卡号出现在访问日志的 URL 里,用 POST 表单,参数放 body。 ## 下一步阅读 - [银行卡归属地查询返回字段逐个说清](https://www.showapi.com/guides/bank-card-attribution-response-fields-30)——看清 `needBin` 控制的是哪四个字段 - [银行卡归属地查询排错:三种失败形态怎么区分](https://www.showapi.com/guides/bank-card-attribution-error-codes-30)——缺 `cardNum` 时的返回形态 - [银行卡归属地查询按次计费下怎么省调用](https://www.showapi.com/guides/bank-card-attribution-cache-cost-30)——BIN 前缀缓存的具体设计 - **本系列共 10 篇**:查看[银行卡归属地查询指南总目录](https://www.showapi.com/guides/bank-card-attribution-guides-30)