File Coverage

blib/lib/Business/OnlinePayment/CyberSource/Role/TransactionHandling.pm
Criterion Covered Total %
statement 24 26 92.3
branch n/a
condition n/a
subroutine 9 9 100.0
pod n/a
total 33 35 94.2


line stmt bran cond sub pod time code
1             package Business::OnlinePayment::CyberSource::Role::TransactionHandling;
2              
3 1     1   671 use 5.010;
  1         3  
4 1     1   4 use strict;
  1         2  
  1         22  
5 1     1   4 use warnings;
  1         2  
  1         26  
6 1     1   4 use namespace::autoclean;
  1         2  
  1         6  
7              
8 1     1   721 use DateTime;
  1         281533  
  1         41  
9 1     1   7 use Moose::Role;
  1         1  
  1         10  
10 1     1   3796 use MooseX::StrictConstructor;
  1         1  
  1         9  
11 1     1   296 use Try::Tiny;
  1         27  
  1         66  
12 1     1   637 use Business::OnlinePayment::CyberSource::Client;
  0            
  0            
13              
14             # ABSTRACT: Transaction handling role for BOP::CyberSource
15             our $VERSION = '3.000010'; # TRIAL VERSION
16              
17             #### Subroutine Definitions ####
18              
19             # Submits the transaction request to CyberSource
20             # Accepts: Nothing
21             # Returns: Nothing
22              
23             sub submit {
24             my ( $self ) = @_;
25             my $content = { $self->content() };
26              
27             # Default values
28             my $data = {
29             reference_code => $content->{invoice_number}
30             };
31              
32             $content->{currency} ||= 'USD';
33              
34             # purchaser information
35             my $map = {
36             ip => 'customer_ip',
37             first_name => 'first_name',
38             last_name => 'last_name',
39             email => 'email',
40             phone_number => 'phone',
41             street1 => 'address',
42             city => 'city',
43             state => 'state',
44             postal_code => 'zip',
45             country => 'country',
46             };
47              
48             foreach my $name ( keys %$map ) {
49             if (
50             $content->{ $map->{$name} }
51             && $content->{action} !~ /^Post\ Authorization|Void$/ix
52             ) {
53             $data->{bill_to}->{$name} = $content->{ $map->{$name} }
54             unless ( $content->{po_number} && $content->{action} =~ /^Credit$/ix );
55             }
56             }
57              
58             # Purchase totals information
59             $data->{purchase_totals} = {
60             total => $content->{amount},
61             currency => $content->{currency},
62             };
63              
64             $data->{service} = { request_id => $content->{po_number} }
65             if $content->{po_number};
66              
67             $data->{reference_code} = $content->{invoice_number}
68             if $content->{invoice_number}
69             ;
70              
71             # Other fields
72             $data->{comments} = $content->{description} if $content->{description};
73              
74             $self->transaction_type( $content->{type} );
75              
76             if ( $content->{action} =~ qr/^authorization\ only|normal\ authorization|credit$/ix ) {
77             given ( $content->{type} ) {
78             when ( /^CC$/x ) {
79             #Credit Card information
80             my $expiration = $self->_expiration_to_datetime( $content->{expiration} );
81              
82             $data->{card}->{account_number} = $content->{card_number};
83              
84             $data->{card}->{expiration} = $expiration if $expiration;
85             $data->{card}->{security_code} = $content->{cvv2} if $content->{cvv2};
86             }
87             default {
88             Exception::Base->throw("$_ is an invalid payment type");
89             }
90             }
91             }
92              
93             $self->username( $content->{login} );
94             $self->password( $content->{password} );
95              
96             my $result = 0;
97              
98             given ( $content->{action} ) {
99             when ( /^authorization\ only$/ix ) {
100             $result = $self->authorize( $data );
101             }
102             when ( /^normal\ authorization$/ix ) {
103             $result = $self->sale( $data );
104             }
105             when ( /^post\ authorization$/ix ) {
106             $result = $self->capture( $data );
107             }
108             when ( /^void$/ix ) {
109             $result = $self->auth_reversal( $data );
110             }
111             when ( /^credit$/ix ) {
112             $result = $self->credit( $data );
113             }
114             default {
115             Exception::Base->throw( "$_ is an invalid action" );
116             }
117             }
118              
119             return $result;
120             }
121              
122             # Converts an expiration date string to a DateTime object
123             # Accepts: An expiration date expressed as YYYY-MM-DD, MM/YY, or MMYY
124             # Returns: A DateTime object on success and undef otherwise
125              
126             sub _expiration_to_datetime {
127             my ( undef, $date ) = @_;
128             my $year = 0;
129             my $month = 0;
130              
131             return unless defined $date;
132              
133             $date = '' unless $date;
134              
135             if ( $date ) {
136             if ( $date =~ /^\d{2}\/\d{2,4}$/x ) {
137             ( $month, $year ) = split '/', $date;
138             }
139              
140             if ( $date =~ /^\d{4}$/x ) {
141             $month = substr $date, 0, 2;
142             $year = substr $date, 2, 2;
143             }
144              
145             if ( $date =~ /^\d{4}-\d{2}-\d{2}\b/x ) {
146             ( $year, $month ) = split '-', $date;
147             }
148             }
149              
150             $year = 0 if ( $year < 0 );
151             $year += 2000 if ( $year < 100 && $year >= 0 );
152              
153             my $expiration = DateTime->last_day_of_month( year => $year, month => $month );
154              
155             return $expiration;
156             }
157              
158             #### Object Attributes ####
159             ## no critic ( RegularExpressions::ProhibitComplexRegexes )
160             has _client => (
161             isa => 'Business::OnlinePayment::CyberSource::Client',
162             is => 'bare',
163             default => sub { Business::OnlinePayment::CyberSource::Client->new() },
164             required => 0,
165             handles => qr/^(?:
166             is_\w+
167             |auth\w+
168             |order\w+
169             |card\w+
170             |fraud\w+
171             |\w*response\w*
172             |\w+code
173             |\w*transaction\w*
174             |require\w+
175             |server
176             |sale
177             |port
178             |path
179             |username
180             |login
181             |password
182             | error_message
183             | failure_status
184             | capture
185             |invoice_number
186             |credit
187             )$/x,
188             init_arg => undef,
189             lazy => 1,
190             );
191              
192             #### Method Modifiers ####
193              
194             1;
195              
196             __END__
197              
198             =pod
199              
200             =head1 NAME
201              
202             Business::OnlinePayment::CyberSource::Role::TransactionHandling - Transaction handling role for BOP::CyberSource
203              
204             =head1 VERSION
205              
206             version 3.000010
207              
208             =head1 SYNOPSIS
209              
210             package Thing;
211              
212             use Moose;
213              
214             with 'Business::OnlinePayment::CyberSource::Role::TransactionHandling';
215             1;
216              
217             my $thing = Thing->new();
218              
219             $thing->submit();
220              
221             =head1 DESCRIPTION
222              
223             This role provides consumers with methods for sending transaction requests to CyberSource and handling responses to those requests.
224              
225             =head1 METHODS
226              
227             =head2 submit
228              
229             =head1 BUGS
230              
231             Please report any bugs or feature requests on the bugtracker website
232             https://github.com/hostgator/Business-OnlinePayment-CyberSource/issues
233              
234             When submitting a bug or request, please include a test-file or a
235             patch to an existing test-file that illustrates the bug or desired
236             feature.
237              
238             =head1 AUTHORS
239              
240             =over 4
241              
242             =item *
243              
244             Jad Wauthier <Jadrien dot Wauthier at GMail dot com>
245              
246             =item *
247              
248             Caleb Cushing <xenoterracide@gmail.com>
249              
250             =item *
251              
252             Peter Bowen <peter@bowenfamily.org>
253              
254             =back
255              
256             =head1 COPYRIGHT AND LICENSE
257              
258             This software is copyright (c) 2012 by Hostgator.com.
259              
260             This is free software; you can redistribute it and/or modify it under
261             the same terms as the Perl 5 programming language system itself.
262              
263             =cut