有没有算法检查正确的NPI(国家提供商标识)号码?

时间:2012-02-17 10:18:57

标签: asp.net algorithm

基本上我正在使用asp.net开发应用程序,我想编写Custom validator来检查正确的NPI编号。

5 个答案:

答案 0 :(得分:6)

Wikipedia说:

  

可以使用Luhn算法验证10位数的NPI编号   将“80840”加前缀为10位数字。

显然,只需验证校验位。要查找是否实际分配了号码,我认为您需要一个列表。例如,有一个online lookup。即使没有这个,如果您对HIPAA如何处理这些数字有任何了解,可以进行额外的检查。

答案 1 :(得分:0)

VB.Net函数验证NPI号码校验和

Private Function ValidateNPI(ByVal sNPI As String) As Boolean
‘KP calculate the Checksum of an NPI using the Luhn Algorithm
‘This can easily be modified to return a checksum instead of a boolean ’1/17/2007.
Dim I As Integer
Dim iCnst80840Prefix As Integer = 24
Dim iRoutine1 As Integer ‘Add the 80840 prefix along with the literal even digits
Dim dRoutine2 As Double
Dim dRoutine3 As Double
Dim dRoutineResult As Double
Dim dRoutineCeiling As Double
Dim dFinalResult As Double

Try
‘example NPI without check sum is “123456789″, The checksum is 3
‘KJP add the even digits (From the left: 2,4,6,8) and the “80840″ Prefix value.
‘This returns the first value.
iRoutine1 = iCnst80840Prefix + CInt(Mid(sNPI, 8, 1)) + CInt(Mid(sNPI, 6, 1))
+ CInt(Mid(sNPI, 4, 1)) + CInt(Mid(sNPI, 2, 1))

‘KJP Loop through the odd digits(From the left: 1,3,5,7,9),
‘multiply by 2 and add the numbers (not the SUM) together
‘This returns the second value.
I = 1
Do Until I > 9
Dim sMidRslt As String
Dim dMidRslt As Double
Dim dMidRslt1 As Double
dMidRslt = Val(Mid(sNPI, I, 1)) * 2
sMidRslt = dMidRslt.ToString
dMidRslt1 = CDbl(Val(Mid(sMidRslt, 1, 1))) + CDbl(Val(Mid(sMidRslt, 2, 1)))
dRoutine2 = dRoutine2 + dMidRslt1
I += 2
Loop

‘KJP add up and calculate all of the individual pieces
dRoutine3 = iRoutine1 + dRoutine2
dRoutineCeiling = (Val(Mid(dRoutine3.ToString, 1, 1)) * 10) + 10
dFinalResult = dRoutineCeiling – dRoutine3

‘KJP result may be 10 so trim it down to the checksum of 0
If dFinalResult = 10 Then
dFinalResult = 0
End If
‘KJP Do the final comparison
If CStr(dFinalResult) = Mid(sNPI, 10, 1) Then
Return True
Else
Return False
End If

Catch ex As Exception
Logger.Trace(SeverityLevel.CriticalError, ex)
Return False
End Try

End Function

答案 2 :(得分:0)

我知道海报要求在asp.net中使用自定义验证器,但在搜索NPI验证时会先弹出此线程。所以,我想我会给我两分钱。

以下是使用NPI / Luhn验证的自定义验证方法 jQuery Validator作为API。随意修改并在需要时应用。这也可以修改为独立运行。

以下是我迄今为止提出的最佳解决方案。

/**
 * jQuery Luhn validator for NPI (USA) WITHOUT the 80840 Prefix
 * Instead, using 24 as the magic bit in replacement of 80840
 * This is a tad bit more verbose than it should be,
 * but you can see how the number is being moved around which is 
 * better for testing purposes.
 * https://www.cms.gov/Regulations-and-Guidance/HIPAA-Administrative-Simplification/NationalProvIdentStand/downloads/NPIcheckdigit.pdf
*/
jQuery.validator.addMethod("NPI",function(value, element){
  var npi = value;
  npi = npi.split('');
  var checkBit = npi.pop(), npi_double = [], npi_unaffected = [];
  npi.reverse();

  for (var i = 0; i < npi.length; i++) {
    if ((i % 2) === 0) { npi_double.push((npi[i] * 2)); }
    if ((i % 2) === 1) { npi_unaffected.push(npi[i]); }
  }

  npi_double = npi_double.toString().replace(/,/g, '');
  npi_unaffected = npi_unaffected.toString().replace(/,/g, '');
  var total = npi_unaffected + npi_double, total_sum = 0;

  for (var i = 0; i < total.length; i++) {
    total_sum += parseInt(total.charAt(i));
  }

  total_sum += 24; //Magic Bit
  var final = Math.ceil((total_sum)/10)*10;
  return ((final - total_sum) == checkBit) ? true : false; 
}, "Not a valid NPI Number");

请务必将其添加到验证输入的规则字段中,例如

npi:{
        required:true,
        NPI:true
      }

答案 3 :(得分:0)

如果有人找到了这篇文章,但正在Java中寻找它,那么下面是一个执行此操作的Java程序:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class NpiUtil {
    private static final String NPI_PATTERN_STRING = "[0-9]{10}";
    private String npi;

    public static boolean isValidNpi(final String npi) {
        return new NpiUtil(npi).isValid();
    }

    private static String fromCharCode(int... codePoints) {
        return new String(codePoints, 0, codePoints.length);
    }

    public static String generateRandomNpi() {
        Double randomNumber = Math.floor(Math.random() * (999999999 - 100000000 + 1) + 100000000);
        int tmp;
        int sum;
        int i;
        int j;
        String npi9 = String.valueOf(randomNumber.intValue());
        i = npi9.length();
        if ((i == 14) && (npi9.indexOf("80840", 5) == 0))
            sum = 0;
        else if (i == 9)
            sum = 24;
        else {
            return "!";
        }

        j = 1;
        while (i != 0) {
            tmp = npi9.charAt(i - 1) - new String("0").charAt(0);
            if ((j++ % 2) != 0) {
                if ((tmp <<= 1) > 9) {
                    tmp -= 10;
                    tmp++;
                }
            }
            sum += tmp;
            i--;
        }
        String checkDigit = fromCharCode(((10 - (sum % 10)) % 10 + 48));
        return randomNumber.longValue() + checkDigit;
    }

    private NpiUtil(final String npi) {
        this.npi = npi.trim();
    }

    private boolean isValid() {
        return this.npi.length() == 10 && this.complies();
    }

    private boolean complies() {
        if (!this.npi.matches(NPI_PATTERN_STRING)) {
            return false;
        }
        final Character lastDigit = this.npi.charAt(9);
        final List<Integer> everyOther = this.listWithEveryOtherDoubled(this.npi.substring(0, 9));
        int sum = 0;
        for (final Integer num : everyOther) {
            sum += sumOfDigits(num);
        }
        final int total = sum + 24;
        final int units = total % 10;
        final int checkDigit = (units != 0) ? (10 - units) : units;
        return Character.getNumericValue(lastDigit) == checkDigit;
    }

    private List<Integer> listWithEveryOtherDoubled(final String str) {
        final List<Integer> nums = new ArrayList<Integer>();
        for (int i = 0; i < str.length(); ++i) {
            if (i % 2 == 0) {
                nums.add(2 * Character.getNumericValue(str.charAt(i)));
            } else {
                nums.add(Character.getNumericValue(str.charAt(i)));
            }
        }
        return nums;
    }

    private static int sumOfDigits(final int number) {
        int num = number;
        int sum = 0;
        while (num > 0) {
            sum += num % 10;
            num /= 10;
        }
        return sum;
    }

    public static void main(final String[] args) {
        System.out.println("Hello, World!");
        System.out.println("1234567890".matches(NPI_PATTERN_STRING));
        System.out.println("123456789".matches(NPI_PATTERN_STRING));
    }
}

用法:

import org.junit.Assert;
import org.junit.Test;

public class NpiUtilTest {
    @Test
    public void testNpiUtil() {
        for (int i = 0; i < 100; ++i) {
            Assert.assertTrue(NpiUtil.isValidNpi(NpiUtil.generateRandomNpi())); 
        }
    }
}

答案 4 :(得分:0)

有多种方法可以验证 NPI。

  1. 使用 API 调用来验证 NPI。参考链接:https://npiregistry.cms.hhs.gov/registry/help-api和数据使用Querying JSON data from CMS NPI data
  2. 使用 Luhn 公式。参考文档https://www.cms.gov/Regulations-and-Guidance/Administrative-Simplification/NationalProvIdentStand/Downloads/NPIcheckdigit.pdf

使用 Python 3.8 进行验证的函数:

kk= '1497842694'
def val_npi(NPI):
    if (len(NPI)==10):
        k = 0
        k1 = 0
        if (NPI[0] in (['1','2'])):
            for i in   NPI[:9][::2]:
                if(int(i)*2<10):
                    k = k + int(i)*2
                else: 
                    k = k+((int(i)*2) % 10)+ 1       
            for i in  NPI[:9][1::2]:
                k1 = k1+int(i)
        if((10-(k+k1+24)%10)==int(NPI[-1])):
             return True
        if ((k+k1+24)%10)==int(NPI[-1]):
             return True
    return False
相关问题