File Coverage

blib/lib/Business/OnlinePayment/Iridium.pm
Criterion Covered Total %
statement 27 125 21.6
branch 0 26 0.0
condition 0 6 0.0
subroutine 9 20 45.0
pod 7 7 100.0
total 43 184 23.3


line stmt bran cond sub pod time code
1             package Business::OnlinePayment::Iridium;
2              
3 1     1   86868 use warnings;
  1         5  
  1         266  
4 1     1   10 use strict;
  1         3  
  1         37  
5 1     1   623 use Moose;
  1         513514  
  1         7  
6 1     1   7268 use aliased 'Business::OnlinePayment::Iridium::Action::GetGatewayEntryPoints';
  1         558  
  1         6  
7 1     1   157 use aliased 'Business::OnlinePayment::Iridium::Action::GetCardType';
  1         3  
  1         8  
8 1     1   163 use aliased 'Business::OnlinePayment::Iridium::Action::CardDetailsTransaction';
  1         22  
  1         7  
9             use aliased
10 1     1   147 'Business::OnlinePayment::Iridium::Action::CrossReferenceTransaction';
  1         2  
  1         6  
11             use aliased
12 1     1   172 'Business::OnlinePayment::Iridium::Action::ThreeDSecureAuthentication';
  1         4  
  1         9  
13 1     1   104 use Carp qw/carp croak/;
  1         2  
  1         1227  
14              
15             our $VERSION = '1.03'; # VERSION: generated by DZP::OurPkgVersion
16              
17              
18             sub FIELD_MAP {
19             return (
20 0     0 1   'login' => 'MerchantID',
21             'password' => 'Password',
22             'card_number' => 'CardNumber',
23             'name_on_card' => 'CardName',
24             'cv2' => 'CV2',
25             'issue_number' => 'IssueNumber',
26             'amount' => 'Amount',
27             'invoice_number' => 'OrderID',
28             'description' => 'OrderDescription',
29             'action' => 'TransactionType',
30             'expiration' => 'Expiration',
31             'cross_reference' => 'CrossReference',
32             'pares' => 'PaRES',
33             'echo_cardtype' => 'EchoCardType',
34             'echo_avs_check_result' => 'EchoAVSCheckResult',
35             'echo_cvs_check_result' => 'EchoCVSCheckResult',
36             'echo_amount_received' => 'EchoAmountReceived',
37             'duplicate_delay' => 'DuplicateDelay',
38             'avs_override_policy' => 'AVSOverridePolicy',
39             'cvs_override_policy' => 'CVSOverridePolicy',
40             'three_d_secure_override_policy' => 'ThreeDSecureOverridePolicy',
41             'address1' => 'Address1',
42             'address2' => 'Address2',
43             'address3' => 'Address3',
44             'address4' => 'Address4',
45             'city' => 'City',
46             'state' => 'State',
47             'postcode' => 'PostCode',
48             'country_code' => 'CountryCode',
49             'email' => 'EmailAddress',
50             'phone_number' => 'PhoneNumber',
51             'customer_ip_address' => 'CustomerIPAddress',
52             'pass_outdata' => 'PassOutData',
53             );
54             }
55              
56              
57             sub ACTION_MAP {
58             return (
59 0     0 1   'normal authorization' => 'SALE',
60             'refund ammount' => 'REFUND',
61             'authorization only' => 'PREAUTH',
62             'post authorization' => 'STORE',
63             );
64             }
65              
66             extends 'Business::OnlinePayment';
67              
68             has 'require_3d' => (
69             isa => 'Bool',
70             is => 'rw',
71             default => '0'
72             );
73              
74             has 'forward_to' => (
75             isa => 'Str',
76             is => 'rw',
77             required => '0'
78             );
79              
80             has 'authentication_key' => (
81             isa => 'Str',
82             is => 'rw',
83             required => '0'
84             );
85              
86             has 'pareq' => (
87             isa => 'Str',
88             is => 'rw',
89             required => '0'
90             );
91              
92             has 'cross_reference' => (
93             isa => 'Str',
94             is => 'rw',
95             required => '0'
96             );
97              
98             # PODNAME: Business::OnlinePayment::Iridium
99             # ABSTRACT: PayVector (Iridium) backend for Business::OnlinePayment
100              
101              
102             sub _check_amount_field {
103 0     0     my %content = shift->content;
104             confess 'missing required field amount'
105             unless exists $content{'amount'}
106 0 0 0       || lc( $content{'action'} ) eq 'authorization only';
107             }
108              
109             sub _running_in_test_mode {
110 0     0     my $self = shift;
111 0 0         if ( $self->test_transaction ) {
112 0           carp $self->error_message('Only test cards work in test mode');
113 0           return 1;
114             }
115             else {
116 0           return 0;
117             }
118             }
119              
120             sub _format_amount {
121 0     0     my ( $self, $amount ) = @_;
122 0           $amount = sprintf( "%.2f", $amount );
123 0           $amount =~ s/\.//;
124 0           return $amount;
125             }
126              
127             sub _submit_callback {
128 0     0     my ( $self, $res_result, $res_data ) = @_;
129 0 0 0       if ( $self->result_code == 0 ) {
    0          
    0          
130 0           $self->is_success(1);
131 0           $self->authorization( $res_data->{'AuthCode'} );
132 0           $self->cross_reference( $res_data->{'CrossReference'} );
133             }
134             elsif ($self->result_code == 20
135             && $res_result->{'PreviousTransactionResult'}->{'StatusCode'} == 0 )
136             {
137 0           $self->is_success(1);
138 0           $self->authorization( $res_data->{'AuthCode'} );
139 0           $self->cross_reference( $res_data->{'CrossReference'} );
140             }
141             elsif ( $self->result_code == 3 ) {
142 0           $self->require_3d(1);
143 0           my $threeD_data = $res_data->{'ThreeDSecureOutputData'};
144 0           $self->forward_to( $threeD_data->{'ACSURL'} );
145 0           $self->pareq( $threeD_data->{'PaREQ'} );
146 0           $self->cross_reference( $res_data->{'CrossReference'} );
147              
148             # Set error_message in case you just use is_success and don't check
149             # for require_3d (for simple users ;-) ).
150 0           $self->error_message( $res_result->{'Message'} );
151             }
152             else {
153 0           $self->is_success(0);
154 0           $self->error_message( $res_result->{'Message'} );
155             }
156             }
157              
158             override remap_fields => sub {
159             my ( $self, %map ) = @_;
160             my %content = $self->content();
161             foreach ( keys %map ) {
162             $content{ $map{$_} } = $content{$_};
163             }
164             $self->content(%content);
165             };
166              
167              
168 0     0 1   sub get_entry_points { confess 'Not supported yet.' }
169              
170              
171             sub get_card_type {
172 0     0 1   my $self = shift;
173 0 0         return $self->is_success(0) if $self->_running_in_test_mode;
174              
175 0           $self->required_fields(qw/login password card_number/);
176 0           my %data = $self->remap_fields( $self->FIELD_MAP );
177              
178             my $tx =
179 0           GetCardType->new( map { $_ => $data{$_} }
  0            
180             qw(MerchantID Password CardNumber) );
181 0           my $res = $tx->request;
182 0           $res = $res->{'soap:Body'}->{'GetCardTypeResponse'};
183 0           my $res_result = $res->{'GetCardTypeResult'};
184 0           my $res_data = $res->{'GetCardTypeOutputData'};
185 0           $self->server_response($res);
186 0           $self->result_code( $res_result->{'StatusCode'} );
187              
188 0 0         if ( $self->result_code == 0 ) {
189 0           $self->is_success(1);
190 0           return $res_data->{'CardTypeData'}->{'CardType'};
191             }
192             else {
193 0           $self->is_success(0);
194 0           return 'Failed: ' . $res_result->{'Message'};
195             }
196             }
197              
198              
199             sub submit {
200 0     0 1   my $self = shift;
201 0 0         return $self->is_success(0) if $self->_running_in_test_mode;
202              
203 0           $self->required_fields(
204             qw/login password card_number name_on_card
205             expiration invoice_number action amount/
206             );
207 0           my %data = $self->remap_fields( $self->FIELD_MAP );
208 0           my $tx_type = lc( $data{'TransactionType'} );
209 0           my %ACTION_MAP = $self->ACTION_MAP;
210              
211             croak "'expiration' is invalid, format is: MM/YY or MMYY"
212 0 0         unless $data{'Expiration'} =~ m|(\d{2})/?(\d{2})|;
213 0           my ( $expire_month, $expire_year ) = ( $1, $2 );
214              
215             my $tx = CardDetailsTransaction->new(
216             (
217 0           map { $_ => $data{$_} }
218 0           grep { $data{$_} }
219             qw/MerchantID Password CardNumber CardName OrderID OrderDescription
220             EchoCardType CV2 EchoAVSCheckResult EchoCVSCheckResult EchoAmountReceived
221             DuplicateDelay AVSOverridePolicy CVSOverridePolicy ThreeDSecureOverridePolicy
222             Address1 Address2 Address3 Address4 City State PostCode CountryCode
223             EmailAddress PhoneNumber CustomerIPAddress PassOutData/
224             ),
225             TransactionType => $ACTION_MAP{$tx_type},
226 0           Amount => $self->_format_amount( $data{'Amount'} ),
227             ExpireMonth => $expire_month,
228             ExpireYear => $expire_year,
229             );
230 0           my $res = $tx->request;
231 0           $res = $res->{'soap:Body'}->{'CardDetailsTransactionResponse'};
232 0           my $res_result = $res->{'CardDetailsTransactionResult'};
233 0           $self->server_response($res);
234 0           $self->result_code( $res_result->{'StatusCode'} );
235              
236 0           $self->_submit_callback( $res_result, $res->{'TransactionOutputData'} );
237             }
238              
239              
240             sub reference_transaction {
241 0     0 1   my $self = shift;
242 0 0         return $self->is_success(0) if $self->_running_in_test_mode;
243              
244 0           $self->required_fields(qw/login password invoice_number action amount/);
245 0           my %data = $self->remap_fields( $self->FIELD_MAP );
246 0           my $tx_type = lc( $data{'TransactionType'} );
247 0           my %ACTION_MAP = $self->ACTION_MAP;
248              
249             my $tx = CrossReferenceTransaction->new(
250             (
251 0           map { $_ => $data{$_} }
252 0           grep { $data{$_} }
253             qw(MerchantID Password OrderID OrderDescription)
254             ),
255             TransactionType => $ACTION_MAP{$tx_type},
256 0           Amount => $self->_format_amount( $data{'Amount'} ),
257             );
258 0           my $res = $tx->request;
259 0           $res = $res->{'soap:Body'}->{'CardDetailsTransactionResponse'};
260 0           my $res_result = $res->{'CardDetailsTransactionResult'};
261 0           $self->server_response($res);
262 0           $self->result_code( $res_result->{'StatusCode'} );
263              
264 0           $self->_submit_callback( $res_result, $res->{'TransactionOutputData'} );
265             }
266              
267              
268             sub submit_3d {
269 0     0 1   my $self = shift;
270 0 0         return $self->is_success(0) if $self->_running_in_test_mode;
271              
272 0           $self->required_fields(qw/login password cross_reference pares/);
273 0           my %data = $self->remap_fields( $self->FIELD_MAP );
274              
275             my $tx = ThreeDSecureAuthentication->new(
276             (
277 0           map { $_ => $data{$_} }
278 0           grep { $data{$_} }
  0            
279             qw(MerchantID Password CrossReference PaRES PassOutData)
280             ),
281             );
282 0           my $res = $tx->request;
283 0           $res = $res->{'soap:Body'}->{'ThreeDSecureAuthenticationResponse'};
284 0           my $res_result = $res->{'ThreeDSecureAuthenticationResult'};
285 0           my $res_data = $res->{'TransactionOutputData'};
286 0           $self->server_response($res);
287 0           $self->result_code( $res_result->{'StatusCode'} );
288              
289 0 0         if ( $self->result_code == 0 ) {
290             carp
291             "Albeit 3D secure auth didn't pass, the transaction will be processed"
292 0 0         if $res_data->{'ThreeDSecureAuthenticationCheckResult'} eq 'UNKNOWN';
293 0           $self->is_success(1);
294 0           $self->authorization( $res_data->{'AuthCode'} );
295             }
296             else {
297 0           $self->is_success(0);
298 0           $self->error_message( $res_result->{'Message'} );
299             }
300             }
301              
302              
303             1;
304              
305             __END__
306              
307             =pod
308              
309             =encoding UTF-8
310              
311             =head1 NAME
312              
313             Business::OnlinePayment::Iridium - PayVector (Iridium) backend for Business::OnlinePayment
314              
315             =head1 VERSION
316              
317             version 1.03
318              
319             =head1 SYNOPSIS
320              
321             use Business::OnlinePayment;
322              
323             my $tx = Business::OnlinePayment->new('Iridium');
324             $tx->content(
325             'login' => 'MerchantID',
326             'password' => 'Password',
327             'card_number' => '4976000000003436',
328             'name_on_card' => 'John Watson',
329             'expiration' => '12/12',
330             'cv2' => '242',
331             'invoice_number' => 'TUID',
332             'amount' => '123.23',
333             'action' => 'normal authorization'
334             );
335             $tx->submit;
336              
337             if ($tx->is_success) {
338             print "Card processed successfully: " . $tx->authorization . "\n";
339             } else {
340             print "Card was rejected: " . $tx->error_message . "\n";
341             }
342              
343             =head1 DESCRIPTION
344              
345             Backend that allows you to easily make payments via the Iridium system, which has now been
346             rebranded to PayVector.
347              
348             =head2 FIELD_MAP
349              
350             Map convenient field names to PayVector SOAP string names
351              
352             =head2 ACTION_MAP
353              
354             A convenient way to set the transaction type
355              
356             =head1 METHODS
357              
358             =head2 get_entry_points
359              
360             NOTE: Not supported yet.
361              
362             Returns the details of all the gateway entry points.
363              
364             =head2 get_card_type
365              
366             This allows the merchant to determine the card type of the card in question.
367              
368             =head2 submit
369              
370             =head2 reference_transaction
371              
372             =head2 submit_3d
373              
374             =head2 test_transaction
375              
376             Please note that ONLY test card details provided in docs will
377             work in test mode - real card numbers will NOT work.
378              
379             =head2 is_success
380              
381             Returns true if the transaction was submitted successfully, false if it failed
382             (or undef if it has not been submitted yet).
383              
384             =head2 result_code
385              
386             Returns the StatusCode.
387              
388             =head2 error_message
389              
390             If the transaction has been submitted but was not accepted, this function will
391             return the provided error message (if any).
392              
393             =head2 authorization
394              
395             If the transaction has been submitted and accepted, this function will provide
396             you with the authorization code.
397              
398             =head1 BUGS
399              
400             Please report any bugs or feature requests to C<bug-business-onlinepayment-iridium at rt.cpan.org>, or through
401             the web interface at L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Business-OnlinePayment-Iridium>. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes.
402              
403             =head1 SUPPORT
404              
405             You can find documentation for this module with the perldoc command.
406              
407             perldoc Business::OnlinePayment::Iridium
408              
409             You can also look for information at:
410              
411             =over 4
412              
413             =item * RT: CPAN's request tracker
414              
415             L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Business-OnlinePayment-Iridium>
416              
417             =item * AnnoCPAN: Annotated CPAN documentation
418              
419             L<http://annocpan.org/dist/Business-OnlinePayment-Iridium>
420              
421             =item * CPAN Ratings
422              
423             L<http://cpanratings.perl.org/d/Business-OnlinePayment-Iridium>
424              
425             =item * Search CPAN
426              
427             L<http://search.cpan.org/dist/Business-OnlinePayment-Iridium>
428              
429             =back
430              
431             =head1 SEE ALSO
432              
433             L<Business::OnlinePayment>
434              
435             =head1 AUTHOR
436              
437             wreis: Wallace Reis <reis.wallace@gmail.com>
438              
439             ghenry: Gavin Henry <ghenry@suretecsystems.com>
440              
441             =head1 ACKNOWLEDGEMENTS
442              
443             To Airspace Software Ltd <http://www.airspace.co.uk>, for the sponsorship.
444              
445             To Simon Elliott, for comments and questioning the design.
446              
447             =head1 COPYRIGHT
448              
449             Copyright (C) 2008 wreis: Wallace Reis <reis.wallace@gmail.com>
450             Copyright (C) 2017 ghenry: Gavin Henry <ghenry@suretecsystems.com>
451              
452             =head1 LICENSE
453              
454             This library is free software under the same license as perl itself.
455              
456             =head1 AUTHOR
457              
458             [ 'Gavin Henry <ghenry@surevoip.co.uk>', 'Wallace Reis <reis.wallace@gmail.com>' ]
459              
460             =head1 COPYRIGHT AND LICENSE
461              
462             This software is copyright (c) 2017 by [ 'Gavin Henry', 'Wallace Reis' ].
463              
464             This is free software; you can redistribute it and/or modify it under
465             the same terms as the Perl 5 programming language system itself.
466              
467             =cut