分享组织机构代码有效性校验的实现


placeholder image
admin 发布于:2015-06-16 11:20:54
阅读:loading

背景介绍

记得去年帮别的组的同事“翻译”了一个组织机构代码生成规则的实现,所谓的“翻译”是指其他项目上有一个经过实践检验的验证组织机构代码有效性的实现方式,但它实现方案是sql的存储过程实现的,由我来协助将其“翻译”成java版的。其实书写大量sql的语句工作以来实际上我写的也不是很多(复杂逻辑还是放在后台程序中做),又是也是一边理解,也是一边请教后,将其给“翻译”过来了,这个活好像是我去年新入职后的第一件事情。

组织机构代码可以理解为企业的身份证号,网上百科说的很详细,在这里只是讨论一下验证机构号的合法性,有的地方看到到它的结构如下:46650460-6,长度一共是10个字符,由8位数字与 - 还有1位数字组成的,本例的校验规则所输入的组织机构号只需要输入9位的纯数字即可(发现网上搜索时的应用程序也只要求输入9位的纯数字)。

废话少说,先从原始的sql实现分析:

原始SQL,采用数据库的自定义函数实现

CREATE OR REPLACE FUNCTION fnc_chkcompanyno ( v_companyno IN VARCHAR2 )
    RETURN CHAR
IS
    /**
    *  输入:组织机构代码号
    *  输出:TRUE     合法
    FALSE    不合法
    *  出错:抛出异常
    */
TYPE type_nocheck
IS
    TABLE OF INTEGER INDEX BY BINARY_INTEGER ;
t_calculate type_nocheck ;
n_bitnum INTEGER ;
n_sum INTEGER := 0 ;
v_bit VARCHAR2 ( 1 );
v_num VARCHAR2 ( 10 ) := '0123456789' ;
BEGIN
    t_calculate ( 1 ) := 3 ;
t_calculate ( 2 ) := 7 ;
t_calculate ( 3 ) := 9 ;
t_calculate ( 4 ) := 10 ;
t_calculate ( 5 ) := 5 ;
t_calculate ( 6 ) := 8 ;
t_calculate ( 7 ) := 4 ;
t_calculate ( 8 ) := 2 ;
FOR nloop IN 1 .. 8
LOOP
    v_bit := SUBSTR ( v_companyno , nloop , 1 );
//从1截取到1,首字符
IF instr ( v_num , v_bit , 1 ) = 0 THEN //indexOf
    n_bitnum := ascii ( v_bit ) - ascii ( 'A' ) + 65 ;
ELSE
    n_bitnum := ascii ( v_bit ) - ascii ( '0' );
END IF ;
n_sum := n_sum + n_bitnum * t_calculate ( nloop );
END LOOP ;
n_sum := 11 - MOD ( n_sum , 11 );
IF n_sum = 10
    AND
    SUBSTR ( v_companyno , 9 , 1 ) = 'X' THEN
    RETURN '1' ;
END IF ;
IF n_sum = 11
    AND
    SUBSTR ( v_companyno , 9 , 1 ) = '0' THEN
    RETURN '1' ;
END IF ;
IF n_sum NOT IN ( 10 ,
                 11 )
    AND
    SUBSTR ( v_companyno , 9 , 1 ) = CAST ( n_sum AS VARCHAR2 ) THEN
    RETURN '1' ;
END IF ;
RETURN '0' ;
EXCEPTION
WHEN OTHERS THEN
    RETURN '0' ;
END fnc_chkcompanyno ;

理解SQL,并添加注释(处于谨慎请教与大乐哥,感谢协助)

CREATE OR REPLACE FUNCTION fnc_chkcompanyno ( v_companyno IN VARCHAR2 ) //
    --定义一varchar2类型的输入参数v_companyno
    RETURN CHAR
IS
    /**
    *  输入:组织机构代码号
    *  输出:TRUE     合法
    FALSE    不合法
    *  出错:抛出异常
    */
TYPE type_nocheck
IS
    TABLE OF INTEGER INDEX BY BINARY_INTEGER ;
t_calculate type_nocheck ;
//这里类似于定义一个数组
n_bitnum INTEGER ;
n_sum INTEGER := 0 ;
v_bit VARCHAR2 ( 1 );
v_num VARCHAR2 ( 10 ) := '0123456789' ;
BEGIN
    t_calculate ( 1 ) := 3 ;
//给数组赋值
t_calculate ( 2 ) := 7 ;
t_calculate ( 3 ) := 9 ;
t_calculate ( 4 ) := 10 ;
t_calculate ( 5 ) := 5 ;
t_calculate ( 6 ) := 8 ;
t_calculate ( 7 ) := 4 ;
t_calculate ( 8 ) := 2 ;
FOR nloop IN 1 .. 8
LOOP //该循环的作用是对组织机构代码中的非数字进行处理,并将其转化为数字
    v_bit := SUBSTR ( v_companyno , nloop , 1 );
//依次截取组织机构代码中的每个字符(substr(v_companyno,nloop,1)的作用是取出v_comanyno中,下标从nloop开始,长度为1的字符)
IF instr ( v_num , v_bit , 1 ) = 0 THEN //如果从v_num中查找v_bit字符找不到,也就是说如果组织机构代码中该字符不是数字
    n_bitnum := ascii ( v_bit ) - ascii ( 'A' ) + 65 ;
//ascii(v_bit)是查找组织机构代码中某个字符在编码表中对应的数字
ELSE
    n_bitnum := ascii ( v_bit ) - ascii ( '0' );
END IF ;
n_sum := n_sum + n_bitnum * t_calculate ( nloop );
//将所有组织机构代码中的字符转化为数字后计算并叠加
END LOOP ;
n_sum := 11 - MOD ( n_sum , 11 );
//MOD函数是取余的作用,MOD(n_sum, 11)是让n_sum对11取余
IF n_sum = 10
    AND
    SUBSTR ( v_companyno , 9 , 1 ) = 'X' THEN //如果n_sum为10的倍数且机构代码最后一位是X
    RETURN '1' ;
END IF ;
IF n_sum = 11
    AND
    SUBSTR ( v_companyno , 9 , 1 ) = '0' THEN //如果余数为10的倍数且机构代码最后一位是0
    RETURN '1' ;
END IF ;
IF n_sum NOT IN ( 10 ,
                 11 )
    AND
    SUBSTR ( v_companyno , 9 , 1 ) = CAST ( n_sum AS VARCHAR2 ) THEN
    RETURN '1' ;
END IF ;
RETURN '0' ;
EXCEPTION
WHEN OTHERS THEN
    RETURN '0' ;
END fnc_chkcompanyno ;

最后是“翻译”后的java实现

package com.function;

/**
 * <pre>
 * 校验组织结构代码是否合法
 * </pre>
 * @author chendd
 * @version V0.1, 2014-7-9 下午5:42:18
 */
public class VaildateOrgCode {

    /**
     * 判断是否为数字的种子
     */
    private static final String NUM_SEED = "0123456789";
    /**
     * 根据下标排列好的数组,值与下标对应
     */
    private static int[] CALCULATE__VALUE = {3, 7, 9, 10, 5, 8, 4, 2 };
    
    public static void main(String[] args) throws Exception {
        
        String companyNo = "466504606";
        int result = vaildate(companyNo);
        System.out.println(result);
        
    }

    /**
     * <pre>
     * 判断传递组织机构代码是否合法
     * </pre>
     * @param companyNo 组织机构代码
     * @return 1 合法,0 不合法
     * @author chendd, 2014-7-9 下午5:33:58
     */
    private static int vaildate(String companyNo) {

        int result = 0;
        if(companyNo == null || "".equals(companyNo) || companyNo.length() != 9 ){
            return result;
        }
        
        Integer bitNum = null;
        int sum = 0;
        for(int i = 0 ; i < CALCULATE__VALUE.length ; i++){
            String bit = companyNo.substring(i, i + 1);//从当前循环的位置开始获取1个长度的字符
            Character c = bit.charAt(0);
            if(NUM_SEED.indexOf(bit) == -1){//判断当前字符是否为数字
                bitNum = (int)c - (int)'A' + 65;
            }else{
                bitNum = (int)c - (int)'0';
            }
            int calculate = CALCULATE__VALUE[i];
            sum = sum + bitNum * calculate;
        }
        
        sum = 11 - sum % 11;
        Character lastChar = companyNo.substring(8).charAt(0);//获取最后一个字符
        
        if(sum == 10 && 'X' == lastChar){
            result = 1;
        }else if(sum == 11 && '0' == lastChar){
            result = 1;
        }else if((sum != 10 && sum != 11) && String.valueOf(sum).equals(lastChar.toString())){
            result = 1;
        }else{
            result = 0;
        }
        
        return result;
    }
    
}

main运行结果很简单,如果验证合法则返回1,否则返回0;

另,附上几处的组织机构代码编号

通过网上搜索组织机构编号,发现其隐私性还是稍微高一点的,能搜到的编号很少,附上两个编号来源的截图(有图为证这两个编号来源于互联网):

image.png

(组织机构编号1)

image.png

(组织机构编号2)

以图2的组织机构编号分别来搜索,使用360好搜与百度搜索,分别查询此编号,截图(只为证明上述java程序“翻译”的是无误的)参考如下:

image.png

image.png

 点赞


 发表评论

当前回复:作者

 评论列表


留言区