Issues with PayPal Pro Code

We're been running into this problem randomly and today just discovered what has been happening. Even though we are not using any AVS verification in our PayPal Fraud filters, we are getting failed orders with the “Payment Processor Response” of “AVS Verification failed”. We thought this was actually coming from PayPal, but as it turns out the order is successfully processed, the money is taken from the credit card, but CScart shows the order as failed. The customer them tries the order multiple times and we bill their card over and over.



It seems to only happen when the code in paypal_pro.php does not find a match for AVS code. There is an array of codes from A-Z (some missing). If you look up the possible AVS responses from banks, all 26 letters are used, but the module in CScart is missing about 8. For example the letter “M”. I believe this is the suspect code that is causing the failure, in combination with the array of codes at the top:


if (preg_match('!]+>([^>]+)!', $response_data, $matches)) {
$paypal_response['avs_code'] = $matches[1];
if (empty($processor_error['avs'][trim($paypal_response['avs_code'])])) {
$paypal_response['order_status'] = 'F';
$paypal_response['reason_text'] .= 'AVS Verification failed'; // FIXME!!!
}




This is the array at the top:


$processor_error['avs'] = array(
"A" => "Address Address only (no ZIP)",
"B" => "International 'A'. Address only (no ZIP)",
"C" => "International 'N'",
"D" => "International 'X'. Address and Postal Code",
"E" => "Not allowed for MOTO (Internet/Phone) transactions",
"F" => "UK-specific X Address and Postal Code",
"G" => "Global Unavailable",
"I" => "International Unavailable",
"N" => "None",
"P" => "Postal Code only (no Address)",
"R" => "Retry",
"S" => "Service not Supported",
"U" => "Unavailable",
"W" => "Nine-digit ZIP code (no Address)",
"X" => "Exact match. Address and five-digit ZIP code",
"Y" => "Address and five-digit ZIP",
"Z" => "Five-digit ZIP code (no Address)"
);




I don't quite understand how the match or no match controls a failed order, so my question is could I just add the missing responses to the array and this would fix the issue? For example for the missing “M” I would add:


"M" => "Street address and postal code match.",



The other issue is that most of the codes are incorrect. For example “D” is NOT an international AVS response. It's for a domestic card. Address verification service - Wikipedia

Same problem here!



We've had numerous successful payments flagged as failed - and numerous people pay for the same order more than once…





A fix would be nice.



CSCart 2.1.4 Pro

Anyone?

You've done a good job of characterizing a potential problem. However, it sounds like you are guessing on the responses.



Why don't you add code to log the responses (or look at your Administration/Logs for http requests) and see what the actual response is before you start adding error codes. You might also want to get the spec from paypal about what the possible values are for the xml tag 'AVSCode'. You might find that the different paypal method have different responses.

[quote name='tbirnseth' timestamp='1321852193' post='126413']

Why don't you add code to log the responses (or look at your Administration/Logs for http requests) and see what the actual response is before you start adding error codes. You might also want to get the spec from paypal about what the possible values are for the xml tag 'AVSCode'. You might find that the different paypal method have different responses.

[/quote]



Everything I posted is based on actual responses. I have checked the logs and spoken in-depth with my PayPal account management team about this problem. They were the ones who directed me to the wiki page with the responses they are expecting. CS-Cart has implementing them incorrectly and missed quite a few as well. Right now I'm just trying to figure out if the suggested solution will correct the problem.

Edit: removing my response since it's not clear to me what they are trying to accomplish by looking at an AVS response code and then generating a status of Fail if the response code can't be found in the list of avs processor errors. It is not clear where the account for AVS success.

[quote name='tbirnseth' timestamp='1321859833' post='126417']

Edit: removing my response since it's not clear to me what they are trying to accomplish by looking at an AVS response code and then generating a status of Fail if the response code can't be found in the list of avs processor errors. It is not clear where the account for AVS success.

[/quote]



That's what I'm trying to find out. I'm not really clear myself why they automatically assume a failed order just becuase the AVS response is not in their list. Not to mention the list of responses that have are wrong anyway.

My supposition would be that regardless of what they've named them as, the AVS codes in the processor_error['avs'] array are in fact valid AVS responses to be handled by the application. I think it's bad to assume that a response not in the list is an automatic fail. But I didn't write the code and I don't have access to paypal pro specifications about what they really return for a fully matched AVS response.



In Anet, a valid AVS response is a 'Y' (you configure what's acceptable or not on the Anet site). But since there's no standardization around AVS responses, it is up to the developer to determine whether to fail the order based on a particular AVS response (normally it would be a Decline rather than a Fail).



You could always change it to set the 'order_status' to 'O' instead and change the message to 'Unknown AVS response ('M')'. This would alert the admin of the store that an order did not succeed but won't make it 'Processed' either. They'd have to take that step manually if the unknown response was acceptable to them.

[quote]

My supposition would be that regardless of what they've named them as, the AVS codes in the processor_error['avs'] array are in fact valid AVS responses to be handled by the application. I think it's bad to assume that a response not in the list is an automatic fail. But I didn't write the code and I don't have access to paypal pro specifications about what they really return for a fully matched AVS response. [/quote]



I made this assumption as the only orders that do fail are the ones without a value in the array.


[quote]

In Anet, a valid AVS response is a 'Y' (you configure what's acceptable or not on the Anet site). But since there's no standardization around AVS responses, it is up to the developer to determine whether to fail the order based on a particular AVS response (normally it would be a Decline rather than a Fail). [/quote]



If I'm reading the code correctly, it seems like if there is no match in the array it fails the order. Really CSC should have an option to turn off AVS processing if required as with PayPal Pro accounts you can subscribe to AVS checking as part of their fraud filter add-on which is a lot more robust than these few lines of code. I have AVS turned off as we process 50% international orders and most banks don't even send back a proper response anyway. It really only works in North America.


[quote]

You could always change it to set the 'order_status' to 'O' instead and change the message to 'Unknown AVS response ('M')'. This would alert the admin of the store that an order did not succeed but won't make it 'Processed' either. They'd have to take that step manually if the unknown response was acceptable to them.

[/quote]



Yeah that's probably a good idea. Although from what I mentioned above, I think the only reason it does fails is becuase they have not included all of the possible AVS responses in their array. My account manager told me there are standard codes that all banks who check AVS use. Which is what what wiki was. At the very least I know the responses built into the CSC code is wrong because they send an international AVS response sometimes on domestic orders. Whereas the actual response code that PayPal sends back is correct and matches the wiki description for the order.

I don't know about “all the banks use”… My experience is that banks are more NIH (Not Invented Here) than most businesses.



I do know that processors do not necessarily return the same codes. For instance, what passes/fails is set on the Anet response and they simply return Y or N for the AVS based on whether it passed what you have configured or not.



So I wouldn't count on a Wiki, I would ask your PayPal rep to give you Paypal documentation about what the possible return values are for the AVSCode xml tag value. If he can't point you to development specifications that describe it, then I sure wouldn't rely upon a Wiki listing.

[quote name='tbirnseth' timestamp='1321999746' post='126565']

I don't know about “all the banks use”… My experience is that banks are more NIH (Not Invented Here) than most businesses.



I do know that processors do not necessarily return the same codes. For instance, what passes/fails is set on the Anet response and they simply return Y or N for the AVS based on whether it passed what you have configured or not.



So I wouldn't count on a Wiki, I would ask your PayPal rep to give you Paypal documentation about what the possible return values are for the AVSCode xml tag value. If he can't point you to development specifications that describe it, then I sure wouldn't rely upon a Wiki listing.

[/quote]



The responses on Wiki are standard. They are simply stating a one letter code for what the exact match and location was for AVS. How those responses are dealt with are cart, payment module or payment processor specific issues. PayPal's own fraud filters can be configured to deal with how a match, partial match or no match are dealt with. CSC however has decided to implement their own which echos their own message for the one letter response. The echos they make are incorrect and they are also failing orders which do not match a one letter code in their array. My fix will be:


  1. Add the missing letters in the array
  2. Correct the AVS echos that CSC has set up to match what they really mean. I know for a fact they are wrong.
  3. Change the order status to O and not F