From: Mark Wells Date: Fri, 25 Jan 2013 00:51:46 +0000 (-0800) Subject: start X-Git-Url: http://git.freeside.biz/gitweb/?p=Business-BatchPayment-CardFortress.git;a=commitdiff_plain;h=d8a1293c21b122228aeb32d965ae6f793e7c6d59 start --- d8a1293c21b122228aeb32d965ae6f793e7c6d59 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..9788afa --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +blib/ +*.sw? +Makefile +Makefile.old +MYMETA.yml +pm_to_blib diff --git a/CardFortress.pm b/CardFortress.pm new file mode 100644 index 0000000..3690f1c --- /dev/null +++ b/CardFortress.pm @@ -0,0 +1,223 @@ +package Business::BatchPayment::CardFortress; + +use 5.006; +use strict; +use warnings; +our $VERSION = '0.01'; + +=head1 NAME + +Business::BatchPayment::CardFortress + +=head1 DESCRIPTION + +Batch payment processing via the CardFortress secure payment proxy service. + +=head1 USAGE + +See Business::BatchPayment for general usage information. + +=head2 PROCESSOR ATTRIBUTES + +=over 4 + +=item login, password + +Your login credentials for CardFortress. + +=item gateway + +The L module to use for upstream processing. You +don't need to have this module installed, but the proxy server does. + +=item gateway_* + +Processor options to pass along to the gateway module. The 'gateway_' prefix +will be stripped. + +=back + +=cut + +use Business::BatchPayment; +use Moose; +with 'Business::BatchPayment::Processor'; +with 'Business::BatchPayment::TestMode'; +with 'Business::BatchPayment::Debug'; + +use Data::Serializer; + +has [ qw(login password private_key gateway) ] => ( + is => 'ro', + isa => 'Str', + required => 1, +); + +has 'gateway_opts' => ( + is => 'ro', + isa => 'HashRef', + default => sub { {login => ''} }, +); + +has 'serializer' => ( + is => 'ro', + lazy => 1, + handles => [qw(serialize deserialize)], + default => sub { +# doesn't have to be Storable, but it must support blessed objects + Data::Serializer->new(serializer => 'Storable', encoding => 'b64') + }, +); + +# pull any arg named "gateway_foo" into gateway_opts +around 'BUILDARGS' => sub { + my ($orig, $class, %args) = @_; + foreach (keys %args) { + if (/^gateway_(.*)/) { + $args{'gateway_opts'}->{$1} = delete $args{$_}; + } + } + $class->$orig(%args); +}; + +sub default_transport { + my $self = shift; + Business::BatchPayment->create('CardFortress::Transport', + login => $self->login, + password => $self->password, + debug => $self->debug, + test_mode => $self->test_mode, + private_key => $self->private_key, + serializer => $self->serializer, + ); +} + +sub format_request { + my $self = shift; + my $batch = shift; + bless $batch, 'Business::BatchPayment::CardFortress::Batch'; + # things that get encoded in the batch: + $batch->gateway($self->gateway); + $batch->gateway_opts($self->gateway_opts); + $self->serialize($batch); # that's all folks +} + +sub parse_response { + my $self = shift; + my $input = shift; + my $batch = $self->deserialize($input); +} + +package Business::BatchPayment::CardFortress::Batch; + +use Moose; +extends 'Business::BatchPayment::Batch'; + +has 'gateway' => ( + is => 'rw', + isa => 'Str', +); +has 'gateway_opts' => ( + is => 'rw', + isa => 'HashRef', +); + +package Business::BatchPayment::CardFortress::Transport; + +use Moose; +use Moose::Util::TypeConstraints; +extends 'Business::BatchPayment::Transport::HTTPS'; +with 'Business::BatchPayment::TestMode'; + +use File::Slurp; +use MIME::Base64; +use Crypt::OpenSSL::RSA; + +has '+host' => ( + default => sub { + my $self = shift; + $self->test_mode ? 'gw.cardfortress.com' + : 'test.cardfortress.com' + }, + lazy => 1, +); + +has ['login', 'password', 'private_key'] => (isa => 'Str', is => 'rw'); + +has 'serializer' => ( handles => [qw(serialize deserialize)] ); + +sub upload { + my ($self, $content) = @_; + warn "Sending batch...\n" if $self->debug; + my ($page, $response, %reply_headers) = + $self->https_post('/batch/submit', { + login => $self->login, + password => $self->password, + content => $content, + }); + $page = $self->deserialize($page); + die $page->{error} if $page->{error}; + my $batchid = $page->{batchid}; + + my $private_key = read_file($self->private_key) + or die "No private key available"; + my $rsa = Crypt::OpenSSL::RSA->new_private_key($private_key); + + my %answers; + foreach my $item (@{ $page->{items} }) { + if ( $item->{error} ) { + # We have no reliable way to report an error in a specific transaction + # at this stage. The server will send the error in the reply batch. + # For now do nothing. + } elsif ( $item->{challenge} ) { + my $challenge = $item->{challenge}; + $answers{ $item->{tid} } = $rsa->decrypt( decode_base64($challenge) ); + } else { + # newly created card--doesn't have a challenge, so do nothing + } + } + # post the response + warn "Answering cryptographic challenge...\n" if $self->debug; + my $answer_content = + $self->serialize({ batchid => $batchid, answers => \%answers }); + ($page, $response, %reply_headers) = + $self->https_post('/batch/run', { + login => $self->login, + password => $self->password, + content => $answer_content, + }); + $page = $self->deserialize($page); + die $page->{error} if $page->{error}; + return; +} + +=head1 AUTHOR + +Mark Wells, C<< >> + +=head1 SUPPORT + +You can find documentation for this module with the perldoc command. + + perldoc Business::BatchPayment::CardFortress + +Commercial support is available from Freeside Internet Services, Inc. + +L + +=head1 ACKNOWLEDGEMENTS + +=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::Paymentech diff --git a/Changes b/Changes new file mode 100644 index 0000000..8e4fd70 --- /dev/null +++ b/Changes @@ -0,0 +1,5 @@ +Revision history for Business-BatchPayment-CardFortress + +0.01 Date/time + First version, released on an unsuspecting world. + diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..fae5736 --- /dev/null +++ b/MANIFEST @@ -0,0 +1,8 @@ +Changes +CardFortress.pm +Makefile.PL +MANIFEST This list of files +README +t/00-load.t +t/manifest.t +t/pod.t diff --git a/Makefile.PL b/Makefile.PL new file mode 100644 index 0000000..cbe9f6c --- /dev/null +++ b/Makefile.PL @@ -0,0 +1,20 @@ +use 5.006; +use strict; +use warnings; +use ExtUtils::MakeMaker; + +WriteMakefile( + NAME => 'Business::BatchPayment::CardFortress', + AUTHOR => q{Mark Wells }, + VERSION_FROM => 'CardFortress.pm', + ABSTRACT_FROM => 'CardFortress.pm', + ($ExtUtils::MakeMaker::VERSION >= 6.3002 + ? ('LICENSE'=> 'perl') + : ()), + PL_FILES => {}, + PREREQ_PM => { + 'Test::More' => 0, + }, + dist => { COMPRESS => 'gzip -9f', SUFFIX => 'gz', }, + clean => { FILES => 'Business-BatchPayment-CardFortress-*' }, +); diff --git a/README b/README new file mode 100644 index 0000000..151bdb7 --- /dev/null +++ b/README @@ -0,0 +1,55 @@ +Business-BatchPayment-CardFortress + +The README is used to introduce the module and provide instructions on +how to install the module, any machine dependencies it may have (for +example C compilers and installed libraries) and any other information +that should be provided before the module is installed. + +A README file is required for CPAN modules since CPAN extracts the README +file from a module distribution so that people browsing the archive +can use it to get an idea of the module's uses. It is usually a good idea +to provide version information here so that people can decide whether +fixes for the module are worth downloading. + + +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::CardFortress + +You can also look for information at: + + RT, CPAN's request tracker (report bugs here) + http://rt.cpan.org/NoAuth/Bugs.html?Dist=Business-BatchPayment-CardFortress + + AnnoCPAN, Annotated CPAN documentation + http://annocpan.org/dist/Business-BatchPayment-CardFortress + + CPAN Ratings + http://cpanratings.perl.org/d/Business-BatchPayment-CardFortress + + Search CPAN + http://search.cpan.org/dist/Business-BatchPayment-CardFortress/ + + +LICENSE AND COPYRIGHT + +Copyright (C) 2013 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..8237b6b --- /dev/null +++ b/ignore.txt @@ -0,0 +1,12 @@ +blib* +Makefile +Makefile.old +Build +Build.bat +_build* +pm_to_blib* +*.tar.gz +.lwpcookies +cover_db +pod2htm*.tmp +Business-BatchPayment-CardFortress-* diff --git a/t/00-load.t b/t/00-load.t new file mode 100644 index 0000000..54a65c1 --- /dev/null +++ b/t/00-load.t @@ -0,0 +1,9 @@ +#!perl -T + +use Test::More tests => 1; + +BEGIN { + use_ok( 'Business::BatchPayment::CardFortress' ) || print "Bail out!\n"; +} + +diag( "Testing Business::BatchPayment::CardFortress $Business::BatchPayment::CardFortress::VERSION, Perl $], $^X" ); diff --git a/t/manifest.t b/t/manifest.t new file mode 100644 index 0000000..45eb83f --- /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(); 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();