Open-sourcing symfony2-paypal-ipn, a Symfony bundle for PayPal IPN

May 13th, 2012 by Alex

Today we are pleased to announce the open-sourcing on GitHub of our new PayPal e-commerce library for Symfony 2. This is a direct port of our CodeIgniter PayPal IPN library which we open-sourced on this blog some 14 months ago.

At Keplar we remain committed to using open-source projects where possible to keep costs down for our clients and to avoid “reinventing the wheel”. Where high-quality open-source projects exist which meet our client’s needs, we use them by default; there are too many of these to name them all, but recent projects would have been impossible without Hive (Hadoop ecosystem), Spray (Scala/Akka), DictShield (Python), WAI (Haskell) and of course Redis.

Where open-source projects do not exist that meet our requirements, we are increasingly looking to develop those tools in-house and open source them where possible (i.e. where they are not part of a client deliverable). Our biggest initiative so far in this area is the SnowPlow web analytics platform, which since its soft-launch in February is already being used externally by one ad network to track ad impression data and internally by our team to perform some sophisticated analytics, such as website cohort analyses.

Other projects we have open-sourced since our CodeIgniter PayPal module include a Scala client for the Amazon Product Advertising API, a command-line tool for exporting Google Analytics data to CSV flatfiles, and a Scala client for the PrestaShop e-commerce API – the latter another release under our “Orderly” initiative for better e-commerce workflow automation and data analysis.

Onto our new Symfony2 library for PayPal IPN…

As with the original CodeIgniter version, this library is designed to make it easier for developers using Symfony 2 to receive, validate and store instant payment notifications (IPNs) sent by PayPal when an order has been paid for by a customer. To be clear: there is already a “maximalist” bundle for handling PayPal payments in Symfony2 – the excellent JMSPaymentPaypalBundle. By contrast, symfony2-paypal-ipn is a “minimalist” bundle which focuses on the post-payment workflow, validating an IPN notification from PayPal and then logging the order and order line items into your database (using the Doctrine 2 ORM). Sending an order confirmation email is also super-simple with our library.

For instructions on installing the bundle, please see the README file in the project’s repository. Once the bundle is installed, using it in a Symfony controller to validate incoming orders and send order confirmation emails is quite straightforward – just write a controller like this:

use Symfony\Component\HttpFoundation\Response;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Orderly\PayPalIpnBundle\Ipn;

class TwigNotificationEmailController extends Controller
{

    public $paypal_ipn;
    /**
     * @Route("/ipn-twig-email-notification")
     * @Template()
     */
    public function indexAction()
    {
        //getting ipn service registered in container
        $this->paypal_ipn = $this->get('orderly_pay_pal_ipn');

        //validate ipn (generating response on PayPal IPN request)
        if ($this->paypal_ipn->validateIPN())
        {
            // Succeeded, now let's extract the order
            $this->paypal_ipn->extractOrder();

            // And we save the order now (persist and extract are separate because you might only want to persist the order in certain circumstances).
            $this->paypal_ipn->saveOrder();

            // Now let's check what the payment status is and act accordingly
            if ($this->paypal_ipn->getOrderStatus() == Ipn::PAID)
            {
                //preparing message
                $message = \Swift_Message::newInstance()
                    ->setSubject('Order confirmation')
                    ->setFrom('support@CHANGEME.com', 'TEST')
                    ->setTo($this->paypal_ipn->getOrder()->getPayerEmail(), $this->paypal_ipn->getOrder()->getFirstName() .' '. $this->paypal_ipn->getOrder()->getLastName())
                    ->setBody($this->renderView('OrderlyPayPalIpnBundle:Default:confirmation_email.html.twig',
                            // Prepare the variables to populate the email template:
                            array('order' => $this->paypal_ipn->getOrder(),
                                  'items' => $this->paypal_ipn->getOrderItems())
                            ), 'text/html')
                ;
                //send message
                $this->get('mailer')->send($message);
            }
        }
        else // Just redirect to the root URL
        {
            return $this->redirect('/');
        }

        $response = new Response();
        $response->setStatusCode(200);

        return $response;
    }
}

If you prefer not to send an order confirmation email, then checkout the NoNotificationController.

Let us know how you get on with this library in the blog comments – and if there’s a feature missing that you would like, feel free to raise a new issue over on GitHub. We hope you find it useful, and stay tuned for more “Orderly” releases very soon!

Leave a Reply