Jim Rey wrote:
> Hi
> 
> I have tried a simple experiment now with only the following lines in my
> HTML::Mason file which is called by PayPal after making a successful
> sandboxed payment:
> 
> <%flags>
> inherit=>undef
> # To sidestep the parameter processing in my autohandler.
> </%flags>
> 
> <%init>
> use Business::PayPal::IPN;
> $Business::PayPal::IPN::GTW = '
> https://www.sandbox.paypal.com/cgi-bin/webscr ';
> my $ipn = Business::PayPal::IPN->new();
> if ($ipn) {
>     print "Content-type: text/plain\n\nipn=yes\n";
> } else {
>     print "Content-type: text/plain\n\nipn=no\n";
> }
> </%init>
> 
> It outputs:
> Content-type: text/plain ipn=no
> 
> Obviously I'm doing something fundamentally wrong, perhaps I need to
> setup some parameters before the call to $ipn =
> Business::PayPal::IPN->new() ?
> 
> Help
> 
> Jim Rey

First of all, you can't set the content type using print with mod_perl,
you need to do this instead:

$r->content_type('text/plain');

Also, if you visit the page, there isn't going to be an IPN.

IPN is when PayPal POSTs data, and your script deals with that. When you
visit the page, your script is dealing with a request from your web
browser, not POSTed data from PayPal. You can't use a web browser to
test your script.

Get it to write out to a file when data is posted to it: Write that the
script has been accessed, whether it is POST or GET, whether you can
create the Business::PayPal::IPN object or not, and if not, write out
Business::PayPal::IPN->error(). Then, after making a test payment, wait
a few minutes, and check this file.

Also, check your webservers access logs to make sure that PayPal is
accessing your script.

I've attached my dhandler that deals with IPN to have a look at if you
like. It doesn't use Business::PayPal::IPN. Functions and variables in
the DeFuturo namespace are specific to my organisation, but it should be
fairly clear what they're doing. I've also cut a huge chunk from the
bottom that is purely business logic that won't be relevant to you.

Where I've done both:
$r->status(xxx);
and
$m->abort(xxx);
the status call shouldn't be neccessary because $m->abort should also do
this. However, I've been having problems where abort isn't doing that,
hence the seemingly superfluous call.

It's not my finest piece of code. But it works.

Also, your problem isn't actually a problem with Mason, so this mailing
list might not be the best place to look for answers.

-Oli
<%flags>
  inherit => '/init.mas'
</%flags>
<%init>
  
  my $debug = $DeFuturoConfig::setting->{devel} ? 1 : 0;
  
  $debug && DeFuturo::Log::log('debug', 'Access to IPN URL, method: ' . 
$r->method);
  
  unless ($r->method eq 'POST')
  {
        ## Something like this...
        $r->status(406);
        $r->allowed($Apache2::Const::M_POST);
        $m->abort(406);
  }
  
  my $rargs = $m->request_args;
  
  $debug && DeFuturo::Log::log('debug', "Recireved the following IPN:\n" . 
join("\n", map {"$_: " . $rargs->{$_}} keys %$rargs));
  
  my %validateargs = %$rargs;
  $validateargs{'cmd'} = '_notify-validate';
  
  my $paypal_url = $DeFuturo::Payment::PayPal::ppurl;
  
  require LWP;
  my $browser = LWP::UserAgent->new;
  
  my $response = $browser->post($paypal_url, \%validateargs);
  
  unless ($response->is_success)
  {
        my $reason = $response->code . ": " . $response->message;
        DeFuturo::Log::log('error', 'HTTP failure when trying to verify IPN, 
response from PayPal: ' . $reason);
        $r->status(400);
        $m->abort(400);
  }
  
  if ($response->content =~ /VERIFIED/)
  {
        $debug && DeFuturo::Log::log('debug', 'Verified PayPal IPN');
  }
  elsif ($response->content =~ /INVALID/)
  {
        $debug && DeFuturo::Log::log('debug', 'Invalid PayPal IPN');
        DeFuturo::Log::log('error', 'Invalid PayPal IPN');
        $r->status(400);
        $m->abort(400);
  }
  else
  {
        $debug && DeFuturo::Log::log('debug', 'Unknown response to IPN 
verification');
        DeFuturo::Log::log('error', 'Unknown response to IPN verification');
        $r->status(400);
        $m->abort(400);
  }
  
  ## Since we haven't aborted... all must be ok...
  
  my $txn_id = $rargs->{'txn_id'};
  my $nstatus = $rargs->{'payment_status'};
  my ($paypal) = DeFuturo::DB::PayPal->search(transactionid => $txn_id);
  
  if ($paypal)
  {
        ## has already been recorded in the DB, so probably a status change
        my $ostatus = $paypal->status;
        $debug && DeFuturo::Log::log('debug', "Change of paypal payment status 
from $ostatus to $nstatus");
        $paypal->status($nstatus);
        $paypal->update;
  }
  else
  {
        ## Not found in DB, likely a new payment
        $paypal = DeFuturo::DB::PayPal->insert(
                {
                 'transactionid'        => $txn_id,
                 'status'               => $nstatus,
                });
        
        $debug && DeFuturo::Log::log('debug', 'Add new paypal entry, txn id: ' 
. $txn_id);
  }
  
  my @tactions = $paypal->transactions;
  
  ## After this point is lots of stuff specific to my organisation
  ## that won't be of help to you.
  ##
  ## However, at this point, I have validated the IPN, and stored the
  ## transaction number and status in a database.
  
</%init>

Attachment: signature.asc
Description: OpenPGP digital signature

-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
Mason-users mailing list
Mason-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/mason-users

Reply via email to