Python实现统一社会信用代码校验
统一社会信用代码国标校验
统一社会信用代码的校验最准确的方式,就是通过调用正式的接口或者对接统一社会信用代码数据库。前者,我们需要支付一定的费用。后者,实施难度较大。在资源有限的情况下,我们可以参照GB- 32100-2015实现代码,对统一社会信用代码合法性作出判断。
统一社会信用代码国标校验规则
简单来说,国标的校验规则就是取统一社会信用代码的前17位(自左至右),每一位的字符/数字都有其对应的值,公式(1)最终求出的值经过转化后与统一社会信用代码的第十八位进行比对,一致则代表统一社会信用代码合法,不一致则代表统一社会信用代码不合法。
C
18
=
31
−
M
O
D
(
∑
i
=
1
17
×
W
i
,
31
)
\begin{aligned}C_{18}=31-MOD(\sum_{i=1}^{17}\times W_{i},31)\end{aligned}
C18=31−MOD(i=1∑17×Wi,31)
其中,
C
i
C_{i}
Ci标识字符/数字对应的值,
M
O
D
(
m
,
n
)
MOD(m,n)
MOD(m,n)标识
m
m
m除
n
n
n后的余数,
W
i
W_i
Wi表示每一位字符/数字的加权因子,可由
W
i
=
M
O
D
(
3
i
−
1
,
31
)
W_i=MOD(3^{i-1},31)
Wi=MOD(3i−1,31)计算得到。需要注意的是,当
31
−
M
O
D
(
m
,
n
)
31-MOD(m,n)
31−MOD(m,n)的结果为31时,校验码用0表示
特别地,摘抄一段国标中统一代码的机构描述“统一社会信用代码由十八位的阿拉伯数字或大写英文字母(不使用I、O、Z、S、V)组成,包括第1位登记管理部门代码、第2位机构类别代码、第3位到第8位登记管理机关行政区划码、第9位到第17位主体标识码(组织机构代码)、第18位校验码五个部分”。由此,我们可以根据代码的对应关系解析出隐藏的信息(详细的代码标识可参照GB- 32100-2015)。
示例说明
以“11320000MB151840XJ”为例。
- 首先,根据代码字符集表获取“11320000MB151840XJ”中每个代码字符对应的代码字符数值。
代 码 字 符 代码字符 代码字符 | 1 | 1 | 3 | 2 | 0 | 0 | 0 | 0 | M | B | 1 | 5 | 1 | 8 | 4 | 0 | X |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
字 符 数 值 字符数值 字符数值 | 1 | 1 | 3 | 2 | 0 | 0 | 0 | 0 | 21 | 11 | 1 | 5 | 1 | 8 | 4 | 0 | 29 |
代码字符 | 代码字符数值 |
---|---|
0 | 0 |
1 | 1 |
2 | 2 |
3 | 3 |
4 | 4 |
5 | 5 |
6 | 6 |
7 | 7 |
8 | 8 |
9 | 9 |
A | 10 |
B | 11 |
C | 12 |
D | 13 |
E | 14 |
F | 15 |
G | 16 |
H | 17 |
J | 18 |
K | 19 |
L | 20 |
M | 21 |
N | 22 |
P | 23 |
Q | 24 |
R | 25 |
T | 26 |
U | 27 |
W | 28 |
X | 29 |
Y | 30 |
- 将对应位置的字符值乘相应的权重并求和。
s u m = 1 × 1 + 1 × 3 + 3 × 9 + 2 × 27 + 0 × 19 + 0 × 26 + 0 × 16 + 0 × 17 + 21 × 20 + 11 × 29 + 1 × 25 + 5 × 13 + 1 × 8 + 8 × 24 + 4 × 10 + 0 × 30 + 29 × 28 = 1966 sum =1\times1+1\times3+3\times9+2\times27+0\times19+0\times26+0\times16+0\times17+21\times20+11\times29+1\times25+5\times13+1\times8+8\times24+4\times10+0\times30+29\times28=1966 sum=1×1+1×3+3×9+2×27+0×19+0×26+0×16+0×17+21×20+11×29+1×25+5×13+1×8+8×24+4×10+0×30+29×28=1966
i i i | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
W i W_i Wi | 1 | 3 | 9 | 27 | 19 | 26 | 16 | 17 | 20 | 29 | 25 | 13 | 8 | 24 | 10 | 30 | 28 |
- 求出校验码
r
e
s
res
res并与
C
18
C_{18}
C18进行比对。
r e s = 31 − M O D ( 1966 , 31 ) = 18 res=31-MOD(1966,31)=18 res=31−MOD(1966,31)=18
易得18对应的字符为 J J J,与 C 18 C_{18} C18一致,“11320000MB151840XJ”通过国标校验,这里,通过国标校验仅能代表编码规则是正确的,如果需要进一步确定统一社会信用代码是否真实存在,还需通过其他渠道。
Python代码实现(仅实现GB- 32100-2015中的规则)
def scVerificate(sc):
# 校验公式(见GB 32100-2015):C_18 = 31-mod(sum(C_i*W_i),31)(i=1,2,...,17),其中C_i为组织机构代码的第i位字符在国标中对应的值,W_i为第i位置的加权因子,C_18为校验码
# 统一社会信用代码中不使用I,O,Z,S,V
result = False;
codeDict = {
'0':0,'1':1,'2':2,'3':3,'4':4,'5':5,'6':6,'7':7,'8':8,'9':9,
'A':10,'B':11,'C':12, 'D':13, 'E':14, 'F':15, 'G':16, 'H':17, 'J':18, 'K':19, 'L':20, 'M':21, 'N':22, 'P':23, 'Q':24,
'R':25, 'T':26, 'U':27, 'W':28, 'X':29, 'Y':30};
weights = ['1', '3', '9', '27', '19', '26', '16', '17', '20', '29', '25', '13', '8', '24', '10', '30', '28'];
sum = 0
for i in range(len(sc) - 1):
#print(codeDict[sc[i]]);
sum += codeDict[sc[i]] * int(weights[i]);
mod = 31-sum % 31
if(mod == codeDict[sc[-1]]) or ((mod == 31) and codeDict[sc[-1]] == 0):
result = True;
return result;