File Coverage

blib/lib/Business/Payment/ClearingHouse.pm
Criterion Covered Total %
statement 1 3 33.3
branch n/a
condition n/a
subroutine 1 1 100.0
pod n/a
total 2 4 50.0


line stmt bran cond sub pod time code
1             package Business::Payment::ClearingHouse;
2 2     2   150457 use Moose;
  0            
  0            
3              
4             use Data::UUID;
5              
6             our $VERSION = '0.01';
7              
8             has 'charges' => (
9             traits => [ 'Hash' ],
10             is => 'ro',
11             isa => 'HashRef[Business::Payment::ClearingHouse::Charge]',
12             default => sub { {} },
13             handles => {
14             'delete_charge' => 'delete',
15             'get_charge' => 'get',
16             'set_charge' => 'set'
17             }
18             );
19              
20             has 'number_verifier' => (
21             traits => [ 'Code' ],
22             is => 'ro',
23             isa => 'CodeRef',
24             default => sub { sub { return 1 } },
25             handles => {
26             verify_number => 'execute'
27             }
28             );
29              
30             has 'states' => (
31             traits => [ 'Hash' ],
32             is => 'ro',
33             isa => 'HashRef[Str]',
34             default => sub { {} },
35             handles => {
36             'delete_state' => 'delete',
37             'get_state' => 'get',
38             'set_state' => 'set'
39             }
40             );
41              
42             has 'uuid' => (
43             is => 'ro',
44             lazy_build => 1
45             );
46              
47             sub _build_uuid {
48             my ($self) = @_;
49              
50             return Data::UUID->new;
51             }
52              
53             sub auth {
54             my ($self, $charge) = @_;
55              
56             # unless($self->verify_number($charge->number)) {
57             # die "Invalid number\n";
58             # }
59              
60             my $uuid = $self->uuid->create_str;
61              
62             $self->set_charge($uuid, $charge);
63             $self->set_state($uuid, 'auth');
64              
65             return $uuid;
66             }
67              
68             sub credit {
69             my ($self, $charge) = @_;
70              
71             my $uuid = $self->uuid->create_str;
72              
73             $self->set_state($uuid, 'credit');
74             $self->set_charge($uuid, $charge);
75             }
76              
77             sub info {
78             my ($self, $uuid) = @_;
79              
80             return $self->get_charge($uuid);
81             }
82              
83             sub postauth {
84             my ($self, $uuid) = @_;
85              
86             my $charge = $self->get_charge($uuid);
87             unless(defined($charge)) {
88             die "Unknown Charge\n";
89             }
90              
91             my $status = $self->get_state($uuid);
92             unless(defined($status) && ($status eq 'preauth')) {
93             die "Must preauth before postauthing\n";
94             }
95              
96             $self->set_state($uuid, 'postauth');
97              
98             return 1;
99             }
100              
101             sub preauth {
102             my ($self, $charge) = @_;
103              
104             # unless($self->verify_number($charge->number)) {
105             # die "Invalid number\n";
106             # }
107              
108             my $uuid = $self->uuid->create_str;
109              
110             $self->set_charge($uuid, $charge);
111             $self->set_state($uuid, 'preauth');
112              
113             return $uuid;
114             }
115              
116             sub settle {
117             my ($self) = @_;
118              
119             my $total = 0;
120              
121             foreach my $uuid (keys %{ $self->states }) {
122             my $state = $self->get_state($uuid);
123             my $charge = $self->get_charge($uuid);
124              
125             if($state eq 'preauth') {
126             # Skip these, as they are in flight
127             next;
128             } elsif($state eq 'auth' || $state eq 'postauth') {
129             $total += $charge->total;
130             } elsif($state eq 'credit') {
131             $total -= $charge->total;
132             }
133              
134             # Since we got here, we can just delete it now.
135             $self->delete_state($uuid);
136             $self->delete_charge($uuid);
137             }
138              
139             return $total;
140             }
141              
142             sub void {
143             my ($self, $uuid) = @_;
144              
145             my $charge = $self->get_charge($uuid);
146              
147             if(defined($charge)) {
148             $self->delete_charge($uuid);
149             $self->delete_state($uuid);
150             return 1;
151             }
152              
153             return 0;
154             }
155              
156             __PACKAGE__->meta->make_immutable;
157              
158             no Moose;
159              
160             1;
161              
162             =head1 NAME
163              
164             Business::Payment::ClearingHouse - ClearingHouse for Business::Payment
165              
166             =head1 SYNOPSIS
167              
168             use Business::Payment::ClearingHouse;
169              
170             my $house = Business::Payment::ClearingHouse->new();
171              
172             # Create a charge
173             my $charge = Business::Payment::ClearingHouse::Charge->new(
174             subtotal => 100,
175             tax => 10
176             );
177             # Authorizate it and get the uuid
178             my $uuid = $house->auth($charge);
179              
180             # Settle!
181             my $total = $house->settle;
182              
183             =head1 DESCRIPTION
184              
185             Business::Payment::ClearingHouse provides an API that emulates a payment
186             processor like the ones used with credit cards. The operations it provides
187             are inspired by those present with a credit card processor: preauth (reserve),
188             postauth (consume the reserved funds), auth (immediately charge), credit
189             (refund) and void (remove a charge).
190              
191             This module is intended to provide a testbed for features of
192             L<Business::Payment> and to provide a testing processor for use in development
193             environments. The C<settle> method allows a developer to examine the net
194             results of a series of transactions.
195              
196             B<Notice>: This module is in development. The API will likely change.
197              
198             =head1 ATTRIBUTES
199              
200             =head2 charges
201              
202             Hashref of charges. Keys are the UUIDs and values are the charge objects.
203              
204             =head2 states
205              
206             Hashref of charge states. Keys are the UUIDs and the values are the strings
207             that represent state. One of preauth, postauth, auth or credit.
208              
209             =head2 uuid
210              
211             The UUID generator used by this object, a lazily insantiated Data::UUID
212             object.
213              
214             =head1 METHODS
215              
216             =head2 auth ($charge)
217              
218             Performs an immediate auth for the supplied charge.
219              
220             =head2 credit ($charge)
221              
222             Performs a credit for the supplied charge.
223              
224             =head2 info ($uuid)
225              
226             Returns the charge associated with the supplied UUID.
227              
228             =head2 postauth ($uuid)
229              
230             Performs a post-authorization for the charge tied to the supplied UUID. This
231             is the second operation after a C<preauth>.
232              
233             =head2 preauth ($charge)
234              
235             Performs a pre-authorization for the supplied charge. This should be followed
236             by a C<postauth>.
237              
238             =head2 settle
239              
240             Totals up and removes all pending transactions. Returns the total (sum of all
241             auth and postauth, less any credits). Any remaining preauth transactions
242             are left in the clearinghouse to be postauthed later.
243              
244             =head2 void ($uuid)
245              
246             Voids the charge with the supplied UUID. Removes any information about the
247             charge from the clearinghouse.
248              
249             =head1 AUTHOR
250              
251             Cory G Watson, C<< <gphat at cpan.org> >>
252              
253             =head1 COPYRIGHT & LICENSE
254              
255             Copyright 2009 Cold Hard Code, LLC.
256              
257             This program is free software; you can redistribute it and/or modify it
258             under the terms of either: the GNU General Public License as published
259             by the Free Software Foundation; or the Artistic License.
260              
261             See http://dev.perl.org/licenses/ for more information.