News:

Looking for documentation? Take a look on our wiki

Main Menu

HSBC CPI Integration

Started by jon.hathaway, July 22, 2005, 19:28:56 PM

Previous topic - Next topic

jon.hathaway

I realise that there are very few payment modules at the moment, and I am currently in the process of writing a payment module that will integrate with HSBC CPI gateway.

However, I am not the best coder going and would liek to know if anyone else is looking at doing this.

The problem with the CPI integration is that it uses a compiled library for the call back for the gateway after authenticating the order.....I have no idea how to do this. I know oscommerce have an HSBC integration and I was wondering if any one could migrate this from oscommerce to phpshop.

I have two interesting links with regards to this topic:

http://www.webmasterworld.com/forum88/3967-2-10.htm
http://forums.oscommerce.com/index.php?showtopic=76967&st=0

Thanks

stovesy

I'm looking to do thet same, and have breifly looked at the os-commerce code. I'm struggling because I don't have any details of the HSBC api or protocols. Do you have such info ?

jon.hathaway

We are still trying to get the info out of HSBC. Everytime we ask for it they seem to gorget as it never arrives. We have had quite a bit of success with using the Hash code and the libraries.

One thing to note on a shared server though is whether or not the server will allow you to set the LD_LIBRARY_PATH. If you are running php in safe_mode=on then you are very unlikely to get HSBC working as you will need to change the library path to point to the location of the libCCPITools.so library that HSBC give you.

We currently have got the point where the hash is being accepeted and is successfully being generated and we are now running into problems posting it to either https://www.cpi.hsbc.com/server or https://www.secure-epayments.api.hsbc.com.

I think our script is in error, but the error we are getting relates to the SSL session not being verified.

Keep in touch and we'll let you know how we get on. You are more than welcome to the code once we have it and we will be releasing it under GPL.

Jon

husayt

Hi again,
I thought this might be useful. Please, find enclosed php port of hash generation procedure fom HSBC CPI.
sample for use:

$h=generateHash(array('1','3','2'),"3jmNetQZP/ZSIUe/cYIHMkB70Bha4RyJe7mOAMqOoH8=");
echo ("<br>h=$h<br>");

and here is the source code:


// helper class
class SecCrypto{
var $_fldif;
    var $a;
    function rot13(&$abyte0)
    {
        for($i = 0; $i < strlen($abyte0); $i++)
        {
            $c = ord($abyte0[$i]);
            if($c >= ord('a') && $c <= ord('m') || $c >= ord('A') && $c <= ord('M'))
                $abyte0[$i] = chr($c + 13);
            else
            if($c >= ord('n') && $c <= ord('z') || $c >= ord('N') && $c <= ord('Z'))
                $abyte0[$i] = chr($c - 13);
        }

    }

    function  encode($abyte0)
    {
        return base64_encode($abyte0);
    }

    function  decode($s)
    {
        return base64_decode($s);
    }

    function encrypt($abyte0, $abyte1)
    {
$td = mcrypt_module_open (MCRYPT_DES, '', MCRYPT_MODE_CBC, '');
$iv = $this->a;
$ks = mcrypt_enc_get_key_size ($td);
$key=substr($abyte1,0,$ks);
  /* Intialize encryption */
    mcrypt_generic_init ($td, $key, $iv);
return  mcrypt_generic ($td, $abyte0);
// old version
// return mcrypt_cbc(MCRYPT_DES,substr($abyte1,0,mcrypt_get_key_size ('des', 'cbc')),$abyte0, MCRYPT_ENCRYPT,$this->a);
    }

    function decrypt($abyte0, $abyte1)
    {
$td = mcrypt_module_open (MCRYPT_DES, '', MCRYPT_MODE_CBC, '');
$iv = $this->a;
$ks = mcrypt_enc_get_key_size ($td);
$key=substr($abyte1,0,$ks);
  /* Intialize encryption */
    mcrypt_generic_init ($td, $key, $iv);
$ret=mdecrypt_generic($td, $abyte0);

// $ret=mcrypt_cbc(MCRYPT_DES,substr($abyte1,0,mcrypt_get_key_size ('des', 'cbc')),$abyte0, MCRYPT_DECRYPT,$this->a);
// Bus fix
while($ret[strlen($ret)-1]=="\4" && strlen($ret)>0){
$ret=substr($ret,0,strlen($ret)-1);
}
return $ret;
    }

    function encryptEncode($abyte0, $abyte1)
    {
        return $this->encode($this->encrypt($abyte0, $abyte1));
    }

    function decodeDecrypt($s, $abyte0)
    {

        return $this->decrypt($this->decode($s),$abyte0);
    }

    function initKey($s, $s1, $s2)
    {
        $abyte0 =chr(0);
        $abyte1 = $s1;
        $abyte2 = $s2;
        $byte0 = 4;
        $i = $byte0 + 9;
        $j = rand(0,30);
$j = 0;
        if($j > $byte0 * $i)
            $j -= $byte0 * $i;
        $k = 0;
        for($l = 0; $l < $byte0 * $i; $l++){
            switch(($j + $l) % $i)
            {
            case 4: // '\004'
            case 6: // '\006'
            case 8: // '\b'
            case 9: // '\t'
            default:
                break;

            case 7: // '\007'
                if($k < 2){
                    $abyte0 = $this->encrypt($abyte1, $abyte2);
}
                break;

            case 5: // '\005'
                if($k < 2){
                    $abyte0 = $this->encrypt($abyte1, $abyte2);
}
                break;

            case 10: // '\n'
                if($k < 2){
                    $abyte0 = $this->encrypt($abyte1, $abyte2);
}
                break;

            case 3: // '\003'
                if($k == 3){
                    $k++;
}
                break;

            case 0: // '\0'
                if($k == 2)
                {
                    $abyte0 = $this->encrypt($abyte1, $abyte2);
                    $k++;
                }
                break;

            case 1: // '\001'
                if($k == 1)
                {
                    $abyte2 = $abyte1;
                    $this->rot13($abyte2);
                    $k++;
                }
                break;

            case 2: // '\002'
                if($k == 0)
                {
                    $i1 = 48 + (ord($abyte1[0]) + 10) % 10;
                    $abyte1[0] = chr($i1);
                    $k++;
                }
                break;
            }
}
        return $this->decodeDecrypt($s, $abyte0);
    }

    function SecCrypto()
    {
        $s = "KmJTwzVPwjoxQdWJb1BxbuhBSa2RuM05+/aUdgYoGdFWWf04CKIQTxtxLeKCp+5J";
        $s1 = "y8YhmjsAoMUW9RxfXBSos0A6LwGd+5pXv/MRAKCYFLG";
        $s2 = "BqRkPAG8DFFAdeN5SMAArktCYuUGXi2q88EDoOs3Ykw0k";
$this->a =chr(98).chr(84).chr(120).chr(114).chr(66).chr(87).chr(80).chr(112);
        $this->_fldif = $this->initKey($s, $s1, $s2);
$this->_fldif=substr($this->_fldif,0,44);
    }

    function encrypt1($s)
    {
        if($s == NULL)
            return NULL;
        else
            return $this->encryptEncode($s, $this->_fldif);
    }


    function decrypt1($s)
    {
        if($s == NULL)
            return NULL;
        else
            return $this->decodeDecrypt($s, $this->_fldif);
    }
function decryptToBinary($s){
        if($s == NULL)
            return NULL;
        else
            return $this->decodeDecrypt($s, $this->_fldif);
}


//echo "iv size=".mcrypt_get_iv_size ('des', 'cbc')."<br>";
//echo "key size=".mcrypt_get_key_size ('des', 'cbc')."<br>";
//$h=generateHash(array('1','3','2'),"3jmNetQZP/ZSIUe/cYIHMkB70Bha4RyJe7mOAMqOoH8=");
//echo ("<br>h=$h<br>");

function generateHash($vector, $s)
{
        $vector1 = array();
        for($i = 0; $i < sizeof($vector); $i++)
        {
            $flag = false;
            $s2 = $vector[$i];
            for($k = 0; $k < sizeof($vector1) && !$flag; $k++)
            {
                $s4 = $vector1[$k];
                $l = strcmp($s2,$s4);
                if($l <= 0)
                {
array_push($vector1,"");
for($r=sizeof($vector1)-2;$r>=$k;$r--){
$vector1[$r+1]=$vector1[$r];
}
                    $vector1[$k]=$s2;
                    $flag = true;
                }
            }

            if(!$flag)
array_push($vector1,$s2);

        }

        $s1 = "";
        for($j = 0; $j < sizeof($vector1); $j++)
        {
            $s3 = $vector1[$j];
            $s1 = $s1 . $s3;
        }
        $seccrypto = new SecCrypto();
        $abyte0 = $seccrypto->decryptToBinary($s);
$ret=base64_encode(mhash(MHASH_SHA1,$s1.$abyte0,$abyte0));
return $ret;
}

stovesy

I'm sortof half way thru (up to exit(0)) but I've got the documentation CD from HSBC
Sadly I'm struggling to get the mcrypt library installed on apache-php under windows - I winder if there is a native PHP equivalent to the mcrypt functions used here ??

Anyway folks - let's keep chipping away at this.


[attachment deleted by admin]

stovesy

This might help (HSBC integration guide - pdf)


[attachment deleted by admin]

stovesy

I've actually got libmcrypt - but am struggling to find php_mcrypt.dll.

I've got linux at work so I'll set it up on that.
The only concern I have is we are putting more requirements on our hosts (to have mcrypt installed). Wouldn't it be nice if we could get this all done in native php ?

stovesy

Just noticed we need another external library 'mhash' ???


husayt

It will be good if HSBC has test server.

But in any case I have got a cusomer account in test mode, we can do tests with.
So I can do tests if I got the module.

Thanks.

stovesy

As soon as I get any joy, I'll post the module.
At work (via a linux based php & apache). I am getting something back from the server.
I'll let you know how far i'm getting.

stovesy

I can't get my head around this.

The HSBC payment system works I think in 3 steps.

1. Various data is posted to the HSBC server to initiate the payment.
2. The HSBC server presents the user with a secure page to fill in payment options
3. With 2 complete, the HSBC server posts back various confirmatory data.

How can I handle this within the payment processor, as far as I can see, it's one peice of code which has no possibility of this. Any of the moderators help on this ??

Thankyou

mitch_a

stovesy, husayt

I also have a requirement for a payment module for the HSBC CPI.
I am in the process of setting up a test account with HSBC and the site will be hosted on a dedicated Linux server.
It would be great to get some more information regarding your progress todate and I would be happy to help, where I can (I'm more PHP hacker rather than coder i'm afraid).

I note above that you are having difficulty setting up a test server - due to a clients sites being live - let me know if I can be of help here.

With regards to your question above re the payment processor being only one piece of code --
I have , in the past, used the paypal module for payment processing  - this is in 3 steps - not sure if this will help you in any way ??

1 - Various data posted to paypal (albeit some in hidden, unsecure form fields)
2 - Payment made on paypal
3 - Code returned to phpshop to confirm payment / change order staus etc.

I have yet to look at the payment processor code and HSBC process in any detail, but image that it it not a simple 'forms' type interface (ala paypal, protx forms etc) - hence the above will not be helpful.

If I can help with testing / any other way, just let me know.

Regards


stovesy

Here's what I have so far.



[attachment deleted by admin]

stovesy

I'm starting to get this after looking at a load of Soerens code.

We've gotta use the 'payment_extrainfo' field to pass our form to the CPI. I installed the ps_pbs payment processor. What happens is the order completes in the phpShop system, then the code in the 'extra_info' field gets evaluated and any output is displayed at the bottom of the 'ThankYou' page.

(This is a little wrong really - because the payment may not go through - so the order is not complete) CPI is also able to return a payment status.. but anyway.

What needs to happen, is instead of posting the CPI variable directly, we need to get all that info into a form which is defined in the 'extra_info' field.

Just have a look at the 'ps_pb.php' file in admin-components-com_phpshop-classes-payment.