We are looking to validate Australian TFN numbers entered by our clients. Is there any official algorithm mentioned somewhere?
The Wikipedia page mentions about a simple modulo-11 algorithm but it seems it is just an example.
We are looking to validate Australian TFN numbers entered by our clients. Is there any official algorithm mentioned somewhere?
The Wikipedia page mentions about a simple modulo-11 algorithm but it seems it is just an example.
Share Improve this question edited Apr 21, 2017 at 5:00 Jeremy Thompson 65.9k37 gold badges223 silver badges340 bronze badges asked Oct 26, 2016 at 2:01 ElevatedLyfElevatedLyf 1161 gold badge2 silver badges8 bronze badges 4- 1 The example on that page does give the weightings for each digit. The same algorithm is provided here (and other places). But as both pages say, officially the ATO doesn't provide details of the algorithm even though it's well known what it is. – nnnnnn Commented Oct 26, 2016 at 2:05
- Yes, but that's what. Until there is something official we can't rely on those weighting factors otherwise we may end up throwing errors for valid numbers as well. :) – ElevatedLyf Commented Oct 26, 2016 at 5:28
- There is an ABN validation algorithm here but nothing for the TFN - abr.business.gov.au/HelpAbnFormat.aspx – ElevatedLyf Commented Oct 26, 2016 at 5:34
- The ABN code is here: stackoverflow./questions/14174738/… – Jeremy Thompson Commented Mar 8, 2017 at 4:31
4 Answers
Reset to default 5In Javascript 9 Digit:
var tfn = $('#tfn').val();
//remove spaces and update
tfn = tfn.replace(/\s+/g, '');
$('#tfn').val(tfn);
//remove hyphens and update
tfn = tfn.replace(/[-]/g, '');
$('#tfn').val(tfn);
//validate only digits
var isNumber = /^[0-9]+$/.test(tfn);
if(!isNumber) {
return doError('Invalid TFN, only numbers are allowed.');
}
//validate length
var length = tfn.length;
if(length != 9) {
return doError('Invalid TFN, must have 9 digits.');
}
var digits = tfn.split('');
//do the calcs
var sum = (digits[0]*1)
+ (digits[1]*4)
+ (digits[2]*3)
+ (digits[3]*7)
+ (digits[4]*5)
+ (digits[5]*8)
+ (digits[6]*6)
+ (digits[7]*9)
+ (digits[8]*10);
var remainder = sum % 11;
if(remainder == 0) {
doSuccess('Valid TFN, hooray!');
} else {
return doError('Invalid TFN, check the digits.');
}
Ref: https://github./steveswinsburg/tfn-validator/blob/master/tfn-validator.html
In C# 9 Digit:
static void Main(string[] args)
{
int count = 0;
StringBuilder sb = new StringBuilder();
Random random = new Random();
while (count < 500000) {
int randomNumber = random.Next(100000000, 999999999);
if (ValidateTFN(randomNumber.ToString()))
{
sb.AppendLine(randomNumber.ToString());
count++;
}
}
System.IO.File.WriteAllText("TFNs.txt", sb.ToString());
}
public static bool ValidateTFN(string tfn)
{
//validate only digits
if (!IsNumeric(tfn)) return false;
//validate length
if (tfn.Length != 9) return false;
int[] digits = Array.ConvertAll(tfn.ToArray(), c => (int)Char.GetNumericValue(c));
//do the calcs
var sum = (digits[0] * 1)
+ (digits[1] * 4)
+ (digits[2] * 3)
+ (digits[3] * 7)
+ (digits[4] * 5)
+ (digits[5] * 8)
+ (digits[6] * 6)
+ (digits[7] * 9)
+ (digits[8] * 10);
var remainder = sum % 11;
return (remainder == 0);
}
public static bool IsNumeric(string s)
{
float output;
return float.TryParse(s, out output);
}
Ref: https://softwaredevelopers.ato.gov.au/obtainTFNalgorithm
In C# 8 Digit:
public static bool ValidateTFN(string tfn)
{
//validate only digits
if (!IsNumeric(tfn)) return false;
//validate length
if (tfn.Length != 8) return false;
int[] digits = Array.ConvertAll(tfn.ToArray(), c => (int)Char.GetNumericValue(c));
//do the calcs
var sum = (digits[0] * 10)
+ (digits[1] * 7)
+ (digits[2] * 8)
+ (digits[3] * 4)
+ (digits[4] * 6)
+ (digits[5] * 3)
+ (digits[6] * 5)
+ (digits[7] * 1);
var remainder = sum % 11;
return (remainder == 0);
}
Ref: https://jeremythompson/Rocks/TFN_algorithm_8_digit.pdf
In VB.Net 9 Digit:
Public Shared Function ValidateTFN(ByVal tfn As String) As Boolean
If Not IsNumeric(tfn) Then Return False
If tfn.Length <> 9 Then Return False
Dim digits As Integer() = Array.ConvertAll(tfn.ToArray(), Function(c) CInt(Char.GetNumericValue(c)))
Dim sum = (digits(0) * 1) + (digits(1) * 4) + (digits(2) * 3) + (digits(3) * 7) + (digits(4) * 5) + (digits(5) * 8) + (digits(6) * 6) + (digits(7) * 9) + (digits(8) * 10)
Dim remainder = sum Mod 11
Return (remainder = 0)
End Function
In PHP 9 Digit:
function ValidateTFN($tfn)
{
$weights = array(1, 4, 3, 7, 5, 8, 6, 9, 10);
// strip anything other than digits
$tfn = preg_replace("/[^\d]/","",$tfn);
// check length is 9 digits
if (strlen($tfn)==9) {
$sum = 0;
foreach ($weights as $position=>$weight) {
$digit = $tfn[$position];
$sum += $weight * $digit;
}
return ($sum % 11)==0;
}
return false;
}
Ref: https://clearwater..au/code/tfn
In Swift 5:
Make sure you use keyboard type Number Pad to prevent users from adding non-numeric characters.
func isTFNValid (tfn: String) -> Bool{
if (tfn.count != 9) {
return false
} else {
let characters = Array(tfn)
let digits = characters.map { Int(String($0))!}
//do the calcs
var sum = (digits[0]*1)
+ (digits[1]*4)
+ (digits[2]*3)
+ (digits[3]*7)
+ (digits[4]*5)
+ (digits[5]*8)
+ (digits[6]*6)
+ (digits[7]*9)
+ (digits[8]*10)
var remainder = sum % 11;
if(remainder == 0) {
return true
} else {
return false
}
}
}
Thank you Jeremy Thompson for the original answer.
An implementation that supports Java 8 and possibly higher
public class TFNUtils {
public static String format(String tfn) {
if (tfn == null) {
return null;
}
tfn = tfn.replaceAll("\\s+","");
tfn = tfn.replaceAll("\\-", "");
if (tfn.length() != 9) {
return null;
}
int sum = (Integer.parseInt(String.valueOf(tfn.charAt(0))))
+ (Integer.parseInt(String.valueOf(tfn.charAt(1)))*4)
+ (Integer.parseInt(String.valueOf(tfn.charAt(2)))*3)
+ (Integer.parseInt(String.valueOf(tfn.charAt(3)))*7)
+ (Integer.parseInt(String.valueOf(tfn.charAt(4)))*5)
+ (Integer.parseInt(String.valueOf(tfn.charAt(5)))*8)
+ (Integer.parseInt(String.valueOf(tfn.charAt(6)))*6)
+ (Integer.parseInt(String.valueOf(tfn.charAt(7)))*9)
+ (Integer.parseInt(String.valueOf(tfn.charAt(8)))*10);
if ((sum % 11) != 0){
return null;
}
StringBuilder tfnCompute = new StringBuilder(11);
tfnCompute.append(tfn.charAt(0));
tfnCompute.append(tfn.charAt(1));
tfnCompute.append(tfn.charAt(2));
tfnCompute.append('-');
tfnCompute.append(tfn.charAt(3));
tfnCompute.append(tfn.charAt(4));
tfnCompute.append(tfn.charAt(5));
tfnCompute.append('-');
tfnCompute.append(tfn.charAt(6));
tfnCompute.append(tfn.charAt(7));
tfnCompute.append(tfn.charAt(8));
return tfnCompute.toString();
}
public static boolean isValid(String tfn) {
return format(tfn) != null;
}
}
public class TFNUtilsTest {
@Test
public void testFormat() throws Exception {
assertEquals("123-456-782", TFNUtilsTest.format("123-456-782"));
assertEquals("123-456-782", TFNUtilsTest.format("123456782"));
assertEquals("123-456-782", TFNUtilsTest.format("123 456 782"));
// invaild returns null
assertNull(TFNUtilsTest.format("123 456 7829"));
assertNull(TFNUtilsTest.format("123 456 78"));
}
@Test
public void testIsValid() throws Exception {
assertTrue(TFNUtilsTest.isValid("123-456-782"));
assertTrue(TFNUtilsTest.isValid("123 456 782"));
assertFalse(TFNUtilsTest.isValid(null));
assertFalse(TFNUtilsTest.isValid(""));
assertFalse(TFNUtilsTest.isValid("123-456-780")); // invalid check-digit
assertFalse(TFNUtilsTest.isValid("123-456.782")); // invalid seperator
assertFalse(TFNUtilsTest.isValid("123-456-7820")); // > 9 digits
}
}
I have checked the c# code shared in this post, Actually the generated TFN number using that code has failed with the TFN validation in the mentioned WebSite. So I came with an alternate solution with the help of this website https://clearwater..au/code/tfn to generate valid TFN.
Try this code:
static void Main(string[] args)
{
int count = 0;
Random random = new Random();
while (count < 50)
{
int randomNumber = random.Next(100000000, 999999999);
// - Validate TFN - [START]
float output;
//validate only digits
string strRandomNumber = randomNumber.ToString();
if (!float.TryParse(strRandomNumber, out output))
{
Console.WriteLine("Invalid Input");
}
else
{
//validate length
if (strRandomNumber.Length != 9)
{
Console.WriteLine("Invalid Length");
}
else
{
int[] digits = Array.ConvertAll(strRandomNumber.ToArray(), c => (int)Char.GetNumericValue(c));
//do the calcs
var sum = (digits[0] * 10)
+ (digits[1] * 7)
+ (digits[2] * 8)
+ (digits[3] * 4)
+ (digits[4] * 6)
+ (digits[5] * 3)
+ (digits[6] * 5)
+ (digits[7] * 2)
+ (digits[8] * 1);
var remainder = sum % 11;
// - Validate TFN - [END]
if ((remainder == 0))
{
Console.WriteLine(randomNumber.ToString());
break;
}
}
}
count++;
}
}