YetAnotherForum
Welcome Guest Search | Active Topics | Log In | Register

free perl ipn script - easy as 123 Options
sloppycoder
#1 Posted : Monday, July 19, 2004 9:10:03 PM
Rank: Starting Member

Groups: Registered

Joined: 7/19/2004
Posts: 1
Location: ,
Hi, I've recently been working on a site that requires online payments but I needed the payment to have a callback (ipn) so I could update my database and send a personalised email to my customer if the payment was succesful. So I found paypal's ipn, it does everything I want it to do....one problem; the documentation is so poorly written I was confused after reading 'how ipn works' I then found this site and noticed that neally everyone has the same issues I do; why do you have return_url & notify_url? can you use them together...if I use just return_url and have variables posted is it safe? etc... I copied paypal's perl sample script (as everyone here probably did) and it still didn't make much sense...so, I used their script and modified it so most of your questions should be answered in the script. BTW, you only need to use notify_url and NOT return_url...why?, well the script not only does the processing it also displays the results of the payment(no need for 2 scripts) You can modify, improve the script any way you want: Criticism welcome #!/usr/bin/perl ##################################### # CONFIG - JUST NEATER IF ITS HERE # ##################################### $paypal_email = 'me@mydomain.com'; # THIS SHOULD BE THE EMAIL ADDRESS YOU SIGNED UP WITH PAYPAL # THIS IS USED TO CHECK THAT THE FUNDS HAVE BEEN PAID TO YOU AND NOT SOMEONE ELSE TRYING TO RIP YOU OFF # READ DATA POSTED FROM PAYPAL read (STDIN, $query, $ENV{'CONTENT_LENGTH'}); $query .= '&cmd=_notify-validate'; # SEND DATA BACK TO PAYPAL TO VALIDATE THE PAYMENT use LWP::UserAgent; $ua = new LWP::UserAgent; $req = new HTTP::Request 'POST','http://www.paypal.com/cgi-bin/webscr''; $req->content_type('application/x-www-form-urlencoded'); $req->content($query); $res = $ua->request($req); # GET POSTED DATA FROM PAYPAL %form = &parse; # VARIABLES SENT FROM PAYPAL ABOUT THE PAYMENT TO YOU $receiver_email = $form{'receiver_email'}; $item_name = $form{'item_name'}; $item_number = $form{'item_number'}; $item_quantity = $form{'quantity'}; $pending_reason = $form{'pending_reason'}; $payment_status = $form{'payment_status'}; $payment_amount = $form{'mc_gross'}; $payment_currency = $form{'mc_currency'}; $payment_date = $form{'payment_date'}; $first_name = $form{'first_name'}; $last_name = $form{'last_name'}; $address_street = $form{'address_street'}; $address_city = $form{'address_city'}; $address_state = $form{'address_state'}; $address_zip = $form{'address_zip'}; $address_country = $form{'address_country'}; $txn_id = $form{'txn_id'}; $payer_email = $form{'payer_email'}; if ($res->is_error) { # HTTP ERROR OCCURED (SCRIPT ERROR OR SOMETHING ALONG THEM LINES) &error("An HTTP error occured"); } elsif ($res->content eq 'VERIFIED') { if ($receiver_email ne $paypal_email){&error("Your payment has been made but it was paid into the wrong paypal account")}; if ($payment_status eq 'Completed'){ # PUT CODE HERE TO CHECK $txn_id HAS NOT BEED PROCESSED BEFORE (SEE BELOW) # YOU NEED TO KEEP A FILE THAT STORES ALL TRANSACTIONS ($txn_id) AND COMPARE THEM WITH # THE CURRENT $txn_id TO CHECK IT DOESN'T ALREADY EXIST. IM NOT SURE WHAT YOU DO IF # IT DOES EXIST??? # PAYMENT WAS SUCCESSFUL print "Content-type: text/html\n\n"; print "<h2>YOUR PAYMENT WAS ACCEPTED - Thank you</h2>\n"; # PUT CODE HERE THAT WILL UPDATE A DATABASE, SEND AN EMAIL OR WHATEVER YOU WANT }elsif ($payment_status eq 'Pending'){ # TO MAKE THINGS SAFE WE SHOULD CHECK IF THE PAYMENT IS PENDING # IF THE PAYMENT IS CLEARED AFTER A FEW DAYS AND BECOMES COMPLETE THEN THE # SCRIPT WILL BE CALLED AGAIN WITH A 'COMPLETE' STATUS AND THE FUNDS WILL BE ADDED TO YOUR ACCOUNT # SO IT WOULD BE BEST TO LET THE CUSTOMER KNOW ABOUT THE PAYMENT PENDING &error("YOUR PAYMENT IS PENDING - As soon as it is completed you will recieve confirmation via email"); }else{ # THIS WILL ONLY HAPPEN IF THE PAYMENT IS VERIFIED BUT THE STATUS OF THE PAYMENT # IS ANYTHING ELSE BUT 'COMPLETE' OR 'PENDING' &error("Your payment was not accepted"); } } elsif ($res->content eq 'INVALID') { # PAYPAL DECLINED THE PAYMENT &error("Your payment was not accepted"); } else { # YOU GUESSED IT - UNKNOWN ERROR &error("An unknown error occurred"); } sub error { $error=$_[0]; print "Content-type: text/html\n\n"; print "<h2>$error</h2>\n"; exit; } ############################################################### ###################### PARSE FORM DATA ######################## ############################################################### sub parse { my $temp; my @data; foreach $temp (split(/&|=/,$query)) { $temp =~ tr/+/ /; $temp =~ s/%([0-9a-fA-F]{2})/pack("c",hex($1))/ge; $temp =~ s/[\r\n]/ /g; push @data, $temp; } return @data; } the names "coder" ... "sloppy coder"
Sponsor  
 
Blnukem
#2 Posted : Wednesday, September 29, 2004 7:40:08 AM
Rank: Starting Member

Groups: Registered

Joined: 9/29/2004
Posts: 10
Location: ,
Code has a error on it change this line: $req = new HTTP::Request 'POST','http://www.paypal.com/cgi-bin/webscr'';


To: $req = new HTTP::Request 'POST','http://www.paypal.com/cgi-bin/webscr';
PayPal_Dave
#3 Posted : Wednesday, January 26, 2005 3:19:43 PM
Rank: Starting Member

Groups: Registered

Joined: 2/13/2004
Posts: 109
Location: ,
Hi Neeta,

You may want to look at the Payment Data Transfer (PDT) feature and the variables "return" and "rm". See pages 80 and 115 of the Merchant User Manual and Integration Guide for more information (https://www.paypal.com/en_US/pdf/integration_guide.pdf).

If you are not experienced with CGI, I recommend acquiring the services of an experienced Webmaster or sysadmin to assist you.


Dave Burchell
PayPal Technical Support
PayPal, an eBay company
Order PayPal Hacks now! http://www.oreilly.com/catalog/payhks/
Neeta
#4 Posted : Monday, January 31, 2005 12:54:52 PM
Rank: Starting Member

Groups: Registered

Joined: 1/20/2005
Posts: 3
Location: ,
Hi,
I am getting Software error:
Global symbol "$query" requires explicit package name at /compass/web/lt23/cgi-bin/return_fullparticipant.cgi line 20.
Global symbol "$query" requires explicit package name at /compass/web/lt23/cgi-bin/return_fullparticipant.cgi line 21.
BEGIN not safe after errors--compilation aborted at /compass/web/lt23/cgi-bin/return_fullparticipant.cgi line 25.

my cgi code is:

#!/usr/bin/perl -wT

use strict;
use CGI;
use DBI;

use CGI::Carp qw(fatalsToBrowser carpout);
#open (LOG,"&gt;&gt;/file path") ||
open (LOG,"&gt;&gt;/www/file path.log") ||
die "couldn't open log file: $!";
carpout(LOG);

$ENV{PATH} = "/bin:/usr/bin";


#$paypal_email = 'xyz@domain.edu'; # THIS IS OUR EMAIL ADDRESS WE SIGNED UP WITH PAYPAL
# THIS IS USED TO CHECK THAT THE FUNDS HAVE BEEN PAID TO US AND NOT SOMEONE ELSE TRYING TO RIP US OFF

# READ DATA POSTED FROM PAYPAL
read (STDIN, $query, $ENV{'CONTENT_LENGTH'});
$query .= '&cmd=_notify-validate';

# SEND DATA BACK TO PAYPAL TO VALIDATE THE PAYMENT
# USE THIS MODULE
use LWP::UserAgent;

# CREATE A NEW USER OBJECT VIA $ua
$ua = new LWP::UserAgent;

# CREATE A NEW REQUEST OBJECT '$req' with METHOD (POST) and URL
$req = new HTTP::Request 'POST','http://www.paypal.com/cgi-bin/webscr';

# ASSIGN THIS 'content_type' method to request object '$req'
$req-&gt;content_type('application/x-www-form-urlencoded');

# ASSIGN THIS 'content' method to request object '$req'
$req-&gt;content($query);

# TELL THE AGENT TO MAKE A REQUEST. IT RETURNS THE RESPONSE OBJECT '$res'
$res = $ua-&gt;request($req);

# GET POSTED DATA FROM PAYPAL
%form = &parse;

$paypal_email = 'xyz@domain.edu'; # THIS IS OUR EMAIL ADDRESS WE SIGNED UP WITH PAYPAL
# VARIABLES SENT FROM PAYPAL ABOUT THE PAYMENT TO US
$receiver_email = $form{'receiver_email'};
$item_name = $form{'item_name'};
#$item_quantity = $form{'quantity'};
$pending_reason = $form{'pending_reason'};
$payment_status = $form{'payment_status'};
$payment_amount = $form{'payment_gross'};
$payment_date = $form{'payment_date'};
$first_name = $form{'first_name'};
$last_name = $form{'last_name'};
$address_street = $form{'address_street'};
$address_city = $form{'address_city'};
$address_state = $form{'address_state'};
$address_zip = $form{'address_zip'};
$address_country = $form{'address_country'};
$txn_id = $form{'txn_id'};
$payer_email = $form{'payer_email'};


# If response is PENDING, nothing happens.
# Otherwise, it will be either: (an http error); VERIFIED; Completed;
# Invalid; or (some other error).


if ($res-&gt;is_error) {
# HTTP ERROR OCCURED (SCRIPT ERROR OR SOMETHING ALONG THEM LINES)
&error("An HTTP error occured");
} # end if ($res-&gt;is_error)

elsif ($res-&gt;content eq 'VERIFIED') {

if ($receiver_email ne $paypal_email){
&error("Your payment has been made but it was paid into the wrong paypal account");
}

if ($payment_status eq 'Completed') {

# CHECK THAT RECEIVER EMAIL IS OUR PAYPAL EMAIL ID

if ($receiver_email eq "xyz@domain.edu") {

# CHECK $txn_id HAS NOT BEED PROCESSED BEFORE (SEE BELOW)
# AND RECORDED IN A FILE THAT STORES ALL TRANSACTIONS ($txn_id) AND COMPARE THEM WITH
# THE CURRENT $txn_id TO CHECK IT DOESN'T ALREADY EXIST.

&check_txn;

} # end email OK

else {
&error("Your payment has been made but it was paid into the wrong paypal account");
} # end else (email)

} # END OF IF payment_status eq 'COMPLETED'

#} # END of elseif

elsif ($payment_status eq 'Pending'){

# TO MAKE THINGS SAFE WE SHOULD CHECK IF THE PAYMENT IS PENDING
# IF THE PAYMENT IS CLEARED AFTER A FEW DAYS AND BECOMES COMPLETE THEN THE
# SCRIPT WILL BE CALLED AGAIN WITH A 'COMPLETE' STATUS AND THE FUNDS WILL BE ADDED TO YOUR ACCOUNT
# SO IT WOULD BE BEST TO LET THE CUSTOMER KNOW ABOUT THE PAYMENT PENDING
&error("YOUR PAYMENT IS PENDING - As soon as it is completed you will recieve confirmation via email");

} # end of else if

} # end of else if VERIFIED


elsif ($res-&gt;content eq 'INVALID') {
# PAYPAL DECLINED THE PAYMENT
print "content-type: text/plain\n\nOK\n";

print "&lt;html&gt;&lt;head&gt;&lt;title&gt;IPN Screendump&lt;/title&gt;&lt;/head&gt;\n";
print "&lt;br&gt;the status was&lt;b&gt;$status&lt;/b&gt;\n";
print "&lt;/body&gt;&lt;/html&gt;\n";

&error("Your payment was not accepted");
}


else {
# YOU GUESSED IT - UNKNOWN ERROR
&error("An unknown error occurred");
}

###############################################################
###################### PRINT ERROR MESSAGE ####################
###############################################################

sub error {
$error=$_[0];
print "Content-type: text/html\n\n";

print "&lt;h2&gt;$error&lt;/h2&gt;\n";
exit;
}

###############################################################
###################### PARSE FORM DATA ########################
###############################################################

sub parse {
my $temp;
my @data;
foreach $temp (split(/&|=/,$query)) {
$temp =~ tr/+/ /;
$temp =~ s/%([0-9a-fA-F]{2})/pack("c",hex($1))/ge;
$temp =~ s/[\r\n]/ /g;
push @data, $temp;
}
return @data;
}

########################################################################
###################### CHECK TRANSACTION ID & UPDATE DATABASE ##########
########################################################################

# This routine will open an order file and check to see if this
# transaction number has already been entered. If not, $processed will
# stay as 0. If so, it will return 1.
sub check_txn
{
$dbh = DBI-&gt;connect("DBI:CSV:f_dirdirectory path");
$statement = "select txn_id from RegPayment where txn_id =\"$txn_id\"";
$sth = $dbh-&gt;prepare($statement) or print "Can't prepare the txnid SQL\n";
$rv = $sth-&gt;execute or print "Can't execute the txnid query: $sth-&gt;errstr";
#If it finds previous txn_id
if ($rv == 1)
{
$processed = 1;
}
#If there is not a previous txn_id.
if ($rv== '0E0')
{

# UPDATE A DATABASE.
$statement = "insert into RegPayment (reg_type, first_name, last_name, txn_id,payment_date,early_late_reg,payment_amount,payment_status, payer_email )";
$statement .= "values (\"$item_name\",\"$first_name\", \"$last_name\", \"$txn_id\",\"$payment_date\",""early"",\"$payment_amount\", \"$payment_status\",\"$payer_email\")";
$sth = $dbh-&gt;prepare($statement) or print "Can't prepare the SQL\n";
$rv = $sth-&gt;execute or print "Can't execute the query: $sth-&gt;errstr";
print $rv, " rows inserted\n";

# PAYMENT WAS SUCCESSFUL
print "Content-type: text/html\n\n";

print "&lt;h2&gt;YOUR PAYMENT WAS ACCEPTED - Thank you&lt;/h2&gt;\n";

print "content-type: text/plain\n\nOK\n";
print "&lt;html&gt;&lt;head&gt;&lt;title&gt;IPN Screendump&lt;/title&gt;&lt;/head&gt;\n";

print "&lt;br&gt;Your First Name: &lt;b&gt;$first_name&lt;/b&gt;\n";
print "&lt;br&gt;Your Last Name : &lt;b&gt;$last_name&lt;/b&gt;\n";
print "&lt;br&gt; Address : \n";
print "&lt;br&gt;Street: &lt;b&gt;$address_street&lt;/b&gt;\n";
print "&lt;br&gt;City :&lt;b&gt;$address_city&lt;/b&gt;\n";
print "&lt;br&gt;State:&lt;b&gt;$address_state&lt;/b&gt;\n";
print "&lt;br&gt;Zip :&lt;b&gt;$address_zip&lt;/b&gt;\n";
print "&lt;br&gt;Country: &lt;b&gt;$address_country&lt;/b&gt;\n";
print "&lt;br&gt;Email: &lt;b&gt;$payer_email&lt;/b&gt;\n";
print "&lt;br&gt;Registration Type: &lt;b&gt;$item_name&lt;/b&gt;\n";
print "&lt;br&gt;Total: &lt;b&gt;$payment_amount&lt;/b&gt;\n";
print "&lt;br&gt;Transaction Date:&lt;b&gt;$payment_date&lt;/b&gt;\n";
print "&lt;br&gt;Transaction ID &lt;b&gt;$txn_id&lt;/b&gt;\n";
print "&lt;br&gt;The payment status is&lt;b&gt;$payment_status&lt;/b&gt;\n";
print "&lt;/body&gt;&lt;/html&gt;\n";
}
$dbh-&gt;disconnect;


} # END OF check_txn

and please tell me how to install LWP.
PayPal_Dave
#5 Posted : Monday, January 31, 2005 2:00:36 PM
Rank: Starting Member

Groups: Registered

Joined: 2/13/2004
Posts: 109
Location: ,
Hi Neeta,

When you "use strict" you need to make sure that all of your variables are declared to be a part of a package. Specifically, try putting "my" in front of the first instance of the variable $query, like this:

my $query .= '&cmd=_notify-validate';

To instally LWP, you may want to try Perl's CPAN module. At your shell prompt, type:

perl -MCPAN -eshell

Once you have the CPAN shell started, install LWP:

install LWP

You may need to do this on your system as the superuser (root). If you are not the sysadmin for the system you will want to work with your sysadmin to add the LWP module. Likewise, if you are not familiar with configuring Perl, you may want to bring in an expert.



Dave Burchell
PayPal Technical Support
PayPal, an eBay company
Order PayPal Hacks now! http://www.oreilly.com/catalog/payhks/
Users browsing this topic
Guest
Forum Jump  
You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.

YAFVision Theme by Jaben Cargman (Tiny Gecko)
Powered by YAF | YAF © 2003-2009, Yet Another Forum.NET
This page was generated in 0.537 seconds.