[Catalyst] PayPal (and others) integration

J. Shirley jshirley at gmail.com
Thu Apr 9 10:14:43 GMT 2009


On Thu, Apr 9, 2009 at 6:23 PM, Edmund von der Burg <
edmund.vonderburg at gmail.com> wrote:

> 2009/4/9 J. Shirley <jshirley at gmail.com>:
> > Your mistake is thinking this is a controller, when in fact it is a mod=
el
> > class and has absolutely no relation to Catalyst :)
>
> I beg to differ.
>
> When something happens on PayPal then can hit a location on your site
> to inform you of this. Usually the url would be something like:
>
>  http://myapp.com/ipn
>
> Your app then needs to confirm the request back to PayPal to check
> that it is legit.
>
> This makes me think that a controller is needed - perhaps I am wrong?
>

> more details:
> https://cms.paypal.com/us/cgi-bin/?cmd=3D_render-content&content_ID=3Ddev=
eloper/e_howto_html_IPNandPDTVariables
>
> Cheers,
>  Edmund
>
> > What you want is a set of simple model classes (nothing more than
> > Catalyst::Model::Adaptor, it's on CPAN) that wraps your
> > (Google::Checkout|Business::PayPal) models.
> >
> > Your controller should simply delegate to the model based on user input,
> and
> > nothing more.
> >
> > Remember: cgi-lib.pl was glue for web 1.0, Catalyst is glue for web *.0.
>
> All too well :)
>
> Cheers,
>   Edmund.
>
> _______________________________________________
> List: Catalyst at lists.scsys.co.uk
> Listinfo: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/catalyst
> Searchable archive:
> http://www.mail-archive.com/catalyst@lists.scsys.co.uk/
> Dev site: http://dev.catalyst.perl.org/
>


Sure, a controller is needed.  But its scope is not anything more than
dispatching the commands into the model.  All the processing still happens
in the model class.

Business::PayPal::IPN exists on CPAN, all you need is a model that wraps
that and then your controller is just a very thin conduit.

What I would do is simply have an action that accepts an IPN parameter and
forwards that to the model.  The model should do the validation, just as if
it were a command line app and a user were using it.  This is what I meant
by "Your controller should simply delegate to it".

It could be something as simple as:

sub ipn : Local {
    my ( $self, $c, $method ) =3D @_;
    eval { $c->model('Whatever')->$method( $c->req->params ); };
    if ( $@ ) {
        $c->error($@);
        $c->stash->{template} =3D 'ohno/weizburning.tt';
    }
}

This keeps your functionality mostly out of your controller, which is bound
to change.  If your MyApp::Model class is also very very thin (since the
solution exists on CPAN for IPN) then you can get by with some very easy
tests, and additionally you can move this code to another application (say
for internal purposes) much easier.

Just for context, I've been preaching this method for a while... but failed
to do this technique and ended up just dumping it in a controller because of
lack of time.

What I ended up with is an untested mess that sucks.  I now, about 9 months
later, have to refactor this into doing exactly what I am describing above,
so that I can share the functionality between two separate applications that
have overlapping functionality.

So, please, don't be like me.

-J
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://lists.scsys.co.uk/pipermail/catalyst/attachments/20090409/9b712=
ec2/attachment.htm


More information about the Catalyst mailing list