Monday, October 6, 2008

Paypal Integration Can Be Painless If You Know How



Here's my primer on how to get going with PayPal for your site. I'll admit that PayPal makes it difficult. I feel for you.

First, you need a product catalog. Don't have one? Fine. Get a CMS, make some categories and subcategories, give people a menu for that on the left, and start drawing up your articles as product pages. So I can here you asking me -- where's the shopping cart and the integration with PayPal? Well, PayPal gives you a FREE shopping cart, and the steps below will show you how to integrate it easily.

Okay, now you need to add two buttons. One is an Add To Cart button. The other is a Checkout Now button. I'll save you the hassle of going to make one on PayPal's site. Here's how it's made:

Replace [ and ] with < and > below.

[form target="paypal" action="$sPayPalDom/cgi-bin/webscr" method="post"]
[input name="cmd" value="_cart" type="hidden"]
[input name="business" value="$sPayTo" type="hidden"]
[input name="lc" value="$sLocation" type="hidden"]
[input name="item_name" value="$sTitle" type="hidden"]
[input name="item_number" value="$sProdID" type="hidden"]
[input name="amount" value="$sPrice" type="hidden"]
[input name="currency_code" value="$sCurrency" type="hidden"]$sNoShipping $sShipping
[input name="rm" value="1" type="hidden"]
[input name="return" value="$sPurchase" type="hidden"]
[input name="cancel_return" value="$sCancel" type="hidden"]
[input name="add" value="1" type="hidden"]
[input name="bn" value="PP-ShopCartBF:btn_cart_LG.gif:NonHosted" type="hidden"]
[input src="images/addcart.png" name="submit" alt="" border="0" type="image"]
[img alt="" src="http://www.blogger.com/$sPayPalDom/en_US/i/scr/pixel.gif" border="0" height="1" width="1" /]
[/form]


In the above, replace $sPayPalDom with 'https://www.paypal.com' when you want to go into production, or 'https://www.sandbox.paypal.com' when you want to be in sandbox test mode. For sandbox test mode, you need to go to sandbox.paypal.com and sign up for two accounts -- a merchant account and a customer account. Then, you'll use those for your sandbox mode -- not only for this button on $sPayTo, but also when you pretend to be a customer and want to purchase something. Remember, when you're on the sandbox, everything is entirely phony, but it feels real.

For $sPayTo, that's either your production PayPal email account that you use, or your sandbox email account as the merchant. For $sLocation, that's your ISO two-letter country code, such as CA, US, etc. For $sTitle, that's the title of your product. For $sProdID, that's some made-up product ID you want to give your product, and it should be unique. For $sPrice and $sCurrency, that's the price you want and in what currency. The currency code is a 3 letter code like USD, GBP, CAD, etc.

Then you see something odd -- $sNoShipping and $sShipping. Okay, if you plan on having a product that will be shipped out, then $sShipping needs to be:

Replace [ and ] with < and > below.

[input type="hidden" name="cn" value="Add special instructions to the seller"]
[input name="no_shipping" value="2" type="hidden"]


If you don't intend on shipping something out, such as provide a hyperlink to download an eBook at the end of the purchase, then $sNoShipping needs to be:

Replace [ and ] with < and > below.

[input name="no_note" value="1" type="hidden"]
[input name="no_shipping" value="1" type="hidden"]


Now, notice I have an addcart.png file. Go make yourself your own Add To Cart button -- PayPal's versions look awful. Navy on orange? Give me a break!

For $sPurchase, make that a url back to a page on your site. It needs to be an absolute URL like http://mydomain.com/purchase.php. For $sCancel, make that a url back to a page on your site. It needs to be an absolute URL like http://mydomain.com/cancel.php. Now go make a cancel.php page that basically says something to the effect of, "Your purchase was cancelled. Have a nice day."

Now, go back and edit your $sPurchase variable. You need to tack on to the end of it:


"?id=$sProdID" . "&s=" . $sSecurityCode;


The $sProdID we already discussed. The $sSecurityCode should be a unique code based on your ProdID in order to reduce the opportunities of hacking purchases from you. So how do you make that? Well, here's an algorithm:


$sSecurityCode = 'PROD' . mt_rand(11, 99) . base64_encode(crc32($sProdID));
$sSecurityCode = str_replace('=','',$sSecurityCode);
$sSecurityCode = urlencode($sSecurityCode);


However, everyone should make their own algorithm and it should at least involve crc32 on the Product ID, and everything else needs to be predictable flourish, but only predictable to you. The reason I do urlencode is, well, we're going to tack it on the end of a URL and we need it to run properly in the browser. PayPal returns back to your site after a purchase by this URL.

So, stick that piece of HTML on your product pages to draw your Add To Cart button. But it's also nice to have a Checkout Now button. Here's what that looks like:

Replace [ and ] with < and > below.

[form target="paypal" action="$sPayPalDom/cgi-bin/webscr" method="post"]
[input name="cmd" value="_cart" type="hidden"]
[input name="business" value="$sPayTo" type="hidden"]
[input name="display" value="1" type="hidden"]
[input src="images/checkout.png" name="submit" alt="" border="0" type="image"]
[img alt="" src="http://www.blogger.com/$sPayPalDom/en_US/i/scr/pixel.gif" border="0" height="1" width="1" /]
[/form]


So, we've already discussed the $sPayTo and $sPayPalDom fields -- they're the same as the Add To Cart button. You can swap just as I mentioned above with the sandbox domain of 'https://www.sandbox.paypal.com' if you want to be in sandbox mode.

Notice also the checkout.png image. You need to draw your own Checkout Now button because PayPal has an ugly one.

Okay, this next part is where most newbie developers get bungled up, so listen carefully.

First, you need to change your merchant account settings in PayPal. Say, are you on Website Payments Standard or Website Payments Pro? You really only need to be Website Payments Standard for this arrangement I'm explaining here. Second, you need to edit your profile (click it's link to see the full set of profile options -- don't choose a submenu item) and do three critical things under Website Payment Preferences -- turn on auto return, type in a return URL. Let's stop there a second. This return URL business is confusing! What they don't make clear with PayPal is that your HTML you generated above will override this parameter, so you could put http://monkeybrains.com/ here and it wouldn't matter. But PayPal requires that you put something there, so make them happy. Now, the next thing you need to flip on in Website Payment Preferences is PDT, or Payment Data Transfer. Turn that on. BTW, they give you an ID there. You can blow that off -- ignore it because we're going to use $sSecurityCode instead. And why? Because I found it more secure and easier to manage than this stupid code they give me from PayPal, that's why.

Second, you need to build a purchase.php page. In it, you need to perform the following functions.

1. Check for a query parameter ($_GET['sig']) that comes back from PayPal. It needs to be a non-empty string. If you come up empty, then fire off an email with mail() to you about a potential hacker, and show a fake 404 page.

2. Check for a query parameter ($_GET['id']). That's your product ID. If you don't get a valid one, then handle as if it's a hacker attack just like in step # 1.

3. Check for a query parameter ($_GET['s']). That's your security code. Basically you need to take the product ID you recevied and then repeat that security code algorithm you came up with upon it. So, for instance:


$sProdID = $_GET['id'];
$sSecurityCode = 'PROD' . mt_rand(11, 99) . base64_encode(crc32($sProdID));
$sSecurityCode = str_replace('=','',$sSecurityCode);
$sSecurityCode = urlencode($sSecurityCode);


Now compare what you received in $_GET['s'] with $sSecurityCode. If they don't match, then, again, email yourself and put up a fake 404.

Otherwise, you need to send a nice message in your purchase.php because we have a valid user:

Replace [ and ] with < and > below.

[h5]Thank you for your payment. Your transaction has been completed, and a receipt for your purchase
has been emailed to you. You may log into your account at [a href="http://www.paypal.com/" target="_new"]www.paypal.com[/a] to view details of this transaction.[/h5]


Now, if this is a downloadable type product, feel free to show your download link to the end user at this point in your purchase.php. Otherwise, that's all you need to send. BTW, you'll want to Google on various methods to prevent people from having a download link that works more than 2 days. I mean, you don't want someone paying for the item, then requesting a refund, and then giving out that link to 100 people off his blog.

So, what do you get from this? You get an email from PayPal letting you know about new purchases, and when you login to PayPal, you have the option to approve or deny that purchase.

Now, there's something more elaborate called IPN (Instant Payment Notification), where PayPal tells your website, live, the status of an order, and then your website can authorize that order or decline it, but in my opinion if you're going to need that, you're doing waaaaaay too much business than to need PayPal. You need something better and on a pay-by-month program. IPN is not only troublesome to set up, but it's known for not always being as reliable -- it has some major outages.