1 package TestComplexApp::Controller::PaymentProvider;
3 use Moose::Meta::Class;
4 use namespace::autoclean;
6 BEGIN { extends 'Catalyst::Controller'; };
10 PaymentApp::Controller::PaymentProvider - Provider Controller factory
14 This module creates dynamic Catalyst controllers based on
15 configuration. It's intended for use with Catalyst::Engine::Stomp,
16 where each controller namespace corresponds to a message queue
19 The generated controllers expect Model classes to be defined for the
20 configured payment providers, as configured by
21 PaymentApp::Model::PaymentProvider - and in fact we borrow that
24 We create one controller for each configured payment provider, for
25 each configured environment. The generated namespace is based on both
26 these names, so you end up with queues like "live_datacash".
28 The relevant configuration comes from Catalyst, and should resemble
31 Model::PaymentProvider:
33 - PaymentProvider::Datacash
34 - PaymentProvider::Cybersource
35 - PaymentProvider::Null
37 Controller::PaymentProvider:
46 We're currently hardcoding the list of methods which form the
47 interface to a payment processor. This will change - we will require
48 that a payment provider class "does" a Moose role, and that role will
49 indicate the methods we should consider dispatchable.
53 PaymentApp::Model::PaymentProvider - this module's partner in crime.
57 __PACKAGE__->config( namespace => '' );
60 my $self = shift->next::method(@_);
62 # Sneakily borrow our corresponding model's config for providers
63 my $model_config = $self->_app->config->{'Model::PaymentProvider'};
64 my $provider_classes = $model_config->{providers};
66 # Environment list is from our own config.
67 my $environments = $self->{environments};
69 # For each configured provider/environment combination, create
70 # a Controller class which dispatches a set of methods to the
72 for my $provider_class (@$provider_classes) {
73 for my $environment (@$environments) {
75 # Compose the name of the Controller
76 my $env_class = ucfirst($environment);
77 my $provider_controller_name = "Controller::${provider_class}::${env_class}";
79 # Compose its namespace - i.e. the STOMP queue name
80 my $namespace = $environment . '_' . $provider_class->name;
81 $self->_app->config( $provider_controller_name => { namespace => $namespace } );
83 # Create the class with Moose
84 my $provider = Moose::Meta::Class->create("PaymentApp::${provider_controller_name}");
85 $provider->superclasses('PaymentApp::ControllerBase::Message');
87 # XXX from interface role, not static list here!
88 my @dispatchable_methods = qw/ payment_auth_request
89 payment_settle_request
90 payment_refund_request
93 # Attach a method for each action, making sure
94 # to apply the right method attribute to turn
96 for my $method_name (@dispatchable_methods) {
98 my ($self, $c, $message) = @_;
99 my $provider_model = $c->model($provider_class);
100 my $response = $provider_model->$method_name($message);
101 $c->stash->{response} = $response;
104 # Why doesn't add_method return the method?
105 $provider->add_method($method_name, $sub);
106 my $method = $provider->get_method($method_name);
107 $provider->register_method_attributes($method->body, ['Local']);
115 __PACKAGE__->meta->make_immutable;