Commit | Line | Data |
d4db6430 |
1 | package TestComplexApp::Controller::PaymentProvider; |
2 | use Moose; |
3 | use Moose::Meta::Class; |
4 | use namespace::autoclean; |
5 | |
6 | BEGIN { extends 'Catalyst::Controller'; }; |
7 | |
8 | =head1 NAME |
9 | |
10 | PaymentApp::Controller::PaymentProvider - Provider Controller factory |
11 | |
12 | =head1 DESCRIPTION |
13 | |
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 |
17 | subscription. |
18 | |
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 |
22 | module's config. |
23 | |
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". |
27 | |
28 | The relevant configuration comes from Catalyst, and should resemble |
29 | this: |
30 | |
31 | Model::PaymentProvider: |
32 | providers: |
33 | - PaymentProvider::Datacash |
34 | - PaymentProvider::Cybersource |
35 | - PaymentProvider::Null |
36 | |
37 | Controller::PaymentProvider: |
38 | environments: |
39 | - qa |
40 | - test |
41 | - custqa |
42 | - uat |
43 | |
44 | =head1 TODO |
45 | |
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. |
50 | |
51 | =head1 SEE ALSO |
52 | |
53 | PaymentApp::Model::PaymentProvider - this module's partner in crime. |
54 | |
55 | =cut |
56 | |
57 | __PACKAGE__->config( namespace => '' ); |
58 | |
59 | sub COMPONENT { |
60 | my $self = shift->next::method(@_); |
61 | |
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}; |
65 | |
66 | # Environment list is from our own config. |
67 | my $environments = $self->{environments}; |
68 | |
69 | # For each configured provider/environment combination, create |
70 | # a Controller class which dispatches a set of methods to the |
71 | # provider's Model. |
72 | for my $provider_class (@$provider_classes) { |
73 | for my $environment (@$environments) { |
74 | |
75 | # Compose the name of the Controller |
76 | my $env_class = ucfirst($environment); |
77 | my $provider_controller_name = "Controller::${provider_class}::${env_class}"; |
78 | |
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 } ); |
82 | |
83 | # Create the class with Moose |
84 | my $provider = Moose::Meta::Class->create("PaymentApp::${provider_controller_name}"); |
85 | $provider->superclasses('PaymentApp::ControllerBase::Message'); |
86 | |
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 |
91 | /; |
92 | |
93 | # Attach a method for each action, making sure |
94 | # to apply the right method attribute to turn |
95 | # these into actions |
96 | for my $method_name (@dispatchable_methods) { |
97 | my $sub = sub { |
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; |
102 | }; |
103 | |
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']); |
108 | } |
109 | } |
110 | } |
111 | |
112 | return $self; |
113 | } |
114 | |
115 | __PACKAGE__->meta->make_immutable; |
116 | |