Note: This guide applies to CakePHP 1.3 but may be adapted with relative ease to work with CakePHP 2.x. The guide is based on code from an old project and is intended for use as a guide, it is not a comprehensive “How To”. For the purposes of this guide, I have removed a lot of the more complex back office functions which don’t really serve a purpose here.
I am not going to go through showing you how to set up user auth, access control and shopping cart functionality. It has been documented to death, in this guide I am focusing solely on Paypal integration.
So, you have a CakePHP based web application with a functional shopping cart and you want to integrate it with Paypal IPN? Well you are in the right place! Before we get started, you’ll need to understand a little bit about the Paypal IPN flow.
Paypal IPN flow
- User on your site submits a Paypal Button (a standard form in this case) to the Paypal servers.
- Paypal sends an Instant Payment Notification (IPN) http request to a predefined handler/listener on your site.
- Assuming you have defined the correct IPN URL, your IPN handler will return a HTTP 200 OK response code (otherwise Paypal will keep sending IPN notifications for up to four days).
- Your IPN handler needs to send the complete unmodified notification (as received from PayPal) back to Paypal to validate the notify request. You can do this by prepending the notification with “cmd=_notify-validate”.
- Upon receiving this request, Paypal will reply with a single word – either “VERIFIED” or “INVALID”.
IPN Overview diagram from developer.paypal.com
As you can see, it is pretty straight forward process. With the flow above in mind, we will need to do a number of things to get our CakePHP based checkout up and running.
- Setup a Paypal Website Payments Standard compatible form that submits to paypal.
- Create a listener/handler to handle the Paypal IPN and perform some back office tasks on your site.
The Paypal Form
So, first things first, lets create the Paypal form that contains all of the items in our shopping cart. All of the more important form fields are described in the code snippet below.
The form is pretty ordinary as far as HTML forms go. You need to make sure that all of your URLs are correct and that you are populating the Cart items correctly in the form.
The IPN handler
Now that we have our form submitting all of our cart details to Paypal, we need to setup our IPN handler that will validate the IPN notification, save the order details and associated items and remove items from the customers cart.
Our controller looks like this.
The critical part here is the “process_ipn” function. This is the function that validates the IPN notification. The “processOrder” function is not complete and is purely for demonstrative purposes and to give you an idea of how you might parse the the IPN details and start your back office workflow.
Routes to the handler
You may have noticed in the form code above, that I am pointing Paypal to some nice clean URLs, but can’t figure out how these line up with my IPN controller. I use CakePHP routes for nicer URLs.
This guide uses postbacks to validate your transaction. The preferred way to validate your transaction is via “shared secret” because it ensures the validity of the data while decreasing traffic two/from your site. However to implement this approach, you need dedicated hosting (not shared), SSL and you need to be using Encrypted Website Payments – making the postback method much cheaper to implement.
Further Security for the postback method
Worried about the potential for fraud in the postback method? Don’t be! The great thing about the postback method is that you can compare the items in the IPN against customers cart contents (and transaction value) before returning the IPN back to Paypal (see comments in the controller code above) to check that the initial post variables have not been modified.
You can also perform the same (or a similar) check after you have received the “Verified”/”Invalid” message if you need to automate some back office tasks such as locking a user account or mailing an in-house fraud team.
A few years back I was working on a customer project in CakePHP 1.3. I must say I fell in love with CakePHP, it made life so easy, but the one aspect that I always had difficulty with was sending E-Mail. Well, sending E-Mail was no problem, applying HTML templates was a bit cumbersome.
I am currently working on a project which is based on CakePHP 2.3 and recently I have been working on features that need to be able to send E-Mail notifications. I was dreading looking into this, but as of CakePHP 2 the process has gotten a whole lot easier. There is still a little bit of configuration to be done, but it all works beautifully.
The CakePHP 2.x book is a little confusing to read, so here are the steps I took to get E-Mail up and running in my application.
First things first, you need to open app/Config/email.php.default and save it as email.php. In your new email config file, add a basic transport details (multiple transports can be created and used). In the example below, I have created a basic SMTP transport which sends email in both plain text and HTML by default.
In your Controller
Make sure that you are loading the CakeEmail class at the top of your controller. Then to send your E-Mail, simply specify recipients, a subject and the name of the view you wish to use to display your email.
In this case, I have added a few more details – I have chosen to override the default sender details as specified in the SMTP transport config. I am also passing in a few variables for use in the E-Mail views.
Plain Text & HTML Layouts
Ok, we are making progress. But there are a few more jobs to be done before we can send our mail. The first thing you need to do is to create both plain text and HTML layouts. You can find the defaults for both in app/View/Layouts/Email/ in their corresponding folders.
If you plan on using an array of different designs for sending email from your application (i.e. for sending out seasonal promotions, internal/external branding, etc.), you can create multiple templates here, each with bespoke CSS for the mail you wish to send.
For the purpose of this example, I am going to keep it simple and use the default layout (default.ctp).
Plain Text & HTML E-Mail Views
E-Mail view are different from layouts in that layouts allow you to define the look and feel of your (HTML) E-Mail (i.e. they contain the structural HTML and CSS). However Views allow you to format the content as you see fit.
As you saw in the snippet above, I chose to use an email view called “new_user_template” and passed in two variables, a user ID and a user name. I will need to create a view with a message in it to display this information. But ,because I am sending the email in both Plain Text and HTML formats, I will need to create a template for each format.
To do this, make your way to app/View/Emails/html and create a new file called new_user_template.ctp. In this file, you can format your E-Mail body content as you would like using HTML. You can access your variables as passed in the $viewVars variable in the controller (see above).
Here is an example of a HTML view that uses the variables passed in from the controller above.
The plain text alternative is very similar – however it doesn’t contain any HTML.
And that’s all there is to it! I have only scratched the surface here, there is much more you can do on both the configuration and templating of emails.
Thanks to the jQuery library, Ajax transactions are a breeze. All you have to do is send an Ajax request off to the server and display the results. The example below sends a request to random_number.php on the server when the user clicks on a button. When a result is successfully returned, it is displayed in a div and the style of the div is updated.
On the server side, we have a tiny file called random_number.php which simply outputs a random number between 0 and 9999.
This example is extremely simple, but it doesn’t get a whole lot more complicated as jQuery also makes it very easy to handle:
- Different datatypes – XML, Json, script and HTML.
- Handle specific HTTP responses (i.e. 404)
- and perform a variety of other functions;
See the jQuery docs for more information about jQuery.ajax().
You can run this script here. Just click the button on the right hand side to generate a new random number (over and over again if you wish!).
Following on from yesterdays post, you can also use SimpleXML to quickly create XML documents.
The example below creates a very short and basic XML document containing a list of cars that I would love to have in my dream garage (well, some of them anyway).
The resulting XML looks like this.
You can run this script here and you can view the output XML file here. The time in the “generated” node will be updated every time the script is run.
Since the introduction of PHP5, a range of XML handling functions have been added to PHP core. Why is this important I hear you ask? Well it makes life easier if you work with XML!
Below is a small script that uses SimpleXML loads and parses an RSS feed (which is XML) from this site. The feed is generated automatically by WordPress. It then displays some of the feed meta data and a list of posts contained in the feed.
Full SimpleXML documentation can be found here.
And you can see the code in action here.
Warning, this is a techie post.
I recently had an issue with Internet Explorer recently when using getJSON to get a result set from the server, however the client browser was displaying an old version of the result set. After a little digging, I found that IE caches ajax transactions by default. Personally, I think this is daft, as I generally want to request new data from the server the majority of the time. From this point of view, I think it would be better to have caching disabled by default – but there you go!
To get around this problem, simlply disable ajax caching after page load (i.e. $(document).ready()).
I was working on a CakePhp project recently and had an Ajax response returning data in the incorrect order even though CakePhp was actually sorting the data correctly. I thought I would post this handy snippet for anyone that is in a similar position.
By default, wordpress limits the files types that you are allowed to upload to images, pdf files, and a few others (full list of allowed file types here). When you try to upload a filetype that isn’t on that list of allowed types, you will get a File type does not meet security guidelines. Try another. error. Not to fear, this is easy to get around by adding the code below to your theme functions.php file.
This quick snippet will allow you to add multiple new filetypes to the allowed list (in this example, I have added .bib and .txt files to the list of allowed filetypes. To add additional filetypes, simply modify the third line below, placing a “|” between your new types. Simple!
Warning: This is a geeky post, prompted by photography-related storage issues.
Being into Photography, I have relatively hefty storage requirements when compared to your average PC user. I don’t really need speed, just space and security. I have one 500GB external hard disk and a full backup copy of my photos on another internal drive (plugged in via USB). But I’ve run into a problem… I’m nearly out of space. And while having two copies is great, it’s tough to keep them in sync – as in it is hassle, so I don’t do it as often as I should!
I have had a stack of old IDE hard drives sitting here for the past (more…)