PHP - Paypal Ipn Listener
I am trying to write a Paypal IPN Listener that will create a confirmation key in the order database I have on the server. Upon completing the order it will then send a email to the buyer with a link to a file upload page with the confirmation code embedding so that when the buyer goes to the upload page it can authenicate based on that code prior to allowing the person to upload a file. I has been a pain and is still not working. Similar to an email confirmation when some one signs up as a user on a site, but using the Paypal order information and the listener to generate the confirmation and authentication. IS THIS POSSIBLE?
Similar TutorialsI am writing a listener to handle IPN notifications from paypal, and one thing I cant seemt o find anywhere - How does IPN handle pending payments, that are then completed/denied? For example, if paypal invokes my IPN once the payment is made, but pending, with a particular transaction ID, when the payment completes, does it then invoke my IPN again, with the payment status as 'completed'? If so, will this second IPN have the same transaction ID? It would seem logical that the same transaction ID is sent again, as it is actually the same customer transaction, however reading this on thepaypal website suggests otherwise: "Avoid duplicate IPN messages. Check that you have not already processed the transaction identified by the transaction ID returned in the IPN message. You may need to store transaction IDs returned by IPN messages in a file or database so that you can check for duplicates. If the transaction ID sent by PayPal is a duplicate, you should not process it again. " Help would be appreciated!! I'm trying to set up paypal payment processing on my website. I have godaddy shared hosting (<--mistake) and I'm trying my hardest to not switch hosts. The payments process fine, it is the listener that I'm having problems with. Paypal POSTs data to a script for which you set the url to a "listener" script in your settings. When a payment is made.... they POST the data to the listener script... you encode the data...append it all together plus another variable and send it back to be verified that it matches... Well I'm not too worried about the script working and all that... the problem is I'm not even RECEIVING the post. I have a simple foreach loop gather and append the data into a string. I have it set up right now to insert into MYSQL just so I can SEE if it's working....You can check your IPN history and I can see that payments are made but paypal is sending it over and over it's in a "retrying" state with a 408 error. My server is not sending a 200ok response. After 4 days of bashing my head against the wall I figured out that there's a problem with godaddy shared hosting.. If I use a virtual private server with the SAME script from godaddy it works just fine. But on the shared hosting it blocks it for some reason...After calling paypal and godaddy countless times with them pointing their finger at each other... one godaddy support rep tells me that I should set my script up with a proxy and he gave me info which I will show you in the script... This is what I need help with right. How can I receive POST data through a proxy in my script.... I want to add that this doesn't make sense to me because in my script I also have the word "yes" insert into MYSQL even if the script is hit at all... All this time my script is NEVER even touched by paypal... So.. if I add this proxy stuff... how will let my script even be accessed? I'm not sure how servers work together too well to process things. It just didn't seem like the proxy thing would even help when my script can't even be accessed it seems. Any help is appreciated. Here's the simple code I'm working with: $con = mysql_connect("","","") or die(mysql_error()); $db = mysql_select_db("swellshirt",$con); $ip = "64.202.165.130"; // proxy IP <-- IP... $port = 3128; // proxy port $url_proxy = 'http://proxy.shr.secureserver.net'; // 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"; } mysql_query("INSERT INTO orders (description, street) VALUES ('$req', 'yes') ") or die(mysql_error()); I am VERY VERY green to PHP. I feel like a fish out of water. I need to create a simple SOAP listener in PHP. This site need not do anything with the SOAP message but send it to another web app within our clients network. The reason for this long winded and exceeds the scope of this request. Our client only has one Apache server exposed to the public internet so I cannot use .NET and IIS. All other web servers are internal and running IIS. The SOAP messages will be coming from SalesForce. They have a plethora of information on doing this in .NET and IIS but not PHP. Can anyone point me in a 'PHP for dummies' way? Thanks in advance. Something I have never done, but want to learn the best practice for doing so, is a listener script. Example: one of our websites is in bespoke PHP and has two links that shows if there are any noticeboard 'notifications' or any new 'messages'. Ideally I'd like to show 1, 2, 3... etc as a count of how many are remaining for Messages. So if a new one comes in while they are on a page, that number literally changes while they are on the page. I assume this is with Ajax, and not straight forward. I don't know any DOM code or Javascript. But would appreciate some help please. Simon This is more of a Paypal question, but I'm using php on the listener and hopefully someone has run into this problem. I'm having trouble finding the correct POST name to use to get the OPTION SELECT for the item on my listener page. I tried: $option = $_POST['os0']; But, I'm not getting anything using that. I've also tried os0_x, on0, and on0_x. This is what I'm posting to Paypal: <input type="hidden" name="on0" value="Term"> <select name="os0"> <option value="1 Year">1 Year</option> <option value="3 Years">3 Years</option> <option value="5 Years">5 Years</option> </select> Edited November 3, 2019 by jakebur01 I have a listener which executes a HTTP request to a remote API before the User entity is persisted and uses the response to set one of the entity's properties. It will also listen for update and remove and will make the appropriate HTTP request to the API but will not modify the entity. All works as desired... Almost. If when persisting the entity, I have some error, the remote API and my application become out of sync. I wish to change my application to perform a second call to the API if an error occurs and reverse the previous call. My thoughts on how to implement a Place a try/catch block when executing the query. Don't like this approach. Add an ExceptionListener which somehow retrieves the entity and makes the applicable changes. Maybe part of the solution, but too complicated to be the full solution. When adding, updating, or deleting a user from the remote API under UserListener's three methods, adding a callback which gets executed upon a PDOException. I think this is the best approach and expanded my thoughts below.
<?php namespace App\EventListener; use Doctrine\Persistence\Event\LifecycleEventArgs; use App\Service\HelpDeskClient; use App\Entity\AbstractUser; final class UserListner { private $helpDeskClient; public function __construct(HelpDeskClient $helpDeskClient) { $this->helpDeskClient = $helpDeskClient; } public function prePersist(AbstractUser $user, LifecycleEventArgs $event) { $this->helpDeskClient->addUser($user); //$user will be updated with the HTTP response } public function preUpdate(AbstractUser $user, LifecycleEventArgs $event) { $this->helpDeskClient->updateUser($user); } public function preRemove (AbstractUser $user, LifecycleEventArgs $event) { $this->helpDeskClient->deleteUser($user); } } Okay, how do I actually do this? Was thinking of modifying UserListner as follows: //... use Symfony\Component\HttpKernel\KernelEvents; final class UserListner { // ... public function prePersist(AbstractUser $user, LifecycleEventArgs $event) { $this->helpDeskClient->addUser($user); $event->getObjectManager()->getEventManager()->addEventListener(KernelEvents::EXCEPTION, function($something) use($user) { // Use $this->helpDeskClient to reverse the changes }); } // Similar for update and remove }
But when trying this approach, I get a PDOException, but my callback never gets excecated. I've also tried replacing KernelEvents::EXCEPTION with '\PDOException' (note the quotes) with no success. Any ideas what I should be doing differently? Maybe some totally different approach? I suppose I could make the request to the API after the DB query is complete for updating and deleting, but not for adding. Hi Does any one know of any good tutorials for paypal web payments pro, or recommend books Thanks in advance I am trying to get a Paypal IPN working using PHP. I have attached the code I have written that is not working. I have no real way to test it other than nothing is being posted to the databases. The transactions seem to complete with paypal, but I get no information and no emails are generated. Any help would be much appreciated. Hey All, I have setup a Paypal API to handle the recurring payments on my website, once the payment is completed I get a token id and ba_token id return. I am storing this in a database, but wondered how people link this with a user table? I could use a cookie to store the user's id before payment and then get it once the payment is complete, but this would not work with the subsequent recurring payments. How do you go about sending the user id when a recurring payment happens? Any advise would be appreciated. Edd Hi guys, my code below works with sanbox for paypal IPN but since it has gone live it doesnt do anything, so i made emails to send me where the issue is and it keep sending me $req = 'cmd=_notify-validate'; could you please tell me what im doing wrong here? my db connection should be fine as it does update the users on sanbox. the account im paying with in paypal keep saying payment status unclaimed. it means the reciever has not recieved the money. I checked the paypal account where i recieve the moeny and looked into my ipn history, nothing there. the same ipn address is used for my account when i tested it on sanbox, thanks <?php $email="princeofpersia@hotmail.co.uk"; include 'global.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"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; $fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30); //$fp = fsockopen ('ssl://www.paypal.com', 443, $errno, $errstr, 30);//Live // assign posted variables to local variables if (!$fp)// failed to connect to url { //write to file $fh = fopen("logipn.txt", 'a');//open file and create if does not exist fwrite($fh, "\r\n/////////////////////////////////////////\r\n HTTP ERROR \r\n");//Just for spacing in log file fwrite($fh, $errstr);//write data fclose($fh);//close file $mail_From = "From: IPN@tester.com"; $mail_To = $email; $mail_Subject = "HTTP ERROR"; $mail_Body = $errstr;//error string from fsockopen mail($mail_To, $mail_Subject, $mail_Body, $mail_From); } else//successful connect to url { fputs ($fp, $header . $req);//send request while (!feof($fp)) //while not end of file { $res = fgets ($fp, 1024);//get response if (strcmp ($res, "VERIFIED") == 0) { //write to file $fh = fopen("logipn.txt", 'a');//open file and create if does not exist fwrite($fh, "\r\n/////////////////////////////////////////\r\n Verified \r\n");//Just for spacing in log file fwrite($fh, $req);//write data fclose($fh);//close file $mail_From = "From: IPN@tester.com"; $mail_To = $email; $mail_Subject = "VERIFIED IPN"; $mail_Body = $req; mail($mail_To, $mail_Subject, $mail_Body, $mail_From); } else if (strcmp ($res, "INVALID") == 0) { //write to file $fh = fopen("logipn.txt", 'a');//open file and create if does not exist fwrite($fh, "\r\n/////////////////////////////////////////\r\n Invalid \r\n");//Just for spacing in log file fwrite($fh, $req);//write data fclose($fh);//close file $mail_From = "From: IPN@tester.com"; $mail_To = $email; $mail_Subject = "INVALID IPN"; $mail_Body = $req; mail($mail_To, $mail_Subject, $mail_Body, $mail_From); } } fclose ($fp);//close file pointer } $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']; //$username=$_POST['username']; if (!$fp) { // HTTP ERROR } else { fputs ($fp, $header . $req); while (!feof($fp)) { $res = fgets ($fp, 1024); if (strcmp ($res, "VERIFIED") == 0) { if (strtolower($payment_status)=="completed") { if ($payment_amount==0.01&&$payment_currency=="GBP") { $update = mysql_query("UPDATE users SET credit= credit+5 WHERE email='$payer_email'"); } } // 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 } else if (strcmp ($res, "INVALID") == 0) { // log for manual investigation } } fclose ($fp); } ?> Hey guys i have created a paypal IPN script and it takes various info from users via paypal. Anyways i store their info into a database along with their email however i dont want them to be able to purchase again with the same email (long story) anways by the time i receive the info from paypal the payments already gone through so its too late for me to do the checking against the database. Is there anyway i can auto refund the payment do paypal allow this? Hope someone can help. Thanks! Hi all I have a quick PayPal IPN question, is this the right group to post the message and does anyone know much about the PayPal IPN? Thanks I just did the ipn page to store paypal transactions into my database but it doesnt seem to be working. Is there anything else that i need to do other than creating the ipn page? <?php mysql_connect("localhost", "root", "") or die(mysql_error()); mysql_select_db("pbstore") or die(mysql_error()); // 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"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); if (!$fp) { // HTTP ERROR } else { fputs ($fp, $header . $req); while (!feof($fp)) { $res = fgets ($fp, 1024); if (strcmp ($res, "VERIFIED") == 0) { // PAYMENT VALIDATED & VERIFIED! $email = $_POST['payer_email']; $name = $_POST['item_name']; mysql_query("INSERT into sales (name, email) VALUES('".$name."', '".$email."')")or die(mysql_error()); mysql_query("INSERT INTO users (email, password) VALUES('". mysql_escape_string($email) ."', '".md5($password)."' ) ") or die(mysql_error()); } else if (strcmp ($res, "INVALID") == 0) { // PAYMENT INVALID & INVESTIGATE MANUALY! } } fclose ($fp); } ?> Hey Guys, i have another problem, i am using paypal IPN, and i want the details of the order to be stored in my orders table of the databse as well as sending me an email. Im pretty sure the code is ok, but it is not working. Can some one please take a look? <?php include('db_fns.php'); // change these to your paypal settings $paypal_email = "benmunns@gmail.com"; $paypal_currency = 'USD'; $shipping = 10.00; /** * checks if paypal trans id is already in database * @param int $trans_id * @return bool */ function no_paypal_trans_id($trans_id) { $connection = db_connect(); $query = sprintf("SELECT id from orders WHERE paypal_trans_id = '%s'", mysql_real_escape_string($trans_id)); $result = mysql_query($query); $num_results = mysql_num_rows($result); if($num_results == 0) { return true; } return false; } /** * checks to make sure that paypal payment amount is correct * @param int $shipping * @param array $params * @return bool */ function payment_amount_correct($shipping, $params) { $amount = 0.00; for ($i=1; $i <= $params['num_cart_items']; $i++) { $query = sprintf("SELECT price from products where id='%s'", mysql_real_escape_string($params["item_number{$i}"])); $result = mysql_query($query); if($result) { $item_price = mysql_result($result, 0, 'price'); $amount += $item_price * $params["quantity{$i}"]; } } if(($amount+$shipping) == $params['mc_gross']) { return true; } else { return false; } } /** * creates order and adds items * @param array $params * @return bool */ function create_order($params) { db_connect(); $query = sprintf("INSERT INTO orders set orders.firstname = '%s', orders.lastname = '%s', orders.email = '%s', orders.country = '%s', orders.address = '%s', orders.city = '%s', orders.zip_code = '%s', orders.state = '%s', orders.status = '%s', orders.amount = '%s', orders.paypal_trans_id = '%s', created_at = NOW() ", mysql_real_escape_string($params['first_name']), mysql_real_escape_string($params['last_name']), mysql_real_escape_string($params['payer_email']), mysql_real_escape_string($params['address_country']), mysql_real_escape_string($params['address_street']), mysql_real_escape_string($params['address_city']), mysql_real_escape_string($params['address_zip']), mysql_real_escape_string($params['address_state']), mysql_real_escape_string($params['payment_status']), mysql_real_escape_string($params['mc_gross']), mysql_real_escape_string($params['txn_id']) ); $result = mysql_query($query); if(!$result) { return false; } $order_id = mysql_insert_id(); for ($i=1; $i <= $params['num_cart_items'] ; $i++) { $product = find_product($params["item_number{$i}"]); $query = sprintf("INSERT INTO items set order_id = '%s', product_id = '%s', title = '%s', price = '%s', qty = '%s' ", mysql_real_escape_string($order_id), mysql_real_escape_string($product['id']), mysql_real_escape_string($product['title']), mysql_real_escape_string($product['price']), mysql_real_escape_string($params["quantity{$i}"]) ); $result = mysql_query($query); if(!$result) { return false; } } return true; } // 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"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; $fp = fsockopen ('www.paypal.com', 80, $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']; if (!$fp) { // HTTP ERROR } else { fputs ($fp, $header . $req); while (!feof($fp)) { $res = fgets ($fp, 1024); if (strcmp ($res, "VERIFIED") == 0) { if ($_POST['payment_status'] == 'Completed' && no_paypal_trans_id($_POST['txn_id']) && $paypal_email == $_POST['receiver_email'] && $paypal_currency == $_POST['mc_currency'] && payment_amount_correct($shipping, $_POST) ) { // process payment create_order($_POST); } } else if (strcmp ($res, "INVALID") == 0) { // log for manual investigation } } fclose ($fp); } ?> Hi, I am new here, so hello everyone. I really need some help with getting Paypal IPN working correctly. This is what I am trying to do. I have a user database, when the user logs in, they have the option to upgrade/subscribe to our website. So when they subscribe and payment is validated, I want a specific field in a specific table updated based on the user's unique ID, not based on [payer_email], so how do I pass on that parameter using IPN? right now I added the "userId" to a hidden field in the Paypal subscription form named "on1".... I hope this isn't confusing - would really appreciate your help - I added code below. Code: [Select] <?php DB info -- // 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"; $header .= "Content-Type: application/x-www-form-urlencoded\r\n"; $header .= "Content-Length: " . strlen($req) . "\r\n\r\n"; $fp = fsockopen ('ssl://www.sandbox.paypal.com', 443, $errno, $errstr, 30); if (!$fp) { // HTTP ERROR } else { fputs ($fp, $header . $req); while (!feof($fp)) { $res = fgets ($fp, 1024); if (strcmp ($res, "VERIFIED") == 0) { // PAYMENT VALIDATED & VERIFIED! $email = $_POST['payer_email']; $userId=$_POST['on1']; $membership = '2'; mysql_query("UPDATE users SET membership=".$membership." WHERE userId=".$userId) or die(mysql_error()); $to = $email; $subject = 'subject line'; $message = ' message here '; mail($to, $subject, $message, $headers); } else if (strcmp ($res, "INVALID") == 0) { // PAYMENT INVALID & INVESTIGATE MANUALY! $to = 'my_email'; $subject = 'subject lin'; $message = ' Dear Administrator, A payment has been made but is flagged as INVALID. Please verify the payment manualy and contact the buyer. Buyer Email: '.$email.' '; $headers = 'From:my_email' . "\r\n"; mail($to, $subject, $message, $headers); } } fclose ($fp); } ?> Hi, How to get paypal transection id on return after someone pay if i've paypal payment form as following Code: [Select] <form action="https://www.paypal.com/cgi-bin/webscr" method="post"> <input type="hidden" name="cmd" value="_xclick"> <input type="hidden" name="business" value="<?=$line[paypalid]?>"> <input type="hidden" name="item_name" value="Payment Your Hits"> <input type="hidden" name="item_number" value="1"> <input type="hidden" name="amount" value="<?=$usd?>"> <input type="hidden" name="no_shipping" value="0"> <input type="hidden" name="no_note" value="payment from website submittion"> <input type="hidden" name="currency_code" value="USD"> <input type="hidden" name="lc" value="AU"> <input type="hidden" name="bn" value="PP-BuyNowBF"> <input type="hidden" name="return" value="<?=$site_root?>/return.php?id=<?=$line[id]?>"> <button type="submit" class="clean-green">Pay Now</button> </form> on return i will get it by id which is <?$line[id]?> but i want to get the transection id of payment too how it comes ? Hi, I am about to incorporate some PayPal functions to my site and am just asking for some advice before I start. Basically a user is going to enter some data into a form and then be passed to PayPal to pay an X amount, once the payment has been verified I want the information entered in the form (before going to PayPal), to be added to a database. But it seems that PayPal does not allow you to pass multiple (about 13) variables through their system. Is this correct? So what I was going to do is just before the customer goes to the PayPal site, I was going to insert all the data into the database and set a payment status, then once the payment is confirmed re-setting the payment status to paid or non-paid. Is that a good way to do what I want? If not is there a better way? Any help would be great. Lee Hi, I have setup my paypal payment method for a shopping cart on my site, all is well but in order for my server to flag an invoice as paid, the user must return to my website after paying and the query string in the url give the script the go ahead to mark it as paid which in turn alerts the appropriate department that its ok to source the order. ~The problem is, if the user for whatever reason skip the redirect back to my site, the invoice is remain 'unpaid' and has to be changed manually when the payment has been checked in the account. As you might imagine this is a bit of a problem because not only can it cause quite a delay, it also requires manually changing values which can lead to other problems. So if there is a better way i would appreciate the info, thanks a lot. Hi, i am building a website where users have a choice to buy a subscription to the next level gold, silver, bronze. Now i have used paypal before for one off payments but i'm finding it to be a problem when i have three seperate buy now buttons Code: [Select] <?php if ($payment_status == "Completed"){ if ($item_name == "Bronze Membership" && $payment_amount == 4.99&&$payment_currency == "USD"){ $update = mysql_query("UPDATE users SET membership = '1' WHERE email = '$payer_email'"); } if ($item_name == "Silver Membership" && $payment_amount == 9.99&&$payment_currency == "USD"){ $update = mysql_query("UPDATE users SET membership = '2' WHERE email = '$payer_email'"); } if ($item_name == "Gold Membership" && $payment_amount == 19.99&&$payment_currency == "USD"){ $update = mysql_query("UPDATE users SET membership = '3' WHERE email = '$payer_email'"); } } ?> As you can see i am checking that the item name is the correct name aswell as price but in the sandbox it wont work. Additional info Code: [Select] <form action="https://www.paypal.com/cgi-bin/webscr" method="post"> <input type="hidden" name="cmd" value="_xclick"> <input type="hidden" name="business" value="myemail"> <input type="hidden" name="item_name" value="Bronze Membership"> <input type="hidden" name="currency_code" value="USD"> <input type="hidden" name="amount" value="4.99"> <input type="image" src = "http://www.paypal.com/en_US/i/btn/x-click-but01.gif" name="submit" height="30" width="65" alt="Make payments with paypal - it's fast, free and secure!"> </form> |