Magento only stores shipping address firstname on Paypal Express orders
> Magento and Paypal Express combine to have a difficulty with first and last names. So you end up with the shipping address only having the firstname filled in and the last name empty.
I did some research and found most of the answer herehttps://magento.stackexchange.com/questions/99884/paypal-express-firstname-and-lastname-instead-of-shiptoname, so thanks to https://magento.stackexchange.com/users/5288/loeffel.
It seems to be that Magento processes the response from Paypal the SHIPTONAME value being firstname lastname. In app/code/core/mage/Paypal/Model/Api/Nvp.php in the function _exportAddressses
Thats ok mostly but it causes some issues if your shipper requires lastname and firstname so can be a bit annoying.
So you can change it if you need to.
I've added a function splitNameIntoFirstAndLast to that file to split the name eg Colin Smith to 'firstname' = Colin, 'lastname' = Smith. I can write a function given the customers of the store that had this problem ok working out about 98% of them. Probably because the customers mostly have European names. I think you would have to rethink this if your customers were from different places say Chinese or Vietnamese for example.
The other file you have to change is app/code/core/mage/Paypal/Model/Express/Checkout.php which just comments out this line in the function returnFromPaypal which makes that lastname editable.
The function I wrote for splitting names looks like this. I think this is the bit you would want to change depending on your customers. I expect I'll tweak this over time.
This is on Magento 1.9.3.4 The query I used to build a list of names from your database to test your name splitting function is
I'm getting about 1.5% with 'Empty' as lastname.
I did some research and found most of the answer herehttps://magento.stackexchange.com/questions/99884/paypal-express-firstname-and-lastname-instead-of-shiptoname, so thanks to https://magento.stackexchange.com/users/5288/loeffel.
It seems to be that Magento processes the response from Paypal the SHIPTONAME value being firstname lastname. In app/code/core/mage/Paypal/Model/Api/Nvp.php in the function _exportAddressses
$shippingAddress->addData(array(
'firstname' => $data['SHIPTONAME'],
));
Thats ok mostly but it causes some issues if your shipper requires lastname and firstname so can be a bit annoying.
So you can change it if you need to.
$nameParts = $this->splitNameIntoFirstAndLast($data['SHIPTONAME']);
$shippingAddress->addData(array(
'firstname' => $nameParts['firstname'],
'lastname' => $nameParts['lastname']
));
I've added a function splitNameIntoFirstAndLast to that file to split the name eg Colin Smith to 'firstname' = Colin, 'lastname' = Smith. I can write a function given the customers of the store that had this problem ok working out about 98% of them. Probably because the customers mostly have European names. I think you would have to rethink this if your customers were from different places say Chinese or Vietnamese for example.
The other file you have to change is app/code/core/mage/Paypal/Model/Express/Checkout.php which just comments out this line in the function returnFromPaypal which makes that lastname editable.
$shippingAddress->setLastname(null);
The function I wrote for splitting names looks like this. I think this is the bit you would want to change depending on your customers. I expect I'll tweak this over time.
function splitNameIntoFirstAndLast($originalName){
$debug = true;
/* if we have debug on we are testing and count failures
* about 1.48% have empty last names in past 7308 with no last name in db
*/
if($debug){
global $count;
}
$titles = ['Dr','Dr.','Mrs','Mrs.','Mr','Mr.','Ms.', 'Ms', 'Miss.',
'Miss'];
$name = trim($originalName);
/* one bloke had name Colin Smith */
$name = str_replace(' ',' ', $name);
/* if the name begins with a . like '. colin smith' */;
$name = preg_replace('/^\. /', '', $name);
/* if the name ends with a . like 'colin smith.' */;
$name = preg_replace('/\.$/', '', $name);
/* replace multiple whitespaces with one people like
colin smith */
$name = preg_replace('/(\s){1,}/',' ', $name);
if(strpos($name,',') !== false){
/*
if they enter their name with commas in then its probably
best to leave it,
we could reverse it but its not always
surname, firstname
*/
//$name = trim(implode(' ', array_reverse(explode(',', $name))));
}
$foundTitle = $cofound = false;
$nameParts = explode(' ', $name);
/* colin smith C/O Some Company */
if(stripos($name,'C/O') !== false){
$nameParts = preg_split('/C\/O/i', $name);
$nameParts[1] = substr($name, stripos($name,'C/O'),3).$nameParts[1];
$cofound = true;
}
$currentNamePartIndex = 0;
$firstName = $nameParts[$currentNamePartIndex];
if(count($nameParts) > 2 && in_array($nameParts[0], $titles)){
$foundTitle = true;
$currentNamePartIndex = 2;
$firstName = $nameParts[1];
}else if(count($nameParts) > 2 &&
strlen($nameParts[$currentNamePartIndex]) == 1){
$currentNamePartIndex = 0;
$firstName = '';
while(strlen($nameParts[$currentNamePartIndex]) == 1){
$firstName .= $nameParts[$currentNamePartIndex].' ';
$currentNamePartIndex++;
}
$currentNamePartIndex-1;
}else{
$currentNamePartIndex = $currentNamePartIndex+1;
}
$lastName = implode(' ',array_slice($nameParts,$currentNamePartIndex));
/* odds and sods */
/* camel case like ColinMcSomething */
if($lastName == '' && mb_strtoupper($firstName, 'utf-8') != $firstName){
$nameParts = preg_split('/(?=[A-Z])/', $firstName, -1,
PREG_SPLIT_NO_EMPTY);
if(count($nameParts) > 1){
$firstName = $nameParts[0];
$lastName = implode('', array_slice($nameParts,1));
}
}
/* colin@twit.com */
if($lastName == '' && strpos($firstName,'@') !== false){
$nameParts = explode('@', $firstName);
$firstName = $nameParts[0];
$lastName = implode('', array_slice($nameParts,1));
}
/* colin no last name */
if($lastName == ''){
$lastName = 'Empty';
if($debug){
$count++;
}
}
$parts = array($originalName, $firstName, $lastName);
return array('firstname' => $parts[1], 'lastname' => $parts[2]);
}
This is on Magento 1.9.3.4 The query I used to build a list of names from your database to test your name splitting function is
SELECT DISTINCT(CONCAT('"',prefix_sales_flat_order_address.firstname,'",'))
FROM prefix_sales_flat_order_address
JOIN prefix_sales_flat_order
on (prefix_sales_flat_order.shipping_address_id = prefix_sales_flat_order_address.entity_id AND prefix_sales_flat_order_address.address_type = 'shipping')
or (prefix_sales_flat_order.billing_address_id = prefix_sales_flat_order_address.entity_id AND
prefix_sales_flat_order_address.address_type = 'billing')
WHERE
prefix_sales_flat_order.created_at > '2017-01-01 00:00:00'
AND lastname is null
AND prefix_sales_flat_order_address.address_type = 'shipping';
I'm getting about 1.5% with 'Empty' as lastname.
/ Adam