summaryrefslogtreecommitdiff
path: root/BatchPayment/Processor.pm
diff options
context:
space:
mode:
authorIvan Kohler <ivan@freeside.biz>2012-07-11 00:08:15 -0700
committerIvan Kohler <ivan@freeside.biz>2012-07-11 00:08:15 -0700
commit3c5cccf1bf74f2e60482fe62cfbcbe06722da1f5 (patch)
treed0bfc425deb44dbaa0cad9f272cd2023407ebd05 /BatchPayment/Processor.pm
initial commit
Diffstat (limited to 'BatchPayment/Processor.pm')
-rw-r--r--BatchPayment/Processor.pm141
1 files changed, 141 insertions, 0 deletions
diff --git a/BatchPayment/Processor.pm b/BatchPayment/Processor.pm
new file mode 100644
index 0000000..26f5ba0
--- /dev/null
+++ b/BatchPayment/Processor.pm
@@ -0,0 +1,141 @@
+=head1 NAME
+
+Business::BatchPayment::Processor - Common interface for batch payment gateways
+
+=head1 DESCRIPTION
+
+Business::BatchPayment::Processor is a Moose role. Modules implementing
+the protocol to talk to specific payment processing services should compose
+it.
+
+There are two general schemes for interacting with a batch payment gateway:
+
+=over 4
+
+=item Request/Reply
+
+In this mode, you (the merchant) assemble a batch of payment requests,
+including account numbers, and send it to the gateway. At some point in
+the future, the gateway sends back one or more reply batches indicating the
+results of processing the payments.
+
+When submitting a request batch, the merchant software marks each payment
+request with a unique transaction ID (the "tid" field). This should be
+stored somewhere. When the reply batch is processed, each item will have
+a tid matching its request.
+
+Note that some gateways will provide results only for approved payments,
+or even only for declined payments. It is then up to the merchant software
+to follow a sensible policy for approving or declining payments whose
+ultimate status is unconfirmed.
+
+=item One-Way
+
+In this mode, the gateway transmits a batch file containing approved
+payments, without those payments being requested. For example, most
+commercial banks provide check lockbox services and periodically
+send the merchant a statement of payments received to the lockbox.
+This statement would be processed as a one-way batch.
+
+=back
+
+=head1 ATTRIBUTES
+
+Most attributes for B::BP::Processor objects are defined by the module.
+
+=over 4
+
+=item transport - See L<Business::BatchPayment::Transport>. This must
+be set before calling submit() or receive(). Some modules will set it
+themselves; others require a transport to be supplied. Check for the
+existence of a 'default_transport' method.
+
+=item debug - Debug level. This may be interpreted in various ways by
+the module.
+
+=item test_mode - Communicate with a test server instead of the production
+gateway. Not all processors support this.
+C<$processor->does('Business::BatchPayment::TestMode')> should tell whether
+it's supported.
+
+=back
+
+=head1 OTHER PARAMETERS
+
+=over 4
+
+=item input FILE
+
+=item output FILE
+
+If either of these is passed when constructing a Processor object, the
+transport will be replaced with a File transport with those parameters.
+Specifying only 'input' will direct 'output' to /dev/null, and vice versa.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item submit BATCH
+
+Send a batch of requests to the gateway. BATCH must be a
+L<Business::BatchPayment::Batch>.
+
+=item receive
+
+Download/otherwise acquire the available confirmed transactions from the
+gateway, parse them, and return a list of L<Business::BatchPayment::Batch>
+objects. The items in these batches will have, at minimum, the 'approved'
+field and either the 'tid' or 'amount' field set.
+
+=back
+
+=cut
+
+package Business::BatchPayment::Processor;
+
+use Moose::Role;
+with 'Business::BatchPayment::Debug';
+
+requires 'format_request', 'parse_response';
+
+has 'transport' => (
+ is => 'rw',
+ does => 'Business::BatchPayment::Transport',
+ # possibly this part should be a separate role
+ lazy => 1,
+ builder => 'default_transport',
+);
+
+around BUILDARGS => sub {
+ my ($orig, $class, %args) = @_;
+ %args = %{ $class->$orig(%args) }; #process as usual
+ # then:
+ if ( $args{input} or $args{output} ) {
+ $args{transport} = Business::BatchPayment->create( 'Transport::File',
+ input => $args{input},
+ output => $args{output},
+ );
+ }
+ \%args;
+};
+
+sub submit {
+ my $self = shift;
+ my $batch = shift;
+ my @items = @_;
+ my $request = $self->format_request($batch);
+ warn $request if $self->debug >= 2;
+ $self->transport->upload($request);
+}
+
+sub receive {
+ my $self = shift;
+ my @responses = $self->transport->download;
+ warn join("\n\n",@responses) if $self->debug >= 2 and scalar(@responses);
+ map { $self->parse_response($_) } @responses;
+}
+
+1;