I am using the following PHP code to calculate a 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 seems that BPAY is version 5 of MOD 10, for which I can't find any documentation. It seems to not be 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 the BPAY numbers.
This PHP function will generate BPay reference numbers based on the mod10 version 5 algorithm.
Who knows why BPay can't add this to their website. I only found an explanation by googling finding the algorithm being called "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;
}
Here's a way of implementing the "MOD10V5" algorithm (or "mod 10 version 5") using a t-sql user defined function in SQL server. It accepts a Customer ID up to 9 characters long, and return an 11 character CRN (Customer Reference Number).
I also prepended a version number onto the start of my CustomerID, you could do this too if you think you might end up changing 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's 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
Modula 10 V1 in PHP. Tested against my Windows dataflex routine 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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With