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