MorayJ has asked for the wisdom of the Perl Monks concerning the following question:
Is anyone using Dancer2 with paypal's IPN?
Paypal have an outdated perl script in their examples which makes it a bit difficult https://github.com/paypal/ipn-code-samples
Also, it's not designed for Dancer2 and I'm hoping I'm missing some obvious way of doing it with Dancer2 without having to call in other modules
Paypal's description of IPN is here https://developer.paypal.com/docs/classic/ipn/integration-guide/IPNImplementation/
The idea, as I understand it, is that PayPal sends me a post request with all the details of the sale as key/value pairs
I then need to acknowledge receipt by sending a blank response
Then I need to post back the key/value pairs they sent me with cmd=_notify-validate& prefixed to the front
They then send me a response telling me whether it is VERIFIED or INVALID (words which are the sole content of their next post).
Using their simulator https://developer.paypal.com/developer/ipnSimulator/ (you must have a developer account to use it), I am told "IPN was sent and the handshake was verified."
The requirement for this seems to be sending back the empty response - a script with just that in gets the same result.
However, even though I think I'm sending back their values identically (with cmd=_notify-validate& prefixed), I seem not to be as I am getting the result as INVALID
I'm not sure if I'm even doing the right thing by invoking LWP here
If anyone can give me a nudge to get me off the bank here, that would be really appreciated
Thanks
MorayJ
use Dancer2; use Dancer2::Plugin::Database; use Template; use LWP::UserAgent 6; use Data::Dumper; use Net::SSLeay post '/cgi-bin/paypal.cgi' => sub { my $return_query = request->body; debug request; $return_query = "cmd=_notify-validate&" . $return_query; # post back to PayPal system to validate my $ua = LWP::UserAgent->new( ssl_opts => { verify_hostname => 1 } ); +#ssl_opts => { verify_hostname => 1 } my $req = HTTP::Request->new('POST', 'https://www.sandbox.paypal.com/c +gi-bin/webscr'); $req->content_type('application/x-www-form-urlencoded; charset=UTF- +8'); $req->header(Host => 'www.paypal.com'); $req->content("\n\n"); my $res = $ua->request($req); debug "First response: " $res; $req->content($return_query); $res = $ua->request($req); debug "Second response: " . Dumper $res; my %variable; foreach my $key (keys params) { my $value = params->{$key}; $value =~ tr/+/ /; $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg; $variable{$key} = $value; } # assign posted variables to local variables my $item_name = $variable{'item_name'}; my $item_number = $variable{'item_number'}; my $payment_status = $variable{'payment_status'}; my $payment_amount = $variable{'mc_gross'}; my $payment_currency = $variable{'mc_currency'}; my $txn_id = $variable{'txn_id'}; my $receiver_email = $variable{'receiver_email'}; my $payer_email = $variable{'payer_email'}; if ($res->is_error) { debug "It's an error"; # HTTP error } elsif ($res->content eq 'VERIFIED') { debug "$payment_status"; # check the $payment_status=Completed # check that $txn_id has not been previously processed # check that $receiver_email is your Primary PayPal email # check that $payment_amount/$payment_currency are correct # process payment } elsif ($res->content eq 'INVALID') { debug "It's invalid"; # log for manual investigation } else { debug "It's an error"; # error }
EDIT: I left this for some time to try not to get into knots. And now it seems to work. As I don't think I've changed the code, I *believe* that I must have not put https in the notify_url setting on paypal. I'm guessing I had assumed that it would be fine as my server resolves to https.
So, this is probably nothing to do with Dancer which seems to work as expected (or perl) and is me doing a settings error with paypal
But there is some very useful info about working with paypal and perl below, so not totally wasted. Thank you
|
|---|