- Really use 111-1111-1111 if no phone number is provided.
[Business-OnlinePayment-Jety.git] / lib / Business / OnlinePayment / Jety.pm
1 package Business::OnlinePayment::Jety;
2
3 use strict;
4 use Carp;
5 use Business::OnlinePayment 3;
6 use Business::OnlinePayment::HTTPS;
7 use vars qw($VERSION @ISA $me $DEBUG);
8
9 use Date::Format;
10 use Tie::IxHash;
11
12 @ISA = qw(Business::OnlinePayment::HTTPS);
13 $VERSION = '0.04';
14 $me = 'Business::OnlinePayment::Jety';
15
16 $DEBUG = 0;
17
18 my @fields = (qw(
19   username
20   password
21   function
22   firstname
23   lastname
24   address1
25   address2
26   city
27   state
28   zip
29   email
30   phone
31   programdesc
32   ref
33   bankname
34   bankcity
35   bankstate
36   accountaba
37   accountdda
38   amount
39 ));
40
41 my %map = (
42   'login'          => 'username',
43   'first_name'     => 'firstname',
44   'last_name'      => 'lastname',
45   'address'        => 'address1',
46   'bank_name'      => 'bankname',
47   'bank_city'      => 'bankcity',
48   'bank_state'     => 'bankstate',
49   'account_number' => 'accountdda',
50   'routing_code'   => 'accountaba',
51   'description'    => 'programdesc',
52 );
53
54 sub set_defaults {
55   my $self = shift;
56   $self->server('api.cardservicesportal.com');
57   $self->port(443);
58   $self->path('/servlet/drafts.echeck');
59   return;
60 }
61
62 sub map_fields {
63   my $self = shift;
64   my $content = $self->{_content};
65
66   $self->remap_fields(%map);
67
68   die "Jety API only supports ECHECK payments.\n" 
69     if(lc($content->{type}) ne 'echeck');
70   die "Jety interface only supports Normal Authorization.\n"
71     if(lc($content->{action}) ne 'normal authorization');
72
73   $content->{'function'} = 'echeck';
74   $content->{'ref'} = time2str('%Y%m%d',time).'-'.int(rand(1000000));
75
76   $content->{'phone'} ||= '111-111-1111';
77
78   $content->{'bankname'} ||= 'unknown';
79   $content->{'bankcity'} ||= 'unknown';
80   $content->{'bankstate'} ||= 'XX';
81
82   return;
83 }
84
85 sub submit {
86   my $self = shift;
87   $Business::OnlinePayment::HTTPS::DEBUG = $DEBUG;
88   $DB::single = $DEBUG; 
89
90   # strip existent but empty fields so that required_fields works right
91   foreach(keys(%{$self->{_content}})) {
92     delete $self->{_content}->{$_} 
93       if (!defined($self->{_content}->{$_} ) or
94            $self->{_content}->{$_} eq '');
95   }
96
97   $self->required_fields(qw(
98     type
99     action
100     first_name
101     last_name
102     address
103     city
104     state
105     zip
106     email
107     account_number
108     routing_code
109     amount
110     description
111   ));
112   $self->map_fields;
113   tie my %request, 'Tie::IxHash', map { $_ => $self->{_content}->{$_} } @fields;
114
115   $DB::single = $DEBUG;
116   if($self->test_transaction()) {
117     print "https://".$self->server.$self->path."\n";
118     print "$_\t".$request{$_}."\n" foreach keys(%request);
119     $self->error_message('test mode not supported');
120     $self->is_success(0);
121     return;
122   }
123   my ($reply, $response, %reply_headers) = $self->https_post(\%request);
124   
125   if(not $response =~ /^200/) {
126     croak "HTTPS error: '$response'";
127   }
128
129   # string looks like this:
130   # P1=1234&P2=General Status&P3=Specific Status
131   # P3 is not always there, though.
132   if($reply =~ /^P1=(\d+)&P2=([\w ]*)(&P3=(\S+))?/) {
133     if($1 == 0) {
134       $self->is_success(1);
135       $self->authorization($4);
136     }
137     else {
138       $self->is_success(0);
139       $self->error_message($2.($4 ? "($4)" : ''));
140     }
141   }
142   else {
143     croak "Malformed server response: '$reply'";
144   }
145
146   return;
147 }
148
149 1;
150 __END__
151
152 =head1 NAME
153
154 Business::OnlinePayment::Jety - Jety Payments ACH backend for Business::OnlinePayment
155
156 =head1 SYNOPSIS
157
158   use Business::OnlinePayment;
159
160   ####
161   # Electronic check authorization.  We only support 
162   # 'Normal Authorization'.
163   ####
164
165   my $tx = new Business::OnlinePayment("Jety");
166   $tx->content(
167       type           => 'ECHECK',
168       login          => 'testdrive',
169       password       => 'testpass',
170       action         => 'Normal Authorization',
171       description    => '111-111-1111 www.example.com',
172       amount         => '49.95',
173       invoice_number => '100100',
174       first_name     => 'Jason',
175       last_name      => 'Kohles',
176       address        => '123 Anystreet',
177       city           => 'Anywhere',
178       state          => 'UT',
179       zip            => '84058',
180       account_type   => 'personal checking',
181       account_number => '1000468551234',
182       routing_code   => '707010024',
183       check_number   => '1001', # optional
184   );
185   $tx->submit();
186
187   if($tx->is_success()) {
188       print "Check processed successfully: ".$tx->authorization."\n";
189   } else {
190       print "Check was rejected: ".$tx->error_message."\n";
191   }
192
193 =head1 SUPPORTED TRANSACTION TYPES
194
195 =head2 ECHECK
196
197 Content required: type, login, password, action, amount, first_name, last_name, account_number, routing_code, description.
198
199 description should be set in the form "111-111-1111 www.example.com"
200
201 =head1 DESCRIPTION
202
203 For detailed information see L<Business::OnlinePayment>.
204
205 =head1 METHODS AND FUNCTIONS
206
207 See L<Business::OnlinePayment> for the complete list. The following methods either override the methods in L<Business::OnlinePayment> or provide additional functions.  
208
209 =head2 result_code
210
211 Returns the four-digit result code.
212
213 =head2 error_message
214
215 Returns a useful error message.
216
217 =head1 Handling of content(%content) data:
218
219 =head2 action
220
221 The following actions are valid:
222
223   normal authorization
224
225 =head1 AUTHOR
226
227 Mark Wells <mark@freeside.biz>
228
229 =head1 SEE ALSO
230
231 perl(1). L<Business::OnlinePayment>.
232
233 =cut
234