Introducing Mismi – Amazon Price Comparison for Norwegian Customers

My main project in December was Mismi – a service that compares the total price of items from Amazon.com and from Amazon.co.uk for Norwegians. The solution is built on top of the Zend_Service_Amazon class (with a few extensions of my own).

The reasoning behind making the service is that there are several factors that are in play when deciding whether to order a product from the US or from the UK: the exchange rate for GBP and USD, the shipping cost, the delivery situation for the item and whether the item is sold in the store at all.

The user enters a list of the URLs to the products they’re considering purchasing from an Amazon-store, press submit and get a list back of which items are in stock, where the item is the cheapest and what the total sum of an order placed at the store would be. In addition I added a alpha stage feature just before Christmas which will also tell you the “optimum” set of items for the orders – “order item 1,4,7,9 from .com, item 2,3,5,6,8 from .co.uk”. This took quite a bit of hacking – you also have to consider the initial price of shipping, shipping for each item and other fun things.

Feel free to play with it over at mismi.e-mats.org. It’s in Norwegian, but it should be easy to understand anyhow with the description above.

Patching Zend_OpenId To Maintain Error Messages

To help anyone else in their quest to implement Zend_OpenId in their code, I’ve created a small patch against trunk which adds error internal error messages in most places where there’s a return false;. This should help when debugging your code, both if you’re implementing an authentication service and use Zend_OpenId as a consumer or if you’re implementing just the consumer part of the equation.

I’ve uploaded the diff: Consumer.php.patch (Consumer.php.patch.txt).

The only thing that seemed a bit weird was that one of the error messages that were present in 1.6.0 had been removed in trunk:

if ($status != 200) {
    this->_setError("'Dumb' signature verification HTTP request failed");
    return false;
}

I’ve readded this message in my patch, but I feel that the error message should be something like:

$this->_setError("The server responded with HTTP status code: " . $status);

instead.

Oh well. Hopefully someone will find this useful.

Adventures in OpenID and Zend Framework

I’ve been toying around with OpenID and the Zend Framework for a night or two now, and I’ve made a few experiences I thought I should share with the intarwebs (now, that’s probably the point where you should make the decision to stop reading for most blog posts). Quite some time has passed since I last had anything to do with OpenID, so just getting up and running was a challenge.

An OpenID identifier is usually represented by an URL (such as https://me.yahoo.com/<login>), which the OpenID consumer then contacts to get information about how to communicate with the OpenID identity provider (Yahoo! in this case). The consumer contacts the provider, gets an URL to redirect the client to, and receives notice after the client has authenticated with the provider.

First I’d like to say that OpenID seems to be too hard to use for any other than those who have a particular interest in it. I have a Yahoo! account and a Google Account, which both can be used for OpenID authentication. I have no idea how I use my Google Account for this, without having to provide endpoints manually. Ugly.

I did at least get the Yahoo! authentication working, but I’m still undecided on wether I’m going to implement OpenID support in any current project. Possibly. We’ll see.

Anyways, my implementation in Zend Framework is mostly a copy of the tutorial in the ZF manual, but there is one important point that they do not mention: In the standard installation, you have to use Zend_Session to handle your sessions. That means calling Zend_Session::start() instead of session_start(), as Zend_Session cannot be used after a session has been started. This dependency kind of killed my enthusiasm, as we just pull the parts of Zend Framework that we need into our project as thing progresses. Changing how we use sessions is a bit too much to ask. Luckily you can still use $_SESSION as usual after starting Zend_Session, but sitll. Not too fond of that. I hope that it will be decoupled some time in the future..

Testing code:

require_once 'Zend/OpenId/Consumer.php';

$consumer = new Zend_OpenId_Consumer();

if (!empty($_POST['openid_identity']))
{
    if(!$consumer->login($_POST['openid_identity']))
    {
        die("OpenID login failed.");
    }
    else
    {
        print('We logged in!');
    }
}

if (isset($_GET['openid_mode']))
{
    switch($_GET['openid_mode'])
    {
        case 'id_res':
            $consumer = new Zend_OpenId_Consumer();
            $id = false;
            
            if ($consumer->verify($_GET, $id))
            {
                $status = "VALID " . htmlspecialchars($id);
            }
            else
            {
                $status = "INVALID " . htmlspecialchars($id);
            }

            print($status);
            break;

        case 'cancel':
            print("someone pressed cancel!");
            break;
    }
}

Switch out $_POST[‘openid_identity’] with your OpenID identifier (the whole URL), and you should be all set.

If you keep getting failed logins without a redirect, check that you have https support in PHP through openssl (the module is named php_openssl). Zend Framework provides no hint that this can be a problem, but after stepping through the source (I’m test driving NetBeans 6.5) the solution became apparent.

Christer Goes Bug Hunting

Christer had the pleasure of hunting down a bug in Zend Framework a couple of days ago, and he has just posted a nice article about the bug in Zend MVC Components and how he debugged it. If you’ve never used a debugger before, this article is probably also going to be a bit helpful, and it gives a little insight into how the Zend Framework MVC-components work.

Christer Puts on His Problem Solver Hat

I’m not sure how much sugar Christer got into his system today, but he’s been completely on fire with his blog posts. This one shows how to write a custom Zend_Form_Decorator_Label , which he wrote after someone asked a question about how to do something in particular on the Zend MVC mail list. That guy is amazing.

Using Objects with Zend_View’s PartialLoop Helper

Christer has obviously been having a good day today too, as he’s actually made yet ANOTHER blog post about something related to Zend Framework: Using Objects with Zend_View’s PartialLoop Helper. This time he’s examining why some methods suddenly has disappeared in his PartialLoop. I’m a bit surprised his father hasn’t helped him with his view scripts, tho. It’s probably just something he’s saying to don’t appear too incompetent.