Function not working properly in PHP vs JS

Hi, We have a function in JS that we are trying to recreate in PHP however the results seem to be inconsistent and don't always match the output from JS. I would appreciate any feedback anyone might be able to give to what the problem might be. Below are the functions and some sample output results.

Thanks in advance

The JS function:

function GenerateVoucherPIN(artwork_code, voucher_number)
{
var a = 43003;
var b = 65536;
var c = 571;
var hash = 0;
var voucher_code = voucher_number + artwork_code;
for (i = 0; i < voucher_code.length; i++)
{
hash = (hash * a * voucher_code.charCodeAt(i) + c) % b;
c = Math.floor((a * hash + c) / b);
}
return hash % 10000;
}


Our PHP function:

function charCodeAt($str, $i){
      return ord(substr($str, $i, 1));
}
function GenerateVoucherPIN($voucher_number,$artwork_code)
{
      $a = 43003;
      $b = 65536;
      $c = 571;
      $hash = 0;
      
      $voucher_number = intval($voucher_number);
      $voucher_code = $voucher_number . $artwork_code;
      for ($i = 0; $i < strlen($voucher_code); $i++)
      {
            $hash = bcmod($hash * $a * charCodeAt($voucher_code,$i) + $c, $b)      ;
            $c = floor(($a * $hash + $c) / $b);
      }
      $result = str_pad($hash % 10000, 4, 0, STR_PAD_LEFT);//Pad with 0 to get a four digit value
      return $result;
}

GenerateVoucherPIN(0001341,'FTR');
GenerateVoucherPIN('0001341','FTR');

Below are some sample output results comparing PHP and JS. We have tried both as an integer and as a string.

Voucher Number (String Format)     PIN Number (PHP)    PIN Number (JS)
'0001341'           0805       8716
'0020448'           7164       7164
'0054695'           4681       4681
'0009997'           8111       8111
'0018001'           2851       2851
'0000401'           0062       3345
'0010177'           4792       2281

Voucher Number (Integer Format)    PIN Number (PHP)     PIN Number (JS)
0001341     8716       8716
0020448     7535       7164
0054695     1159       4681
0009997     7298       8111
0018001     3977       2851
0000401     3345       3345
0010177     2281       2281
LetsLearnAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Dave BaldwinFixer of ProblemsCommented:
I put it all in one page and I'm not getting what you are getting.  

This is my results:
_Code__ _PHP _jscript

0001341 0805 6000
0020448 5206 4058
0054695 5140 2206
0009997 4306 1693
0018001 0601 2364
0000401 8214 6053
0010177 7700 4185

Open in new window



And this is the code I copied from above:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
 "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<title>Untitled</title>
<script type="text/javascript">
<!--
function GenerateVoucherPIN(artwork_code, voucher_number)
{
var a = 43003;
var b = 65536;
var c = 571;
var hash = 0;
var voucher_code = voucher_number + artwork_code;
for (i = 0; i < voucher_code.length; i++)
{
hash = (hash * a * voucher_code.charCodeAt(i) + c) % b;
c = Math.floor((a * hash + c) / b);
}
return hash % 10000;
}

// -->
</script>
</head>
<body>
<pre>
_Code__ _PHP _jscript<br>
<?php 
function charCodeAt($str, $i){
      return ord(substr($str, $i, 1));
}
function GenerateVoucherPIN($voucher_number,$artwork_code)
{
      $a = 43003;
      $b = 65536;
      $c = 571;
      $hash = 0;
      
      $voucher_number = intval($voucher_number);
      $voucher_code = $voucher_number . $artwork_code;
      for ($i = 0; $i < strlen($voucher_code); $i++)
      {
            $hash = bcmod($hash * $a * charCodeAt($voucher_code,$i) + $c, $b)      ;
            $c = floor(($a * $hash + $c) / $b);
      }
      $result = str_pad($hash % 10000, 4, 0, STR_PAD_LEFT);//Pad with 0 to get a four digit value
      return $result;
}
$tstcodes = array('0001341','0020448','0054695','0009997','0018001','0000401','0010177');
foreach($tstcodes as $val) {
	echo $val." ".GenerateVoucherPIN($val,'FTR')." <script type='text/javascript'>document.write(GenerateVoucherPIN('$val','FTR'));</script><br>";
	}
 ?>
 
</pre>
</body>
</html>

Open in new window

0
LetsLearnAuthor Commented:
Hi Dave,

I probably should have added a couple of details in the above question - there is an artwork code of 3 letters. The artwork code is added to the sequence prior to the serial number. Not sure if this is why you are getting different results.

What we are trying to generate is 4 number security number for a product. We need to use the function in one area in JS and in another in PHP.

Thanks Cat
0
Dave BaldwinFixer of ProblemsCommented:
I understand what you are trying to do.  But the code you have posted does not give the results that you showed.  That makes it difficult for us to help you.  As far as I can tell, I copied your code correctly and then added a section to the PHP code to run thru the values you have posted.  But it's not matching up.  ??
0
Determine the Perfect Price for Your IT Services

Do you wonder if your IT business is truly profitable or if you should raise your prices? Learn how to calculate your overhead burden with our free interactive tool and use it to determine the right price for your IT services. Download your free eBook now!

LetsLearnAuthor Commented:
Hmmm let me check
0
LetsLearnAuthor Commented:
Hi Dave,

Attached is a  PHP file with both the JS and PHP functions. We have added two voucher numbers as an example. For first voucher number, the integer value output is same as JS output. And for second example, the string value output is same as the JS output.

But it doesn't always give consistent results. Hope this helps clarify what we have at the moment.

Any feedback would be most welcome.

Thanks Cat
0
LetsLearnAuthor Commented:
And the attachment!
Genpin.php
0
Dave BaldwinFixer of ProblemsCommented:
I got it so it works with strings.  I don't think it will work passing numbers because PHP comes up with something different than javascript.  In your original post above, you were passing the parameters to the JS and the PHP in the opposite order which meant they would never agree.  In addition, the 'intval' statement in the PHP section was changing the $voucher_number to something unusable.

You can see some of the commented out statements that I used to test the code in the attached file.
Genpin2.php
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
LetsLearnAuthor Commented:
Thanks Dave I'll take a look now
0
TobiasCommented:
Dear, I have test and the fonction charCodeAt in php have some bug.

If you look the char, you see clairly that there's a bug ( one char is missing on php) I think because of the split 0020448 have one more number maybe the problem doesn't occur with other number that contain a even number ex : 120448.


charCodeAt !!! :::: 55
charCodeAt !!! :::: 51
charCodeAt !!! :::: 55
charCodeAt !!! :::: 70
charCodeAt !!! :::: 84
charCodeAt !!! :::: 82
JS PIN Output for 0001341 :::: 8716
charCodeAt !!! :::: 50
charCodeAt !!! :::: 48
charCodeAt !!! :::: 52
charCodeAt !!! :::: 52
charCodeAt !!! :::: 56
charCodeAt !!! :::: 85
charCodeAt !!! :::: 65
JS PIN Output for 0020448 :::: 7164

PHP charCodeAt !!!!!!!!! 55
PHP charCodeAt !!!!!!!!! 51
PHP charCodeAt !!!!!!!!! 55
PHP charCodeAt !!!!!!!!! 70
PHP charCodeAt !!!!!!!!! 84
PHP charCodeAt !!!!!!!!! 82
PHP PIN Output (Integer) for 0001341 :::: 8716

PHP charCodeAt !!!!!!!!! 49
PHP charCodeAt !!!!!!!!! 48
PHP charCodeAt !!!!!!!!! 54
PHP charCodeAt !!!!!!!!! 48
PHP charCodeAt !!!!!!!!! 85
PHP charCodeAt !!!!!!!!! 65
PHP PIN Output (Integer) for 0020448 :::: 7535

Open in new window


Hope that help you :)
0
TobiasCommented:
Yes, got it working :)

If you have any question don't hesitate to ask.

Regards
Genpin.php
0
LetsLearnAuthor Commented:
Thanks MadShiva I'll have a look at this today and let you know how we get on. Thanks so much for your help.
0
LetsLearnAuthor Commented:
Thanks Dave, we found what you said was absolutely correct. The only way we could match the outputs was to pass the parameters as strings.
0
Dave BaldwinFixer of ProblemsCommented:
You're welcome, glad to help.  It was an interesting question.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Content Management

From novice to tech pro — start learning today.