Description
Hello,
I faced an error using your module which crashes the checkout behavior when using a multibyte char in the address field.
The error was the checkout javascript being broken with the message :
Uncaught URIError: malformed URI sequence
jQuery 2
isPlaceOrderActionAllowed ..../Lyranetwork_Payzen/js/view/payment/method-renderer/payzen-oney.min.js:1
wrapSuper ....mage/utils/wrapper.min.js:3
initialize
The cookie value being encoded via url encode method, the cookie becomes corrupted once the payzen_oney_error is set into it.
The error (and it's resolution) is quiet easy once you found it:
// In https://github.com/lyra/plugin-magento/blob/master/Helper/Checkout.php
[...]
private function checkFieldValidity($field, $regex, $fieldName, $addressType, $mandatory = true)
{
// Error messages.
$invalidMsg = 'The field %1 of your %2 is invalid.';
$emptyMsg = 'The field %1 of your %2 is mandatory.';
if ($mandatory && ! $field) {
$this->setErrorMsg($emptyMsg, $fieldName, $addressType);
}
if ($field && ! preg_match($regex, $field)) {
// Delete valid characters to retrieve invalid ones.
$replaceRegex = preg_replace("/{(.*?)}/", '', $regex);
$replaceRegex = str_replace(array('^', '$'), '', $replaceRegex);
$invalidChars = preg_replace($replaceRegex, '', $field);
if (empty($invalidChars)) {
$this->setErrorMsg($invalidMsg, $fieldName, $addressType);
return;
}
// ======================================================= Error happens here :
// If the remaining string contains multibyte characters, this str_split will split them in 2
$arr = str_split($invalidChars);
$invalidChars = '';
foreach ($arr as $char) {
$invalidChars .= '<b>' . $char . '</b> ';
}
$this->setErrorMsg($invalidMsg, $fieldName, $addressType, $invalidChars);
}
}
For example, we had a customer having the following characters in its address (quiet common in France) :
n°123 Test Street
The degree sign is a problem because it's encoded C2 B0 in UTF8. So the str_split will split this into 2 invalid codes (C2 and B0)
To validate the behavior, you can run the following code :
$addressField = "n°123 Test Street";
$replaceRegex = preg_replace("/{(.*?)}/", '', "#^[A-Z0-9ÁÀÂÄÉÈÊËÍÌÎÏÓÒÔÖÚÙÛÜÇ/ '.,-]{1,127}$#ui");
$replaceRegex = str_replace(array('^', '$'), '', $replaceRegex);
$invalidChars = preg_replace($replaceRegex, '', $addressField);
echo $invalidChars . "\n";
var_dump(str_split($invalidChars));
var_dump(array_map(function ($char) { return bin2hex($char);}, str_split($invalidChars)));
var_dump(mb_str_split($invalidChars));
var_dump(array_map(function ($char) { return bin2hex($char);}, mb_str_split($invalidChars)));
/* Result here :
°
array(2) {
[0]=>
string(1) "�"
[1]=>
string(1) "�"
}
array(2) {
[0]=>
string(2) "c2"
[1]=>
string(2) "b0"
}
array(1) {
[0]=>
string(2) "°"
}
array(1) {
[0]=>
string(4) "c2b0"
}
*/
Correction is quiet simple as mb_str_split() exists in PHP codebase.
I'll open the PR directly.
Kind Regards,
Baptiste