From 3c5cccf1bf74f2e60482fe62cfbcbe06722da1f5 Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Wed, 11 Jul 2012 00:08:15 -0700 Subject: [PATCH] initial commit --- BatchPayment.pm | 113 +++++++++++++++++ BatchPayment/Batch.pm | 52 ++++++++ BatchPayment/Debug.pm | 20 +++ BatchPayment/Item.pm | 273 ++++++++++++++++++++++++++++++++++++++++ BatchPayment/Processor.pm | 141 +++++++++++++++++++++ BatchPayment/TestMode.pm | 18 +++ BatchPayment/Transport.pm | 32 +++++ BatchPayment/Transport/File.pm | 63 ++++++++++ BatchPayment/Transport/HTTPS.pm | 58 +++++++++ BatchPayment/Transport/SFTP.pm | 88 +++++++++++++ Changes | 4 + MANIFEST | 19 +++ META.yml | 28 +++++ Makefile.PL | 26 ++++ README | 35 ++++++ ignore.txt | 13 ++ t/00-load.t | 9 ++ t/manifest.t | 13 ++ t/pod.t | 12 ++ 19 files changed, 1017 insertions(+) create mode 100644 BatchPayment.pm create mode 100644 BatchPayment/Batch.pm create mode 100644 BatchPayment/Debug.pm create mode 100644 BatchPayment/Item.pm create mode 100644 BatchPayment/Processor.pm create mode 100644 BatchPayment/TestMode.pm create mode 100644 BatchPayment/Transport.pm create mode 100644 BatchPayment/Transport/File.pm create mode 100644 BatchPayment/Transport/HTTPS.pm create mode 100644 BatchPayment/Transport/SFTP.pm create mode 100644 Changes create mode 100644 MANIFEST create mode 100644 META.yml create mode 100644 Makefile.PL create mode 100644 README create mode 100644 ignore.txt create mode 100644 t/00-load.t create mode 100644 t/manifest.t create mode 100644 t/pod.t diff --git a/BatchPayment.pm b/BatchPayment.pm new file mode 100644 index 0000000..86ee6b9 --- /dev/null +++ b/BatchPayment.pm @@ -0,0 +1,113 @@ +package Business::BatchPayment; + +use 5.006; +use strict; +use vars '$DEBUG'; +use warnings; + +use Class::MOP; +use Business::BatchPayment::Processor; +use Business::BatchPayment::Item; +use Business::BatchPayment::Transport; + +$DEBUG = 0; + +=head1 NAME + +Business::BatchPayment - Batch-oriented payment processing + +=head1 VERSION + +Version 0.01 + +=cut + +our $VERSION = '0.01'; + +=head1 SYNOPSIS + + use Business::BatchPayment; + + my %options = ( merchant_id => '00451', password => 'opensesame' ); + my $processor = Business::BatchPayment->create(MyGateway => %options); + + my @request; + push @request, Business::BatchPayment->create(Item => + action => 'payment', # as opposed to 'credit' + payment_type => 'CC', #credit card, or 'ECHECK' for check/ACH + amount => '49.95', + tid => '0001234', # transaction id, like a customer/order number + card_number => '1234123412341238', + expiration => '0100', # MM/YY + # these fields are optional + first_name => 'John', + last_name => 'Doe', + address => '123 Main Street', + address2 => 'Suite H', + city => 'Anytown', + state => 'CA', + country => 'US', + zip => '99015', + ); # returns a Business::OnlinePayment::Item; + + $processor->submit(@request); + + # at some point in the future + + my @reply = $processor->receive(); + foreach my $item (@reply) { + ... process items and record successful/failed payments + } + +=head1 CLASS METHODS + +=over 4 + +=item create MODULE[, OPTIONS ] + +Loads Business::BatchPayment::MODULE, then attempts to call +Business::BatchPayment::MODULE->new(OPTIONS). + +=cut + +# not a Moose method + +sub create { + my $class = shift; + my $subclass = shift; + $subclass = "Business::BatchPayment::$subclass"; + Class::MOP::load_class($subclass); + $subclass->new(@_); +} + +=back + +=head1 AUTHOR + +Mark Wells, C<< >> + +=head1 BUGS + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Business::BatchPayment + +Commercial support is available from Freeside Internet Services, +L. + +=head1 LICENSE AND COPYRIGHT + +Copyright 2012 Mark Wells. + +This program is free software; you can redistribute it and/or modify it +under the terms of either: the GNU General Public License as published +by the Free Software Foundation; or the Artistic License. + +See http://dev.perl.org/licenses/ for more information. + + +=cut + +1; # End of Business::BatchPayment diff --git a/BatchPayment/Batch.pm b/BatchPayment/Batch.pm new file mode 100644 index 0000000..eb6716e --- /dev/null +++ b/BatchPayment/Batch.pm @@ -0,0 +1,52 @@ +=head1 NAME + +Business::BatchPayment::Batch + +=head1 DESCRIPTION + +A Business::BatchPayment::Batch object represents a group of payment +requests or confirmations (L) submitted +to a bank (or returned from a bank) as a batch. + +=head1 ATTRIBUTES + +=over 4 + +=item batch_id - Batch identifier. The format is processor-specific +but usually must be a positive integer, if it's used at all. + +Processor modules may include C in a reply batch ONLY if +it is guaranteed to match the batch_id of a request batch AND all +the items in the reply batch come from that request batch. Otherwise, +C must be null. It must always be null when using one-way +(receive-only) workflow, since there are no request batches. + +=item items - An arrayref of L objects +included in the batch. + +=back + +=cut + +package Business::BatchPayment::Batch; + +use Moose; + +has batch_id => ( + is => 'rw', + isa => 'Str', + default => '', +); + +has items => ( + traits => ['Array'], + is => 'rw', + isa => 'ArrayRef[Business::BatchPayment::Item]', + handles => { + count => 'count', + elements => 'elements', + push => 'push', + }, +); + +1; diff --git a/BatchPayment/Debug.pm b/BatchPayment/Debug.pm new file mode 100644 index 0000000..71a9e6d --- /dev/null +++ b/BatchPayment/Debug.pm @@ -0,0 +1,20 @@ +package Business::BatchPayment::Debug; + +=head1 DESCRIPTION + +The 'debug' attribute. All Business::BatchPayment classes should support +this. $Business::BatchPayment::DEBUG can be set to turn on debugging +globally. + +=cut + +use Moose::Role; + +has 'debug' => ( + is => 'rw', + isa => 'Int', + default => sub { $Business::BatchPayment::DEBUG || 0 }, + lazy => 1, +); + +1; diff --git a/BatchPayment/Item.pm b/BatchPayment/Item.pm new file mode 100644 index 0000000..6e1e8e5 --- /dev/null +++ b/BatchPayment/Item.pm @@ -0,0 +1,273 @@ +package Business::BatchPayment::Item; + +use Moose; +use Moose::Util::TypeConstraints; +use MooseX::UndefTolerant; +use DateTime; + +=head1 NAME + +Business::BatchPayment::Item + +=head1 DESCRIPTION + +A Business::BatchPayment::Item represents a single payment request or +reply (approval or rejection). When submitting a batch, the merchant +system constructs B::BP::Item objects for each attempted payment in +the batch. Results downloaded from the gateway are returned as a +list of Items with the 'approved' field set to a true or false value. + +=head1 REQUIRED ATTRIBUTES + +=over 4 + +=item action + +"payment" or "credit". Most processors support only "payment". +"payment" is defined as "money transfer FROM the account identified in the +Item TO the account identified by the Processor object's login settings." +"credit" is the other direction. + +=cut + +enum 'Action' => qw(payment credit); +coerce 'Action', from 'Str', via { lc $_ }; +has action => ( + is => 'rw', + isa => 'Action', + default => 'payment', + required => 1, + coerce => 1, +); + +=item payment_type + +"CC" or "ECHECK". Most processors will only support +one or the other, and if set on the BBP::Processor object, this is not +required. + +=cut + +# are we okay with these names? +enum 'PaymentType' => qw( CC ECHECK ); +has payment_type => ( is => 'rw', isa => 'PaymentType' ); + +=item amount + +the amount, as a decimal number. Required only in request +items. + +=cut + +# perhaps we should apply roles that distinguish request and reply items? +# they have different required fields. +has amount => ( + is => 'rw', + isa => 'Num', +); + +=item tid + +transaction identifier. Requests must provide this. It's +a token of some kind to be passed to the gateway and used to identify the +reply. For now it's required to be an integer. An invoice number would +be a good choice. + +=cut + +has tid => ( is => 'rw', isa => 'Int' ); + +=back + +=head1 OPTIONAL ATTRIBUTES + +=head2 Customer Information + +=over 4 + +=item customer_id + +A customer number or other identifier, for the merchant's +use. + +=item first_name + +First name. + +=item last_name + +Last name. + +=item company + +Company name. + +=item address, address2, city, state, country, zip + +Billing address fields. Credit card processors may use these (especially +zip) for authentication. + +=cut + +has [ qw( + customer_id + first_name + last_name + company + address + address2 + city + state + country + zip +) ] => ( is => 'rw', isa => 'Str', default => '' ); + +=back + +=head2 Transaction Information + +=over 4 + +=item process_date + +The date requested for processing. + +=item invoice_number + +An invoice number, for your use. + +=cut + +class_type 'DateTime'; +coerce 'DateTime', from 'Int', via { DateTime->from_epoch($_) }; +has process_date => ( is => 'rw', isa => 'DateTime', coerce => 1 ); + +has invoice_number => ( is => 'rw', isa => 'Str' ); + +=back + +=head2 Bank Transfer / ACH / EFT + +=over 4 + +=item account_number + +Bank account number. + +=item routing_code + +Bank's routing code. + +=item account_type + +Can be 'personal checking', 'personal savings' +'business checking', or 'business savings'. + +=cut + +enum 'Account_Type' => [ + 'personal checking', + 'personal savings', + 'business checking', + 'business savings', +]; +coerce 'Account_Type', from 'Str', via { lc $_ }; + +has account_number => ( is => 'rw', isa => 'Str' ); +has routing_code => ( is => 'rw', isa => 'Str' ); +has account_type => ( is => 'rw', isa => 'Account_Type', coerce => 1 ); + +=back + +=head2 Credit Card + +=over 4 + +=item card_number + +Credit card number. + +=item expiration + +Credit card expiration, MMYY format. + +=cut + +has card_number => ( is => 'rw', isa => 'Str' ); +has expiration => ( is => 'rw', isa => 'Str' ); + +=back + +=head2 Tokenized Payment + +=over 4 + +=item pay_by_token + +If your gateway supports it, this may be +provided instead of card_number/account_number. See also +C below. + +=cut + +has pay_by_token => ( is => 'rw', isa => 'Str' ); + +=back + +=head1 REPLY ATTRIBUTES + +=over 4 + +=item approved + +Boolean field for whether the item was approved. This +will always be set on replies. + +=item payment_date + +The date the payment was processed, as a DateTime +object. + +=item order_number + +The transaction identifier returned by the gateway +(not to be confused with 'tid', which is a transaction identifier assigned +by the merchant system). This is usually the identifier for performing +other operations on the transaction, like voiding or refunding it. + +=item authorization + +The authorization code, probably only meaningful for credit cards. +Should be undef (or not present) if the transaction wasn't approved. + +=item assigned_token + +In tokenized systems which store the customer's account number or +credit card for future transactions, this is the token assigned to +identify that account. Pass it as 'pay_by_token' to use that payment +account again. + +=item error_message + +The message returned by the gateway. This may +contain a value even if the payment was successful (use C +to determine that.) + +=back + +=cut + +has approved => ( is => 'rw', isa => 'Maybe[Bool]' ); + +has payment_date => ( is => 'rw', isa => 'DateTime' ); + +has [qw( + authorization + error_message + order_number + assigned_token +)] => ( is => 'rw', isa => 'Str'); + +__PACKAGE__->meta->make_immutable; + +1; 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; diff --git a/BatchPayment/TestMode.pm b/BatchPayment/TestMode.pm new file mode 100644 index 0000000..551a9aa --- /dev/null +++ b/BatchPayment/TestMode.pm @@ -0,0 +1,18 @@ +package Business::BatchPayment::TestMode; + +=head1 DESCRIPTION + +The 'test_mode' attribute. A module that does this role is promising that +requests will not be submitted to a live account if test_mode is true. + +=cut + +use Moose::Role; + +has 'test_mode' => ( + is => 'rw', + isa => 'Bool', + default => 0, +); + +1; diff --git a/BatchPayment/Transport.pm b/BatchPayment/Transport.pm new file mode 100644 index 0000000..4ac8b71 --- /dev/null +++ b/BatchPayment/Transport.pm @@ -0,0 +1,32 @@ +package Business::BatchPayment::Transport; + +use Moose::Role; +with 'Business::BatchPayment::Debug'; + +requires 'upload'; +requires 'download'; + +=head1 NAME + +Business::BatchPayment::Transport + +=head1 USAGE + +Business::BatchPayment::Processor classes must have a 'transport' attribute +which does the Business::BatchPayment::Transport role (implements 'upload' +and 'download'). The B::BP::Processor class can implement 'default_transport' +to construct a B::BP::Transport object. + +'upload' must take a scalar argument containing the (correctly formatted) +batch for upload. On success, it may return nothing, or a scalar identifier +for the batch (such as a serial number) if the gateway requires one. + +'download' takes the return value from 'upload' (if any) as its argument, +and returns any number of scalars containing batch files. If there are no +batches available, it should return an empty list. + +Both of these methods should die on error. + +=cut + +1; diff --git a/BatchPayment/Transport/File.pm b/BatchPayment/Transport/File.pm new file mode 100644 index 0000000..eaaba49 --- /dev/null +++ b/BatchPayment/Transport/File.pm @@ -0,0 +1,63 @@ +package Business::BatchPayment::Transport::File; + +=head2 File transport + +The simplest case. Takes two arguments, 'input' and 'output'. These can +be open filehandles or strings naming files. If unspecified, they default +to /dev/null. + +=cut + +use IO::File; +use Moose; +with 'Business::BatchPayment::Transport'; + +has 'input' => ( + is => 'rw', + isa => 'Maybe[FileHandle|Str]', + default => sub { + warn "no input passed to file transport; using /dev/null"; + '/dev/null' + }, + #lazy => 1, +); + +has 'output' => ( + is => 'rw', + isa => 'Maybe[FileHandle|Str]', + default => sub { + warn "no output passed to file transport; using /dev/null"; + '/dev/null' + }, + #lazy => 1, +); + +sub upload { + my $self = shift; + my $text = shift; + my $fh; + if ( ref $self->output ) { + $fh = $self->output; + } else { + $fh = IO::File->new(); + $fh->open($self->output,'>') + or die "couldn't write to ".$self->output; + } + print $fh $text; +} + +sub download { + my $self = shift; + my $fh; + if ( ref $self->input ) { + $fh = $self->input; + } else { + $fh = IO::File->new(); + $fh->open($self->input,'<') + or die "couldn't read from ".$self->input; + } + local $/; + my $text = <$fh>; +} + +1; diff --git a/BatchPayment/Transport/HTTPS.pm b/BatchPayment/Transport/HTTPS.pm new file mode 100644 index 0000000..c40a78f --- /dev/null +++ b/BatchPayment/Transport/HTTPS.pm @@ -0,0 +1,58 @@ +package Business::BatchPayment::Transport::HTTPS; + +=head2 HTTPS transport + +Sends a request by HTTPS POST, and downloads the response the same way. +Options are 'server', 'port', 'get_path', 'put_path', optionally +'content_type'. + +=cut + +use Net::HTTPS::Any 0.10; +use Moose; +with 'Business::BatchPayment::Transport'; + +has [ qw( host port get_path put_path ) ] => ( + is => 'ro', + isa => 'Str' +); + +has 'content_type' => ( + is => 'rw', + isa => 'Str', + default => 'text/plain' +); + +sub https_post { + my $self = shift; + my $path = shift; + my $content = shift; + + warn "starting https_post...\n" if $self->debug; + my ( $page, $response, %reply_headers ) = Net::HTTPS::Any::https_post( + host => $self->host, + port => $self->port, + path => $path, + content => $content, + debug => ($self->debug >= 3), + ); + warn "PAGE:\n$page\n\nRESPONSE:\n$response\n\n" if $self->debug >= 2; + return ($page, $response, %reply_headers); +} + +sub upload { + my $self = shift; + my $content = shift; + $self->https_post($self->put_path, $content); +} + +sub download { + # will probably need to be overridden in most cases + my $self = shift; + my ($page, $response, %reply_headers) = $self->https_post($self->get_path); + $page; +} + +__PACKAGE__->meta->make_immutable; + +1; diff --git a/BatchPayment/Transport/SFTP.pm b/BatchPayment/Transport/SFTP.pm new file mode 100644 index 0000000..08d2fb7 --- /dev/null +++ b/BatchPayment/Transport/SFTP.pm @@ -0,0 +1,88 @@ +package Business::BatchPayment::Transport::SFTP; + +=head2 Business::BatchPayment::Transport::SFTP + +Import this role to use SFTP. Requires "host", "port', "user", and +"password" to be set. The 'sftp' method returns a Net::SFTP::Foreign +object providing 'get' and 'put' methods (among others). All of these +methods die on error. + +Also provides "get_path" and "put_path" attributes. The default 'download' +and 'upload' methods get and put to those paths on the SFTP host. You +may find it useful to modify or override that behavior. + +=cut + +use Net::SFTP::Foreign; +use File::Slurp qw(read_file); +use Moose; +with 'Business::BatchPayment::Transport'; + +has [ qw( host login password ) ] => ( + is => 'rw', + isa => 'Str', +); + +has 'port' => ( + is => 'rw', + isa => 'Int', + default => 22, +); + +has [ 'get_path', 'put_path' ] => ( + is => 'rw', + isa => 'Str', +); + +has 'sftp' => ( + is => 'ro', + isa => 'Net::SFTP::Foreign', + handles => [ 'get', 'put', 'ls', 'setcwd' ], + builder => '_sftp', + lazy => 1, +); + +has 'timeout' => ( + is => 'rw', + isa => 'Int', + default => 60, +); + +sub _sftp { + my $self = shift; + my %args = ( + host => $self->host, + port => $self->port, + user => $self->login, + password => $self->password, + timeout => $self->timeout, + autodie => 1, + ); + $args{'more'} = '-v' if $self->debug >= 2; + Net::SFTP::Foreign->new(%args); +} + +sub upload { + my $self = shift; + die "default SFTP upload requires 'put_path'\n" unless $self->put_path; + my $content = shift; + my ($out, $tmpfile) = tempfile(); + die "failed to open temporary file $tmpfile\n" unless $out; + print $out $content; + close $out; + $self->sftp->put($tmpfile, $self->put_path); + unlink $tmpfile; +} + +sub download { # mostly illustrative rather than directly useful + my $self = shift; + die "default SFTP download requires 'get_path'\n" unless $self->get_path; + my ($out, $tmpfile) = tempfile(); + $self->sftp->get($self->get_path, $out); + close $out; + return read_file($tmpfile); +} + +__PACKAGE__->meta->make_immutable; + +1; diff --git a/Changes b/Changes new file mode 100644 index 0000000..8d5f1fc --- /dev/null +++ b/Changes @@ -0,0 +1,4 @@ +Revision history for Business-BatchPayment + +0.01 unreleased + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..4c44ff2 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,19 @@ +Changes +ignore.txt +Makefile.PL +BatchPayment/Item.pm +BatchPayment/Transport/HTTPS.pm +BatchPayment/Transport/SFTP.pm +BatchPayment/Transport/File.pm +BatchPayment/Debug.pm +BatchPayment/TestMode.pm +BatchPayment/Processor.pm +BatchPayment/Transport.pm +BatchPayment/Batch.pm +BatchPayment.pm +t/manifest.t +t/pod.t +t/00-load.t +README +MANIFEST +META.yml Module meta-data (added by MakeMaker) diff --git a/META.yml b/META.yml new file mode 100644 index 0000000..10ceacf --- /dev/null +++ b/META.yml @@ -0,0 +1,28 @@ +--- #YAML:1.0 +name: Business-BatchPayment +version: 0.01 +abstract: Batch-oriented payment processing +author: + - Mark Wells +license: perl +distribution_type: module +configure_requires: + ExtUtils::MakeMaker: 0 +build_requires: + ExtUtils::MakeMaker: 0 +requires: + DateTime: 0 + File::Slurp: 0 + Moose: 2 + MooseX::UndefTolerant: 0 + Net::HTTPS::Any: 0.1 + Net::SFTP::Foreign: 0 + Test::More: 0 +no_index: + directory: + - t + - inc +generated_by: ExtUtils::MakeMaker version 6.57_05 +meta-spec: + url: http://module-build.sourceforge.net/META-spec-v1.4.html + version: 1.4 diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..34dc397 --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,26 @@ +use 5.006; +use strict; +use warnings; +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'Business::BatchPayment', + AUTHOR => q{Mark Wells }, + VERSION_FROM => 'BatchPayment.pm', + ABSTRACT_FROM => 'BatchPayment.pm', + ($ExtUtils::MakeMaker::VERSION >= 6.3002 + ? ('LICENSE'=> 'perl') + : ()), + PL_FILES => {}, + PREREQ_PM => { + 'Moose' => 2.000, + 'MooseX::UndefTolerant' => 0, + 'DateTime' => 0, + 'File::Slurp' => 0, + 'Net::SFTP::Foreign' => 0, + 'Net::HTTPS::Any' => 0.10, + 'Test::More' => 0, + }, + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, + clean => { FILES => 'Business-BatchPayment-*' }, +); diff --git a/README b/README new file mode 100644 index 0000000..664b691 --- /dev/null +++ b/README @@ -0,0 +1,35 @@ +Business::BatchPayment is a generic interface for processing credit card +or electronic checking payments in an asynchronous manner. It fills a +similar role to Business::OnlinePayment, but works with processors that +expect periodic delivery of payment requests and return results in a +later step. + +INSTALLATION + +To install this module, run the following commands: + + perl Makefile.PL + make + make test + make install + +SUPPORT AND DOCUMENTATION + +After installing, you can find documentation for this module with the +perldoc command. + + perldoc Business::BatchPayment + +Contact Freeside Internet Services for commercial +support and custom development services. + +LICENSE AND COPYRIGHT + +Copyright (C) 2012 Mark Wells + +This program is free software; you can redistribute it and/or modify it +under the terms of either: the GNU General Public License as published +by the Free Software Foundation; or the Artistic License. + +See http://dev.perl.org/licenses/ for more information. + diff --git a/ignore.txt b/ignore.txt new file mode 100644 index 0000000..1bdd2ac --- /dev/null +++ b/ignore.txt @@ -0,0 +1,13 @@ +.git* +blib* +Makefile +Makefile.old +Build +Build.bat +_build* +pm_to_blib* +*.tar.gz +.lwpcookies +cover_db +pod2htm*.tmp +Business-BatchPayment-* diff --git a/t/00-load.t b/t/00-load.t new file mode 100644 index 0000000..271e8d2 --- /dev/null +++ b/t/00-load.t @@ -0,0 +1,9 @@ +#!perl -T + +use Test::More tests => 1; + +BEGIN { + use_ok( 'Business::BatchPayment' ) || print "Bail out!\n"; +} + +diag( "Testing Business::BatchPayment $Business::BatchPayment::VERSION, Perl $], $^X" ); diff --git a/t/manifest.t b/t/manifest.t new file mode 100644 index 0000000..74d8cac --- /dev/null +++ b/t/manifest.t @@ -0,0 +1,13 @@ +#!perl -T + +use strict; +use warnings; +use Test::More; + +unless ( $ENV{RELEASE_TESTING} ) { + plan( skip_all => "Author tests not required for installation" ); +} + +eval "use Test::CheckManifest 0.9"; +plan skip_all => "Test::CheckManifest 0.9 required" if $@; +ok_manifest({ exclude => ['/.git', '/blib'] }); diff --git a/t/pod.t b/t/pod.t new file mode 100644 index 0000000..ee8b18a --- /dev/null +++ b/t/pod.t @@ -0,0 +1,12 @@ +#!perl -T + +use strict; +use warnings; +use Test::More; + +# Ensure a recent version of Test::Pod +my $min_tp = 1.22; +eval "use Test::Pod $min_tp"; +plan skip_all => "Test::Pod $min_tp required for testing POD" if $@; + +all_pod_files_ok(); -- 2.11.0