简介JSON格式银行卡BIN码大全面向前端开发者和支付相关功能实现者聚焦银行卡号前六位与发卡机构、卡类型、币种之间的映射查询适用于支付表单、收银台、账户绑定等场景可用于输入卡号时的即时识别、表单校验和发卡行提示。压缩包内共1个文件为单个JSON数据文件整体约33KB采用键值对组织每条BIN码对应银行名称、借记卡或信用卡类别及币种等字段结构紧凑、便于直接解析和按需接入。已有1751人学习说明该数据在银行卡识别场景中具有一定参考价值。使用时可按前六位检索目标记录快速获得银行信息并围绕未匹配、数据更新和隐私保护设计容错逻辑JSON体积小巧也方便嵌入前端项目或作为本地对照表维护适合需要快速搭建银行卡BIN查询能力的开发者参考。1. 银行卡 BIN 码到底是什么卡号前六位里藏着的身份标签填一张支付表单刚敲完前六位数字下面立刻跳出一行小字「某银行 储蓄卡」。这个瞬间背后起作用的东西就是银行卡 BIN 码。BIN 是 Bank Identification Number 的缩写中文通常译成发卡行识别码它藏在卡号最前面那几位数字里像身份证前六位代表地区一样负责告诉系统这张卡由谁发行、大致属于哪一类。搞懂它不是为了背数字而是为了弄明白两件事为什么有些页面看一眼卡号就能认出卡种为什么有些校验只能判断格式对不对、判断不了这张卡是否真的存在。这份 JSON 格式的 BIN 码大全本质上是把一张「号段对照表」整理成程序能直接读取的结构化文件让 bank 号段查询这件事从人工翻表变成一行读取。2. 为什么前几位就能认出银行BIN 码背后的编号与清算逻辑2.1 卡号不是一串随机数从分段规则说起很多人以为银行卡号就是随机发的一串数字其实它从头到尾都被切成了几段每一段都有明确分工。最左边的一位叫主行业标识用来区分这张卡属于哪个大行业支付类卡片通常集中在固定的几个数字上紧跟着的就是 BIN 码也就是发卡行识别码长度在历史上长期是 6 位后来因为发卡量太大、号段不够分业界逐步允许扩展到 8 位再往右是发卡行自己分配的个人账号段长度不固定最后一位是校验位用来做格式自检。打个比方这结构很像手机号前面几位告诉你这是哪家运营商、哪个号段后面才是具体到某个人的号码。你看到前几位就知道大概归属但看不到后面几位就没法确定具体是谁。BIN 码扮演的就是「号段」这个角色它标记的是一批卡不是一张卡。卡号总长度也不是固定的。早期有 13 位的卡号现在主流是 16 位一些场景下还会出现 19 位。这就带来一个实际后果写匹配逻辑的时候不能假设「前 6 位一定是 BIN」也不能假设「卡号一定 16 位」。一份靠谱的 BIN 数据通常会带上卡号长度字段让程序在匹配号段的同时校验长度否则一张 19 位的卡可能被 16 位的规则误判。长度扩展这件事本身也说明了一个道理编号体系是会生长的。6 位号段理论上能容纳的组合同样有限当全球发卡量涨到某个量级扩容就成了必然。所以拿到一份 BIN 数据时先看它记录的号段长度覆盖到几位比看它收录了多少条更重要——只覆盖 6 位的表遇到 8 位号段就会匹配到错误的上一级。2.2 为什么非要有这套编号路由、识别、风控三件事一套编号能活几十年是因为它同时解决了三个绕不开的问题。第一是路由。一笔跨行交易发生时受理方需要知道把这笔请求送到哪个网络去。卡号前缀就是最直接的路标看到某个号段就知道该走哪条清算通道。如果没有统一编号每一笔交易都得靠人工或额外字段去判断去向成本和出错率都会高得离谱。第二是识别。用户在一个支付页面输入卡号页面需要立刻判断这是借记卡还是信用卡、是境内卡还是境外卡因为不同卡类型的后续流程不一样信用卡可能要填有效期和安全码借记卡可能要验证密码。让用户自己去下拉框里选「卡类型」等于把系统该干的活推给了人还容易选错。BIN 匹配把这一步变成了自动完成。第三是风控与对账。批量交易进来以后按 BIN 归类可以快速统计出「哪个号段的交易失败率异常」「哪个卡等级的用户退款率高」。这些分析不需要拿到完整卡号只用前缀就能完成分类对数据安全也更友好。对账场景同理一笔笔流水按发卡行归集靠的也是 BIN。提示BIN 能告诉你「这张卡属于哪个号段」但永远告诉不了你「这个号段下某个具体账户是否有效」。这两件事在系统设计里必须分开否则很容易写出看起来能跑、实际上判断错误的逻辑。2.3 为什么是 JSON比表格更适合被程序读把号段资料存成 Excel 或 CSV 也能用但一旦要接进代码差别就出来了。存放形式读取难度能表达层级版本对比适合场景Excel需要额外库格式易被改坏弱二进制难以 diff人工查阅CSV简单但字段顺序即契约无文本可 diff但一行一变扁平数据导入JSON各语言原生支持强可嵌套对象与数组文本可 diff改动清晰程序读取与集成YAML需额外库强可 diff但缩进敏感配置文件JSON 的优势主要在三点一是文本格式任何语言都有内置或成熟的解析器不用为了读一张表引入重型依赖二是能表达嵌套比如一个 BIN 号段下面挂着多个卡等级用数组一写就清楚CSV 只能拆成多行再自己拼三是纯文本便于版本管理哪条记录改了、哪个字段加了diff 一眼就能看出来。当然 JSON 也有代价。它没有索引几万条记录读进内存后还得自己建查找结构文件体积比二进制大字段名重复出现会浪费空间。这些代价在号段这种规模的资料上完全可以接受——它不像日志那样每天增长一次加载常驻内存就够了。3. 一份 BIN 数据里到底有什么字段拆解与能力边界3.1 一条记录长什么样字段拆解先看一条记录的结构比任何解释都直观。{ schema: 1, records: [ { bin: 400000, network: 国际卡组织A, type: credit, level: classic, issuer: 示例银行A, country: CN, length: 16, luhn: true } ] }这段 JSON 里schema是结构标记方便程序判断文件格式是否对得上records是记录数组每一条对应一个号段。单条记录里的字段含义如下字段含义取值示例说明bin号段本身400000字符串而非数字避免前导零丢失network所属卡网络卡组织A决定交易走哪条通道type卡类型credit / debit信用卡与借记卡流程不同level卡等级classic / gold影响权益与费率issuer发卡机构示例银行A展示用不一定精确到支行country发卡地区CN用于判断境内境外length卡号总长度16匹配时的硬约束luhn是否满足校验true表示该号段卡号需过校验位这里有个容易被忽略的细节bin要存成字符串。如果存成数字012345这种带前导零的号段在解析后就会变成12345匹配直接失效。凡是编号类字段一律按字符串处理这是踩过坑的人才会记住的规矩。另一个细节是length。同一个号段下可能同时存在 16 位和 19 位的卡这时候length就该写成数组而不是单值。数据里字段是单值还是数组直接决定了查询代码要不要多写一层判断。3.2 卡类型、卡等级、卡网络三层信息不要混着读新手最容易把这三层当成一回事其实它们回答的是三个不同的问题。卡网络回答「走哪条路」。它是清算通道的归属决定了交易请求发往哪个方向。卡类型回答「怎么扣款」。信用卡是先消费后还款借记卡是直接扣账户余额两者在支付流程里需要的验证要素不一样。卡等级回答「享受什么待遇」。同一家机构发的卡普卡、金卡、白金卡在额度、权益、费率上都有差别。举个具体场景一个页面识别出某张卡是「卡网络 A 信用卡 金卡」这三条信息是并行使用的——卡网络决定后续走哪个接口卡类型决定要不要展示安全码输入框卡等级决定要不要提示用户有分期权益。如果把它们压缩成一个笼统的「卡种」字段后面想拆开用就没法拆了。数据结构上这三层最好是三个独立字段而不是拼成一个字符串。拼字符串看起来省事实际用的时候每次都要再切分一次等于把复杂度推迟到了下游。3.3 为什么「能查到」不等于「这张卡真实存在」这是 BIN 数据最容易被误用的地方。号段资料能告诉你的是「这个前缀被分配给某家机构、属于某种卡类型」它说的是分配关系不是账户状态。至于这个号段下某个具体卡号是不是真的存在、有没有被注销、额度多少号段表一概不知道。校验位也是同理。校验位只做一件事检查这串数字在录入时有没有敲错、顺序有没有颠倒。它能挡住「把 8 打成 3」这种手误但挡不住故意构造的假号码——只要按规则凑出最后一位任何一串数字都能通过校验。所以正确的理解是BIN 匹配负责「归属判断」校验位负责「格式判断」两者加起来也只能说明「这串数字形式上像一张卡并且号段对得上」。真正的有效性判断必须由发卡方在线完成任何离线的号段资料都替代不了这一步。4. 最容易搞混的五组概念BIN 码、卡号、校验位与卡组织4.1 易混点一BIN 码就是卡号易混点把卡号前几位直接叫成「卡号」或者反过来以为 BIN 能唯一确定一张卡。为什么混BIN 确实是从卡号里截出来的两者字面上都是数字日常对话里也常被混着说。怎么区分记住一个包含关系——BIN 是卡号的前缀卡号是 BIN 加上个人账号段再加上校验位。BIN 对应一批卡卡号对应一张卡。写代码时的体现是BIN 用来查表得到归属信息完整卡号用来做校验和提交两者的变量名、用途、生命周期都不该混在一起。日志里更要注意BIN 可以记录完整卡号不能随便落盘。4.2 易混点二号段匹配就是卡号校验易混点以为「在 BIN 表里查到了」就等于「这个卡号是有效的」。为什么混两种操作都发生在用户输入卡号的那一刻界面上看起来是同一件事。怎么区分号段匹配查的是归属校验位查的是格式。前者是查表后者是一段固定算法。下面这段代码就是校验位的完整实现可以看清它和查表完全是两回事。def luhn_ok(number: str) - bool: # 从右往左取数字奇数位从 0 计翻倍 digits [int(c) for c in number if c.isdigit()][::-1] total 0 for i, d in enumerate(digits): if i % 2 1: d * 2 if d 9: # 翻倍后超过 9 就减 9等价于两位相加 d - 9 total d return total % 10 0 # 总和能被 10 整除即通过参数只有一个待校验的数字串。函数内部会先过滤掉空格和短横线再从右往左遍历对偶数下标位置的数字翻倍并按规则折算最后看总和能否被 10 整除。注意它对输入长度没有任何要求也不查任何表——一串随手编的数字只要末位凑对就能通过。这就是它不能代替号段匹配的原因反过来也一样。4.3 易混点三卡组织就是发卡行易混点看到卡号前缀就以为知道了是哪家银行发的卡。为什么混卡面上既印着卡网络的标志也印着发卡机构的名称两个标志挨在一起很容易被当成同一层信息。怎么区分卡网络负责搭建清算通道、制定规则自己不発卡发卡行负责审批账户、发卡、收单。一张卡可以同时在多个网络下使用也可以换发卡行而号段不变。在数据里network和issuer是两个字段前者相对稳定后者可能随着机构合并、业务调整而变化。做展示时别把网络名当成银行名显示给用户这是很常见的翻车点。4.4 易混点四BIN 库就是银行卡数据库易混点把一份号段资料理解成「能查出银行卡主人」的东西。为什么混「BIN 码大全」这个名字听起来很像一个庞大的数据库容易让人产生它能查到具体信息的错觉。怎么区分号段资料的每一条记录只描述一批卡的共同属性记录数通常在几千到几万级别银行卡数据库描述的是具体账户规模是亿级且属于受严格管控的信息。前者是公开的编号规则整理后者是账户系统。判断标准很简单如果一份资料里出现了姓名、身份证、余额这类字段那它就不是号段资料也不该被随意传播。4.5 易混点五JSON 就是随便写个对象易混点觉得 JSON 没有约束字段想加就加、想改就改。为什么混JSON 语法确实宽松多一个字段少一个字段都能解析成功。怎么区分语法宽松不等于语义宽松。一份给人用的资料和一份给程序用的资料差别就在字段约定上。bin必须是字符串、length可能是数组、type的取值必须来自一个固定集合——这些约定不写在语法里但写在使用方的代码里。改动字段名而不改版本号下游就会静默出错。稳妥的做法是给文件加一个schema标记字段发生不兼容变化时同步升级它让读取方能够主动拒绝不认识的格式。5. 查询是怎么跑起来的从 JSON 读入到前缀匹配的完整链路5.1 把 JSON 读进内存一次前缀查找的最小实现号段查询的逻辑本身不复杂难点在于边界处理。下面这段代码是一个可以直接跑起来的最小实现。import json # 1. 读入文件。encoding 必须显式指定否则中文机构名会乱码 with open(bin_table.json, r, encodingutf-8) as f: raw json.load(f) # 2. 把数组转成字典键是号段查询时不用遍历 BIN_INDEX {item[bin]: item for item in raw[records]} # 3. 长度从长到短尝试避免 8 位号段被 6 位号段抢先命中 PREFIX_LENS (8, 7, 6) def lookup(card_number: str): # 去掉用户可能输入的空格和短横线 digits .join(ch for ch in card_number if ch.isdigit()) for n in PREFIX_LENS: if len(digits) n: continue hit BIN_INDEX.get(digits[:n]) if hit: # 长度字段可能是单值也可能是数组统一成列表判断 allowed hit[length] allowed allowed if isinstance(allowed, list) else [allowed] if len(digits) in allowed: return hit return None这段代码有几个关键点值得展开。第一行打开文件时显式指定了utf-8因为记录里通常含中文机构名用系统默认编码在部分环境下会直接抛异常。第二步用字典推导式把数组转成哈希表把查询从「遍历几万条」降为「一次哈希查找」这是性能上最关键的一步。第三步定义了尝试顺序(8, 7, 6)从长到短因为长号段更具体短号段更宽泛先匹配长的才不会误判。函数体内部的长度过滤也很有必要。同一个 6 位号段下可能既有 16 位卡也有 19 位卡如果只比对前缀不看长度就可能把一张 19 位的卡判成 16 位卡种。isinstance那一行是在兼容「长度字段是单值还是数组」两种写法实际数据里两种都可能出现写死成一种早晚会翻车。5.2 最长前缀优先为什么不能从头到尾顺序匹配如果不用最长优先而是简单地「找到第一个匹配就返回」会出什么问题假设数据里同时存在400000某类信用卡和40000012同网络下的另一类卡。用户输入一张以40000012开头的卡号顺序遍历时先命中 6 位的记录就会返回错误的卡类型。号段体系天然是分层的越长的前缀越具体匹配逻辑必须尊重这个层级。除了顺序还有一个性能上的考量如果每次查询都遍历全表做startswith几万条记录乘以每次请求开销会很明显。转成字典后一次查询最多做三次哈希查找与数据规模基本无关。这个优化在单次调用上看不出差别放到每秒几百次请求的接口里就是数量级的差异。还有一种做法是构建前缀树把号段逐位挂到树上查询时沿着数字一路往下走。这种结构对超大规模数据更友好但对几万条记录来说属于过度设计字典加定长尝试已经完全够用。选方案要看数据规模别为了「看起来专业」把简单问题复杂化。5.3 典型落地场景表单提示、对账归类、风控分层号段数据最直接的用法是支付表单的实时提示。用户输入前几位页面就能显示卡类型和所属机构省掉一个下拉框也减少了用户选错导致的后续失败。这里要注意的是提示只是辅助不能作为拦截依据——用户可能输错也可能输入的是不常见的号段。第二个场景是对账归类。一批交易流水导出来以后按号段归集到不同机构、不同卡类型能快速看出哪类交易占比高、哪类失败率异常。这个场景不需要完整卡号只用前缀就行对数据脱敏也更友好。第三个场景是风控分层。不同卡类型、不同地区的交易风险特征不一样规则引擎可以依据号段信息做初步分层再叠加金额、频次、设备等维度做综合判断。这里的分层只是「初筛」不能单独作为拦截理由否则会误伤大量正常用户。6. 什么时候该用、什么时候别用一份 BIN 数据的适用边界判断一份号段资料该不该接进系统可以对着下面这张表过一遍。场景适不适合原因支付表单自动识别卡类型适合只做提示不参与最终判定批量流水按机构归类统计适合只需前缀不必触碰完整卡号离线数据清洗与格式规范化适合号段加长度校验能过滤大量脏数据判断某个账户是否存在不适合号段只描述分配关系不描述账户作为交易放行的唯一依据不适合必须由发卡方在线验证用于反查持卡人信息不适合号段资料不含任何个人字段具体到工程实践有几个边界值得反复提醒。第一号段数据会变。机构合并、业务调整、新号段启用都会让一份旧表逐渐失准所以要预留更新机制而不是把它当成一次性导入的常量。第二匹配失败不等于卡无效。冷门号段、新启用号段没被收录都会导致查不到这时候的正确做法是「放行并标记未知」而不是直接拒绝。第三任何涉及完整卡号的处理都要谨慎能在前缀阶段解决的问题就不要把完整卡号带进日志和缓存。我自己在这件事上栽过一次。早期做一个表单识别功能图省事用了「顺序遍历、命中即返回」的写法测试时用常见号段一路绿灯上线后遇到一批长号段用户卡类型全部显示错误客服那边收到一堆反馈。排查了两个小时才定位到是匹配顺序的问题改成从长到短尝试之后立刻正常。从那以后我每次接号段相关的逻辑都会强制走一遍「最长优先 长度校验 未知放行」这三步哪怕数据量再小也不省这一步。这份 JSON 格式的 BIN 码大全价值就在于它把号段、卡类型、卡等级、长度这些散落的信息收拢成一份结构统一、能直接被程序读取的文件省掉自己从零整理和清洗的功夫。如果你的项目里正好有表单识别、流水归类或者数据清洗这类需求拿去接进代码里就能用比自己拼一张表要省心得多。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?