I'm using Micha's PayPal IPN script and for the most part it worked great: https://github.com/Quixotix/PHP-PayPal-IPN
When i click Pay now on the website it redirects to paypal with correct information, allows payment to be made, but on return nothing happens, ie it does not upgrade the user as it should. Now i've tested the script my code outside of the IPN and it works perfect so it looks to me like the IPN script is losing the session?
Here is my button code:
<form name="_xclick" action="https://www.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="EMAIL_TO">
<input type="hidden" name="currency_code" value="GBP">
<input type="hidden" name="item_name" value="Text Light">
<input type="hidden" name="amount" value="0.01">
<input type="hidden" name="return" value="http://domain.co.uk/editors">
<input type="hidden" name="notify_url" value="http://domain.co.uk/account/upgrade">
<input type="submit" value="Pay now" class="btn btn-preview" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
</form>
So the notify url (IPN code) is /account/upgrade -- as far as i know this is where it should perform the upgrade task? so here is my (stripped down) code
if ($verified) {
$errmsg = '';
// some error checking
if (!empty($errmsg)) {
// manually investigate errors from the fraud checking
} else {
// upgrade user
$package = serialize($_SESSION['package']);
$this->db->update('users',array('id' => $_SESSION['user']['id']),array('payment_plan' => $package));
}
} else {
// not verified, investigate problems
}
As above, the code under '// upgrade user' works fine outside, but on return from paypal it's obviously not keeping hold of the session. It's not throwing any errors, it's just not doing anything.
Where have i gone wrong? how can i ensure that session information will be passed back from PayPal.
Thanks
Your question has a short answer: IPN isn't done as the user.
To expand on the answer, here's how IPN works. You make a payment, your visitor returns to your site, and PayPal pings your IPN URL. The important bit is in bold - the request will come from PayPal and not from the user, and will therefore not inherit the user's session!
The reason for this is pretty simple - the IPN URL is supposed to be private, as you could do all sort of silly shenanigans if it wasn't (including creating virtual transactions). For this very reason, the user never sees this address. (Another reason is that not all browsers will follow redirects - and IPN is designed to provide information 100% of the time).
If you would like to do this, you'll need to pass a parameter to the IPN request indicating who the user is. Passing the user ID is a very bad idea - as parameters as modifiable. Instead, generate a transaction ID of some sort containing the info on the user, and pass this. On the IPN call, you'll get this variable back as a custom parameter, which will allow you to fetch stuff from your DB and do whatever you want, knowing who the user was.
Hope this helped.
I saw an answer posted elsewhere that worked for me. For the return_url, I simply removed the "www" part of my web address. So, instead of the retun_url being "https://www.mywebsite.com/ReturnPage.aspx" I changed it to "https://mywebsite.com/ReturnPage.aspx". This seems to keep the session intact.
Related
I implemented a paypal checkout about 3 years ago and it is currently working well. I now want to create a new checkout page for a new set of items. I copied the code from the page that I previously used and updated it for the new items. I set up the new page to use my sandbox for initial testing. The code below is cut from the actual page for display here.
<!DOCTYPE HTML >
<html>
<head>
</head>
<body>
<div>
<form id='paypal_form' action="https://www.sandbox.paypal.com/cgi-bin/webscr" method="post">
<input type="hidden" name="cmd" value="_xclick" />
<input type="hidden" name="add" value="1" />
<input type="hidden" name="business" value="buyer#test.com" />
<input type="hidden" name="item_name" value="non-member RTV Renewal" />
<input type="hidden" name="amount" value="75.00" />
<input type="hidden" name="custom" value="Id=Joe;fixedName=Joe Smith;pw=1234;email=buyer#google.com;expdate=2024-02-14" />
<input type="hidden" name="currency_code" value="USD" />
<input type="hidden" name="lc" value="US" />
<input type="hidden" name="cancel_return" value="https://www.roundalab.org/Figures_Subscriptions_All/test_renew.htm">
<input type="hidden" name="return" value="https://www.roundalab.org/Figures_Subscriptions_All/success_test.php">
<input type="hidden" name="rm" value="2">
<center>
<div id="add-cart" style="padding:30px;">
<button onClick="document.getElementById('paypal_form').submit();">Click Here To Submit Order To Paypal</button>
</div>
</center>
</form>
</div>
</div>
</body>
</html>
The code works and creates an order in the paypal sandbox. It is then supposed to go the the url in the "return' item, which it does. The problem is that paypal is supposed to return a bunch of data in $_POST. When the return page is displayed, $_POST is empty. I also display $_GET and it contains 1 field which is the payer_id. A couple of questions...
Anyone know why no data in $_POST?
Is there a way that I can get any kind of error message that shows info on why no POST data was sent when going to the url in the return item?
I assume that this method of using paypal is deprecated. Is there a place that I can still get to the docs for using this interface?
The receiving sandbox Business account needs to enable Payment Data Transfer for any data to be returned.
With this sort of HTML-only (no API) PayPal integration that redirects away from your site, a return after a completed transaction is never guaranteed to occur. PayPal may be obligated to show the payer a receipt, or they may never click to return, or their browser may be closed or crash. Therefore, you should not depend on this returned data for absolutely anything of any importance. It is for extra informational purposes only.
If you are trying to do anything important with data returned via _GET/_POST , your integration is flawed.
With such an HTML-only <form> post integration, the only reliable way to receive data is by implementing the IPN service, which is also very old. All of these are poor choices if you need to do anything important with the data being returned.
Instead, use a current PayPal Checkout integration. Follow the Set up standard payments guide and make 2 routes on your server, one for 'Create Order' and one for 'Capture Order', documented here. Both routes should return only JSON data (no HTML or text). Inside the 2nd route, when the capture API is successful you should store its resulting payment details in your database (particularly purchase_units[0].payments.captures[0].id, which is the PayPal transaction ID) and perform any necessary business logic (such as sending confirmation emails or reserving product) immediately before forwarding your return JSON to the frontend caller.
Pair those 2 routes with the frontend approval flow: https://developer.paypal.com/demo/checkout/#/pattern/server
On my order page, I'm using this form:
<input type="hidden" name="item_number" value="<?php echo $refNumber; ?>">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="<?php echo $paypal_email; ?>" />
<input type="hidden" name="currency_code" value="USD" />
<input type="hidden" name="return" value="<?=$_SESSION["web_site_url"]?>/payment_success.php?OrderID=<?=$refNumber;?>" />
input type="hidden" name="amount" id="amount" value="<?=$product_vals["discount_prize"]?>" />
<input type="hidden" name="item_name" id="item_name" value="<?=$product_vals["name"]?>" />
now I want a sample code for my payment_success page from that i came to know whether paypal authenticate the client payment or the client's payment is success of not.. so that i can proceed to next step of gathering information from client.
I have read the Paypal docs but unable to learn useful from them. help me out to solve this problem.Moreover i also want to get the paypal email of client and transaction id / payment_success variable (that is true/false) so that i will help me to identify the payment is succesful or not..
Thanks in advance.
You can use paypal class by Micah Carrick. This is pretty clear class which support notify URL, return URL and success URL. You dont need to use any form or something but just use this class and let this class to do your job.
sample code is:
$p = new paypal_class;
$p->add_field('business', $paypal_email);
$p->add_field('return', $add_fund_url.'/success.php');
$p->add_field('cancel_return', $add_fund_url.'/cancel.php');
$p->add_field('notify_url', $notify_url );
$p->add_field('item_name', $item_name);
$p->add_field('item_number', $item_number);
$p->add_field('custom',$custom_field);
$p->add_field('amount', $amount);
$p->add_field('no_shipping', '1');
$p->submit_paypal_post(); // submit the fields to paypal
If you're gather more data after they pay then you should really using Express Checkout APIs instead of PayPal Standard like you're using now. Even with Auto-Return enabled in your PayPal profile the user still may not make it back to your site (for example, they could simply close their browser before the redirect happens.)
With Express Checkout the user will always end up back on your site even before the final call to finalize the payment, so you could actually gather the additional details from the user even before finalizing the payment if you wanted to.
Check out this guide on Implementing the Simplest Express Checkout Integration. That will get you familiar with how Express Checkout should be setup (ie. the API calls you'll be making).
Then, grab this PayPal PHP SDK and use it to make the API calls. It has everything setup for you so that it would be very quick and easy for you to integrate into your checkout.
I am attempting to set up a PayPal 'subscription' payment button on a site I'm working on. It's a form that gets sent to PayPal and then sends the user back to a return URL when the transaction is successfully completed. I'm currently using the PayPal Sandbox to test this. The problem is that the POST variables are not being sent to the thank you page (which is a PHP page FYI).
The reason I need this is that I'm updating a database and if a user successfully completes a transaction, it needs to take a look at the variables being returned, determine that the user paid and then update the user's information in the MySQL database automatically.
I've been in touch with a PayPal rep for the past two weeks and they can't seem to help. I've also researched all over the web and Stack Overflow and none of the current answers seem to address my issue. Here's what I've tried:
I started by trying to use GET variables (like but GET variables are not supported in this way. It caused the return URL to have a crazy string of variables returned on the end of it and not my ID variable (it was like a charset and something else). The PayPal rep explained that the variables I needed to use are POST variables.
I've set up the pages on three different servers/hosting packages to see if the host was the issue. The three I've used are GoDaddy, JustHost and 123-reg (UK). None work. I assumed the hosts would be fine since PayPal is so ubiquitous but I double checked to be sure. I know that the .htaccess file isn't preventing POST variables from working because I've used the PHP mail function from a form on this site already so that all works.
I tried $_REQUEST variables instead of $_POST variables as suggested here: Paypal Hidden variables doesn't work
Here is the code being used on the two pages. Feel free to go to these pages as well to test out the issue yourself and see that is doesn't work:
Page
http://www.miller-media.com/sites/paypal_test/test_form.php
Code
<html>
<head>
</head>
<body>
<form action="https://www.sandbox.paypal.com/cgi-bin/webscr" id="paypal_form" method="post" target="_top">
<input type="hidden" name="cmd" value="_xclick-subscriptions">
<input type="hidden" name="item_name" value="Test Monthly Subscription">
<input type="hidden" name="business" value="mbizz#paypal.com">
<input type="hidden" name="a3" value="7.00">
<input type="hidden" name="p3" value="1">
<input type="hidden" name="t3" value="M">
<input type="hidden" name="src" value="1">
<input type="hidden" name="sra" value="1">
<input type="hidden" name="no_note" value="1">
<input type="hidden" name="custom" value="20130731 it worked">
<input type="hidden" name="cancel_return" value="http://www.miller-media.com">
<input type="hidden" name="return" value="http://www.miller-media.com/sites/paypal_test/mmiller.php">
<input type="hidden" name="rm" value="2">
<input type="submit">
</form>
</body>
</html>
And the return URL
Page
http://www.miller-media.com/sites/paypal_test/mmiller.php
Code
<html>
<head>
</head>
<body>
TEST FOR MILLER MEDIA
THIS IS FOR POST
<?php
echo ("Custom = " . $_POST['custom']);
echo ("Transaction = " . $_POST['txn_id']);
echo ("First name = " . $_POST['first_name']);
echo ("Last name = ". $_POST['last_name']);
?>
</body>
</html>
This code above is what was provided by the PayPal rep to me (mine was slightly different when I first set it up). If you go through the process (with a PayPal sandbox account), no variables will show up on the thank you page (mmiller.php).
Here is a message that the PayPal rep provided to me and it showed that he get variables working correctly. It looks like he was testing locally, so I'm not sure if that had something to do with it:
Here is the screenshot http://i.imgur.com/zno0UkK.jpg . But I just noticed I was using a Buy Now button but your button is a subscription.
The txn_id is not returned for subscription (that is by design) . Please see below for variables that are returned. https://cms.paypal.com/uk/cgi-bin/?cmd=_render-content&content_ID=developer/e_howto_html_IPNandPDTVariables#id091EB0901HT
This is what I get with subscription signup http://i.imgur.com/BOrw1Hn.jpg . A txn_id is not returned.
Here is also the complete POST data :
POSTDATA=txn_type=subscr_signup&subscr_id=I-0RSGVWA904CF&last_name=Connor&residence_country=GB&mc_currency=USD&item_name=StormAware+Monthly+Subscription&business=mbizz%40paypal.com&amount3=7.00&recurring=1&address_street=1+Main+Terrace&payer_status=verified&payer_email=UKrealPro%40paypal.com&address_status=confirmed&first_name=John&receiver_email=mbizz%40paypal.com&address_country_code=GB&payer_id=UXPBYWUW8ZDHA&address_city=Wolverhampton&reattempt=1&payer_business_name=John+Connor%27s+Test+Store&address_state=West+Midlands&subscr_date=16%3A37%3A38+Aug+05%2C+2013+PDT&address_zip=W12+4LQ&custom=20130731+it+worked&charset=windows-1252&period3=1+M&address_country=United+Kingdom&mc_amount3=7.00&address_name=John+Connor%27s+Test+Store&auth=AOgsYFMneBuxymkc0UoZ6OI6D-BXCQmWRz5xyilJR1-7uCvNI1kB Om1eHPbogzB7YnoOUIAZZiFOrx0ZcUgN-gQ&form_charset=UTF-8
Any help would be greatly appreciated as this has frustrated me for the past several weeks. Thank you in advance!
If you want POST data included with your return page you'll need to setup PDT (payment data transfer.)
This is not recommended for updating databases or anything that you need to make sure happens, though, because even with Auto-Return enabled there is no guarantee the user will actually make it back to your site and you will undoubtedly end up with transactions that don't get updated correct.
That is why IPN is recommended instead. IPN will be triggered regardless of whether or not the user makes it back to your site.
Keep your thank you page simple and do all of your post-payment processing within IPN.
I am trying to (using a sandbox account) sell items using google checkout. I am displaying a form to the user which results in a buy now button
<form method="POST" action="https://sandbox.google.com/checkout/api/checkout/v2/checkoutForm/Merchant/..." accept-charset="utf-8">
<input type="hidden" name="item_name_1" value="Test"/>
<input type="hidden" name="item_description_1" value="An item "/>
<input type="hidden" name="item_quantity_1" value="1"/>
<input type="hidden" name="item_price_1" value="1.50"/>
<input type="hidden" name="item_currency_1" value="GBP"/>
<input type="hidden" name="_charset_"/>
<input type="hidden" name="checkout-flow-support.merchant-checkout-flow-support.continue-shopping-url" value="redirect to this url"/>
<input type="image" name="Google Checkout" alt="Fast checkout through Google" src="http://sandbox.google.com/checkout/buttons/checkout.gif?merchant_id=....&w=180&h=46&style=white&variant=text&loc=en_US" height="46" width="180"/>
</form>
On the google seller account i am setting the url to be called back too. In this instance i am using the php file from the google docs example
// Include Google Checkout PHP Client Library
include ("GlobalAPIFunctions.php");
// Include Response Message Processor
include ("ResponseHandlerAPIFunctions.php");
// Retrieve the XML sent in the HTTP POST request to the ResponseHandler
$xml_response = $HTTP_RAW_POST_DATA;
// Get rid of PHP's magical escaping of quotes
if (get_magic_quotes_gpc()) {
$xml_response = stripslashes($xml_response);
}
// Log the XML received in the HTTP POST request
LogMessage($GLOBALS["logfile"], $xml_response);
/*
* Call the ProcessXmlData function, which is defined in
* ResponseHandlerAPIFunctions.php. The ProcessXmlData will route
* the XML data to the function that handles the particular type
* of XML message contained in the POST request.
*/
ProcessXmlData($xml_response);
The issue is, as soon as i buy an item i get no call back whatsoever. No error message, no nothing so how can i see what is going on? Hopefully someone could help me out
Thanks
Check your Sandbox Integration Console for errors (if any) - just making sure that you are referring to your sandbox account (sandbox and production accounts are distinct)
On the google seller account i am setting the url to be called back too
"too" - just making sure. There is only one place where you set the API Callback URL - and that is in your Account Integration Settings (so there is no "too").
<input type="hidden" name="checkout-flow-support.merchant-checkout-flow-support.continue-shopping-url" value="redirect to this url"/>
Again, just clarifying that you are not referring to the above as the callback api url. The above is the link presented to a buyer after purchase (it's just a link back to your web site). It is not the callback api url.
I have my own shopping cart.
When the client click on Submit Order, I Redirect the user to paypal page where the client will be able to pay the order.
Here is my form
<form name="paypalform" action="https://www.sandbox.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="invoice" value="<? echo $idInvoice; ?>">
<input type="hidden" name="business" value="aa_aaa_biz#hotmail.com">
<input type="hidden" name="notify_url" value="http://domaine.com/catalog/IPNReceip">
<?
$cpt = 1;
foreach($ordering as $k => $v)
{
?>
<input type="hidden" name="item_number_<? echo $cpt?>" value="<? echo$v->Product->id; ?>">
<input type="hidden" name="item_name_<? echo $cpt?>" value="<? echo$v->Product->ProductNumber; ?>">
<input type="hidden" name="quantity_<? echo $cpt?>" value="<? echo $v->Qty; ?>">
<input type="hidden" name="amount_<? echo $cpt?>" value="<? echo $v->Price ?>">
<?
$cpt++;
}
?>
<input type="hidden" name="currency_code" value="CAD">
<input type="hidden" name="tax_cart" value="<? echo $taxes;?>">
<input type="image" src="http://www.paypal.com/en_US/i/btn/x-click-but01.gif" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
</form>
I would like to do the samething but within the code behind.
Somebody have an idea.
I don't want to use form anymore to redirect to paypal.
Thanks
The first thing you'll want to decide is decide which products suits you best.
What you describe, would be easiest to accomplish with Express Checkout.
Express Checkout consists of three API calls: SetExpressCheckout, GetExpressCheckoutDetails and DoExpressCheckoutPayment.
SetExpressCheckout prepares the transaction and returns a token. You must take this token from the API response and append it to a url to which you'll redirect the buyer.
Once the buyer has agreed to the purchase on the PayPal page, he/she is redirected back to the URL you specified in the RETURNURL parameter of the SetExpressCheckout API call.
On this return page, you need to call GetExpressCheckoutDetails or (optionally) look at 'PayerID' in the $_GET array for the return URL.
Once you have the token and the PayerID; either through GetExpressCheckoutDetails or as part of the GET data, call DoExpressCheckoutPayment to finalize the payment. This can be accomplished on the same return page, or can be actioned after the buyer clicks a 'Buy now' button on your return page.
See also the general Express Checkout page on X.com, Getting Started with Express Checkout and the Express Checkout Integration Guide (PDF).
Some sample code for SetExpressCheckout, GetExpressCheckoutDetails and DoExpressCheckoutPayment is available on https://www.x.com/developers/PayPal/documentation-tools/code-sample/78 as well.
Hope this helps! Let me know if anything is unclear.
Robert's answer is a great option - Express Checkout cannot be altered because its server to server and users need your API credentials - but if you want to stick with Website Payments Standard (WPS) see below:
Your concern is that your button can be tampered with. Yes this is possible if the buttons on your website are unhosted/unencrypted buttons. There are tools (like tamper data) that edit HTTP POST's before they are sent to the receiving address, or users can download the HTML form and alter it, then click the button (the referring URL would be different, but could be spoofed); unencrypted buttons are vunerable.
I would advise either using one of the options below to prevent this from occurring in the future:
The button manager API to create dynamic hosted buttons for payments
Create and use hosted buttons
Create and use encrypted website payment buttons