mike182uk / paypal-ipn-listener

A PayPal IPN (Instant Payment Notification) listener for PHP
MIT License
89 stars 31 forks source link

IPN sandbox returns invalid 100% of the time #28

Closed Swader closed 8 years ago

Swader commented 8 years ago

When using this package, I get INVALID as a response 100% of the time. I have followed the debugging steps, and made sure that I'm calling the correct sandbox URL (that's automatic with this package) and that I'm sending the exact same params in the exact same order back, as per the docs.

If anyone is using this and getting valid responses in local development mode (I'm using Ngrok to pipe my localhost as an endpoint for IPN to talk to), I'd appreciate some tips and next steps.

This might have something to do with PayPal going SHA256, but I have no idea how to directly debug this. Info that might be relevant: https://www.paypal-knowledge.com/infocenter/index?page=content&id=FAQ1766&expand=true&locale=en_US

mablae commented 8 years ago

Hey @Swader

I had similar issues when testing the sandbox. For me the issue was, that the paypal sandbox has sent its IPNs in windows-1252 by default. After overidering the the charset in the initial payment request to UTF-8 it was validated correctly. I was also using ngrok. Maybe ngrok is the source of the error? I never thought about that as error source until now.

There is a setting in the paypal developer console, where you can set an default charset but it only affects production environment it seems.

We use this lib in production and it processes hundreds of IPN every day.

Hope this helps.

Swader commented 8 years ago

Hey @mablae thanks, that sounds like it's going in the right direction. When you say you changed the charset, where did you change it exactly and how, without tweaking the internals of this package?

mablae commented 8 years ago

Put the charset parameter in the initial payment request where the checkout process redirects to paypal.

https://developer.paypal.com/docs/classic/paypal-payments-standard/integration-guide/Appx_websitestandard_htmlvariables/#technical-variables

This is outside of the Scope of this IPN listener lib. But paypal uses the charset parameter in the IPN responses, too.

Swader commented 8 years ago

Ah, but there is no way to edit the charset value in the IPN simulation, and it doesn't seem to get sent along with the other, standard fields? Did you end up being able to test with the IPN simulator in the end?

I now know it's off topic and out of scope, and I'll close this asap, just bear with me please as I'd really love to get this over with.

mablae commented 8 years ago

How do you initiate the IPN beeing sent? Is that your custom codebase? Or another third party lib?

Yes, In the end I was able to test it successfully. Once it worked I never touched it again 😄 Please also note, that this library does not handle sending a proper 200: Success Http Status Code to paypal after the validating the IPN. This is needed to convince paypal, the IPN has been processed successfully.

Swader commented 8 years ago

How do you initiate the IPN beeing sent?

I use the IPN Simulator

this library does not handle sending a proper 200: Success Http Status Code to paypal after the validating the IPN

Why not? Shouldn't it?

mablae commented 8 years ago

I use the IPN Simulator Ah, now I understand. I never tried that thing since I needed to test the whole checkout cycle anyway.

Why not? Shouldn't it? It is called Listener not Responder :smile:

Swader commented 8 years ago

Ah, now I understand. I never tried that thing since I needed to test the whole checkout cycle anyway.

Makes sense why it ended up working for you in the end :) It's ok, I think I finally found some other people having the same problem.

It is called Listener not Responder 😄

Touche! :)

mablae commented 8 years ago

PayPals "Developer Experience" and Docs is real crap compared to the amount of money they do with their product btw. 😄

It's their crap. And thousands of coders like you and me are forced to work with that :smile:

overint commented 8 years ago

I'm having the same problem. Unfortunately I cannot set the charset, as I am trying to track payments received which include direct send-money payments. These come through with the same problematic windows-1252 charset. Is there any way we can fix this inside the PHP library?

overint commented 8 years ago

I ended up writing my own library, which can be found here: https://github.com/overint/php-paypal-ipn

It's not as complex as this one, but it is simple and easy to use :)

mablae commented 8 years ago

@overint It was already fixed.

thanter commented 7 years ago

It seems I am facing a similar issue. I am in sandbox mode and when I am testing with the IPN Simulator the messages are valid. When I am using my application though I always get INVALID messages. I am using the rest api to create/cancel billing agreements (they are created sucessfully). I have changed the charset in settings, as mentioned in other posts, but it didn't fix the problem. Any suggestions?

thanter commented 7 years ago

@mablae Following my own question, I changed back the 'rawurlencode' to 'urlencode', as it was before #29 and it fixed my issue. Maybe paypal changed something on their own end. If someone can verify this maybe undo #29

overint commented 7 years ago

I authored my own library which makes sure the date is encoded correctly, and there's a copy of the class in official paypal IPN sample repo as well, so if the authors want to use the logic that checks the date encoding they are free to use the code. https://github.com/paypal/ipn-code-samples/tree/master/php

mike182uk commented 7 years ago

@thanter Would you mind opening a new issue for this? Your problem seems a little different to this (although its related). The original issue here was that the listener would fail 100% of the time, where as it sounds like you aren't having that problem (as its working in sandbox mode), which is strange. To help with debugging, would you be able to compare the encoded data you received to the encoded data we send back so we can see where the difference is?

@overint Why did you end up creating your own lib? What did you fix in your lib that we didn't resolve here?

mablae commented 7 years ago

There are two methods: Using the lib's own request decoder or pass an already decoded array of values.

2nd is what I use and works (with symfony parsing the request) - So I guess the error may be environment dependent when decoding the plain input.

We should and CAN fix this. Maybe it is related to date.timezone setting in php.ini?

sebdesign commented 7 years ago

Hello, I'm using the v7.0.1 (i'm on PHP 5.5) but I'm always getting an invalid response on the production URL. The issue appeared a few months ago. I have set up the encoding to utf-8 on the merchant profile, and I'm sending a hidden input <input type="hidden" name="charset" value="utf-8"> with the payment.

While debugging the incoming request data in the controller which is handling the IPN, there is a charset field with a value UTF-8.

I'm not sure how to proceed further to find the root of the issue. Could you point me to some direction?

mike182uk commented 7 years ago

@sebdesign Just to be clear, is everything working correctly for you in sandbox mode? To help with debugging, would you be able to compare the encoded data you received to the encoded data we send back so we can see where the difference is?

@mablae I some how missed your last comment. When you say:

We should and CAN fix this. Maybe it is related to date.timezone setting in php.ini?

Im not quite sure what we should be fixing 😕

Swader commented 7 years ago

Yeah, PayPal's dev team isn't being too helpful. What's even weirder, mine now works just fine. It'd be cool if we could compare implementations and list out the system specs running each installation - which PHP version, all php.ini settings, an output of $_SERVER, etc?

sebdesign commented 7 years ago

Hi @mike182uk ,

I'm investigating the incoming input stream. It seems paypal is sending values with spaces as + instead of %20. As per the documentation, rawurldecode() cannot decode + to spaces.

sebdesign commented 7 years ago

Although some other characters (like @) are encoded according to RFC 3986.

mike182uk commented 7 years ago

@sebdesign can you try using v6.0.0 of the library and see if your still having the same problem?

sebdesign commented 7 years ago

I just made a payment using v6.0.0 and the response is still invalid. Maybe it has something to do with the payment_date field? This is the official example: https://github.com/paypal/ipn-code-samples/blob/master/php/PaypalIPN.php#L81

sebdesign commented 7 years ago

I just forked this repo and will try to implement this for v7.0. I'll let you know how it goes.

sebdesign commented 7 years ago

After some investigation, I found that the payment_date doesn't have any + character in my case, so there's no need to override this parameter, although that would be advisable.

I did play around with the IPN simulator, and I'm getting a successful message IPN was sent and the handshake was verified. every time. BUT, on my end I'm always getting an INVALID response for the those simulations.

So maybe this package is working as intended, but something else is going on. My server is running on CentOS 5, which doesn't support TLS 1.2. I have manually updated the curl library and the root certificate, and Guzzle returns a successful response.