You are viewing this forum as a guest. Login to an existing account, or create a new account, to reply to topics and to create new topics.
Hi,
I have just installed the latest version of Europacart and have integrated with the latest version of Joomla. All looks great, Paypal works but HSBC doesn't. I have put in my HSBC supplied Hash number and my merchant number and have checked this with them. I keep getting a communication error. When you click on "Enter Payment Information" then press the continue button it goes to HSBC and says communication error :
Communication Failure
*
We have been unable to proceed with your transaction due to a communication failure.
Please Close your browser window and confirm the status of your order with the merchant
Any ideas cannot get it to work and am launching the site at the end of the week HELP smile
Offline
There are lots of reasons why the HSBC link won't work. Search in the CCP6 forum for some of them.
Have you checked whether you are in test or production mode?
You may also still need to change the line
$tmp[7] = $order['order']['epochorder'] * 1000;
to
$tmp[7] = $order['order']['epochorder'] . '000';
to prevent an illegal timestamp on the comms to HSBC's page, as has been reported many times but is still unfixed.
Finally, I believe that you need to be using a secure link to HSBC - is your site running in https: mode?
Offline
Hi,
I am running is https, I have checked the hash and merchant number details with hsbc and i have edited the line you suggested. Still has same error?
Any thoughts?
Offline
i am also getting this error, did you manage to sort this?
Offline
I'm looking into this as I now have a problem where I didn't before. Could you please create a small php script as below, run it and post the results?
<pre> <? echo "PHP_INT_MAX is " . PHP_INT_MAX . "\n"; echo "PHP_INT_SIZE is " . PHP_INT_SIZE . "\n"; ?> </pre>
Offline
I now have a fix for my system, which is a 64-bit build of PHP rather than the current standard of 32-bits. If the reply to the small script above is
PHP_INT_MAX is 2147483647 PHP_INT_SIZE is 4
then you don't have the same problem that I've just fixed. If is says
PHP_INT_MAX is 9223372036854775807 PHP_INT_SIZE is 8
then you might have.
I'll post the full code if anyone else is seeing the HSBC Error code 10 (invalid hash) on a 64-bit system and wants to try it.
Offline
Hello,
mine does say
PHP_INT_MAX is 9223372036854775807
PHP_INT_SIZE is 8
I am seeing the error code 10, did you get a fix for this?
Thanks
Offline
The problem I had was with the file hsbc_crypto.php in {private}/apps/gbu0/GBU_OLP/ext and was caused by left and right shifting integer values to create a key. The algorithm assumes that an integer is 32 bits long. Therefore a left shift will lose bits to the left; if a large number is shifted it may reduce its value if the remaining bits are so arranged. Similarly a right shift will keep its sign but lose bits to the right.
Now with a 64-bit machine this left shifting does not lose the bits in the same way as before, because they just move up the chain into their correct position. Therefore the result of a left shift is different. For example, on a 32-bit OS the result of one operation was 0x728B4536, the same operation on a 64-bit machine gave 0x26CC000054474536.
There is another issue caused by a strange operation, a negative left-shift, that is used in the crypto code. A negative left shift of 16 (eg $right ^= ($temp << -16); ) needs to be replaced by a shift of -48 (ie $right ^= ($temp << -48); )
Finally, the results of each operation need to be stripped to 32 bits before the next step.
I am lucky in that I have both 32-bit and 64-bit machines available to compare results from each step in the code (lots of "echo"s involved).
Please note that I am running CCP6 not CCP7, so you may need to modify my fixes if the code is different in CCP7 (don't think that it is).
To fix the code, backup the hsbc_crypto.php file and then edit it. Find the function at line 316 called des_createKeys and rename it (eg to des_createKeys32). Go to the bottom of the file and insert the following code before line 395 ("////TEST////")
//des_createKeys NEW for 32 or 64 bit systems //Piers Glydon 02May2010 //this takes as input a 64 bit key (even though only 56 bits are used) //as an array of 2 integers, and returns 16 48 bit keys function des_createKeys ($key) { //echo "Function des_createKeys (in) \$key=$key\n"; //declaring this locally speeds things up a bit $pc2bytes0 = array (0,0x4,0x20000000,0x20000004,0x10000,0x10004,0x20010000,0x20010004,0x200,0x204,0x20000200,0x20000204,0x10200,0x10204,0x20010200,0x20010204); $pc2bytes1 = array (0,0x1,0x100000,0x100001,0x4000000,0x4000001,0x4100000,0x4100001,0x100,0x101,0x100100,0x100101,0x4000100,0x4000101,0x4100100,0x4100101); $pc2bytes2 = array (0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808,0,0x8,0x800,0x808,0x1000000,0x1000008,0x1000800,0x1000808); $pc2bytes3 = array (0,0x200000,0x8000000,0x8200000,0x2000,0x202000,0x8002000,0x8202000,0x20000,0x220000,0x8020000,0x8220000,0x22000,0x222000,0x8022000,0x8222000); $pc2bytes4 = array (0,0x40000,0x10,0x40010,0,0x40000,0x10,0x40010,0x1000,0x41000,0x1010,0x41010,0x1000,0x41000,0x1010,0x41010); $pc2bytes5 = array (0,0x400,0x20,0x420,0,0x400,0x20,0x420,0x2000000,0x2000400,0x2000020,0x2000420,0x2000000,0x2000400,0x2000020,0x2000420); $pc2bytes6 = array (0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002,0,0x10000000,0x80000,0x10080000,0x2,0x10000002,0x80002,0x10080002); $pc2bytes7 = array (0,0x10000,0x800,0x10800,0x20000000,0x20010000,0x20000800,0x20010800,0x20000,0x30000,0x20800,0x30800,0x20020000,0x20030000,0x20020800,0x20030800); $pc2bytes8 = array (0,0x40000,0,0x40000,0x2,0x40002,0x2,0x40002,0x2000000,0x2040000,0x2000000,0x2040000,0x2000002,0x2040002,0x2000002,0x2040002); $pc2bytes9 = array (0,0x10000000,0x8,0x10000008,0,0x10000000,0x8,0x10000008,0x400,0x10000400,0x408,0x10000408,0x400,0x10000400,0x408,0x10000408); $pc2bytes10 = array (0,0x20,0,0x20,0x100000,0x100020,0x100000,0x100020,0x2000,0x2020,0x2000,0x2020,0x102000,0x102020,0x102000,0x102020); $pc2bytes11 = array (0,0x1000000,0x200,0x1000200,0x200000,0x1200000,0x200200,0x1200200,0x4000000,0x5000000,0x4000200,0x5000200,0x4200000,0x5200000,0x4200200,0x5200200); $pc2bytes12 = array (0,0x1000,0x8000000,0x8001000,0x80000,0x81000,0x8080000,0x8081000,0x10,0x1010,0x8000010,0x8001010,0x80010,0x81010,0x8080010,0x8081010); $pc2bytes13 = array (0,0x4,0x100,0x104,0,0x4,0x100,0x104,0x1,0x5,0x101,0x105,0x1,0x5,0x101,0x105); $masks = array (4294967295,2147483647,1073741823,536870911,268435455,134217727,67108863,33554431,16777215,8388607,4194303,2097151,1048575,524287,262143,131071,65535,32767,16383,8191,4095,2047,1023,511,255,127,63,31,15,7,3,1,0); //how many iterations (1 for des, 3 for triple des) $iterations = ((strlen($key) >= 24) ? 3 : 1); //stores the return keys $keys = array (); // size = 32 * iterations but you don't specify this in php //now define the left shifts which need to be done $shifts = array (0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0); //other variables $m=0; $n=0; $is64bit = ( 8 == PHP_INT_SIZE ) ? true : false; //echo "PHP_INT_MAX is " . PHP_INT_MAX . "\n"; //echo "PHP_INT_SIZE is " . PHP_INT_SIZE . "\n"; //echo "\$is64bit is $is64bit\n"; for ($j=0; $j<$iterations; $j++) { //either 1 or 3 iterations $left = (ord($key{$m++}) << 24) | (ord($key{$m++}) << 16) | (ord($key{$m++}) << 8) | ord($key{$m++}); $right = (ord($key{$m++}) << 24) | (ord($key{$m++}) << 16) | (ord($key{$m++}) << 8) | ord($key{$m++}); $left = intval32bits( $left ) ; $right = intval32bits ( $right ); $temp = intval32bits( $temp ); $temp = (($left >> 4 & $masks[4]) ^ $right) & 0x0f0f0f0f; $right ^= $temp; $left ^= ($temp << 4); $left = intval32bits( $left ) ; $right = intval32bits ( $right ); $temp = intval32bits( $temp ); $temp = (($right >> 16 & $masks[16]) ^ $left) & 0x0000ffff; $left ^= $temp; $right ^= $is64bit ? ($temp << -48) : ($temp << -16) ; $left = intval32bits( $left ) ; $right = intval32bits ( $right ); $temp = intval32bits( $temp ); $temp = (($left >> 2 & $masks[2]) ^ $right) & 0x33333333; $right ^= $temp; $left ^= ($temp << 2); $left = intval32bits( $left ) ; $right = intval32bits ( $right ); $temp = intval32bits( $temp ); $temp = (($right >> 16 & $masks[16]) ^ $left) & 0x0000ffff; $left ^= $temp; $right ^= $is64bit ? ($temp << -48) : ($temp << -16) ; $left = intval32bits( $left ) ; $right = intval32bits ( $right ); $temp = intval32bits( $temp ); $temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1); $left = intval32bits( $left ) ; $right = intval32bits ( $right ); $temp = intval32bits( $temp ); $temp = (($right >> 8 & $masks[8]) ^ $left) & 0x00ff00ff; $left ^= $temp; $right ^= ($temp << 8); $left = intval32bits( $left ) ; $right = intval32bits ( $right ); $temp = intval32bits( $temp ); $temp = (($left >> 1 & $masks[1]) ^ $right) & 0x55555555; $right ^= $temp; $left ^= ($temp << 1); $left = intval32bits( $left ) ; $right = intval32bits ( $right ); $temp = intval32bits( $temp ); //the right side needs to be shifted and to get the last four bits of the left side $temp = ($left << 8) | (($right >> 20 & $masks[20]) & 0x000000f0); $left = intval32bits( $left ) ; $right = intval32bits ( $right ); $temp = intval32bits( $temp ); //left needs to be put upside down $left = ($right << 24) | (($right << 8) & 0xff0000) | (($right >> 8 & $masks[8]) & 0xff00) | (($right >> 24 & $masks[24]) & 0xf0); $right = $temp; $left = intval32bits( $left ) ; $right = intval32bits ( $right ); //now go through and perform these shifts on the left and right keys for ($i=0; $i < count($shifts); $i++) { //shift the keys either one or two bits to the left if ($shifts[$i] > 0) { $left = (($left << 2) | ($left >> 26 & $masks[26])); $right = (($right << 2) | ($right >> 26 & $masks[26])); } else { $left = (($left << 1) | ($left >> 27 & $masks[27])); $right = (($right << 1) | ($right >> 27 & $masks[27])); } $left = $left & -0xf; $right = $right & -0xf; //now apply PC-2, in such a way that E is easier when encrypting or decrypting //this conversion will look like PC-2 except only the last 6 bits of each byte are used //rather than 48 consecutive bits and the order of lines will be according to //how the S selection functions will be applied: S2, S4, S6, S8, S1, S3, S5, S7 $lefttemp = $pc2bytes0[$left >> 28 & $masks[28]] | $pc2bytes1[($left >> 24 & $masks[24]) & 0xf] | $pc2bytes2[($left >> 20 & $masks[20]) & 0xf] | $pc2bytes3[($left >> 16 & $masks[16]) & 0xf] | $pc2bytes4[($left >> 12 & $masks[12]) & 0xf] | $pc2bytes5[($left >> 8 & $masks[8]) & 0xf] | $pc2bytes6[($left >> 4 & $masks[4]) & 0xf]; $righttemp = $pc2bytes7[$right >> 28 & $masks[28]] | $pc2bytes8[($right >> 24 & $masks[24]) & 0xf] | $pc2bytes9[($right >> 20 & $masks[20]) & 0xf] | $pc2bytes10[($right >> 16 & $masks[16]) & 0xf] | $pc2bytes11[($right >> 12 & $masks[12]) & 0xf] | $pc2bytes12[($right >> 8 & $masks[8]) & 0xf] | $pc2bytes13[($right >> 4 & $masks[4]) & 0xf]; $temp = (($righttemp >> 16 & $masks[16]) ^ $lefttemp) & 0x0000ffff; $keys[$n++] = $lefttemp ^ $temp; $keys[$n++] = $righttemp ^ ($temp << 16); } } //for each iterations //return the keys we've created return $keys; } //end of des_createKeys //http://stackoverflow.com/questions/300840/force-php-integer-overflow/2123458#2123458 //Vadzim Struk http://stackoverflow.com/users/257425/vadzim-struk function intval32bits($value) { $value = ($value & 0xFFFFFFFF); if ($value & 0x80000000) $value = -((~$value & 0xFFFFFFFF) + 1); return $value; }
Save the new file back to hsbc_crypto.php and you should be sorted.
The HSBC guide gives examples of what the hashed values should be, given a known hash key and input array. I've written this up into a small script which should show whether your new code is working. Stick this on your webserver, modify the path in line 3 to point to your hsbc_crypto.php, and run it. You could try this before and after modifying the crypto file to see whether it has made a difference.
<pre> <?php //PG 02May2010 $path_to_crypto = "/home/xxx/yyy/apps/gbu0/GBU_OLP/ext/hsbc_crypto.php"; include_once ( $path_to_crypto ); $keyHSBC = "zEeWQNKelqPE2DRFueuDq1QrASjux2lM"; $key = $keyHSBC; $array = array(); $array[] = "aaa"; echo "First hash should be m4uGmXow+lcJYycNrbM7M8xS3No=\n"; echo "First hash is " . generateHash ( $array , $key ); $array[] = "bbb"; echo "\n\nSecond hash should be zaM6DPT7GkEJtg2OWYzSePUa0rc=\n"; echo "Second hash is " . generateHash ( $array , $key ); $array[] = "ccc ddd"; echo "\n\nThird hash should be 1sMZc6TaxcMnQthq2Dp0QKe7obk=\n"; echo "Third hash is " . generateHash ( $array , $key ); $array[] = "eee fff ggg"; echo "\n\nFourth hash should be 6FLZlCBhHTj5Tr9XbgFhuZVsh7M=\n"; echo "Fourth hash is " . generateHash ( $array , $key ); ?> </pre>
Hope this helps - if not, you have another problem! This fixed it for me though.
Offline
Hi,
Tried the above, now I get relayed back to my site and see the following in red at the top of the page:
"Unfortunately, we are unable to accept your transaction. There may be a problem with the payment information you entered, or our online processor may be experiencing technical difficulties at the present time. You can attempt to process your order again, or contact us to discuss other payment options."
Offline
karlconnor wrote:
"Unfortunately, we are unable to accept your transaction. There may be a problem with the payment information you entered, or our online processor may be experiencing technical difficulties at the present time. You can attempt to process your order again, or contact us to discuss other payment options."
Are you getting the correct hash generated, according to the small script I posted? Are you running a 64-bit or 32-bit OS?
HSBC will tell you the reason that the transaction failed if you call them on the phone. A code is also returned from the bank back to your site - you will need to set debug level 1 or 2 to see this value. I have added code which emails to me the return code and order number every time the response comes back from the bank. You can then look up what the code means according to the table in your documentation, or see post https://forum.kryptronic.com/viewtopic.php?id=22971
However, I'm sorry but as I'm running CCP6 not CCP7 I can't really offer much more help here, much as I'd love to. These fixes solved my most recent issue with HSBC, one of many!
Offline
HSBC tell me that the timestamp is coming through as zero and it should be 13 digits?
Offline
Looks like you may have made a mistake when making the change in step 2 of this thread.
Offline