Python实现统一社会信用代码合法性校验
1 统一代码的构成
1.1 结构
统一代码由十八位的阿拉伯数字或大写英文字母(不使用I、O、Z、S、V)组成,包括第1位登记管理部门代码、第2位机构类别代码、第3位第8位登记管理机关行政区划码、第9位第17位主体标识码(组织机构代码)、第18位校验码五个部分。
1.2 代码及说明
1.2.1 第1位:登记管理部门代码
登记管理部门代码使用阿拉伯数字或大写英文字母表示,登记管理部门代码标识如下:
djglbmdm={'1':'机构编制','2':'外交','3':'司法行政','4':'文化','5':'民政','6':'旅游','7':'宗教','8':'工会','9':'工商','A':'中央军委改革和编制办公室','N':'农业','Y':'其他'}
1.2.2 第2位:机构类别代码
机构类别代码使用阿拉伯数字或大写英文字母表示,机构类别代码如下:
# 不同登记管理部门下相同机构类别代码代表的机构类别不同
jglbdm={'1':{'1':'机关','2':'事业单位','3':'编办直接管理机构编制的群众团体','9':'其他'},
'2':{'1':'外国常驻新闻机构','9':'其他'},
'3':{'1':'律师执业机构','2':'公证处','3':'基层法律服务所','4':'司法鉴定机构','5':'仲裁委员会','9':'其他'},
'4':{'1':'外国在华文化中心','9':'其他'},
'5':{'1':'社会团体','2':'民办非企业单位','3':'基金会','9':'其他'},
'6':{'1':'外国旅游部门常驻代表机构','2':'港澳台地区旅游部门常驻内地(大陆)代表机构','9':'其他'},
'7':{'1':'宗教活动场所','2':'宗教院校','9':'其他'},
'8':{'1':'基层工会','9':'其他'},
'9':{'1':'企业','2':'个体工商户','3':'农民专业合作社'},
'A':{'1':'军队事业单位','9':'其他'},
'N':{'1':'组级集体经济组织','2':'村级集体经济组织','3':'乡镇级集体经济组织','9':'其他'},
'Y':{'1':''}}
1.2.3 第3位~第8位:登记管理机关行政区划码
登记管理机关行政区划码使用阿拉伯数字表示。按照GB/T 2260编码。
1.2.4 第9位~第17位:主体标识码(组织机构代码)
主体标识码使用阿拉伯数字或大写英文字母表示。按照GB 11714编码。
1.2.5 第18位:校验码
校验码使用阿拉伯数字或大写英文字母表示。校验码计算方法参照GB/T 17710。
校验码按式如下公式计算:
C
18
=
31
−
M
O
D
(
∑
i
=
1
17
C
i
×
W
i
,
31
)
C_{18}=31-MOD(\sum_{i=1}^{17}C_{i}\times W_{i},31)
C18=31−MOD(i=1∑17Ci×Wi,31)
式中:
MOD(n,m) ——整数求余函数,例如:函数MOD(31,31)的值为0;
i ——代码字符 从左到右的位置序号;
Ci ——第i位置上的代码字符的值,字符对应的值如下:
dmci={'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}
C18 ——校验码;
Wi ——第i位上的加权因子,Wi= MOD(3(i-1) ,31) ,加权因子如下:
# i 位置列表
i=[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17]
# wi 位置对应的加权因子
wi=[1,3,9,27,19,26,16,17,20,29,25,13,8,24,10,30,28]
当MOD函数值为1(即C18 = 30)时,校验码应用符号Y表示;当MOD函数值为0(即C18 = 31)时,校验码用0表示。
1.2.6 校验码计算方法实例
某统一代码前17位为91350100M000100Y4,其第18位校验码可按下列步骤与方法计算。
第一步:列出代码前17位字符位置序号i相对应的各个位置上的字符值Ci。
# M:21,Y:30
ci=[9,1,3,5,0,1,0,0,21,0,0,0,1,0,0,30,4]
第二步:列出与字符位置序号i相对应的加权因子值Wi。
# wi 位置对应的加权因子
wi=[1,3,9,27,19,26,16,17,20,29,25,13,8,24,10,30,28]
第三步:计算与字符位置序号i相对应的乘积Ci × Wi。
# ci[j]*wi[j]
ciwi=[]
for j in range(0,17):
ciwi.append(ci[j]*wi[j])
第四步:计算级数之和。
∑
i
=
1
17
C
i
×
W
i
=
1640
\sum_{i=1}^{17}C_{i}\times W_{i} =1640
i=1∑17Ci×Wi=1640
第五步:计算整数求余函数MOD。
级数之和1640模31余28,即MOD(1640,31)值为28。
第六步:求出校验码字符值。
C18=31-28=3
第七步:查出校验码字符。
校验码字符值18对应的字符为3,该统一代码为91350100M000100Y43
以上参考:中华人民共和国国家标准 GB 32100-2015《法人和其他组织统一社会信用代码编码规则》
2 Python代码实现
def check_social(code):
#统一代码由十八位的阿拉伯数字或大写英文字母(不使用I、O、Z、S、V)组成
valid_char='0123456789ABCDEFGHJKLMNPQRTUWXY'
invlid_char='IOZSV'
modulus=31
if code is None or code.isspace():
return False
#位数校验 18 位
if len(code)!=18:
return False
codeu = code.upper()
#含有不使用大写英文字母
for i in invlid_char:
if i in codeu:
return False
#不在有效字符范围内
for i in code:
if not(i in valid_char):
return False
#前两位登记管理部门代码和机构类别代码
d_o_code=['11','12','13','19','21','29','31','32','33','34','35','39',
'41','49','51','52','53','59','61','62','69','71','72','79',
'81','89','91','92','93','A1','A9','N1','N2','N3','N9','Y1']
if not(code[0:2] in d_o_code):
return False
#3-8位登记管理机关行政区划码先不检测了
#9-17位主体标识码(组织机构代码)先不拿出来校验了
#第18位校验码,这部分是关键
#第i位置对应的加权因子
wi=[1,3,9,27,19,26,16,17,20,29,25,13,8,24,10,30,28]
#第i位置上的字符对应值
corres_value={'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}
#前17位字符位置序号i相对应的各个位置上的字符值
ci=[]
for v in code[0:17]:
j=corres_value.get(v)
ci.append(j)
#计算与字符位置序号i相对应的乘积
ciwi=[]
for i in range(len(ci)):
ciwi.append(ci[i]*wi[i])
#计算级数之和
ciwi_sum=sum(ciwi)
#级数之和求余,求出校验码字符值
c18 = modulus-ciwi_sum % modulus
#查出校验码字符
if c18 == modulus:
c18=0
check_code=None
for k,v in corres_value.items():
if v == c18:
check_code=k
break
if check_code==code[17]:
return True
else:
return False
3 未检测部分
3.1 管理部门行政区划代码
全国行政区划代码比较多,在本文实现代码中就没有做校验。
3.2 组织机构代码
组织机构代码也有待定的规则,本文实现代码中没有做校验,有兴趣的可做补充!