thephpleague / omnipay-sagepay

Sage Pay driver for the Omnipay PHP payment processing library
MIT License
54 stars 78 forks source link

getting error when I submit billing info #20

Closed funju47shin closed 9 years ago

funju47shin commented 10 years ago

If I don't submit BillingAddress2, it keeps showing error invalid BillingCity.

I think if it cannot get a value from $card, for example, $card->getBillingAddress2() returns null, the next parameter BillingCity gets something wrong. so, it should be assigned blank string like '' explicitly if it doesn't have any value.

judgej commented 10 years ago

Don't underestimate how screwy SagePay's errors can be. Sometimes the error can be directed at the completely wrong field. If you send a blank ('') BillingState with a non-US country, SagePay will tell you that the country is missing or invalid.

The documentation is also not clear:

"All mandatory fields must contain a value, apart from the postcode. The postcode can be blank for countries that do not have postcodes ( e.g. Ireland) but is required in all countries that do have them. Providing a blank field when information is required will cause an error."

The postcode is listed as "mandatory=yes", and yet it's not mandatory. The address 2 is listed as "mandatory=no" except that reading between the lines, it may need to be set to something non-empty if it is supplied at all.

I'm rambling. In short, (generally) if a field is null or blank, then don't sent it to SagePay at all through the API.

Do also be aware that SagePay can reject a payment request for several dozen address-related issues, such as quotes in names, hyphens in postcodes - all sorts of things that other payment gateways will accept as perfectly reasonable. Either allow the user to change their address details until it goes through (SagePay Server or SagePay Direct), or heavily filter the address to ensure it is guaranteed to be a valid format, even if it ends up scrambled, and the user can make adjustments on the SagePay site (assuming you are using SagePay Server).

Sorry - that doesn't really fix your problem, but is just a little background information.

judgej commented 9 years ago

Is this still a problem?

Doing a PAYMENT without setting the BillingAddress2 will submit this (some bits cropped out):

VPSProtocol=3.00&TxType=PAYMENT&Vendor=academe&AccountType=E&Description=xxxxx&Amount=10.01&Currency=GBP&VendorTxCode=tx-code-3899194074&ClientIPAddress&ApplyAVSCV2=0&Apply3DSecure=0&ReferrerID=3F7A4119-8671-464F-A091-9E59EB47B80C&BillingFirstnames=Joe&BillingSurname=Bloggs&BillingAddress1=Billing%20Address%201&BillingAddress2&BillingCity=Billing%20City&BillingPostCode=412&BillingState=&BillingCountry=GB&BillingPhone=01234%20567%20890&DeliveryFirstnames=Joe&DeliverySurname=Bloggs&...&CustomerEMail=test%40example.com&NotificationURL=...&Profile

Note BillingAddress2 is in there, without a value set. SagePay protocol v3.00 seems to have no problem with this, on the test instance at least. It is possible live has an issue with this or protocol v2.23 did not read the POST data properly.

If I set $card->setBillingAddress2 = '';

then Guzzle posts a subtly different string by putting a "=" after BillingAddress2. SagePay test instance v3.00 treats this in exactly the same way.

I have not tried this on SagePay live though.

judgej commented 9 years ago

Guzzle docs here says:

http://guzzle.readthedocs.org/en/latest/quickstart.html

// Setting a value to false or null will cause the "=" sign to be omitted
$query['empty'] = null;
echo $query;
// foo=bar&baz=bam&empty

The BillingAddress2 parameter is always being sent, but Guzzle will add an "=" on the end or not, depending on whether it is null or an empty string.

judgej commented 9 years ago

This is an interesting read:

http://stackoverflow.com/questions/4557387/is-a-url-query-parameter-valid-if-it-has-no-value

The name=value pair format of the parameters is defined by HTML, not HTTP. It is possible that the ASP platform SagePay use (or used to use) does not recognise name and name= as being equivalent. Guzzle makes the assumption that they are, but there are no standards that state they are the same. TIL.

So:

judgej commented 9 years ago

This is where Guzzle formats the parameters. It adds a "=" only if the parameter is not null:

https://github.com/guzzle/guzzle/blob/1330e3a1fe1979ccd6550722091d7f94a30838c8/src/Query.php#L86

That throws the first option out.

judgej commented 9 years ago

And here is a SO answer that confirms ASP did not parse parameters without an "=", at least not in a consistent way:

http://stackoverflow.com/questions/3130541/query-string-parameters-with-no-values

SagePay up to at least v2.23 used to run on ASP.