uscc-utils
Version:
Utils about unified social credit code | 统一社会信用代码工具方法
278 lines (277 loc) • 5.56 kB
JavaScript
//#region src/constants.ts
/**
* 正则 统一社会信用代码
* @see {@link https://www.wikidata.org/wiki/Property:P6795}
* @see {@link https://regexper.com/#%2F%5B1-9ANY%5D%5B1-59%5D%5Cd%7B6%7D%5B%5CdA-Z%5D%7B8%7D%5B%5CdX%5D%5B%5CdA-HJ-NP-RTUW-Y%5D%2F}
*/
const USCC_PATTERN = /^[1-9ANY][1-59]\d{6}[\dA-Z]{8}[\dX][\dA-HJ-NP-RTUW-Y]$/u;
/**
* 登记管理部门代码
*/
const USCC_CATEGORY_MAP = {
1: {
category: "机构编制",
map: {
1: "机关",
2: "事业单位",
3: "编办直接管理机构编制的群众团体",
9: "其他"
}
},
2: {
category: "外交",
map: {
1: "外国常驻新闻机构",
9: "其他"
}
},
3: {
category: "司法行政",
map: {
1: "律师执业机构",
2: "公证处",
3: "基层法律服务所",
4: "司法鉴定机构",
5: "仲裁委员会",
9: "其他"
}
},
4: {
category: "文化",
map: {
1: "外国在华文化中心",
9: "其他"
}
},
5: {
category: "民政",
map: {
1: "社会团体",
2: "民办非企业单位",
3: "基金会",
9: "其他"
}
},
6: {
category: "旅游",
map: {
1: "外国旅游部门常驻代表机构",
2: "港澳台地区旅游部门常驻内地(大陆)代表机构",
9: "其他"
}
},
7: {
category: "宗教",
map: {
1: "宗教活动场所",
2: "宗教院校",
9: "其他"
}
},
8: {
category: "工会",
map: {
1: "基层工会",
9: "其他"
}
},
9: {
category: "工商",
map: {
1: "企业",
2: "个体工商户",
3: "农民专业合作社"
}
},
A: {
category: "中央军委改革和编制办公室",
map: {
1: "军队事业单位",
9: "其他"
}
},
N: {
category: "农业",
map: {
1: "组级集体经济组织",
2: "村级集体经济组织",
3: "乡镇级集体经济组织",
9: "其他"
}
},
Y: {
category: "其他",
map: {}
}
};
//#endregion
//#region src/validate.ts
/**
* 统一社会信用代码长度
*/
const USCC_LENGTH = 18;
/**
* 统一社会信用代码 取模值
*/
const USCC_MOD = 31;
/**
* 统一社会信用代码字符集
*/
const USCC_CHARS = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"J",
"K",
"L",
"M",
"N",
"P",
"Q",
"R",
"T",
"U",
"W",
"X",
"Y"
];
/**
* 统一社会信用代码加权因子
*/
const USCC_WEIGHTS = [
1,
3,
9,
27,
19,
26,
16,
17,
20,
29,
25,
13,
8,
24,
10,
30,
28
];
/**
* 标准化统一社会信用代码输入
* @param code - 原始统一社会信用代码
* @returns 标准化后的统一社会信用代码
*/
function normalizeUSCC(code) {
return code.trim().toUpperCase();
}
function getCodeByOptions(code, options = {}) {
const { normalize = false } = options;
return normalize ? normalizeUSCC(code) : code;
}
/**
* 获取统一社会信用代码的详细校验结果
* @param code - 统一社会信用代码
* @param options - 校验选项
* @returns 详细校验结果
*/
function explainUSCC(code, options = {}) {
const normalizedCode = getCodeByOptions(code, options);
if (normalizedCode.length !== USCC_LENGTH) return {
normalizedCode,
isValid: false,
errorCode: "INVALID_LENGTH"
};
if (!USCC_PATTERN.test(normalizedCode)) return {
normalizedCode,
isValid: false,
errorCode: "INVALID_PATTERN"
};
if (!(USCC_CHARS[(USCC_MOD - [...normalizedCode].filter((_, idx) => idx < 17).reduce((acc, char, idx) => acc + USCC_CHARS.indexOf(char) * USCC_WEIGHTS[idx], 0) % USCC_MOD) % USCC_MOD] === normalizedCode.charAt(17))) return {
normalizedCode,
isValid: false,
errorCode: "INVALID_CHECKSUM"
};
return {
normalizedCode,
isValid: true
};
}
/**
* 校验统一社会信用代码
* @param code - 统一社会信用代码
* @param options - 校验选项
* @returns 是否有效
*
* @example
* ```
* import { validateUSCC } from 'uscc-utils'
* validateUSCC('91110108551385082Q') // true
* ```
*/
function validateUSCC(code, options = {}) {
return explainUSCC(code, options).isValid;
}
/**
* 按标准结构拆分统一社会信用代码
* @param code - 统一社会信用代码
* @param options - 校验选项
* @returns 若代码有效则返回结构化字段,否则返回 `null`
*/
function splitUSCC(code, options = {}) {
const { isValid, normalizedCode } = explainUSCC(code, options);
if (!isValid) return null;
return {
registrationAuthorityCode: normalizedCode.slice(0, 1),
entityTypeCode: normalizedCode.slice(1, 2),
regionCode: normalizedCode.slice(2, 8),
organizationCode: normalizedCode.slice(8, 17),
checkChar: normalizedCode.slice(17, 18)
};
}
//#endregion
//#region src/parse.ts
/**
* 解析统一社会信用代码
* @param code - 待解析的统一社会信用代码
* @param options - 解析选项
* @returns 解析结果 `ParseResult`
*
* @example
* ```
* import { parseUSCC } from 'uscc-utils'
* parseUSCC('91110108551385082Q') // { isValid: true, category: '工商', type: '企业' }
* ```
*/
function parseUSCC(code, options = {}) {
const { unknownCategory = "", unknownType = "", normalize = false } = options;
const { isValid, normalizedCode } = explainUSCC(code, { normalize });
if (!isValid) return {
isValid,
category: unknownCategory,
type: unknownType
};
const matched = USCC_CATEGORY_MAP[normalizedCode.charAt(0)];
return {
isValid,
category: matched?.category ?? unknownCategory,
type: matched?.map[normalizedCode.charAt(1)] ?? unknownType
};
}
//#endregion
export { USCC_CATEGORY_MAP, USCC_PATTERN, explainUSCC, normalizeUSCC, parseUSCC, splitUSCC, validateUSCC };