Rewrite the return from paypal with clean urls

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
Hey there folks i am rather new to writing a .htaccess file and have only went as far to make it rewrite a route for my framework Cabbit.
Now it works for standard urls in my framwork such as http://mysite.com/controller/function/action however it falls on its bum when getting back the url from paypal(part of the framework is payments pro and express checkout) where the return is http://mysite.com/controller/function?token=thistokenfortheuser&PayerID=something
So i need it to come out as
http://mysite.com/controller/function/thistokenfortheuser/something

Also i am not sure if it is possible but it would be terrific for it to be possible that http://mysite.com/eshop/checkout is rewritten to https://mysite.com/eshop/checkout instead though as i said i don't know if this is possible and right now i can do it with php.

Thanks in advance for any help and suggestions.

current .htaccess
Code:
Options +FollowSymLinks
Options -Indexes
DirectoryIndex /public/index.php
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule (.*) public/index.php?rt=$1 [L]
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
Something like this should work.

Code:
RewriteRule /controller/function?[a-z]+=([B][COLOR="Red"][a-z]+[/COLOR][/B])&[a-zA-Z]+=([B][COLOR="Red"][a-zA-Z]+[/COLOR][/B])$ /controller/function/$1/$2
 

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
this is the htaccess file now
HTML:
Options +FollowSymLinks
Options -Indexes
DirectoryIndex /public/index.php
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) public/index.php?rt=$1 [L]
RewriteRule /products/returnexpress/?[a-z]+=([a-z]+)&[a-zA-Z]+=([a-zA-Z]+)$ /products/returnexpress/$1/$2
It still spits back http://dev.mysite.com/products/returnexpress/?token=EC-828925359S785910B&PayerID=VRAUNMCBL692W
Where i really want it to return
http://dev.mysite.com/products/returnexpress/EC-828925359S785910B/VRAUNMCBL692W

Perhaps i miss understood.

Just for my understanding, this is how the current rt works.
http://dev.mysite.com?rt=/products/returnexpress/?token=EC-828925359S785910B&PayerID=VRAUNMCBL692W
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
Well, the example you provided before wasn't representative of what you needed so that's why it didn't work. Things like character case, the types of letter allowed and such are very important when constructing regex. Here's an updated line that should accommodate the sample you provided.
Code:
RewriteRule /products/returnexpress/?[a-z]+=([A-Z0-9-]+)&[a-zA-Z]+=([A-Z0-9]+)$ /products/returnexpress/$1/$2
 

elppa

macrumors 68040
Nov 26, 2003
3,229
106
Maybe a dumb question, but do you need to escape the ? after the /products/returnexpress/ bit, or does Apache do some cleverness.

So:
Find:
Code:
/products/returnexpress/\?[a-z]+=([A-Z0-9-]+)&[a-zA-Z]+=([A-Z0-9]+)$
Replace:
Code:
/products/returnexpress/$1/$2
(obviously it needs to be run into one line, with a space between each of the sections above, I just split it up to save scrolling)
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
Maybe a dumb question, but do you need to escape the ? after the /products/returnexpress/ bit, or does Apache do some cleverness.
Good catch. You're right, it needs the backslash. Apache does have some option for looking at the query string alone, but isn't as helpful here.
 

elppa

macrumors 68040
Nov 26, 2003
3,229
106
Slightly related, Regexhibit is good for trying out perl like regular expressions.

Hasn't been developed in a while, but it is completely free and the source is available.

You use it like this, blue means matched, pink means captured, purple shows the replacement.
 

Attachments

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
Well i tried this like ya guys said.

HTML:
Options +FollowSymLinks
Options -Indexes
DirectoryIndex /public/index.php
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) public/index.php?rt=$1 [L]
RewriteRule /products/returnexpress/\?[a-z]+=([A-Z0-9-]+)&[a-zA-Z]+=([A-Z0-9]+)$ /products/returnexpress/$1/$2
But the URL being returned remains http://dev.mysite.com/products/returnexpress/?token=EC-20H486245S384273B&PayerID=VRAUNMCBL692W :(
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
I started wondering about this, but it's not completely clear when you said,
when getting back the url from paypal(part of the framework is payments pro and express checkout) where the return is http://mysite.com/controller/functio...erID=something
The rewrites we have been working on are applied when someone either types in the URL or clicks on a link for a certain URL, then it is rewritten to the new format. I don't know that this case necessarily falls under this. Can you explain more about the PayPal part? Is PayPal accessing a URL that needs to be rewritten? Does a file exists where the rewritten URL points to?
 

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
Ok well i send a request to paypal from my site at http://mysite.com/products/doexpress

That sends https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$Paypal->Token.'

Which spouts back to my return url

http://dev.mysite.com/products/returnexpress/?=token=bladebla&=payerid=bladebla

Now my problem with this is that i cant get php to read the bit after the ? because ? is already set at ?rt=$1 which is for all the internal framework stuff.
So i don't know how to get the values token and payerid out of the url unless i manually do it in the url bar but i could not expect a user to want to do with.
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
Can you share what you're trying to use to get the stuff after the ? that you're having issues with? It's not clear why you can't access that info. I've never messed with the PayPal checkout stuff so I'm still having trouble following the code logic you're using, but I think the Apache rewrite likely won't get you there based on what I think I understand on your situation.
 

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
I am gona sleep on it then post the code structure and ins and outs of what is happening.
 

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
Ok well i have slept on it for a couple days trying to work it out but i can't get my head round it.
In a nut shell it is a 3 step process.

This is the first script this sends out the request to paypal with the return address. The real address with htaccess off would be index.php?rt=products/returnexpress

PHP:
public function paypalexpress()
	{
		// SetExpressCheckout
		// On Success Will return a token with value like EC-7EG51014BE327234S
		// Customer should then be redirected by your server to URL like 
		// https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token=EC-7EG51014BE327234S
		// Customer will then enter payment at paypal.com and upon success customer will be sent back to the $ReturnURL
		// that you provided in the operation with the tokon and PayerID appended as parameters to the $ReturnURL
		//==========================================================================================================
		$API = $this->Cabbit->Paypal;
		
		$API_USERNAME = '*';
		
		$API_PASSWORD = '*';
		
		$API_SIGNATURE = '*';
		
		$API->prepare($API_USERNAME, $API_PASSWORD, $API_SIGNATURE);
		
		$Paypal = $API->selectOperation('SetExpressCheckout');
		
		$cart = $_SESSION['cart'];
		if ($cart) 
		{
			$items = explode(',',$cart);
			$contents = array();
			foreach ($items as $item) 
			{
				$contents[$item] = (isset($contents[$item])) ? $contents[$item] + 1 : 1;
			}			
			foreach ($contents as $id=>$qty) 
			{
				// Get product data from product model
				$productdata = new model_product;
				$products = $productdata->productData(); // gets the user data array
				
				// Basket
				foreach ($products as $key => $value) 
				{
					if ($key == $id)
					{
						// Update total
						$item = $value['price'] * $qty;
					}
				}
				$item_total = $item_total + $item;
			}
		}
		$productdata = new model_product;
		$shippingCost = $productdata->shippingRate();
		$shipping    = $_SESSION["ShippingRate"];
		
		$OrderTotal = $item_total + $shipping;
		
		$ReturnURL = 'http://dev.mysite.com/products/returnexpress/';
		
		$CancelURL = 'http://dev.mysite.com/';
		
		$PaymentAction = 'Sale'; // or Order
		
		$Paypal->setParams($OrderTotal, $ReturnURL, $CancelURL, $PaymentAction);
		
		$Paypal->execute();
		
		if ($Paypal->success())
		{
			$Responce->getAPIResponse();
		} 
		else 
		{
			$Responce->getAPIException();
		} 	
		header('Location: https://www.sandbox.paypal.com/cgi-bin/webscr?cmd=_express-checkout&token='.$Responce->Token.''); // Sent user to home page
			exit();
	}
What paypal returns is http://dev.mysite.com/products/returnexpress?token=EC-7SX97880L96523901&PayerID=VRAUNMCBL692W

Which means it is http://dev.mysite.com?rt=products/returnexpress?token=EC-7SX97880L96523901&PayerID=VRAUNMCBL692W

That makes it impossible to read the contents of token.
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
I get most of that except the
Which means it is http://dev.mysite.com/?rt=products/returnexpress?token=EC-7SX97880L96523901&PayerID=VRAUNMCBL692W
From the look of the documentation it should just be that link you provided as "what paypal returns." What puts in the ?rt= part? That's what is confusing me now.

Also, I don't think it's a good idea to reuse the $Paypal variable the way you are, to capture the response. I'd recommend using a different variable, like $response.
 

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
The rt is the un url rewritten path to the receiving page. Paypal returns a token to the page i specify but the token it returns is ?token when my pages are all rewritten index.php?rt=class/function to /class/function to make it nice and neat.

Is there a way i could put in some conditional logic to a htaccess to rewrite index.php?token=****&payerid=****
to
index.php?rt=****/****&token=****&payerid=*****

I think that would cut out a lot of the complexity.

Paypal it self attaches the ?token to the url i give it, what would be ideal is if i could ether change the ?token or set it to return to index to php and have the url rewritten to /class/function/token/payerid/ from there rather than doing it at the /class/function/ stage.
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
Well, that's just a slight variation of what we presented before.
Code:
RewriteRule /\?token=([a-zA-Z0-9-]+)&payerid=([a-zA-Z0-9]+)$ /products/returnexpress/$1/$2/
 

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
^_^ thanks i'll try it.

Just to be sure
Options +FollowSymLinks
Options -Indexes
DirectoryIndex /public/index.php
RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
<-- it goes here before the normal rewrite
RewriteRule (.*) public/index.php?rt=$1 [L]
<-- or here after
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
You'll need it before as your current line will match pretty much everything and has [L] at the end so will stop processing after that for the rewrites.
 

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
^_^ oh thats what the L means, emm can you recommend a book i would love to know how to do this bit without needing to ask for help it seems there is more to programming than php/rails/html/css and javascript when making sites.
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
I just Google. Apache's pages tend to be overly technical, but can provide some guidance. Otherwise, I do searches like "rewriterule tutorial" or ".htaccess tips OR tutorial"
 

Cabbit

macrumors 68020
Original poster
Jan 30, 2006
2,129
1
Scotland
using

Code:
Options +FollowSymLinks
Options -Indexes
DirectoryIndex /public/index.php
RewriteEngine On
RewriteBase /
RewriteRule /\?token=([a-zA-Z0-9-]+)&payerid=([a-zA-Z0-9]+)$ /products/returnexpress/$1/$2/
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule (.*) public/index.php?rt=$1 [L]
The sale is still not being redirected to the products/returnexpress/ page
http://dev.mysite.com/?token=EC-0JV78003MU996243K&PayerID=VRAUNMCBL692W

The htaccess should redirect the user to
http://dev.mysite.com/products/returnexpress/EC-0JV78003MU996243K/VRAUNMCBL692W/
 

angelwatt

Moderator emeritus
Aug 16, 2005
7,842
7
USA
The link has different capitalization for payerid vs PayerID. Regexes are very particular like that.
Code:
RewriteRule /\?token=([a-zA-Z0-9-]+)&PayerID=([a-zA-Z0-9]+)$ /products/returnexpress/$1/$2/