Paypal REST API Return Page - php

I'm currently using the Paypal REST API to process billing agreements for users with multiple plans.
When a user signs up for a plan, it takes them to PayPal to pay. After they finish that step, PayPal redirects them to a return URL that I have supplied.
The problem is, sometimes the user's session does not persist when they return from PayPal!
I have session_start() as the first line in all of my files, so the sessions are being created. I have verified, before taking the user to PayPal, that the $_SESSION array is being populated - it's just when they are brought back after PayPal.
Is there a better way to persist data like that so I can update a users account on return back from PayPal? Or maybe there is a way to pass the email with the PayPalrequest so that it is returned in the object they send back to my website on return?

If you're properly starting the session via session_start() on both your sign-up page and the page that PayPal redirects back to, your session should be starting properly.
Assuming that you're not inadvertently closing the session, or regenerating the ID, it sounds like there isn't an actual "session management" issue, but perhaps it has to do with the URL that PayPal is redirecting back to.
A common issue with PHP sessions is that, with a default PHP config, they don't carry between subdomains.
For example, if I visit your domain domain at example.com, my session will only be active on example.com. If I then go to www.example.com, I will receive a new session.
You can verify this by going to your site at example.com or www.example.com and checking what domain the PHPSESSID cookie is set for. If it is not .example.com (note the leading .), then this is the issue =]
To help resolve this, you can modify your server's config to set the .example.com as the cookie's domain. Taken from this answer:
session.cookie_domain = ".example.com"

The same answer I gave to a recent question should work here as well:
The solution I used for this same problem was to set
override_merchant_preferences on the billing agreement, with the
return_url containing the user id in the query, like
www.domain.com/api/handler.php?uid=42&action=return.
Though of course you can pass any identifiers you'd like through the $_GET that way.

Related

Will a user's PHP session persist if they navigate away from the site and back?

I'm creating a session variable in one PHP page and on that page I am redirecting to an online payment portal.
After payment, the user is redirected to a payment success page on my server. Will the session variable still be valid?
The above answers are true if you are storing sessions using cookies. If cookies are disabled then a PHP_SESSION parameter will be passed in the URL. For the returning user to be able to continue using the session the payment gateway would need to redirect back with the same session hash.
As stated if you are using the default PHP session settings then cookies should be in use and this would not be an issue. What about the users whom may have cookies disabled, your flow will break. Chances are slim and the amount of users effected may be small.

Redirect to PayPal breaks sessions

I am running into an issue with a redirect and sessions.
The flow of the applications is this:
Customer goes to site
Adds product to cart
Selects to checkout with PayPal
Is redirected to PayPal
Logs in to PayPal
Redirected back to site
Continues through billing/shipping pages
Confirms the order and submits
This is working in development without an issue.
When I go to the live server, the session keeps getting lost after the redirect to PayPal.
Any idea what it could be?
Extra Info:
I found that when I first go to the website, I have a session ID.
When I go through the checkout process and I am redirect to PayPal, then directed back to the return URL (back to the merchant website), the same session ID is in the cookie. So it looks like the session is not being restarted, but rather that the session data is just empty.
I have same issue, and I found that it's mistake in domain name, as before redirecting to paypal url is
'http://www.example.com/paypal-redirect.php'
while at the time of return from paypal url is
'http://example.com/paypal-return.php'
so here I missed www, so it might be that, or http/https just do check that thing, hope that will help to resolve this issue
Are you calling session_start() on the page that returns from Paypal?
That is usually the common mistake.
http://www.w3schools.com/php/php_sessions.asp
in php.ini,
set session.cookie_domain= '.yourdomain.com';
or if you don't have access to it change domain parameter
session_set_cookie_params ( lifetime,'/','.yourdomain.com',false);
note that you have to call it before session_start();
this would share the session over all subdomains including www.domain.com, this solved my problem. this has the advantage that we need not worry whether user typed www.domain.com or simply domain.com to access the page.Hope this helps

Cookies being deleted on redirect

I have a problem with cookies.
Basically I'm trying to store the user's session ID as a cookie like so:
setcookie("CheckoutSessionID",session_id(),time()+3600);
This works fine on my site, the cookie has the correct value and is valid for long enough. However, my site redirects to PayPal so the user can confirm a payment. The user is then redirected back to my site. It's when the user is redirected back to my site that ALL cookie variables are gone.
As in, print_r($_COOKIE), var_dump($_COOKIE) etc have no values. This only occurs after being directed to and from PayPal.
Any ideas as to why this is happening?
Thanks in advance for all help, I'm stumped!
Okay I've been digging quite deep and realised that an earlier question of mine is related:
PHP sessions and session_start()
Basically I had problems because PHP sessions were being deleted when I went to PayPal and back. However, I believe this was actually caused by the session COOKIE being destroyed, not the entire session.
I also found this topic here: Do PHP sessions get lost when directing to a payment gateway?
Answer given by someone suggests using a GET request with the return URL to send data back, instead of using cookies or sessions.
The whole reason I was using a cookie in the first place was to save the user's session ID, as the sessions weren't working properly, so basically I've just made my return URL something like this:
mydomain.co.uk/mypage.php?SessionID=[session ID goes here] and then obtained it then set the user's session ID to it.
Sorted! For now... I mean I'll probably end up hitting another brick wall due to cookies/sessions not working properly.
Thanks everyone for your help :)
Actually whatever is happening (cookie is being empty), logically it's right. When you submit a page/make request the browser sends the cookie from the client's computer with the request so that you can find the cookie in the cookie variable.
But once you redirect the user to another external page/site and come back again to your page then you should not get the cookie in the cookie variable because (in your case) when the user is getting back to your site from the paypal the paypal is not submitting the cookie with the request.
In this case you can save your data in the database before you redirect the user to the paypal and once the user comes back to your site you can retrieve that data from the database.
I got similar problem cookies being removed after redirect from Paypal.
it took me a while to figure out where was a problem.
Samesite=**"Strict"** // Removes cookies after redirect from Paypal.
Samesite=**"Lax"** // does not remove cookies after redirect from Paypal.

Do PHP sessions get lost when directing to a payment gateway?

If i was to store some order details in a session whilst the customer is redirected to a payment gateway, would they be lost by the time the custom returns back from the gateway?
My plan is:
website take order -> store order in session -> website goes to paypal -> payment made -> returns using paypal autoreturn to confirmation page -> on return get session order data and submit to database.
I found the problem.
Paypal redirect back client to yoursite.com without the www.
cookies on http://www.yoursite.com are http://yoursite.com are not considered the same.
To fix that, add .htaccess to your www root;
RewriteEngine on
RewriteCond %{HTTP_HOST} ^yoursite.com$
RewriteRule ^.*$ "http\:\/\/www\.yoursite\.com" [R=301,L]
That depends on how long it takes them to come back to your site. I don't know what the default expire time is for sessions but you can assume it to be anywhere from a few minutes to a few hours.
If you want to assure the user gets to see whatever he needs to, you will need the payment gateway to redirect the user to a URL that you specify. For instance:
/payment.php?status=complete&receipt=875628dwf87sdfsg785623
Where the receipt identifies anything you want it to: the user, the transaction, both?
Most payment gateways support such a feature. If yours does not, contact your payment gateway.
If you want to show them a receipt, do not use sessions or cookies, use the return URL method I describe.
Session may be lost if visitor was in HTTP when leaving and comes back as HTTPS (or vice-versa)
Sessions won't get "lost" as long as your server supports session cookies, but they may expire.
The session is an ID to identify the session and the data belonging to the session. The data is stored on your server as long as you like. The ID is either saved as a cookie or handled as a GET-parameter which should be avoided generally. If you have the ID saved in a cookie then there is no reason why another site should interfere with it.
So I see no reason why your session should be lost.
As long as the customer has cookies enabled in their browser, the session will remain when they return, unless they've closed their browser window first. Sessions IDs are kept in a cookie, which expires when the browser closes.
You could also, if you wanted to, keep the information in a cookie, though this would be less preferable if there was any private information you needed to be kept.
EDIT
also, the answer about creating a session in HTTPS then accessing it again in HTTP is correct.
The session remains active as per your application's session expiry settings.
The new versions of the browsers might be destroying the session because of the new cookie policy.
References
https://developers.google.com/search/blog/2020/01/get-ready-for-new-samesitenone-secure
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
Whenever the cookie is required to be sent to server, the browser sees the SameSite attribute to decide if the cookie to be sent to server or blocked. For user actions, it is sent to the server but for auto-redirects, it doesn't if SameSite is set to 'Strict' or 'Lax' (Lax is going to be the default value now).
Solution:
The cookie attribute SameSite can be set to 'None' along with specifying the 'Secure' attribute to 'true'. Setting 'Secure' attribute to 'true' would require your site to run on https. Sites running with http:// protocol will not be able to set 'Secure' cookie.
Please set the 'HttpOnly' attribute to 'true' for making it accessible for http requests to the server only.
In PHP, it can be achieved as below
session_set_cookie_params(0, '/PATH/; SameSite=None', <COOKIE_DOMAIN>, true, true);

Cross domain cookies

I have a small problem.
How do I set a cookie for multiple domains?
I do understand the security problems, and I am sure it has been done before. The reason for this is SSO.
ie.
account.domain.com will need to set domain logged in for:
domain.com,
domain1.com,
domain2.com.
Is there any easy way, using PHP and cookies, or any alternatives?
There is absolutely no way for domain.com to set a cookie for domain1.com. What you are attempting to do can only be solved by getting the user's browser to submit requests to each domain which will then set its own cookie.
Then you need a way for each domain to verify the user's identity. There are two approaches to this:
Back channel - the sites contact each other directly to determine if a user is logged in.
Passing a token in the GET or POST - when the user's broweser is redirected to the other site a digitally signed parameter is passed containing the identity and session status.
It's really quite complicated. I suggest you don't roll your own. Take a look at SimpleSAMLPHP for a PHP implementation of what I'm describing.
What you're attempting can't be done. (It's a browser security issue, not a PHP one.)
Other than using some form of off-site authentication, the nearest you can achieve is making a cookie accessible across sub-domains, in which case you just use the optional 'domain' arg of PHP's set_cookie function.
This can be done via one domain acting like a master and others like a slave.
Say we've got a domain accounts.domain.com and it's our master.
Then we've got our slaves domain.com, something.com and another.com
When you'll log on on domain.com, it'll be actually site accounts.domain.com, then you'll get a cookie with unique ID for your browser and then you'll be redirected to domain.com's post-logon landing page (ie. domain.com/logon?check=true&unique-id=<browser unique id>&request-id=<unique request ID>). the landing page will contact the accounts.domain.com, querying it with the browser ID. If the transaction's okay, then you'll get logon cookie from domain.com.
Next, on every domain (domain.com, something.com and another.com) will be initial redirect to accounts.domain.com/roaming-check?return-url=<URL the redirect was initiated from>. Because we're returning home (we're logged already on accounts.domain.com), we'll be redirected again on our landing page (<domain name>.com/logon?check=true&unique-id=<browser unique id>&request-id=<unique request ID>) and from this point it's the same as the part with logging on. We're seamlessly roamed to another domain (without user knowing it as browsers doesn't usually show the redirected page until it passed the headers send(server)/receive(browser) section).
In case there's in fact no active logon, the site will save this "negative logon" to session and not try to check logon anymore (until we try to logon or load another domain).
I think this solution will suit your needs: "Simple Single Sign-On for PHP"

Categories