Solved

Function not working properly in PHP vs JS

Posted on 2012-04-01
13
313 Views
Last Modified: 2012-04-03
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
0
Comment
Question by:LetsLearn
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 4
  • 2
13 Comments
 
LVL 83

Expert Comment

by:Dave Baldwin
ID: 37794414
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
 

Author Comment

by:LetsLearn
ID: 37794428
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
 
LVL 83

Expert Comment

by:Dave Baldwin
ID: 37794447
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
Creating Instructional Tutorials  

For Any Use & On Any Platform

Contextual Guidance at the moment of need helps your employees/users adopt software o& achieve even the most complex tasks instantly. Boost knowledge retention, software adoption & employee engagement with easy solution.

 

Author Comment

by:LetsLearn
ID: 37794460
Hmmm let me check
0
 

Author Comment

by:LetsLearn
ID: 37794622
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
 

Author Comment

by:LetsLearn
ID: 37794623
And the attachment!
Genpin.php
0
 
LVL 83

Accepted Solution

by:
Dave Baldwin earned 500 total points
ID: 37794735
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
 

Author Comment

by:LetsLearn
ID: 37794738
Thanks Dave I'll take a look now
0
 
LVL 10

Expert Comment

by:Tobias
ID: 37795074
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
 
LVL 10

Expert Comment

by:Tobias
ID: 37795317
Yes, got it working :)

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

Regards
Genpin.php
0
 

Author Comment

by:LetsLearn
ID: 37798796
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
 

Author Closing Comment

by:LetsLearn
ID: 37804294
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
 
LVL 83

Expert Comment

by:Dave Baldwin
ID: 37804322
You're welcome, glad to help.  It was an interesting question.
0

Featured Post

Edgartown IT Case Study

Learn about Edgartown's quest to ensure the safety and security of the entire town's employee and citizen data. Read the case study!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction This article is intended for those who are new to PHP error handling (https://www.experts-exchange.com/articles/11769/And-by-the-way-I-am-New-to-PHP.html).  It addresses one of the most common problems that plague beginning PHP develop…
This article discusses how to implement server side field validation and display customized error messages to the client.
The viewer will learn how to look for a specific file type in a local or remote server directory using PHP.
This tutorial will teach you the core code needed to finalize the addition of a watermark to your image. The viewer will use a small PHP class to learn and create a watermark.

739 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question