Мой php скрипт не расшифровывает возвратный крипт в Sagepay Form version 3.00 - PullRequest
0 голосов
/ 27 августа 2018

Я переместил свой сайт на нового хостинг-провайдера, где мой скрипт Sagepay Form v3, который получает зашифрованный ответ, теперь не работает.

У предыдущего хостинг-провайдера скрипт работал (версия php была 5.5.9), и новый хостинг предлагает выбор от 5.4 до 6. У первого хостинг-провайдера версия php долгое время назад была 5.2 (или может быть, это было 5,3), и когда они, наконец, применили изменение к 5,5, это повредило много вещей в сценариях моего сайта, что привело к очень трудному периоду, когда я пытался их исправить, чего я и добился в итоге.

Одной из таких вещей было то, что расшифровка не удалась, точно так же, как сейчас. В этом случае я в конце концов исправил это, изменив строку дешифрования с:

$Decoded = DHclassInFunc::decryptAes($crypt,$EncryptionPassword);

до:

$Decoded = DHclassInFunc::decryptAes(($_GET['crypt']),$EncryptionPassword);

Я пробовал много других вариантов, но сработал только последний.

Так что теперь проблема вернулась, и я полностью растерялся. Я перепробовал все предыдущие варианты, но ничего не работает. Также на моем новом хосте предлагаются различные версии php.

Мой (ДЛИННЫЙ) вопрос по предыдущему случаю также был размещен здесь: см. Веб-сайт Sagepay, отправляющий код шифрования, работал, но теперь не работает после обновления php сервера

Кто-нибудь может подсказать, почему это не помогает в этот раз и что я могу сделать, чтобы это исправить?

РЕДАКТИРОВАТЬ 14/12/18 Дополнительная информация после расследования, плюс я включаю дополнительные пояснения и полный код из двух соответствующих сценариев ---------------- --------

Я не продвинулся, и заказами на сайте приходилось управлять вручную, пока возврат Sagepay не работал. Теперь у меня есть немного времени, поэтому я пытаюсь снова.

Теперь я обнаружил, что, если я удалю эту строку (ниже) на странице "complete.php" (URL-адрес, на который направлен ответ Sagepay), скрипт не зависнет; однако это потому, что именно эта строка вызывает фатальную ошибку.

$Decoded = DHclassInFunc::decryptAes(($_GET['crypt']),$EncryptionPassword);

Без строки и возникшей ошибки скипт может двигаться дальше и вызывать следующую страницу («return.php»), которая затем отображает информацию о результате платежа для клиента, а также выполняет другие действия (такие как отправка полной Закажите подробности в нашей локальной - не в интернете - базе данных).

Однако с удаленной строкой крипта в url не обрабатывается, и, следовательно, в результирующих переменных нет значений, которые перенаправляет страница complete.php на страницу return.php.

Это означает, что переменная $ status пуста; на странице return.php это оценивается как ошибка, и поэтому клиенту показывается сообщение, в котором говорится, что произошла ошибка и что платеж не был принят - что неверно.

Отсутствие значения статуса «success» также означает, что заказ в базе данных web mysql не помечен как подтвержденный.

Я перепробовал многие другие варианты этой линии, но безрезультатно (хотя приведенный здесь работал до того, как сайт был перенесен на новый хост).

Строка, конечно, вызывает функцию в классе "DHclassInFunc", который находится в файле functions.php.

Я прилагаю ниже активный код из двух файлов, complete.php и functions.php

Насколько я могу понять, корень проблемы в том, что строка

$Decoded = DHclassInFunc::decryptAes(($_GET['crypt']),$EncryptionPassword);

не получает никакого значения в 'crypt', поэтому отсутствует строка для работы функции расшифровки function.php, что приводит к фатальной ошибке при вызове этой функции: «PHP-фатальная ошибка: класс« SagepayApiException »не найден» в /redacted/redacted/redacted.com/www/redacted/protx/functions.php в строке 208 "

Я добавил строку в коде functions.php, как показано ниже:

echo '$strIn' . "  string in with @ should be here?";

, чтобы попытаться раскрыть значение, которое передается в функцию, но оно просто печатает имя переменной, а не значения из содержимого URL-адреса, которое находится в адресной строке страницы complete.php, когда она получает ответ от Sagepay - например:

https://www.redacted.com/redacted/protx/completed.php?crypt=@ad6721a09c786829cd839586df0fe047ea0f0e9c791ddfe5d55b7175881aa4609ccfb4768a8b84dd9f259614d0edf0f03254a1967279693509e72190c8248cd56d1cefa713592f84eca4e8d7477ac89c9dd783b350a21766500c1c91fde3dbe5deb7887bea0e5c07e58274dec93224729f265730a4aecf5cf9c7216dad2b5eecc4d128e6c8389c1c9d5d297b7a10ccb53e37eae5b7a996a308c10f2d0edc0b41b6b38c6e56375a6421d110a0a3fe40cdfa2daa2fa6e0bf767204d209aa300d9f907ea686ee9a9dcc0992c14c325123ab53d7885bc6dc66eebf3c341002034fbce6277ccc6fbb8734c3cdab58dcd294d0a3a4430c7b091beed81fd97cadbf24b9149f9541e5d8e8c45a4e267fc0d14222c45963fe847ec12a9fedf05eba2a78caf769825046584b112d353d92d38aedc3cb086fc0c8250e20ef975dc377438b7c3a34c96cacba9ed1670b2af1bcd0945a5a0424c0532f23b0a6662db8198a2368d60ee3785f07826005593292154abe06abf55ff1d461b714e1fb53b5da3db1f21eb6b01169a2cf78d872de5ac96e41e088a7bf1e6f88aa8cc5c6b4bfd5d82f63

Относительно того, может ли это быть проблема Unicode / ISO, я не могу понять, почему это привело бы к пустому значению в $ strIn, так как это еще не было обработано, просто захвачено(или нет?).

COMPLETED.php ---------------------

<?php
include "functions.php";

$Decoded = DHclassInFunc::decryptAes($_GET['crypt'],$EncryptionPassword); 

$values = getToken($Decoded);
$VendorTxCode = $values['VendorTxCode'];
$Status = $values['Status'];
$VPSTxID = $values['VPSTxId'];
$TxAuthNo = $values['TxAuthNo'];
$AVSCV2 = $values['AVSCV2'];
$Amount = $values['Amount'];
// protocol 2.22 fields
$AddressResult = $values[ 'AddressResult' ];
$PostCodeResult = $values[ 'PostCodeResult' ];
$CV2Result = $values[ 'CV2Result' ];
$GiftAid = $values[ 'GiftAid' ];
$VBVSecureStatus = $values[ '3DSecureStatus' ];
$CAVV = $values[ 'CAVV' ];

// DH my all-in-one details var

$ResultDetails = $ResultDetails . "Vendor Code: " . $VendorTxCode . " - "; 
$ResultDetails = $ResultDetails . "Status: " . $Status . " - "; 
$ResultDetails = $ResultDetails . "VPS Transaction ID: " . $VPSTxID . " - ";                                                                                                                                                                                                         
$ResultDetails = $ResultDetails . "Auth Num: " . $TxAuthNo . " - "; 
$ResultDetails = $ResultDetails . "AVS / CV2 response: " . $TxAuthNo . " - "; 
$ResultDetails = $ResultDetails . "Amount: " . $Amount . " - ";         
$ResultDetails = $ResultDetails . "Address Result: " . $AddressResult . " - ";  
$ResultDetails = $ResultDetails . "PostCode Result: " . $PostCodeResult . " - ";   
$ResultDetails = $ResultDetails . "PostCode Result: " . $PostCodeResult . " - ";    
$ResultDetails = $ResultDetails . "CV2 Result: " . $CV2Result . " - ";  
$ResultDetails = $ResultDetails . "GiftAid Result: " . $GiftAid . " - ";     
$ResultDetails = $ResultDetails . "3DSecure Status: " . $VBVSecureStatus . " - "; 
$ResultDetails = $ResultDetails . "CAVV Result: " . $CAVV . " - ";  

$FindHyphen = strpos($VendorTxCode,'-');
$LastIdChar = $FindHyphen;
$MyOrderID = substr($VendorTxCode,0,$LastIdChar);

$StatusSave = $Status;

echo '  <FORM METHOD="POST" FORM NAME="GoToReturn" ACTION="../MXKart/return.php">'."\n";

echo ' <input type="hidden" name="response_code" value= "';
echo $Status;
echo '">'."\n";
echo ' <input type="hidden" name="order_number" value= "';
echo $MyOrderID;
echo '">'."\n";
echo ' <input type="hidden" name="secretword" value= "';
echo $secret_word;
echo '">'."\n";

//echo addslashes($ResultDetails);
echo ' <input type="hidden" name="response_reason_text" value= "';
echo $ResultDetails;
echo '">'."\n";
echo ' <input type="hidden" name="amount" value= "';
echo $Amount;
echo '">'."\n";
echo ' <input type="hidden" name="force" value= "';
echo $VendorTxCode;
echo '">'."\n";
$msg = "<br><strong>Getting payment result.... </strong> <br><br><h2 style=\"color:green;\">PLEASE WAIT AT THIS PAGE - do not close the page or move on. <br>There can be a delay of up to a minute so please be patient.</h2>";
echo $msg."\n"; 
    echo '</FORM>'."\n";

echo '<script language="javascript">'."\n";
echo 'document.forms[0].submit();'."\n";
echo '</script>'."\n";
?>

ФУНКЦИИ.php ---------------------

<?

$VendorName="redacted";

$EncryptionPassword="redacted"; //   LIVE  server destination

//************ NEW CRYPT STUFF COPIED FRON SAGEPAY KIT util.php
//DH added class definition as shown in stackoverflow page - trying to fix error when run, on line static private function etc
class DHclassInFunc{
/**
* PHP's mcrypt does not have built in PKCS5 Padding, so we use this.
*
* @param string $input The input string.
*
* @return string The string with padding.
*/

static protected function addPKCS5Padding($input)
{
$blockSize = 16;
$padd = "";

// Pad input to an even block size boundary.
$length = $blockSize - (strlen($input) % $blockSize);
for ($i = 1; $i <= $length; $i++)
{
$padd .= chr($length);
}

return $input . $padd;
}


/**
* Remove PKCS5 Padding from a string.
*
* @param string $input The decrypted string.
*
* @return string String without the padding.
* @throws SagepayApiException
*/
static protected function removePKCS5Padding($input)
{
$blockSize = 16;
$padChar = ord($input[strlen($input) - 1]);

/* Check for PadChar is less then Block size */
if ($padChar > $blockSize)
{
throw new SagepayApiException('Invalid encryption string');
}
/* Check by padding by character mask */
if (strspn($input, chr($padChar), strlen($input) - $padChar) != $padChar)
{
throw new SagepayApiException('Invalid encryption string');
}

$unpadded = substr($input, 0, (-1) * $padChar);
/* Chech result for printable characters */
if (preg_match('/[[:^print:]]/', $unpadded))
{
throw new SagepayApiException('Invalid encryption string');
}
return $unpadded;
}


/**
* Encrypt a string ready to send to SagePay using encryption key.
*
* @param  string  $string  The unencrypyted string.
* @param  string  $key     The encryption key.
*
* @return string The encrypted string.
*/
static public function encryptAes($string, $key)
{
// AES encryption, CBC blocking with PKCS5 padding then HEX encoding.
// Add PKCS5 padding to the text to be encypted.
$string = self::addPKCS5Padding($string);

// Perform encryption with PHP's MCRYPT module.
$crypt = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $string, MCRYPT_MODE_CBC, $key);

// Perform hex encoding and return.
return "@" . strtoupper(bin2hex($crypt));
}

/**
* Decode a returned string from SagePay.
*
* @param string $strIn         The encrypted String.
* @param string $password      The encyption password used to encrypt the string.
*
* @return string The unecrypted string.
* @throws SagepayApiException
*/

static public function decryptAes($strIn, $password)

{
echo '$strIn' . "  string in with @ should be here?";

$strIn = htmlspecialchars($strIn, ENT_COMPAT,'utf-8', true);

// HEX decoding then AES decryption, CBC blocking with PKCS5 padding.
// Use initialization vector (IV) set from $str_encryption_password.
$strInitVector = $password;

// Remove the first char which is @ to flag this is AES encrypted and HEX decoding.
$hex = substr($strIn, 1);

// Throw exception if string is malformed
if (!preg_match('/^[0-9a-fA-F]+$/', $hex))
{
//DH added section to print result of decryption onto page for debugging
//$hex = "pseudo hex";
//echo "throw error at line 188";
// echo $hex;

throw new SagepayApiException('Invalid encryption string');
}
$strIn = pack('H*', $hex);

// Perform decryption with PHP's MCRYPT module.
$stringReturn = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $password, $strIn, MCRYPT_MODE_CBC, $strInitVector);
return self::removePKCS5Padding($string);
}

}

/* The getToken function.                                                                                         **
** NOTE: A function of convenience that extracts the value from the "name=value&name2=value2..." VSP reply string **
**     Works even if one of the values is a URL containing the & or = signs.                                      */


function getToken($thisString) {
// List the possible tokens
$Tokens = array(
"Status",
"StatusDetail",
"VendorTxCode",
"VPSTxId",
"TxAuthNo",
"Amount",
"AVSCV2", 
"AddressResult", 
"PostCodeResult", 
"CV2Result", 
"GiftAid", 
"3DSecureStatus", 
"CAVV" );

// Initialise arrays
$output = array();
$resultArray = array();

// Get the next token in the sequence
for ($i = count($Tokens)-1; $i >= 0 ; $i--){
// Find the position in the string
$start = strpos($thisString, $Tokens[$i]);
// If it's present
if ($start !== false){
// Record position and token name
$resultArray[$i]->start = $start;
$resultArray[$i]->token = $Tokens[$i];
}
}

// Sort in order of position
sort($resultArray);

// Go through the result array, getting the token values
for ($i = 0; $i<count($resultArray); $i++){
// Get the start point of the value
$valueStart = $resultArray[$i]->start + strlen($resultArray[$i]->token) + 1;
// Get the length of the value
if ($i==(count($resultArray)-1)) {
$output[$resultArray[$i]->token] = substr($thisString, $valueStart);
} else {
$valueLength = $resultArray[$i+1]->start - $resultArray[$i]->start - strlen($resultArray[$i]->token) - 2;
$output[$resultArray[$i]->token] = substr($thisString, $valueStart, $valueLength);
}      

}

// Return the ouput array
return $output;

}

// Randomise based on time
function randomise() {
list($usec, $sec) = explode(' ', microtime());
return (float) $sec + ((float) $usec * 100000);
}


?>

Мне очень нужна помощь, чтобы решить проблему с кодомили я делаю ошибки в том, как я пытаюсь раскрыть значение, казалось бы, пустой строки, и поэтому делаю неверный вывод.

РЕДАКТИРОВАТЬ ВТОРНИК 18/12/18 ---------------

Я добился определенного прогресса в том, что обнаружил причину, по которой $ _GET на странице "complete.php" вообще не получал никакого значения отURL страницы в ответном ответе, отправленном Sagepay.

Это произошло потому, что настройки php-сервера хост-платформы по умолчанию принимали до 512 символов в URL;Мне удалось изменить это до 2000 символов (см. Более поздние комментарии), что устранило проблему;фатальная ошибка исчезла, но расшифровка все равно не удалась.Однако теперь я мог отлаживать, потому что теперь у функций были данные для работы, и я мог отслеживать значения в разных частях скрипта.

К сожалению, теперь я совершенно не понимаю, что такое вывод отладки - потому что в первомместо, где я вообще не понимаю функции дешифрования, несмотря на поиск помощи.

Вывод выглядит разумным, если считать строку дешифрования

$hex = substr($strIn, 1);

в "functions.php", которая возвращает содержимое входящего крипта после удаления символа "@".

Но как только скрипт переместится в строку

$strIn = pack('H*', $hex);

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

Ссылка на изображение скриншота символов

Символы, которые отображаются в виде вопросительного знака внутри черного ромба на изображении, указанном выше, являются некоторыми из них:

e?g! xh) ̓G] / | C Ֆ '#] Ws ܀͝ Y? Ig @ uQ * ߎ @ KѦ

, когда я фиксирую текст с помощью быстрого выбора и копирования, а затем перехожу в текстовый редактор.

Но я не знаю, ограничиваются ли символы мусора теми, которые вставляются функцией «pack», и поэтому несоответствие кодировки ограничивается только функцией, а не является общей проблемой кодирования сотправка и возврат данных в и из Sagepay.

К сожалению, я довольно удивлен после долгого и долгого процесса путаницы (пробования всего) с кодировками, поскольку веб-сайт перемещается на новый хост, изменяя сценарии, заголовки, явные операторы кодированиякодировки файлов сценариев, объявления кодировки php.ini, кодировки базы данных Mysql и т. д. от старого (в основном) ISO до utf_8.В основном просто пытаюсь избавиться от аномальных символов, которые на самом деле видны пользователям на сайте.Разрежьте один, и вы получите другой вместо него.

Так что теперь моя голова мучается при мысли, как отследить, как с этим справиться, если это чисто проблема кодирования.Sagepay сказал мне, что форма 3 совместима с юникодом, но я знаю, что это противоречит другим советам, которые я получил, и действительно мой собственный опыт, связанный с изменениями предыдущих версий php и sagepay у моего старого хостинг-провайдера.

Невозможно изменить основы веб-сайта и базы данных на ISO, но если это так, я должен как-то позволить Sagepay в одиночку поужинать в ISO, как я могу сделать это проще всего?- Какие предметы первой необходимости?

Передача в Sagepay прекрасно работает под utf-8, но нужно ли мне изменить это, чтобы отправить в ISO, прежде чем я смогу указать ISO для возврата, в чем и заключается настоящая проблема? И как лучше использовать этот ISO в любом случае - только для Sagepay - учитывая, что кодирование часто кажется «не прилипающим», полем битвы веб-технологий, влияющих на кодирование.

С другой стороны, было бы замечательно, если бы это была просто функция 'pack', которая безнадежна; и если есть простой способ или место, чтобы это исправить. Может кто-нибудь посоветовать, пожалуйста.


1 Ответ

0 голосов
/ 19 декабря 2018

Как реализовано в драйвере Omnipay Sage Pay (Omnipay Common v3.x)плагины на основе этого старого кода) использовать.Вместо этого используйте openssl функции.

Все, что будет возвращено в $data, будет ASCII (оно будет возвращать только четко определенные идентификаторы и коды, а не введенные пользователем данные).Я не верю, что он будет содержать какие-либо расширенные символы ASCII, поэтому может рассматриваться как UTF-8 без какого-либо преобразования при желании.

...