<< Previous | Home

Groovily Verifying a PayPal Event

I've been dealing with PayPal subscriptions for a little while now, using it to manage quite a complex subscription scheme. Though I encrypt my PayPal buttons, the notifications from PayPal are sent to an unencrypted URL, so I need check with PayPal to make sure the notifications are in fact from them. To do this, one sends back the notification's request parameters, to which PayPal respond with a 'VERIFIED' or 'INVALID' string.

After digging about for some Java code to do this, I couldn't resist converting it to Groovy. I like to do this, both to understand what the code does, and also to practice some of the Groovy APIs I don't get to use every day. And of course, any excuse to call one of my favourites, inject.
The code is quite terse:

def verifyIPN(request) {
    def names = request.getParameterNames().toList()
    def paramString = names.inject('cmd=_notify-validate') { result, name ->
        def value = request.getParameter(name)
        result << "&${name}=${URLEncoder.encode(value)}"
    }

    def url = new URL(grailsApplication.config.grails.paypal.url)
    def conn = url.openConnection()
    conn.setDoOutput(true)
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded")

    conn.getOutputStream().withWriter { writer -> writer << paramString }
    return conn.getInputStream().withReader { reader -> reader.readLine() }
}
In the end, all I want is clear code.
I sometimes think my code will start appealing to Perl hackers. What do you think?

Grails and Error Handling

I finished writing my first plugin today. As with most things Grails, it was surprisingly easy. The plugin injects some methods into my domain and controller classes which I can use to streamline my code.

I am not too fond of using if statements to direct flow around error handling code. For me, it clouds the core logic of a piece of code. If the normal flow of the code is assumed to execute error free, why shouldn't the code look like it does?

The idea is very simple. I inject some new methods that will throw exceptions on failure. I've called them trySave, tryDelete and tryValidate. Consider this code, generated kindly by Grails:

 def save = {
    def jsecUser = new JsecUser(params)
    if(!jsecUser.hasErrors() && jsecUser.save()) {
        flash.message = "JsecUser ${jsecUser.id} created"
        redirect(action:show,id:jsecUser.id)
    }
    else {
        render(view:'create',model:[jsecUser:jsecUser])
    }
}
After installing my plugin, I can do this:
 def save = {
    withErrorHandling {
        try {
            def jsecUser = new JsecUser(params)
            jsecUser.trySave()
            render(view:'create',model:[jsecUser:jsecUser])
        } catch (ValidationException e) {
            flash.message = "JsecUser ${jsecUser.id} created"
            redirect(action:show,id:jsecUser.id)
        }
    }
}
And if I define a closure named errorHandler in my controller, I can add custom error handling for all actions in this controller:
def errorHandler = { ex ->
    if (ex.class == StoreException) {
        // log this and redirect to somewhere useful to the user, or perhaps return to the 'edit' page if there is an 'id' parameter.
    } else {
        defaultErrorHandler()
    }
}
Ideally, I would like to wrap the controller actions in a try..catch block and not have the extra withErrorHandling syntax, though I am not sure how to go about this yet. Any pointers anyone?

All in all, I rather like not dealing with the save method returning null on failure, and also catching those annoying constraint exceptions, as the try* methods are called with flush:true by default. Now it's time to use this a little and see how I like it in practice - I can already see I've over-designed this simple API as I can't think of a use case for tryValidate :)

Vancouver's 1st Groovy/Grails Meetup

If anyone in Vancouver is wondering what Groovy/Grails is about, come over to Workspace on the 26th and find out. Gerald Bauer and I (perhaps a 3rd person) will be presenting.

My presentation will be on Grails - my plan is go from a big picture to the details by deconstructing a little web app, and then reconstructing parts of it to demonstrate what it is like to create with Grails. It should be a lot of fun.