Validating Medicare Provider Numbers
Australian Medicare Provider Number Validation
Provider numbers are issued by Medicare Australia to general practitioners, consultants, specialists and allied health professionals. The numbers are issued to individuals (not practices) and a separate number is required for each distinct location where the provider practices.
Provider numbers (eg 4024742F ) have the following structure:
Component | Length | Valid Symbols |
---|---|---|
Stem | 6 digits | digits 0-9 |
Location Character | 1 digit or alphabetic character | digits 0-9 and characters except I, O, S and Z |
Check Character | 1 alphabetic character | only A, B, F, H, J, K, L, T, W, X, Y |
Note that the letters ‘I’, ‘O’, ‘S’ and ‘Z’ are not valid location characters (presumably due to the likelihood of confusion with similar-looking digits). Some documentation also incorrectly removes the digit ‘1’ from this table, but ‘1’ is a valid location code.
When calculating the check digit, the location character is translated into a numeric Practice Location Value (PLV) as follows.
Location Character | PLV | Location Character | PLV |
---|---|---|---|
0 | 0 | G | 16 |
1 | 1 | H | 17 |
2 | 2 | J | 18 |
3 | 3 | K | 19 |
4 | 4 | L | 20 |
5 | 5 | M | 21 |
6 | 6 | N | 22 |
7 | 7 | P | 23 |
8 | 8 | Q | 24 |
9 | 9 | R | 25 |
A | 10 | T | 26 |
B | 11 | U | 27 |
C | 12 | V | 28 |
D | 13 | W | 29 |
E | 14 | X | 30 |
F | 15 | Y | 31 |
The check character is calculated using the following formula, where PLV is the numeric value for the location digit determined in the table above.
R = ((digit 1x3) + (digit 2x5) + (digit 3x8) + (digit 4x4) + (digit 5x2) + (digit 6) + (PLV x 6)) % 11
The remainder R is in the range 0..10, and is then converted into an alpha check character using the following table:
Remainder | Check Character | Remainder | Check Character |
---|---|---|---|
0 | Y | 6 | J |
1 | X | 7 | H |
2 | W | 8 | F |
3 | T | 9 | B |
4 | L | 10 | A |
5 | K |
Incorrectly Issued Provder Numbers
In Sept 2015 a reader reported a provider number ending in an ‘S’ which failed validation - ‘S’ is not a valid checkdigit. Medicare initially insisted the number was correct, but eventually agreed the number had been incorrectly issued. So it can happen, and it sounds like it took some persistence to get it resolved.
PHP Sample Code
// ValidateMedicareProviderNumber
// Checks medicare provider number for validity
// using the published checksum algorithm.
// Returns: true if the number is valid, false otherwise.
//
// Note - this allows for a leading 0 to be dropped,
// reducing the 6-digit stem to 5 digits.
//
// Source: http://www.clearwater.com.au/code
// Author: Guy Carpenter
// License: The author claims no rights to this code.
// Use it as you wish.
function ValidateMedicareProviderNumber($ProviderNumber)
{
/*
* The Medicare provider number comprises:
* - six digits (provider stem)
* - a practice location character (one alphanum char)
* - a check-digit (one alpha character)
*/
$locTable = '0123456789ABCDEFGHJKLMNPQRTUVWXY';
$checkTable = 'YXWTLKJHFBA';
$weights = array(3,5,8,4,2,1);
$re = "/^(\d{5,6})([{$locTable}])([{$checkTable}])$/";
$providerNumber = preg_replace("/[^\dA-Z]/",
"",
strtoupper($ProviderNumber));
if (preg_match($re, $providerNumber, $matches)) {
$stem = $matches[1];
// accommodate dropping of leading 0
if (strlen($stem)==5) $stem="0".$stem;
$location = $matches[2];
$checkDigit = $matches[3][0];
// IMPORTANT - letters I, O, S and Z are not included
// Some documentation incorrectly removes the digit 1.
$plv = strpos($locTable, $location);
$sum = $plv * 6;
foreach ($weights as $position=>$weight) {
$sum += $stem[$position] * $weight;
}
if ($checkDigit == $checkTable[$sum % 11]) {
return true;
}
}
return false;
}
References
This seems to be a secret. For a while the algorithm could be found here: http://www.medicareaustralia.gov.au/provider/vendors/files/acir-immunisation-document-formats.pdf but that’s now gone.
As of Sept 2015 this document is only available in Google’s cache: http://www.health.vic.gov.au/pcps/downloads/coordination/sctt_guide_vol3.pdf but be careful. It contains a definition of the algorithm with a couple of critical errors of ommission that would make it unimplementable.