JAVA實現社會統一信用代碼較驗

網上找了幾個,寫的都不太適合,有的寫出來了,也沒有給出參考的算法連接。這樣就致使了若是產生錯誤咱們沒法排查(不懂原理怎麼排查對吧)。java

若是在使用過程當中有疑慮,請參考:較驗規則算法

代碼實現

package com.mengyunzhi.common.utils;

import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.TreeBidiMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.validation.ValidationException;
import java.util.Map;
import java.util.Random;

/**
 * 統一社會停用用代碼
 */
public interface UnifiedCreditCodeUtils {
    Logger logger = LoggerFactory.getLogger(UnifiedCreditCodeUtils.class);
    String baseCode = "0123456789ABCDEFGHJKLMNPQRTUWXY";
    char[] baseCodeArray = baseCode.toCharArray();
    int[] wi = {1, 3, 9, 27, 19, 26, 16, 17, 20, 29, 25, 13, 8, 24, 10, 30, 28};

    /**
     * 生成供較驗使用的 Code Map
     *
     * @return BidiMap
     */
    static BidiMap<Character, Integer> generateCodes() {
        BidiMap<Character, Integer> codes = new TreeBidiMap<>();
        for (int i = 0; i < baseCode.length(); i++) {
            codes.put(baseCodeArray[i], i);
        }

        return codes;
    }

    /**
     * 較驗社會統一信用代碼
     *
     * @param unifiedCreditCode 統一社會信息代碼
     * @return 符合: true
     */
    static boolean validateUnifiedCreditCode(String unifiedCreditCode) {
        if ((unifiedCreditCode.equals("")) || unifiedCreditCode.length() != 18) {
            return false;
        }

        Map<Character, Integer> codes = generateCodes();
        int parityBit;
        try {
            parityBit = getParityBit(unifiedCreditCode, codes);
        } catch (ValidationException e) {
            return false;
        }

        return parityBit == codes.get(unifiedCreditCode.charAt(unifiedCreditCode.length() - 1));
    }

    /**
     * 獲取較驗碼
     *
     * @param unifiedCreditCode 統一社會信息代碼
     * @param codes             帶有映射關係的國家代碼
     * @return 獲取較驗位的值
     */
    static int getParityBit(String unifiedCreditCode, Map<Character, Integer> codes) {
        char[] businessCodeArray = unifiedCreditCode.toCharArray();

        int sum = 0;
        for (int i = 0; i < 17; i++) {
            char key = businessCodeArray[i];
            if (baseCode.indexOf(key) == -1) {
                throw new ValidationException("第" + String.valueOf(i + 1) + "位傳入了非法的字符" + key);
            }
            sum += (codes.get(key) * wi[i]);
        }
        int result = 31 - sum % 31;
        return result == 31 ? 0 : result;
    }

    /**
     * 獲取一個隨機的統一社會信用代碼
     *
     * @return 統一社會信用代碼
     */
    static String generateOneUnifiedCreditCode() {
        Random random = new Random();
        StringBuilder buf = new StringBuilder();

        for (int i = 0; i < 17; ++i) {
            int num = random.nextInt(baseCode.length() - 1);
            buf.append(baseCode.charAt(num));
        }

        String code = buf.toString();
        String upperCode = code.toUpperCase();
        BidiMap<Character, Integer> codes = generateCodes();
        int parityBit = getParityBit(upperCode, codes);

        if (codes.getKey(parityBit) == null) {
            logger.debug("生成社會統一信用代碼不符合規則");
            upperCode = generateOneUnifiedCreditCode();
        } else {
            upperCode = upperCode + codes.getKey(parityBit);
        }

        return upperCode;
    }
}

測試

package com.mengyunzhi.common.utils;

import org.assertj.core.api.Assertions;
import org.junit.Test;

import static org.junit.Assert.*;

public class UnifiedCreditCodeUtilsTest {

    @Test
    public void validateUnifiedCreditCode() {
        String code = "911310827965850580";
        Assertions.assertThat(UnifiedCreditCodeUtils.validateUnifiedCreditCode(code)).isTrue();
    }
}

但願對你有幫助apache

相關文章
相關標籤/搜索