Use 111-111-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.02';
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 );
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->{'programdesc'} = "415-462-1624 Business::OnlinePayment::Jety v$VERSION";
75   $content->{'ref'} = time2str('%Y%m%d',time).'-'.int(rand(1000000));
76
77   $content->{'phone'} ||= '111-111-1111';
78
79   $content->{'bankname'} ||= 'unknown';
80   $content->{'bankcity'} ||= 'unknown';
81   $content->{'bankstate'} ||= 'XX';
82
83   return;
84 }
85
86 sub submit {
87   my $self = shift;
88   $Business::OnlinePayment::HTTPS::DEBUG = $DEBUG;
89   $DB::single = $DEBUG; 
90
91   # strip existent but empty fields so that required_fields works right
92   foreach(keys(%{$self->{_content}})) {
93     delete $self->{_content}->{$_} 
94       if (!defined($self->{_content}->{$_} ) or
95            $self->{_content}->{$_} eq '');
96   }
97
98   $self->required_fields(qw(
99     type
100     action
101     first_name
102     last_name
103     address
104     city
105     state
106     zip
107     email
108     phone
109     account_number
110     routing_code
111     amount
112     ) );
113   $self->map_fields;
114   tie my %request, 'Tie::IxHash', (
115     map { $_, $self->{_content}->{$_} } @fields
116     );
117
118   $DB::single = $DEBUG;
119   if($self->test_transaction()) {
120     print "https://".$self->server.$self->path."\n";
121     print "$_\t".$request{$_}."\n" foreach keys(%request);
122     $self->error_message('test mode not supported');
123     $self->is_success(0);
124     return;
125   }
126   my ($reply, $response, %reply_headers) = $self->https_post(\%request);
127   
128   if(not $response =~ /^200/) {
129     croak "HTTPS error: '$response'";
130   }
131
132   # string looks like this:
133   # P1=1234&P2=General Status&P3=Specific Status
134   # P3 is not always there, though.
135   if($reply =~ /^P1=(\d+)&P2=([\w ]*)(&P3=(\S+))?/) {
136     if($1 == 0) {
137       $self->is_success(1);
138       $self->authorization($4);
139     }
140     else {
141       $self->is_success(0);
142       $self->error_message($2.($4 ? "($4)" : ''));
143     }
144   }
145   else {
146     croak "Malformed server response: '$reply'";
147   }
148
149   return;
150 }
151
152 1;
153 __END__
154
155 =head1 NAME
156
157 Business::OnlinePayment::Jety - Jety Payments ACH backend for Business::OnlinePayment
158
159 =head1 SYNOPSIS
160
161   use Business::OnlinePayment;
162
163   ####
164   # Electronic check authorization.  We only support 
165   # 'Normal Authorization'.
166   ####
167
168   my $tx = new Business::OnlinePayment("Jety");
169   $tx->content(
170       type           => 'ECHECK',
171       login          => 'testdrive',
172       password       => 'testpass',
173       action         => 'Normal Authorization',
174       description    => 'Business::OnlinePayment test',
175       amount         => '49.95',
176       invoice_number => '100100',
177       first_name     => 'Jason',
178       last_name      => 'Kohles',
179       address        => '123 Anystreet',
180       city           => 'Anywhere',
181       state          => 'UT',
182       zip            => '84058',
183       account_type   => 'personal checking',
184       account_number => '1000468551234',
185       routing_code   => '707010024',
186       check_number   => '1001', # optional
187   );
188   $tx->submit();
189
190   if($tx->is_success()) {
191       print "Check processed successfully: ".$tx->authorization."\n";
192   } else {
193       print "Check was rejected: ".$tx->error_message."\n";
194   }
195
196 =head1 SUPPORTED TRANSACTION TYPES
197
198 =head2 ECHECK
199
200 Content required: type, login, password, action, amount, first_name, last_name, account_number, routing_code.
201
202 =head1 DESCRIPTION
203
204 For detailed information see L<Business::OnlinePayment>.
205
206 =head1 METHODS AND FUNCTIONS
207
208 See L<Business::OnlinePayment> for the complete list. The following methods either override the methods in L<Business::OnlinePayment> or provide additional functions.  
209
210 =head2 result_code
211
212 Returns the four-digit result code.
213
214 =head2 error_message
215
216 Returns a useful error message.
217
218 =head1 Handling of content(%content) data:
219
220 =head2 action
221
222 The following actions are valid:
223
224   normal authorization
225
226 =head1 AUTHOR
227
228 Mark Wells <mark@freeside.biz>
229
230 =head1 SEE ALSO
231
232 perl(1). L<Business::OnlinePayment>.
233
234 =cut
235