LuhnCalc and BPay MOD10 version 5

I use the following PHP code to calculate CRN for BPay:

<?php function LuhnCalc($number) { $chars = array_reverse(str_split($number, 1)); $odd = array_intersect_key($chars, array_fill_keys(range(1, count($chars), 2), null)); $even = array_intersect_key($chars, array_fill_keys(range(0, count($chars), 2), null)); $even = array_map(function($n) { return ($n >= 5)?2 * $n - 9:2 * $n; }, $even); $total = array_sum($odd) + array_sum($even); return ((floor($total / 10) + 1) * 10 - $total) % 10; } print LuhnCalc($_GET['num']); ?> 

However, it looks like BPAY is version 5 of MOD 10 for which I cannot find any documentation. This seems to be not the same as MOD10.

The following numbers where tested:

2005.1597.3651.0584.9675

 bPAY 2005 = 20052 1597 = 15976 3651 = 36514 0584 = 05840 9675 = 96752 MY CODE 2005 = 20057 1597 = 15974 3651 = 36517 0584 = 05843 9675 = 96752 

As you can see, none of them match BPAY numbers.

+6
source share
7 answers

This PHP function will generate BPay reference numbers based on the mod10 version 5 algorithm.

Who knows why BPay cannot add this to their site. I just found an explanation on a Google search in which the algorithm was named "MOD10V05" instead of "Mod 10 version 5".

 function generateBpayRef($number) { $number = preg_replace("/\D/", "", $number); // The seed number needs to be numeric if(!is_numeric($number)) return false; // Must be a positive number if($number <= 0) return false; // Get the length of the seed number $length = strlen($number); $total = 0; // For each character in seed number, sum the character multiplied by its one based array position (instead of normal PHP zero based numbering) for($i = 0; $i < $length; $i++) $total += $number{$i} * ($i + 1); // The check digit is the result of the sum total from above mod 10 $checkdigit = fmod($total, 10); // Return the original seed plus the check digit return $number . $checkdigit; } 
+3
source

Here is a way to implement the algorithm "MOD10V5" (or "mod 10 version 5") using the custom t-sql function on the SQL server. It takes a customer identifier up to 9 characters long and returns 11 CRN characters (customer reference number).

I also added a version number at the beginning of my CustomerID, you can do this too if you think you can change it in the future.

 CREATE Function [dbo].[CalculateBPayCRN] ( @CustomerID nvarchar(9) ) RETURNS varchar(11) AS BEGIN DECLARE @NewCRN nvarchar(11) DECLARE @Multiplier TINYINT DECLARE @Sum int DECLARE @SubTotal int DECLARE @CheckDigit int DECLARE @ReturnVal BIGINT SELECT @Multiplier = 1 SELECT @SubTotal = 0 -- If it less than 9 characters, pad it with 0's, then prepend a '1' SELECT @NewCRN = '1' + right('000000000'+ rtrim(@CustomerID), 9) -- loop through each digit in the @NewCRN, multiple it by the correct weighting and subtotal it: WHILE @Multiplier <= LEN(@NewCRN) BEGIN SET @Sum = CAST(SUBSTRING(@NewCRN,@Multiplier,1) AS TINYINT) * @Multiplier SET @SubTotal = @SubTotal + @Sum SET @Multiplier = @Multiplier + 1 END -- mod 10 the subtotal and the result is our check digit SET @CheckDigit = @SubTotal % 10 SELECT @ReturnVal = @NewCRN + cast(@CheckDigit as varchar) RETURN @ReturnVal END GO 
+1
source

Module 10 V1 in PHP. Tested against my Windows dataflex procedure, and it is the same.

 function generateBpayRef($number) { //Mod 10 v1 $number = preg_replace("/\D/", "", $number); // The seed number needs to be numeric if(!is_numeric($number)) return false; // Must be a positive number if($number <= 0) return false; $stringMemberNo = "$number"; $stringMemberNo = str_pad($stringMemberNo, 6, "0", STR_PAD_LEFT); //echo " Padded Number is $stringMemberNo "; $crn = $stringMemberNo; for($i=0;$i<7;$i++){ $crnval = substr($crn,(5-$i),1); $iPartVal = $iWeight * $crnval; if($iPartVal>9){ //echo " Greater than 9: $iPartVal "; $firstChar = substr($iPartVal,0,1); $secondChar = substr($iPartVal,1,1); $iPartVal=$firstChar+$secondChar; //$iPartVal -= 9; } $iSum+=$iPartVal; $iWeight++; if ($iWeight>2){$iWeight=1;} //echo " CRN: $crnval ] Weight: $iWeight ] Part: $iPartVal ] SUM: $iSum "; } $iSum %= 10; if($iSum==0){ //echo " zero check is $iSum "; //return $iSum; } else{ //return 10-$iSum; $iSum=(10-$iSum); } //echo " Check is a $iSum "; $BpayMemberNo = $stringMemberNo . $iSum ; echo " New: $BpayMemberNo "; return ($BpayMemberNo); } 
+1
source

Here is the ruby ​​class that I quickly whipped for Mod 10 v5

 module Bpay class CRN attr_accessor :number, :crn class << self def calculate_for(number) new(number).crn end end def initialize(number) @number = number calculate end def calculate raise ArgumentError, "The number '#{number}' is not valid" unless valid? digits = number.to_s.scan(/\d/).map { |x| x.to_i } raise ArgumentError, "The number '#{number}' must be at least 2 digits in length" if digits.size < 2 check_digit = digits.each_with_index.map { |d, i| d * (i + 1) }.inject(:+) % 10 @crn = "#{number}#{check_digit}" end def valid? return false unless !!Integer(number.to_s) rescue false return false if number.to_i <= 0 true end end end 
+1
source

This is in C #, but this is what I have for generating a BPay check digit:

 private void btnBPayGenerate_Click(object sender, EventArgs e) { var originalChars = txtBPayNumber.Text.ToCharArray(); List<int> oddDigits = new List<int>(); List<int> evenDigits = new List<int>(); int oddTotal = 0, evenTotal = 0, total = 0, checkDigit ; const int oddMultiplier = 3; const int modulus = 10; bool isOdd = true; for (int x = 0; x < originalChars.Length; x++) { if(isOdd) oddDigits.Add(Int32.Parse(originalChars[x].ToString())); else evenDigits.Add(Int32.Parse(originalChars[x].ToString())); isOdd = !isOdd; } foreach (var digit in oddDigits) oddTotal += digit; foreach (var digit in evenDigits) evenTotal += digit; oddTotal = oddTotal * oddMultiplier; total = oddTotal + evenTotal; checkDigit = (modulus - (total % modulus)); lblBPayResult.Text = txtBPayNumber.Text + checkDigit.ToString(); } 

I have not finished testing, I will send back as soon as BPAY returns to me.

EDIT: try the following: https://gist.github.com/1287893

0
source

I needed to develop a version for javascript, that's what I came up with. It correctly generates the expected numbers in the original question.

 var startingNumber = 2005; var reference = startingNumber.toString(); var subTotal = 0; for (var x = 0; x < reference.length; x++) { subTotal += (x + 1) * reference.charAt(x); } var digit = subTotal % 10; var bpayReference = reference + digit.toString(); 
0
source

Here is the function I created using vb.net to calculate the check digit of mod 10 version 5

 Private Function CalcCheckDigit(ByRef psBaseNumber As String) As String Dim lCheckDigit, iLoop As Integer Dim dCalcNumber As Double lCheckDigit = 0 dCalcNumber = 0 For iLoop = 0 To (psBaseNumber.Length - 1) lCheckDigit = lCheckDigit + (psBaseNumber.Substring(iLoop, 1) * (iLoop + 1)) Next iLoop lCheckDigit = lCheckDigit Mod 10 CalcCheckDigit = psBaseNumber & CStr(lCheckDigit) End Function 
0
source

Source: https://habr.com/ru/post/918039/


All Articles