从本质上讲,工商营业执照号码和统一社会信用代码是两套完全不一样的编码规则,识别结果也仅有行政区划部分为两者共有,但因为这两种编码同时存在的原因,所以如果需要在系统中唯一标志一家企业时,还是可以通过工商营业执照号码或统一社会信用代码来进行识别。
工商营业执照号码长度按工商规定为15位,统一社会信用代码按国家规定是18位,你可以在此类库的验证基础上,通过其它网站(比如企查查)来进一步查验企业是否真实存在。
在NumberValidators
中,该部分验证相关的内容均在NumberValidators.BusinessRegistrationNos
下,你可以在此处查看具体源代码。
IRegistrationNoValidator
约定了要实现的验证的规范。
/// <summary>
/// 工商注册码/统一社会信用代码验证接口
/// </summary>
public interface IRegistrationNoValidator<out TResult> : IValidator<TResult>
where TResult : RegistrationNoValidationResult, new()
{
/// <summary>
/// 用于验证的行政区划字典数据
/// </summary>
IValidationDictionary<int, string> Dictionary { get; set; }
/// <summary>
/// 号码长度
/// </summary>
RegistrationNoLength RegistrationNoLength { get; }
/// <summary>
/// 验证号码是否正确
/// </summary>
/// <param name="code">待验证的工商注册码/统一社会信用代码</param>
/// <param name="validLimit">行政区划验证限制,因为存在工商管理机构代码,所以默认为null</param>
/// <returns></returns>
TResult Validate(string code, AreaValidLimit? validLimit = null);
}
验证结果定义如下:
RegistrationNoValidationResult
默认验证结果类RegistrationNo15ValidationResult
工商营业执照特有的验证结果类RegistrationNo18ValidationResult
统一社会信用代码特有的验证结果类
RegistrationNoValidationResult
代码如下
/// <summary>
/// 注册码通用验证结果类
/// </summary>
public class RegistrationNoValidationResult : ValidationResult
{
/// <summary>
/// 行政区划或工商行政管理机关编码
/// </summary>
public int AreaNumber { get; internal set; }
/// <summary>
/// 身份证颁发行政区域或工商行政管理机关(识别出Depth最深的区域),可通过FullName来获取完整的名称
/// 注意此处有可能为null
/// </summary>
public Area RecognizableArea { get; internal set; }
/// <summary>
/// 号码长度
/// </summary>
public RegistrationNoLength RegistrationNoLength { get; internal set; }
/// <summary>
/// 校验码
/// </summary>
public char CheckBit { get; internal set; }
}
RegistrationNo15ValidationResult
在RegistrationNoValidationResult
的基础上额外包含了工商营业执照专有的识别信息,你可以通过该部分得知该企业是内资企业、外资企业还是个体户
。
/// <summary>
/// 工商行政管理市场主体注册号 专用验证结果类
/// </summary>
public class RegistrationNo15ValidationResult : RegistrationNoValidationResult
{
/// <summary>
/// 顺序码
/// </summary>
public int SequenceNumber { get; internal set; }
/// <summary>
/// 企业类型
/// </summary>
public EnterpriseType EnterpriseType
{
get
{
var comp = this.SequenceNumber / 10000000;
if (comp <= (int)EnterpriseType.Domestic)
{
return EnterpriseType.Domestic;
}
else if (comp <= (int)EnterpriseType.Foreign)
{
return EnterpriseType.Foreign;
}
else { return EnterpriseType.Individual; }
}
}
}
RegistrationNo18ValidationResult
则是在RegistrationNoValidationResult
的基础上额外包含了社会统一信用代码的专有信息,你可以通过该部分信息得知其登记管理部门
,以及其组织机构代码
。
/// <summary>
/// 法人和其他组织统一社会信用代码 专用验证结果类
/// </summary>
public class RegistrationNo18ValidationResult : RegistrationNoValidationResult
{
/// <summary>
/// 登记管理部门代码标志
/// </summary>
public ManagementCode ManagementCode { get; internal set; }
/// <summary>
/// 登记管理部门下机构类别代码标志
/// </summary>
public ManagementKindCode ManagementKindCode { get; internal set; } = ManagementKindCode.NonSpecific;
/// <summary>
/// 组织机构代码,遵循GB/T 11714-1997
/// </summary>
public string OrganizationCode { get; internal set; }
}
可根据IsValid
来判断验证是否成功,如果验证失败,Errors
属性则包含了验证失败的原因,具体的错误原因列表如下
/// <summary>
/// 错误提示信息类
/// </summary>
internal class ErrorMessage
{
/// <summary>
/// 字符串为空
/// </summary>
public const string Empty = "工商注册码/统一社会信用代码为空";
/// <summary>
/// 号码错误
/// </summary>
public const string Error = "错误的工商注册码/统一社会信用代码";
/// <summary>
/// 无效的登记管理部门代码
/// </summary>
public const string InvalidManagement = "无效的登记管理部门代码";
/// <summary>
/// 无效的登记管理部门机构类别代码
/// </summary>
public const string InvalidManagementKind = "无效的登记管理部门机构类别代码";
/// <summary>
/// 无效的组织机构代码
/// </summary>
public const string InvalidOrganizationCode = "无效的组织机构代码";
/// <summary>
/// 行政区划识别失败
/// </summary>
public const string InvalidArea = "工商管理机关或行政区划识别失败";
/// <summary>
/// 错误的校验码
/// </summary>
public const string InvalidCheckBit = "错误的校验码";
/// <summary>
/// 无效实现
/// </summary>
public const string InvalidImplement = "未能找到或无效的 {0} 位工商注册码/统一社会信用代码实现";
/// <summary>
/// 长度错误
/// </summary>
public const string LengthOutOfRange = "工商注册码/统一社会信用代码非 {0} 位";
}
同其它验证类一致,RegistrationNoValidatorHelper
可自动识别待识别号码究竟为工商营业执照号码还是社会统一信用代码,当然因为有可能待识别号码哪种号码都不是,所以最终识别结果可能为RegistrationNoValidationResult
、RegistrationNo15ValidationResult
和RegistrationNo18ValidationResult
中的某一种。
最后是简单的使用示例
Console.WriteLine("***工商注册码/统一社会信用代码***");
string[] rnArr = { "110108000000016", "91320621MA1MRHG205" };
foreach (var rn in rnArr)
{
var valid = RegistrationNoValidatorHelper.Validate(rn, validLimit: null);
Console.WriteLine("{0}验证结果:{1} 长度{2} 行政区划名称({3}) 验证结果类型:{4}", rn, valid.IsValid, valid.RegistrationNoLength, valid.RecognizableArea.FullName, valid);
}
Console.WriteLine("随机的工商注册码:" + new RegistrationNo15Validator().GenerateRandomNumber());
Console.WriteLine("随机的统一社会信用代码:" + new RegistrationNo18Validator().GenerateRandomNumber());