Интеграция Sage Pay v3.00

Может ли кто-нибудь помочь мне включить алгоритм Sagepay v3.00 AES/CBC/PKCS#5 (шифрование) в следующий файл. Я действительно изо всех сил пытаюсь понять, как включить, чтобы данные клиентов были зашифрованы в соответствии с новым стандартом, а затем расшифрованы на обратном пути. Используя Sagepay Form с очень старой версией cs-cart, удалось успешно обновить версию 2.22 до 2.23, но Sagepay прекращает поддержку с июля.

Не уверен, насколько этот скрипт имеет отношение к шифрованию:

<?php

if ( !defined('IN_CSCART') ) { die('Access denied'); }

if (defined('PAYMENT_NOTIFICATION')) {  

// Get the password
$payment_id=db_get_field("SELECT $db_tables[payments].payment_id FROM $db_tables[payments] LEFT JOIN $db_tables[payment_processors] ON $db_tables[payment_processors].processor_id = $db_tables[payments].processor_id WHERE $db_tables[payment_processors].processor_script='protx_form.php'");
$processor_data = fn_get_payment_method_data($payment_id);

$result = "&".simpleXor(base64Decode($_REQUEST['crypt']), $processor_data["params"]["password"])."&";

preg_match("/Status=(.+)&/U", $result, $a);
if(trim($a[1]) == "OK") {
    $pp_response['order_status'] = ($processor_data["params"]["transaction_type"] == 'PAYMENT') ? 'P' : 'O';
    preg_match("/TxAuthNo=(.+)&/U", $result, $authno);
    $pp_response["reason_text"] = "AuthNo: ".$authno[1];
    preg_match("/VPSTxID={(.+)}/U", $result, $transaction_id);
    $pp_response["transaction_id"] = @$transaction_id[1];
} else {
    $pp_response['order_status'] = 'F';
    preg_match("/StatusDetail=(.+)&/U", $result, $stat);
    $pp_response["reason_text"] = "Status: ".trim($stat[1])." (".trim($a[1]).") ";
}
preg_match("/AVSCV2=(.*)&/U", $result, $avs);
if(!empty($avs[1])) {
    $pp_response['descr_avs'] = $avs[1];
}
include $payment_files_dir.'payment_cc_complete.php';
fn_order_placement_routines($order_id);

}
else
{
    global $http_location, $b_order, $_total_back;

    $post_address = ($processor_data['params']['testmode'] != "N") ? "https://test.sagepay.com/gateway/service/vspform-register.vsp" : "https://live.sagepay.com/gateway/service/vspform-register.vsp";

    $post["VPSProtocol"] = "2.23";
    $post["TxType"] = $processor_data["params"]["transaction_type"];
    $post["Vendor"] = htmlspecialchars($processor_data["params"]["vendor"]);

    // Form Cart products
    $strings = 0;
    if (is_array($cart['products'])) {
        $strings += count($cart['products']);
    }

    if (!empty($cart['products'])) {
        foreach ($cart['products'] as $v) {
            $_product = db_get_field("SELECT product FROM $db_tables[product_descriptions] WHERE product_id='$v[product_id]' AND lang_code='$cart_language'");
            $products_string .= ":".str_replace(":", " ", $_product).":".$v['amount'].":".fn_format_price($v['subtotal']/$v['amount']).":::".fn_format_price($v['subtotal']);
        }
    }
    if (!empty($cart['payment_surcharge'])) {
        $products_string .= ":Payment surcharge:---:---:---:---:".fn_format_price($cart['payment_surcharge']);
        $strings ++;
    }
    if (!empty($cart['shipping_cost'])) {
        $products_string .= ":Shipping cost:---:---:---:---:".fn_format_price($cart['shipping_cost']);
        $strings ++;
    }
    $post_encrypted .= "Basket=".$strings.$products_string;

    $post["Crypt"] = base64_encode(simpleXor($post_encrypted, $processor_data["params"]["password"]));
    $post["Crypt"] = htmlspecialchars($post["Crypt"]);

    $msg = fn_get_lang_var('text_cc_processor_connection');
    $msg = str_replace('[processor]', 'Protx Server', $msg);

echo <<<EOT
<html>
<body onLoad="document.process.submit();">
<form action="{$post_address}" method="POST" name="process">
<INPUT type=hidden name="VPSProtocol" value="{$post['VPSProtocol']}">
<INPUT type=hidden name="Vendor" value="{$post['Vendor']}">
<INPUT type=hidden name="TxType" value="{$post['TxType']}">
<INPUT type=hidden name="Crypt" value="{$post['Crypt']}">
<p>
<div align=center>{$msg}</div>
</p>
</body>
</html>
EOT;
}

exit;

//
// ---------------- Additional functions ------------
//
function simpleXor($InString, $Key) {
$KeyList = array();
$output = "";

for($i = 0; $i < strlen($Key); $i++){
    $KeyList[$i] = ord(substr($Key, $i, 1));
}
for($i = 0; $i < strlen($InString); $i++) {
    $output.= chr(ord(substr($InString, $i, 1)) ^ ($KeyList[$i % strlen($Key)]));
}

return $output;
}

function base64Decode($scrambled) {
// Initialise output variable
$output = "";
// Fix plus to space conversion issue
$scrambled = str_replace(" ","+",$scrambled);
// Do encoding
$output = base64_decode($scrambled);
// Return the result
return $output;
}
?>

person Community    schedule 15.02.2015    source источник


Ответы (2)


Вы можете попробовать добавить в скрипт следующие функции, а затем заменить simpleXor на encryptAes. Убедитесь, что вы также добавили символ «@» в качестве первого символа строки шифрования (и удалите его при декодировании ответа от Sage Pay).

function addPKCS5Padding($input)
{
     $blockSize = 16;
     $padd = "";
     $length = $blockSize - (strlen($input) % $blockSize);
     for ($i = 1; $i <= $length; $i++)
{
     $padd .= chr($length);
}
     return $input . $padd;
}

function removePKCS5Padding($input)
{
    $blockSize = 16;
    $padChar = ord($input[strlen($input) - 1]);
    $unpadded = substr($input, 0, (-1) * $padChar);
    return $unpadded;
}


function encryptAes($string, $key)
{
    $string = addPKCS5Padding($string);
    $crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $key);
    return  strtoupper(bin2hex($crypt));
}


function decryptAes($strIn, $password)
{
    $strInitVector = $password;
    $strIn = pack('H*', $hex);
    $string = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $password, $strIn, MCRYPT_MODE_CBC,$strInitVector);
    return removePKCS5Padding($string);
}
person Rik Blacow    schedule 27.02.2015
comment
Возможно ли, чтобы вы включили свой сценарий в мой именно так, как вы думаете, чтобы я мог его протестировать. Я действительно понятия не имею, какие части моего скрипта мне нужно удалить и где добавить ваши, а также где разместить символ «@» и т. д. - person ; 28.02.2015
comment
Если вы хотите связаться со мной напрямую (подробности через профиль / по ссылке), это может быть проще - я не хочу публично раскрывать данные учетной записи поставщика! - person Rik Blacow; 11.03.2015

Вы можете попробовать это. Я не могу проверить это, так что дайте мне знать, как у вас дела.

<?php

    if ( !defined('IN_CSCART') ) { die('Access denied'); }

    if (defined('PAYMENT_NOTIFICATION')) {  

    // Get the password
    $payment_id=db_get_field("SELECT $db_tables[payments].payment_id FROM $db_tables[payments] LEFT JOIN $db_tables[payment_processors] ON $db_tables

    [payment_processors].processor_id = $db_tables[payments].processor_id WHERE $db_tables[payment_processors].processor_script='protx_form.php'");
    $processor_data = fn_get_payment_method_data($payment_id);


    #Rik added:
    $result = "&".decryptAes($_REQUEST['crypt'], $processor_data["params"]["password"])."&";

    #$result = "&".simpleXor(base64Decode($_REQUEST['crypt']), $processor_data["params"]["password"])."&";

    preg_match("/Status=(.+)&/U", $result, $a);
    if(trim($a[1]) == "OK") {
        $pp_response['order_status'] = ($processor_data["params"]["transaction_type"] == 'PAYMENT') ? 'P' : 'O';
        preg_match("/TxAuthNo=(.+)&/U", $result, $authno);
        $pp_response["reason_text"] = "AuthNo: ".$authno[1];
        preg_match("/VPSTxID={(.+)}/U", $result, $transaction_id);
        $pp_response["transaction_id"] = @$transaction_id[1];
    } else {
        $pp_response['order_status'] = 'F';
        preg_match("/StatusDetail=(.+)&/U", $result, $stat);
        $pp_response["reason_text"] = "Status: ".trim($stat[1])." (".trim($a[1]).") ";
    }
    preg_match("/AVSCV2=(.*)&/U", $result, $avs);
    if(!empty($avs[1])) {
        $pp_response['descr_avs'] = $avs[1];
    }
    include $payment_files_dir.'payment_cc_complete.php';
    fn_order_placement_routines($order_id);

    }
    else
    {
        global $http_location, $b_order, $_total_back;

        $post_address = ($processor_data['params']['testmode'] != "N") ? "https://test.sagepay.com/gateway/service/vspform-register.vsp" : 

    "https://live.sagepay.com/gateway/service/vspform-register.vsp";

        $post["VPSProtocol"] = "2.23";
        $post["TxType"] = $processor_data["params"]["transaction_type"];
        $post["Vendor"] = htmlspecialchars($processor_data["params"]["vendor"]);

        // Form Cart products
        $strings = 0;
        if (is_array($cart['products'])) {
            $strings += count($cart['products']);
        }

        if (!empty($cart['products'])) {
            foreach ($cart['products'] as $v) {
                $_product = db_get_field("SELECT product FROM $db_tables[product_descriptions] WHERE product_id='$v[product_id]' AND lang_code='$cart_language'");
                $products_string .= ":".str_replace(":", " ", $_product).":".$v['amount'].":".fn_format_price($v['subtotal']/$v['amount']).":::".fn_format_price($v

    ['subtotal']);
            }
        }
        if (!empty($cart['payment_surcharge'])) {
            $products_string .= ":Payment surcharge:---:---:---:---:".fn_format_price($cart['payment_surcharge']);
            $strings ++;
        }
        if (!empty($cart['shipping_cost'])) {
            $products_string .= ":Shipping cost:---:---:---:---:".fn_format_price($cart['shipping_cost']);
            $strings ++;
        }
        $post_encrypted .= "Basket=".$strings.$products_string;


    #Rik added:

     $post["Crypt"] = "@".encryptAes($post_encrypted, $processor_data["params"]["password"]);

    #    $post["Crypt"] = base64_encode(simpleXor($post_encrypted, $processor_data["params"]["password"]));
    #    $post["Crypt"] = htmlspecialchars($post["Crypt"]);

        $msg = fn_get_lang_var('text_cc_processor_connection');
        $msg = str_replace('[processor]', 'Protx Server', $msg);

    echo <<<EOT
    <html>
    <body onLoad="document.process.submit();">
    <form action="{$post_address}" method="POST" name="process">
    <INPUT type=hidden name="VPSProtocol" value="{$post['VPSProtocol']}">
    <INPUT type=hidden name="Vendor" value="{$post['Vendor']}">
    <INPUT type=hidden name="TxType" value="{$post['TxType']}">
    <INPUT type=hidden name="Crypt" value="{$post['Crypt']}">
    <p>
    <div align=center>{$msg}</div>
    </p>
    </body>
    </html>
    EOT;
    }

    exit;

    //
    // ---------------- Additional functions ------------
    //
    function simpleXor($InString, $Key) {
    $KeyList = array();
    $output = "";

    for($i = 0; $i < strlen($Key); $i++){
        $KeyList[$i] = ord(substr($Key, $i, 1));
    }
    for($i = 0; $i < strlen($InString); $i++) {
        $output.= chr(ord(substr($InString, $i, 1)) ^ ($KeyList[$i % strlen($Key)]));
    }

    return $output;
    }

    function base64Decode($scrambled) {
    // Initialise output variable
    $output = "";
    // Fix plus to space conversion issue
    $scrambled = str_replace(" ","+",$scrambled);
    // Do encoding
    $output = base64_decode($scrambled);
    // Return the result
    return $output;
    }


    #added by Rik

    function addPKCS5Padding($input)
    {
         $blockSize = 16;
         $padd = "";
         $length = $blockSize - (strlen($input) % $blockSize);
         for ($i = 1; $i <= $length; $i++)
    {
         $padd .= chr($length);
    }
         return $input . $padd;
    }

    function removePKCS5Padding($input)
    {
        $blockSize = 16;
        $padChar = ord($input[strlen($input) - 1]);
        $unpadded = substr($input, 0, (-1) * $padChar);
        return $unpadded;
    }


    function encryptAes($string, $key)
    {
        $string = addPKCS5Padding($string);
        $crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $key);
        return  strtoupper(bin2hex($crypt));
    }


    function decryptAes($strIn, $password)
    {

    #Sagepay specific - remove the '@'
    $strIn = substr($strIn,1)

        $strInitVector = $password;
        $strIn = pack('H*', $hex);
        $string = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $password, $strIn, MCRYPT_MODE_CBC,$strInitVector);
        return removePKCS5Padding($string);
    }

    ?>
person Rik Blacow    schedule 02.03.2015
comment
Я пробовал (после изменения $post[VPSProtocol] = 3.00;), но он просто зависает на «подключении к Sage Pay». Нет журнала ошибок, что не помогает. Я чувствую, что вы очень близки к тому, чтобы разузнать об этом, если вы можете сделать еще один замах? - person ; 03.03.2015