Oli,
Thanks for your reply. Before I continue, I was aware that the print
"Content-type: text/plain\n\nipn=yes\n"; was incorrect, but this wasn't the
real problem (and I have never used a dhandler) because I wasn't sure how to
go about it.
I'm also aware that this may not be a Mason problem, but I haven't been able
to get help anywhere else.
My autohandler sets up the the main display framework to give a consistent
look an feel to my site and at the same time it picks up the parameters and
stores them in $MyGlobal{'params'}. I can and do pick up all the parameters
passes back via the IPN. My problem has been handling the response
handshake to post back to PayPal system to validate. because using LWP
causes the IPN response to return to the same page again losing all the
values it sent the first time. I'm just not sure where to place the response
code. I did write a small module to do this:
package postPayPal;
require Exporter;
use LWP::UserAgent;
use HTTP::Request;
our @ISA = qw(Exporter);
our @EXPORT = qw(CheckIPN);
sub CheckIPN {
my ($SandBox, $Query) = @_;
# post back to PayPal system to validate
# use LWP::UserAgent;
my $Status = 'UNDEFINED';
# read post from PayPal system and add 'cmd'
$Query .= 'cmd=_notify-validate';
my $ua = new LWP::UserAgent;
my $req = new HTTP::Request 'POST',
$SandBox
? 'https://www.sandbox.paypal.com/cgi-bin/webscr'
: 'https://www.paypal.com/cgi-bin/webscr';
$req->content_type('application/x-www-form-urlencoded');
$req->content($Query);
my $res = $ua->request($req);
if ($res->is_error) {
$Status = 'SUSPICIOUS';
} elsif ($res->content eq 'INVALID') {
$Status = 'INVALID';
} elsif ($res->content eq 'VERIFIED') {
$Status = 'VERIFIED';
} else {
$Status = 'CANCELLED';
}
return $Status;
}
1;
I had hoped that it might run like a detached process as I've used LWP in
perl scripts (outside the browser of course) and it all works. I did think
of setting up a cron job to check the database and autosend responses, but
this cannot be sane. Anyway, what I'm missing is a mechanism to integrate
IPN smoothly. I must be missing something vital in my approach, I'm not
normally slow, but this is the first real problem I've had and I'm a
relative newcomer to web programming. This is the only thing stopping my
site from going live.
Jim
On 07/03/07, Oliver Jeeves <[EMAIL PROTECTED]> wrote:
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>
--
Jim Rey
48 Laburnum Park
Bradshaw
Bolton BL2 3BU
United Kingdom
Tel: 01204 593 222
Mob: 07816 751 874
-------------------------------------------------------------------------
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