From 3c5cccf1bf74f2e60482fe62cfbcbe06722da1f5 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Wed, 11 Jul 2012 00:08:15 -0700 Subject: initial commit --- BatchPayment/Processor.pm | 141 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 BatchPayment/Processor.pm (limited to 'BatchPayment/Processor.pm') 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. 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. + +=item receive + +Download/otherwise acquire the available confirmed transactions from the +gateway, parse them, and return a list of L +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; -- cgit v1.2.1