131

This is a follow up question to: PHP: Easy way to start PayPal checkout?

So, my problem is that I am specifying the return url. However, after paying with PayPal, I end up at a a screen that says:

You just completed your payment. XXXX, you just completed your payment. Your transaction ID for this payment is: XXXXXXXXXXXXX.

We'll send a confirmation email to XX@XXXX.com. This transaction will appear on your statement as PAYPAL.

Go to PayPal account overview

I need it to not show this screen and go directly to the return URL. I have:

  • Set the "return" variable
  • Set the "rm" variable to: 2 (which according to the guide = "the buyer’s browser is redirected to the return URL by using the POST method, and all payment variables are included")

In fact, here's my whole form:

<form method="post" action="https://www.sandbox.paypal.com/cgi-bin/webscr">
  <input type="hidden" value="_xclick" name="cmd">
  <input type="hidden" value="onlinestore@thegreekmerchant.com" name="business">
  <!-- <input type="hidden" name="undefined_quantity" value="1" /> -->
  <input type="hidden" value="Order at The Greek Merchant:&lt;Br /&gt;Goldfish Flock BLG&lt;br /&gt;" name="item_name">
  <input type="hidden" value="NA" name="item_number">
  <input type="hidden" value="22.16" name="amount">
  <input type="hidden" value="5.17" name="shipping">
  <input type="hidden" value="0" name="discount_amount">        
  <input type="hidden" value="0" name="no_shipping">
  <input type="hidden" value="No comments" name="cn">
  <input type="hidden" value="USD" name="currency_code">
  <input type="hidden" value="http://XXX/XXX/XXX/paypal/return" name="return">
  <input type="hidden" value="2" name="rm">      
  <input type="hidden" value="11255XXX" name="invoice">
  <input type="hidden" value="US" name="lc">
  <input type="hidden" value="PP-BuyNowBF" name="bn">
  <input type="submit" value="Place Order!" name="finalizeOrder" id="finalizeOrder" class="submitButton">
</form>

Any idea how I can get it to automatically go back? Alternatively, how do I get the result of the payment back to my website so I can update the database? What is IPN?

Community
  • 1
  • 1
rockstardev
  • 13,479
  • 39
  • 164
  • 296
  • Please note, that the enteres host in your custom return parameter must be the same as configured in your paypal account. – Andreas Nov 23 '17 at 13:13

6 Answers6

203

You have to enable auto return in your PayPal account, otherwise it will ignore the return field.

From the documentation (updated to reflect new layout Jan 2019):

Auto Return is turned off by default. To turn on Auto Return:

  1. Log in to your PayPal account at https://www.paypal.com or https://www.sandbox.paypal.com The My Account Overview page appears.
  2. Click the gear icon top right. The Profile Summary page appears.
  3. Click the My Selling Preferences link in the left column.
  4. Under the Selling Online section, click the Update link in the row for Website Preferences. The Website Payment Preferences page appears
  5. Under Auto Return for Website Payments, click the On radio button to enable Auto Return.
  6. In the Return URL field, enter the URL to which you want your payers redirected after they complete their payments. NOTE: PayPal checks the Return URL that you enter. If the URL is not properly formatted or cannot be validated, PayPal will not activate Auto Return.
  7. Scroll to the bottom of the page, and click the Save button.

IPN is for instant payment notification. It will give you more reliable/useful information than what you'll get from auto-return.

Documentation for IPN is here: https://www.x.com/sites/default/files/ipnguide.pdf

Online Documentation for IPN: https://developer.paypal.com/docs/classic/ipn/gs_IPN/

The general procedure is that you pass a notify_url parameter with the request, and set up a page which handles and validates IPN notifications, and PayPal will send requests to that page to notify you when payments/refunds/etc. go through. That IPN handler page would then be the correct place to update the database to mark orders as having been paid.

artfulrobot
  • 20,637
  • 11
  • 55
  • 81
Kevin Stricker
  • 17,178
  • 5
  • 45
  • 71
  • Why I cannot see Website Payment Preferences link? I just use Sandbox tets account..... – NoWar Nov 16 '12 at 00:41
  • 2
    Have a look here https://www.paypal.com/cgi-bin/webscr?cmd=p/mer/express_return_summary-outside – NoWar Nov 16 '12 at 00:52
  • 5
    With Paypal's new web site layout, this is no longer exactly accurate. Step 3) Click `My Selling Tools` Step 4) Click `Website Preferences` under `Selling Online` – Ben Mar 18 '13 at 11:28
  • That's a real shame. Supplying a dynamic return url is a really useful feature and having to force users to go and modify a setting in their paypal account sucks because if you're writing a general paypal plugin you want the user to copy and paste. – Rob Evans Apr 30 '13 at 19:42
  • @RobEvans It shouldn't continue to ignore the return URL you pass as long as you've set a default in the account. – Kevin Stricker Apr 30 '13 at 19:46
  • @mootinator That's cool but it's that step of getting a user to modify their account setting first that is upsetting, most users have a hard time installing a basic wordpress plugin let alone following instructions to mess with their paypal account settings. It should be something that is developer-controlled IMHO but I appreciate you pointing out that it WILL override when that setting is set. – Rob Evans Apr 30 '13 at 22:06
  • @RobEvans - If you turn Auto-return On, you skip the PayPal "Receipt" page where the customer can print a receipt, and go directly to your website. PayPal wants to make sure that your *Return* page explains that the payment was successful, and the purchase is completed, and explains how the customer will receive their purchase... In other words, they want to make sure it provides at least an acceptable user experience so the customer won't be confused or unnecessarily concerned. They *Assume* if you've made your Return page correctly once, you'll continue to do so. – Kevin Fegan May 03 '13 at 23:04
  • 2
    IPN should be used to verify the order was correctly handled by PayPal, however, you still need the return url to show to the user your aware of the success. So many times user's don't get the email you send out, so it is nice if they can get access to the product (download, etc) right away. – pcunite Jun 05 '13 at 00:37
  • 1
    @Kevin Stricker How can we setup return url for 2 different sites? like if i use one paypal account for 2 websites, but i can add only one URL as return url using your steps. how can i use that for 2 sites? – Gaurav Sep 02 '15 at 17:32
  • Have you tried passing an alternate url in the "return" variable? – Kevin Stricker Sep 02 '15 at 18:31
  • Thanks. If you are looking for an auto return setting for sandbox account, this post helps me http://stackoverflow.com/questions/15355265/how-to-configure-paypal-sandbox-auto-return-url – Han Oct 27 '15 at 10:17
  • @Rob Evans and anyone reading this message. A person setting up a PayPal Business account has a lot of settings required to set up for it. If you are providing a PP plugin, you also MUST provide explicit and complete (not origami-style 1 in 3 steps) instructions for how your users set up EVERY relevant PP setting, otherwise they are likely to get bad results, and at worst, lose customers. Of course, if your plugin can ENSURE that it ALWAYS provides 'return' and 'cancel_return' URLs for EVERY transaction, then you can instruct your users to just put their site's URL there as a placeholder. – Patanjali Mar 01 '16 at 21:43
  • @Patanjali Not sure you added anything there... all you're saying is when you write software make sure you document it and write easy to read instructions for users. – Rob Evans Mar 02 '16 at 10:01
  • @KevinStricker , Can you have a look on this question ? http://stackoverflow.com/questions/20406455/paypal-not-posting-data-on-return-url-on-mobile-browsers – sijo vijayan Mar 03 '16 at 05:57
  • @RobEvans, You were complaining that you couldn't protect users from themselves, and I was laying out what needed to provided by any plugin AND what the documentation needed to cover, given the CURRENT situation. However, I reiterate that interfacing with PayPal is non-trivial, and PP require that some things are done by the users, perhaps because they want to make sure that the users take final responsibility, rather than just leaving it to developers. – Patanjali Mar 10 '16 at 15:33
  • Go [here](https://www.sandbox.paypal.com/us/cgi-bin/webscr?cmd=_profile-website-payments) to enable this option in sandbox mode. – Maxime Lafarie Jul 05 '16 at 14:46
  • 4
    It's not quite accurate that _"You have to enable auto return in your PayPal account, otherwise it will ignore the `return` field."_ Any `return` URL parameter you pass to checkout would be honored and override any Auto Return URL (or lack thereof) configured in the seller's PayPal account profile, but if they don't have Auto Return enabled there, the buyer would need to manually click past the end of checkout in order to be redirected to that URL, rather than being redirected automatically. – SubGothius Aug 11 '16 at 20:58
  • Okay here is the thing. I have implemented IPN and it has executed when recurring payments occurs. When IPN URL is down, the recurring payment will happen ofcourse but we wont get notified from IPN and so we cannot update values in the database. How to handle this issue? – viper Aug 19 '16 at 05:33
  • @Gaurav The return url set in your account is the catchall one, but you can override it by setting a `return` hidden HTML field for each transaction. – Patanjali Jan 25 '18 at 19:11
  • 1
    PayPal has redesigned their site again (after 2018 as described above in the comment from @Webnet ). The sequence is now 2) Click the gear icon 3) Select `Account Settings` 4) On the left under `Products & Services` click `Website payments` 5) To the right of `Website preferences` click `Update`. Then continue in the sequence described in the answer at step `5` – gene_wood Feb 24 '20 at 05:51
45

Sample form using PHP for direct payments.

<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
    <input type="hidden" name="cmd" value="_cart">
    <input type="hidden" name="upload" value="1">
    <input type="hidden" name="business" value="you@youremail.com">

    <input type="hidden" name="item_name_' . $x . '" value="' . $product_name . '">
    <input type="hidden" name="amount_' . $x . '" value="' . $price . '">
    <input type="hidden" name="quantity_' . $x . '" value="' . $each_item['quantity'] . '"> 
    <input type="hidden" name="custom" value="' . $product_id_array . '">
    <input type="hidden" name="notify_url" value="https://www.yoursite.com/my_ipn.php">
    <input type="hidden" name="return" value="https://www.yoursite.com/checkout_complete.php">
    <input type="hidden" name="rm" value="2">
    <input type="hidden" name="cbt" value="Return to The Store">
    <input type="hidden" name="cancel_return" value="https://www.yoursite.com/paypal_cancel.php">
    <input type="hidden" name="lc" value="US">
    <input type="hidden" name="currency_code" value="USD">
    <input type="image" src="http://www.paypal.com/en_US/i/btn/x-click-but01.gif" name="submit" alt="Make payments with PayPal - its fast, free and secure!">
</form>

kindly go through the fields notify_url, return, cancel_return

sample code for handling ipn (my_ipn.php) which is requested by paypal after payment has been made.

For more information on creating a IPN, please refer to this link.

<?php
// Check to see there are posted variables coming into the script
if ($_SERVER['REQUEST_METHOD'] != "POST")
    die("No Post Variables");
// Initialize the $req variable and add CMD key value pair
$req = 'cmd=_notify-validate';
// Read the post from PayPal
foreach ($_POST as $key => $value) {
    $value = urlencode(stripslashes($value));
    $req .= "&$key=$value";
}
// Now Post all of that back to PayPal's server using curl, and validate everything with PayPal
// We will use CURL instead of PHP for this for a more universally operable script (fsockopen has issues on some environments)
//$url = "https://www.sandbox.paypal.com/cgi-bin/webscr";
$url = "https://www.paypal.com/cgi-bin/webscr";
$curl_result = $curl_err = '';
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $req);
curl_setopt($ch, CURLOPT_HTTPHEADER, array("Content-Type: application/x-www-form-urlencoded", "Content-Length: " . strlen($req)));
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_VERBOSE, 1);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_TIMEOUT, 30);
$curl_result = @curl_exec($ch);
$curl_err = curl_error($ch);
curl_close($ch);

$req = str_replace("&", "\n", $req);  // Make it a nice list in case we want to email it to ourselves for reporting
// Check that the result verifies
if (strpos($curl_result, "VERIFIED") !== false) {
    $req .= "\n\nPaypal Verified OK";
} else {
    $req .= "\n\nData NOT verified from Paypal!";
    mail("you@youremail.com", "IPN interaction not verified", "$req", "From: you@youremail.com");
    exit();
}

/* CHECK THESE 4 THINGS BEFORE PROCESSING THE TRANSACTION, HANDLE THEM AS YOU WISH
  1. Make sure that business email returned is your business email
  2. Make sure that the transaction�s payment status is �completed�
  3. Make sure there are no duplicate txn_id
  4. Make sure the payment amount matches what you charge for items. (Defeat Price-Jacking) */

// Check Number 1 ------------------------------------------------------------------------------------------------------------
$receiver_email = $_POST['receiver_email'];
if ($receiver_email != "you@youremail.com") {
//handle the wrong business url
    exit(); // exit script
}
// Check number 2 ------------------------------------------------------------------------------------------------------------
if ($_POST['payment_status'] != "Completed") {
    // Handle how you think you should if a payment is not complete yet, a few scenarios can cause a transaction to be incomplete
}

// Check number 3 ------------------------------------------------------------------------------------------------------------
$this_txn = $_POST['txn_id'];
//check for duplicate txn_ids in the database
// Check number 4 ------------------------------------------------------------------------------------------------------------
$product_id_string = $_POST['custom'];
$product_id_string = rtrim($product_id_string, ","); // remove last comma
// Explode the string, make it an array, then query all the prices out, add them up, and make sure they match the payment_gross amount
// END ALL SECURITY CHECKS NOW IN THE DATABASE IT GOES ------------------------------------
////////////////////////////////////////////////////
// Homework - Examples of assigning local variables from the POST variables
$txn_id = $_POST['txn_id'];
$payer_email = $_POST['payer_email'];
$custom = $_POST['custom'];
// Place the transaction into the database
// Mail yourself the details
mail("you@youremail.com", "NORMAL IPN RESULT YAY MONEY!", $req, "From: you@youremail.com");
?>

The below image will help you in understanding the paypal process. Paypal process flow

For further reading refer to the following links;

hope this helps you..:)

Christo
  • 2,330
  • 3
  • 24
  • 37
  • 1
    Anyone know if this is still valid with todays paypal APIs? I see that the question is 2 years old. – Matt Welander Apr 25 '14 at 10:42
  • 1
    The 'return' and 'cancel_return' URLs are used for providing immediate transaction feedback to the buyer, and can use PDT variables for that. However, PP only tries once with them, so they cannot be relied upon for critical order fulfilment (say buyer closes browser after payment, but still at PP). For that, you may want to also back it up with the reliable IPN process, via 'notify_url', processing the 'Completed' status at a minimum (assume anything else is a fail, perhaps requiring manual negotiation). Your PDT and IPN server processing will need to ensure that the order is only filled once. – Patanjali Mar 01 '16 at 22:14
  • I belive things have changed and Paypal success.php now only works with GET variables. See here: https://stackoverflow.com/questions/45671366/paypal-buynow-get-instead-of-post-with-params-for-returnurl – SolaceBeforeDawn Aug 31 '17 at 01:05
23

one way i have found:

try to insert this field into your generated form code:

<input type='hidden' name='rm' value='2'>

rm means return method;

2 means (post)

Than after user purchases and returns to your site url, then that url gets the POST parameters as well

p.s. if using php, try to insert var_dump($_POST); in your return url(script),then make a test purchase and when you return back to your site you will see what variables are got on your url.

Matt
  • 3,617
  • 2
  • 27
  • 39
T.Todua
  • 53,146
  • 19
  • 236
  • 237
4

Sharing this as I've recently encountered issues similar to this thread

For a long time, my script worked well (basic payment form) and returned the POST variables to my success.php page and the IPN data as POST variables also. However, lately, I noticed the return page (success.php) was no longer receiving any POST vars. I tested in Sandbox and live and I'm pretty sure PayPal have changed something !

The notify_url still receives the correct IPN data allowing me to update DB, but I've not been able to display a success message on my return URL (success.php) page.

Despite trying many combinations to switch options on and off in PayPal website payment preferences and IPN, I've had to make some changes to my script to ensure I can still process a message. I've accomplished this by turning on PDT and Auto Return, after following this excellent guide.

Now it all works fine, but the only issue is the return URL contains all of the PDT variables which is ugly!

You may also find this helpful

Chamilyan
  • 9,347
  • 10
  • 38
  • 67
SolaceBeforeDawn
  • 958
  • 1
  • 8
  • 16
3

I think that the idea of setting the Auto Return values as described above by Kevin is a bit strange!

Say, for example, that you have a number of websites that use the same PayPal account to handle your payments, or say that you have a number of sections in one website that perform different purchasing tasks, and require different return-addresses when the payment is completed. If I put a button on my page as described above in the 'Sample form using PHP for direct payments' section, you can see that there is a line there:

input type="hidden" name="return" value="https://www.yoursite.com/checkout_complete.php"

where you set the individual return value. Why does it have to be set generally, in the profile section as well?!?!

Also, because you can only set one value in the Profile Section, it means (AFAIK) that you cannot use the Auto Return on a site with multiple actions.

Comments please??

Tim Makins
  • 394
  • 4
  • 12
  • 3
    the return parameter can be passed for each form overriding the auto return url setup in the paypal config – DropHit Sep 18 '15 at 02:25
  • 1
    yeah what DropHit said, that is just the default auto return value, in case you forget to pass it in as a parameter. if you pass it in as a parameter it will use your return url for each of your websites. – hamish Oct 23 '15 at 23:27
  • does this help? https://codeseekah.com/2012/02/11/how-to-setup-multiple-ipn-receivers-in-paypal/ – hamish Oct 23 '15 at 23:41
  • @DropHit Does PDT still work with per-button overrriden `return` values then? So I can have different return pages that will still all receive PDT data? – Dai Dec 03 '16 at 02:39
  • Sorry for the late reply - i am not certain that it will work BUT my current integrations are still operating as expected although that does not guarantee that your use case will work as mine does – DropHit Mar 08 '17 at 03:46
  • So as @Tim Makins said, I am having the same question... I have one checkout page and many PayPal accounts... Could I have ONE return URL ? And this URL will overwrite the one inside Merchant's Paypal account? – Kiriakos Grhgoriadhs Oct 10 '18 at 21:00
1

on the checkout page, look for the 'cancel_return' hidden form element:

set the value of the cancel_return form element to the URL you wish to return to:

Rahul Shinde
  • 1,522
  • 1
  • 15
  • 17
  • Actually, 'cancel return' is only used when the transaction fails. You MUST also provide a 'return' URL to handle successfully completed transactions, otherwise the default URL will be used for them. – Patanjali Mar 01 '16 at 21:54
  • Not when the transaction fails but, rather, when the buyer clicks the "Cancel and return to [merchant name]" link during checkout to abandon completing their order. – SubGothius Aug 11 '16 at 21:11