File Coverage

blib/lib/Business/CyberSource/Client.pm
Criterion Covered Total %
statement 36 38 94.7
branch n/a
condition n/a
subroutine 13 13 100.0
pod n/a
total 49 51 96.0


line stmt bran cond sub pod time code
1             package Business::CyberSource::Client;
2 3     3   2986644 use 5.010;
  3         8  
3 3     3   9 use strict;
  3         3  
  3         51  
4 3     3   10 use warnings;
  3         3  
  3         71  
5 3     3   383 use namespace::autoclean;
  3         5212  
  3         19  
6              
7             our $VERSION = '0.010007'; # VERSION
8              
9 3     3   628 use Moose;
  3         208178  
  3         19  
10             with 'MooseY::RemoteHelper::Role::Client';
11              
12 3     3   15362 use Type::Utils qw( duck_type );
  3         60709  
  3         16  
13 3     3   2298 use Type::Params qw( compile Invocant );
  3         110720  
  3         36  
14 3     3   1965 use MooseX::Types::Common::String qw( NonEmptyStr NonEmptySimpleStr );
  3         302121  
  3         19  
15              
16 3     3   6043 use Config;
  3         6  
  3         112  
17 3     3   22 use Module::Runtime qw( use_module );
  3         3  
  3         23  
18 3     3   1773 use Module::Load qw( load );
  3         2365  
  3         19  
19              
20 3     3   1446 use XML::Compile::SOAP::WSS 1.04;
  3         321124  
  3         81  
21 3     3   1274 use XML::Compile::WSDL11;
  0            
  0            
22             use XML::Compile::SOAP11;
23             use XML::Compile::Transport::SOAPHTTP;
24             use File::ShareDir::ProjectDistDir 1.000
25             dist_file => defaults => { strict => 1 };
26              
27             our @CARP_NOT = ( __PACKAGE__, qw( Class::MOP::Method::Wrapped ) );
28              
29             sub submit { ## no critic ( Subroutines::RequireArgUnpacking )
30             state $check = compile( Invocant, duck_type(['serialize']));
31             my ( $self, $request ) = $check->( @_ );
32              
33             if ( $self->has_rules && ! $self->rules_is_empty ) {
34             my $result;
35             RULE: foreach my $rule ( @{ $self->_rules } ) {
36             $result = $rule->run( $request );
37             last RULE if defined $result;
38             }
39             return $self->_response_factory->create( $result, $request )
40             if defined $result
41             ;
42             }
43              
44             my %request = (
45             merchantID => $self->user,
46             clientEnvironment => $self->env,
47             clientLibrary => $self->name,
48             clientLibraryVersion => $self->version,
49             %{ $request->serialize },
50             );
51              
52             if ( $self->debug >= 1 ) {
53             load 'Carp';
54             load 'Data::Printer', alias => 'Dumper';
55              
56             Carp::carp( 'REQUEST HASH: ' . Dumper( \%request ) );
57             }
58              
59             my ( $answer, $trace ) = $self->_soap_client->( %request );
60              
61             if ( $self->debug >= 2 ) {
62             Carp::carp "\n> " . $trace->request->as_string;
63             Carp::carp "\n< " . $trace->response->as_string;
64             }
65              
66             $request->_http_trace( $trace );
67              
68             if ( $answer->{Fault} ) {
69             die ## no critic ( ErrorHandling::RequireCarping )
70             use_module('Business::CyberSource::Exception::SOAPFault')
71             ->new( $answer->{Fault} );
72             }
73              
74             if ( $self->debug >= 1 ) {
75             Carp::carp( 'RESPONSE HASH: ' . Dumper( $answer ) );
76             }
77              
78             return $self->_response_factory->create( $answer->{result}, $request );
79             }
80              
81             sub _build_soap_client {
82             my $self = shift;
83             # order in this subroutine matters changing it may break stuff
84              
85             my $wss = XML::Compile::SOAP::WSS->new( version => '1.1' );
86              
87             my $wsdl = XML::Compile::WSDL11->new( $self->cybs_wsdl );
88             $wsdl->importDefinitions( $self->cybs_xsd );
89              
90             $wss->basicAuth(
91             username => $self->user,
92             password => $self->pass,
93             );
94              
95             my $call = $wsdl->compileClient('runTransaction');
96              
97             return $call;
98             }
99              
100             sub _build_cybs_wsdl {
101             my $self = shift;
102              
103             my $dir = $self->test ? 'test' : 'production';
104              
105             return dist_file(
106             'Business-CyberSource',
107             $dir
108             . '/'
109             . 'CyberSourceTransaction_'
110             . $self->_version_for_filename
111             . '.wsdl'
112             );
113             }
114              
115             sub _build_cybs_xsd {
116             my $self = shift;
117              
118             my $dir = $self->test ? 'test' : 'production';
119              
120             return dist_file(
121             'Business-CyberSource',
122             $dir
123             . '/'
124             . 'CyberSourceTransaction_'
125             . $self->_version_for_filename
126             . '.xsd'
127             );
128             }
129              
130             sub _build__rules {
131             my $self = shift;
132              
133             return [] if ! $self->has_rules || $self->rules_is_empty;
134              
135             my @rules
136             = map {
137             $self->_rule_factory->create( $_, { client => $self } ) if defined $_
138             } $self->list_rules;
139              
140             return \@rules;
141             }
142              
143             sub _version_for_filename {
144             my $self = shift;
145             my $version = $self->cybs_api_version;
146             $version =~ s/\./_/xms;
147             return $version;
148             }
149              
150             has _soap_client => (
151             isa => 'CodeRef',
152             is => 'ro',
153             lazy => 1,
154             init_arg => undef,
155             builder => '_build_soap_client',
156             );
157              
158             has _response_factory => (
159             isa => 'Object',
160             is => 'ro',
161             lazy => 1,
162             default => sub {
163             return
164             use_module('Business::CyberSource::Factory::Response')
165             ->new;
166             },
167             );
168              
169             has _rule_factory => (
170             isa => 'Object',
171             is => 'ro',
172             lazy => 1,
173             default => sub {
174             return use_module('Business::CyberSource::Factory::Rule')->new;
175             },
176             );
177              
178             has rules => (
179             isa => 'ArrayRef[Str]',
180             predicate => 'has_rules',
181             traits => ['Array'],
182             is => 'ro',
183             reader => undef,
184             default => sub { [qw( ExpiredCard RequestIDisZero )] },
185             handles => {
186             list_rules => 'elements',
187             rules_is_empty => 'is_empty',
188             },
189             );
190              
191             has _rules => (
192             isa => 'ArrayRef[Object]',
193             is => 'ro',
194             lazy_build => 1,
195             traits => ['Array'],
196             );
197              
198             has version => (
199             required => 0,
200             lazy => 1,
201             init_arg => undef,
202             is => 'ro',
203             isa => 'Str',
204             default => sub {
205             my $version
206             = $Business::CyberSource::VERSION ? $Business::CyberSource::VERSION
207             : '0'
208             ;
209             return $version;
210             },
211             );
212              
213             has name => (
214             required => 0,
215             lazy => 1,
216             init_arg => undef,
217             is => 'ro',
218             isa => 'Str',
219             default => sub { return 'Business::CyberSource' },
220             );
221              
222             has env => (
223             required => 0,
224             lazy => 1,
225             init_arg => undef,
226             is => 'ro',
227             isa => 'Str',
228             default => sub {
229             return "Perl $Config{version} $Config{osname} $Config{osvers} $Config{archname}";
230             },
231             );
232              
233             has cybs_api_version => (
234             required => 0,
235             lazy => 1,
236             is => 'ro',
237             isa => 'Str',
238             default => '1.71',
239             );
240              
241             has cybs_wsdl => (
242             lazy => 1,
243             is => 'ro',
244             isa => 'Str',
245             builder => '_build_cybs_wsdl',
246             );
247              
248             has cybs_xsd => (
249             lazy => 1,
250             is => 'ro',
251             isa => 'Str',
252             builder => '_build_cybs_xsd',
253             );
254              
255              
256             __PACKAGE__->meta->make_immutable;
257             1;
258              
259             # ABSTRACT: User Agent Responsible for transmitting the Response
260              
261             __END__
262              
263             =pod
264              
265             =encoding UTF-8
266              
267             =head1 NAME
268              
269             Business::CyberSource::Client - User Agent Responsible for transmitting the Response
270              
271             =head1 VERSION
272              
273             version 0.010007
274              
275             =head1 SYNOPSIS
276              
277             use Business::CyberSource::Client;
278              
279             my $request = 'Some Business::CyberSource::Request Object';
280              
281             my $client = Business::CyberSource::Request->new({
282             user => 'Merchant ID',
283             pass => 'API KEY',
284             test => 1,
285             });
286              
287             my $response = $client->run_transaction( $request );
288              
289             =head1 DESCRIPTION
290              
291             A service object that is meant to provide a way to run the requested
292             transactions.
293              
294             =head1 WITH
295              
296             L<MooseY::RemoteHelper::Role::Client>
297              
298             =head1 METHODS
299              
300             =head2 submit
301              
302             my $response = $client->submit( $request );
303              
304             Takes a L<Business::CyberSource::Request> subclass as a parameter and returns
305             a L<Business::CyberSource::Response>
306              
307             =head1 ATTRIBUTES
308              
309             =head2 user
310              
311             CyberSource Merchant ID
312              
313             =head2 pass
314              
315             CyberSource API KEY
316              
317             =head2 test
318              
319             Boolean value when false your requests will go to the live server, when
320             true they will go to the testing server.
321              
322             =head2 debug
323              
324             Integer value that causes the HTTP request/response to be output to STDOUT
325             when a transaction is run. defaults to value of the environment variable
326              
327             =over
328              
329             =item value 0
330              
331             no output (default)
332              
333             =item value 1
334              
335             request/response hashref
336              
337             =item value 2
338              
339             1 plus actual HTTP and XML
340              
341             =back
342              
343             =head2 rules
344              
345             ArrayRef of L<Rule Names|Business::CyberSource::Rule>. Rules names are modules
346             prefixed by L<Business::CyberSource::Rule>. By default both
347             L<Business::CyberSource::Rule::ExpiredCard> and
348             L<Business::CyberSource::Rule::RequestIDisZero> are included. If you decide to
349             add more rules remember to add C<qw( ExpiredCard RequestIDisZero )> to the
350             new ArrayRef ( if you want them ).
351              
352             =head2 name
353              
354             Client Name defaults to L<Business::CyberSource>
355              
356             =head2 version
357              
358             Client Version defaults to the version of this library
359              
360             =head2 env
361              
362             defaults to specific parts of perl's config hash
363              
364             =head2 cybs_wsdl
365              
366             A L<Path::Class::File> to the WSDL definition file
367              
368             =head2 cybs_xsd
369              
370             A L<Path::Class::File> to the XSD definition file
371              
372             =head2 cybs_api_version
373              
374             CyberSource API version, currently 1.71
375              
376             =head1 BUGS
377              
378             Please report any bugs or feature requests on the bugtracker website
379             https://github.com/xenoterracide/business-cybersource/issues
380              
381             When submitting a bug or request, please include a test-file or a
382             patch to an existing test-file that illustrates the bug or desired
383             feature.
384              
385             =head1 AUTHOR
386              
387             Caleb Cushing <xenoterracide@gmail.com>
388              
389             =head1 COPYRIGHT AND LICENSE
390              
391             This software is Copyright (c) 2016 by Caleb Cushing <xenoterracide@gmail.com>.
392              
393             This is free software, licensed under:
394              
395             The Artistic License 2.0 (GPL Compatible)
396              
397             =cut