Forum Moderators: coopster

Message Too Old, No Replies

PayPal IPN > email to buyer - looking for input

would like some help verifying and implementing this script

         

atomMan

5:26 am on Jul 19, 2011 (gmt 0)

10+ Year Member



i don't mess with PHP much, so i'm trying to avoid having to do a bunch of research for just a simple script. would like some input on what i have though :)

objective:
buyer pays > PP IPN info sent to script > IF verify, send buyer an email > create a file in an existing directory

most of this is straight from PP, i just need a little help with creating the file using a string and variable in the //// BEGIN FILE WRITE CODE //// section

<?php
// read the post from PayPal system and add 'cmd'
$req = 'cmd=_notify-validate';

foreach ($_POST as $key => $value) {
$value = urlencode(stripslashes($value));
$req .= "&$key=$value";
}

// post back to PayPal system to validate

$header = "POST /cgi-bin/webscr HTTP/1.0\r\n";

// If testing on Sandbox use:
// $header .= "Host: www.sandbox.paypal.com:443\r\n";
$header .= "Host: www.paypal.com:443\r\n";
$header .= "Content-Type: application/x-www-form-urlencoded\r\n";
$header .= "Content-Length: " . strlen($req) . "\r\n\r\n";

// If testing on Sandbox use:
//$fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30);
$fp = fsockopen('ssl://www.paypal.com', 443, $errno, $errstr, 30);

// assign posted variables to local variables
$item_name = $_POST['item_name'];
$item_number = $_POST['item_number'];
$payment_status = $_POST['payment_status'];
$payment_amount = $_POST['mc_gross'];
$payment_currency = $_POST['mc_currency'];
$txn_id = $_POST['txn_id'];
$receiver_email = $_POST['receiver_email'];
$payer_email = $_POST['payer_email'];

//set email variables
$From_email = "From: me";
$Subject_line = "subject";

$email_msg = "main message body here";
$email_msg .= "\n\nThe details of your order are as follows:";
$email_msg .= "\n\n" . "Transaction ID: " . $txn_id;
$email_msg .= "\n" . "Payment Date: " . $payment_date;

if (!$fp) {
// HTTP ERROR
} else {
fputs($fp, $header . $req);
while (!feof($fp)) {
$res = fgets($fp, 1024);
if (strcmp($res, "VERIFIED") == 0) {
// check the payment_status is 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

$mail_From = $From_email;
$mail_To = $payer_email;
$mail_Subject = $Subject_line;
$mail_Body = $email_msg;

mail($mail_To, $mail_Subject, $mail_Body, $mail_From);

//// BEGIN FILE WRITE CODE ////
$regFile = "./home/sroot/public_html/licverify/" . $payer_email; // not sure if syntax is right?
$fh = fopen($regFile, "x") or die("can't open file");
chmod($fh, 0644); // this in right place in the sequence?
$stringData = $payer_email . "|" . $txn_id; // not sure about syntax?
fwrite($fh, $stringData);
fclose($fh);
//// END FILE WRITE CODE ////

} elseif (strcmp($res, "INVALID") == 0) {
// log for manual investigation

$mail_From = $From_email;
$mail_To = $receiver_email;
$mail_Subject = "INVALID IPN POST";
$mail_Body = "INVALID IPN POST. The raw POST string is below.\n\n" . $req;

mail($mail_To, $mail_Subject, $mail_Body, $mail_From);
}
}
fclose($fp);
}
?>

rocknbil

3:43 pm on Jul 19, 2011 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Don't have time to fully explore - but here is the way I set these up.

When you use IPN, the clear of the funds may not be instantaneous. If the user pays by eCheck, for example, the IPN may come up to three days later.

So what you do is logic like this:

buyer sets up order -> store in database -> mark "completed" field as 0 (zero)

Note no emails, no response to user. The completed field acts as a switch to prevent the order from being submitted twice (you'll have to code logic in for it) and once set to 1 on completion, prevents it from being used again.

At this point, the user is on payPal and often won't use the "return to merchant site" link, which is the biggest reason to use IPN. If they do use that link, you have some variable you've sent to paypal that gets returned

if ($_GET['returned']) {
// output a "processing your order message
}

Now you have a second script - let's call it a "listener" script - that you'd enter as the IPN URL. At any time, PP can send a message to this script and you act accordingly. Most of what you have there is the "listener."

If declined or invalid, send an email saying so, but otherwise, open your database, update the "completed" field to 0, then send the confirmation emails.

I'd use a database, even if it's a flat text database. There are two things I see wrong here:

$regFile = "./home/sroot/public_html/licverify/" . $payer_email; // not sure if syntax is right?

The dot is not needed, and you can likely do this instead:

$regFile = $_SERVER['DOCUMENT_ROOT] . '/licverify/'... $some_file;

Second, I don't know if you can create a file with mail@example.com as a file name. Seems rather cumbersome and security prone.

atomMan

4:46 pm on Jul 19, 2011 (gmt 0)

10+ Year Member



thanks for the tips rocknbil

i seem to have it working pretty good. i agree naming the files using the buyer email is not the brightest idea, even though that dir is pwd protected. i had planned on changing that anyway.

i'm selling software licenses so i have no need (i don't think) for a cart/store/db since the purchase and registration verification is initiated from within the program. so my process is..

buyer clicks button in program >
browser opens PP product page >
purchase is made >
PP phones the IPN listener script at some point >
if payment verified, buyer gets email with registration credentials > (i have to add code if verification fails yet)
unique file is created in .htaccess protected dir on server containing buyer credentials > (this should go before the above)
buyer runs program and enters credentials >
program reads the unique file (this is SSL) >
if his info match the strings in the file on server, we unlock program