2171c36a1713ec534b5ee4963112e1166a6a0ed2
[Business-OnlinePayment-Exact.git] / lib / Business / OnlinePayment / Exact.pm
1 package Business::OnlinePayment::Exact;
2
3 use 5.006001;
4 use strict;
5 use warnings;
6 use SOAP::Lite;
7 use Business::OnlinePayment;
8
9 our @ISA = qw(Business::OnlinePayment);
10 our @EXPORT_OK = ();
11 our @EXPORT = qw();
12
13 our $VERSION = '0.01';
14
15 sub set_defaults {
16     my $self = shift;
17     $self->build_subs(qw(proxy on_action uri tns types process encodingstyle
18         order_number));
19     $self->proxy('https://secure2.e-xact.com/vpos/process/vpos.asmx');
20     $self->on_action('http://secure2.e-xact.com/vpos/process/Process');
21     $self->uri('http://secure2.e-xact.com/vpos/process/');
22     $self->tns('http://secure2.e-xact.com/vpos/process/');
23     $self->types('http://secure2.e-xact.com/vpos/process/encodedTypes');
24     $self->process('http://secure2.e-xact.com/vpos/process/Request');
25     $self->encodingstyle('http://schemas.xmlsoap.org/soap/encoding/');
26 }
27
28 sub map_fields {
29     my $self = shift;
30     my %content = $self->content();
31     my %actions = ('normal authorization' => '00',
32                    'authorization only' => '01',
33                    'credit' => '04',
34                    'post authorization' => '02',
35                    'void' => '13',
36     );
37     $content{'action'} = $actions{lc($content{'action'})};
38     $content{'name'} = $content{'first_name'}.' '.$content{'last_name'} ||
39         $content{'name'} if $content{'first_name'} and $content{'last_name'};
40     $content{'expiration'} =~ /(\d\d)\D*(\d\d)/ if $content{'expiration'};
41     $content{'expiration_month'} = $1 || $content{'expiration_month'};
42     $content{'expiration_year'} = $2 || $content{'expiration_year'};
43     $content{'expiration'} = $content{'expiration_month'}.
44         $content{'expiration_year'} || $content{'expiration'};
45     $self->content(%content);
46 }
47
48 sub remap_fields {
49     my($self,%map) = @_;
50
51     my %content = $self->content();
52     foreach(keys %map) {
53         $content{$map{$_}} = $content{$_};
54     }
55     $self->content(%content);
56 }
57
58 sub submit {
59     my $self = shift;
60     $self->map_fields;
61     $self->remap_fields(
62         login => 'ExactID',
63         password => 'Password',
64         action => 'Transaction_Type',
65         amount => 'DollarAmount',
66         customer_ip => 'Client_IP',
67         order_number => 'Reference_No',
68         name => 'CardHoldersName',
69         address => 'VerificationStr1',
70         email => 'Client_Email',
71         card_number => 'Card_Number',
72         expiration => 'Expiry_Date',
73         referer => 'Customer_Ref', 
74     );
75     my %content = $self->content();
76     #make data here
77     my @data;
78     foreach (keys %content) {
79         push @data, SOAP::Data->name($_ => $content{$_})->type('string');
80     }
81
82     my $data = 
83     SOAP::Data->attr({'xsi:type' => 'types:Transaction'})
84         ->name('Transaction')->value(\SOAP::Data->value(@data));
85     #figure out action
86     #make request
87
88     my $s = SOAP::Lite
89     ->proxy($self->proxy)
90     ->on_action(sub{return $self->on_action})
91     ->uri($self->uri)
92     ->readable(1);
93
94     $s->serializer->register_ns($self->tns => 'tns');
95     $s->serializer->register_ns($self->types => 'types');
96
97     my $m = SOAP::Data->name('q1:Process')
98         ->attr({'xmlns:q1' => $self->process,
99         'soap:encodingStyle' => $self->encodingstyle});
100
101     my $result = $s->call($m => $data);
102     #get result
103     if ($result->fault) {
104         $self->is_success(0);
105         $self->error_message($result->faultstring);
106     }
107     else {
108         if ($result->valueof('//TransactionResult/Transaction_Approved') 
109         eq '1' and $result->valueof('//TransactionResult/EXact_Resp_Code') 
110         eq '00' and $result->valueof('//TransactionResult/Transaction_Error') 
111         eq '0') {
112             $self->is_success(1);
113             $self->error_message(
114                 $result->valueof('//TransactionResult/EXact_Message'));
115             $self->authorization(
116                 $result->valueof('//TransactionResult/Authorization_Num'));
117             $self->order_number(
118                 $result->valueof('//TransactionResult/SequenceNo'));
119             }
120         else {
121             $self->is_success(0);
122             $self->error_message(
123                 $result->valueof('//TransactionResult/EXact_Message'));
124         }
125
126     }
127 }
128
129
130 1;
131 __END__
132 =head1 NAME
133
134 Business::OnlinePayment::Exact - Perl extension for doing credit card 
135 processing through the E-xact v7 Web Services API payment gateway.
136
137 =head1 SYNOPSIS
138
139   use Business::OnlinePayment;
140   my $tx = new Business::OnlinePayment('Exact');
141   $tx->content(
142     amount => '19.00',
143     card_number => '4200000000000000',
144     expiration => '0110',
145     name => 'Some Guy',
146     action => 'authorization only',
147     login => 'A000XX-XX'
148     password => 'password'
149   );
150   $tx->submit;
151   if ($tx->is_success()) {
152     my $ordernum = $tx->order_number;
153     print "Got the cash";
154   }
155   else {
156     print $tx->error_message;
157   }
158
159 =head1 ABSTRACT
160
161     This is a Business::OnlinePayment module for E-xact loosely based on
162     Business::OnlinePayment::AuthorizeNet.  I've only used it for normal
163     authorization so it may require some work to do pre auth, etc.
164
165
166 =head1 DESCRIPTION
167
168     See synopsis.  It works like any other Business::OnlinePayment module.
169     The following content keys are usefull:
170     login
171     password
172     amount
173     card_number
174     expiration
175     name
176     referer
177     email
178     address
179     order_number
180     customer_ip
181     action
182
183     The following content keys are also available (but not really usefull):
184     'first_name' and 'last_name' will combine to override 'name'
185     'expiration_month' and 'expiration_year' will combine to override 
186     'expiration'
187
188     The 'authorization' method will return the bank authorization code, and the
189     'order_number' method will contain the sequence number from E-xact.
190     The content key 'referer' can be used to store any string data (20 bytes)
191     and used to search for those transactions from the web interface.
192
193 =head2 EXPORT
194
195 None by default.
196
197 =head1 SEE ALSO
198
199 Business::OnlinePayment
200 SOAP::Lite
201 "Exact Payment WebService Plug-In Programming Reference Guide v7"
202 (which can be found on www.e-xact.com with enough digging)
203
204 =head1 AUTHOR
205
206 mock, E<lt>mock@obscurity.orgE<gt>
207
208 =head1 COPYRIGHT AND LICENSE
209
210 Copyright (C) 2005 by mock
211
212 This library is free software; you can redistribute it and/or modify
213 it under the same terms as Perl itself, either Perl version 5.8.1 or,
214 at your option, any later version of Perl 5 you may have available.
215
216 =cut