1 # Vend::Payment::iTransact - Interchange iTransact Support
3 # $Id: iTransact.pm,v 2.9 2009-03-16 19:34:01 jon Exp $
5 # Copyright (C) 2002-2007 Interchange Development Group
6 # Copyright (C) 1999-2002 Red Hat, Inc.
8 # Written by Cameron Prince and Mark Johnson, based on code by Mike Heins.
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
20 # You should have received a copy of the GNU General Public
21 # License along with this program; if not, write to the Free
22 # Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
25 package Vend::Payment::iTransact;
29 Vend::Payment::iTransact - Interchange iTransact Support
37 [charge mode=itransact param1=value1 param2=value2]
45 LWP::UserAgent and Crypt::SSLeay
47 Only one of these need be present and working.
51 The Vend::Payment::iTransact module implements the itransact() routine
52 for use with Interchange. It is compatible on a call level with the other
53 Interchange payment modules.
55 To enable this module, place this directive in C<interchange.cfg>:
57 Require module Vend::Payment::iTransact
59 This I<must> be in interchange.cfg or a file included from it.
61 Make sure CreditCardAuto is off (default in Interchange demos).
63 The mode can be named anything, but the C<gateway> parameter must be set
64 to C<itransact>. To make it the default payment gateway for all credit
65 card transactions in a specific catalog, you can set in C<catalog.cfg>:
67 Variable MV_PAYMENT_MODE itransact
69 It uses several of the standard settings from Interchange payment. Any time
70 we speak of a setting, it is obtained either first from the tag/call options,
71 then from an Interchange order Route named for the mode, then finally a
72 default global payment variable, For example, the C<id> parameter would
75 [charge mode=itransact id=YouriTransact]
79 Route itransact id YouriTransactID
83 Variable MV_PAYMENT_ID YouriTransactID
85 The active settings are:
91 Your iTransact account ID, supplied by iTransact when you sign up.
92 Global parameter is MV_PAYMENT_ID.
96 The internet address of your site. Defaults to C<http://__SERVER_NAME__> if
97 not set. Global parameter is MV_PAYMENT_HOME_PAGE.
101 This remaps the form variable names to the ones needed by iTransact. See
102 the C<Payment Settings> heading in the Interchange documentation for use.
106 =head2 Troubleshooting
108 Try the instructions above, then enable test mode. A test order should complete.
110 Then move to live mode and try a sale with the card number C<4111 1111 1111 1111>
111 and a valid expiration date. The sale should be denied, and the reason should
112 be in [data session payment_error].
120 Make sure you "Require"d the module in interchange.cfg:
122 Require module Vend::Payment::iTransact
126 Make sure either Net::SSLeay or Crypt::SSLeay and LWP::UserAgent are installed
127 and working. You can test to see whether your Perl thinks they are:
129 perl -MNet::SSLeay -e 'print "It works\n"'
133 perl -MLWP::UserAgent -MCrypt::SSLeay -e 'print "It works\n"'
135 If either one prints "It works." and returns to the prompt you should be OK
136 (presuming they are in working order otherwise).
140 Check the error logs, both catalog and global.
144 Make sure you set your account ID properly.
148 Try an order, then put this code in a page:
152 my $string = $Tag->uneval( { ref => $Session->{payment_result} });
154 $string =~ s/,/,\n/g;
159 That should show what happened.
163 If all else fails, consultants are available to help with integration for a fee.
164 See http://www.icdevgroup.org/
170 There is actually nothing *in* Vend::Payment::iTransact. It changes packages
171 to Vend::Payment and places things there.
175 Mark Johnson and Cameron Prince, based on original code by Mike Heins.
183 package Vend::Payment;
185 import Net::SSLeay qw(post_https make_form make_headers);
186 $selected = "Net::SSLeay";
189 $Vend::Payment::Have_Net_SSLeay = 1 unless $@;
191 unless ($Vend::Payment::Have_Net_SSLeay) {
194 package Vend::Payment;
195 require LWP::UserAgent;
196 require HTTP::Request::Common;
197 require Crypt::SSLeay;
198 import HTTP::Request::Common qw(POST);
199 $selected = "LWP and Crypt::SSLeay";
202 $Vend::Payment::Have_LWP = 1 unless $@;
206 unless ($Vend::Payment::Have_Net_SSLeay or $Vend::Payment::Have_LWP) {
207 die __PACKAGE__ . " requires Net::SSLeay or Crypt::SSLeay";
210 ::logGlobal("%s payment module initialized, using %s", __PACKAGE__, $selected)
211 unless $Vend::Quiet or ! $Global::VendRoot;
215 package Vend::Payment;
218 my ($opt, $amount) = @_;
220 my $user = $opt->{id} || charge_param('id');
222 my $company = $opt->{company} || "$::Variable->{COMPANY} Order";
226 %actual = %{$opt->{actual}};
229 %actual = map_actual();
232 $actual{mv_credit_card_exp_month} =~ s/\D//g;
233 $actual{mv_credit_card_exp_month} =~ s/^0+//;
234 $actual{mv_credit_card_exp_year} =~ s/\D//g;
236 my $exp_year = $actual{mv_credit_card_exp_year};
237 $exp_year += 2000 unless $exp_year =~ /\d{4}/;
239 $actual{mv_credit_card_number} =~ s/\D//g;
241 my @month = (qw/January
254 my $exp_month = @month[$actual{mv_credit_card_exp_month} - 1];
255 my $precision = $opt->{precision} || charge_param('precision') || 2;
257 $amount = "$opt->{total_cost}" || undef;
260 $amount = Vend::Interpolate::total_cost();
261 $amount = Vend::Util::round_to_frac_digits($amount,$precision);
265 if($opt->{test} and $gen = charge_param('generate_error') ) {
266 #::logDebug("trying to generate error");
267 $actual{mv_credit_card_number} = '4111111111111112'
275 ret_addr => "success",
277 '1-desc' => $company,
279 first_name => $actual{b_fname},
280 last_name => $actual{b_lname},
281 address => $actual{b_address},
282 city => $actual{b_city},
283 state => $actual{b_state},
284 zip => $actual{b_zip},
285 country => $actual{b_country},
286 phone => $actual{phone_day},
287 email => $actual{email},
288 ccnum => $actual{mv_credit_card_number},
291 ret_mode => "redirect",
294 my $hp = $opt->{home_page}
295 || charge_param('home_page')
296 || $::Variable->{SERVER_NAME};
297 $hp = "http://$hp" unless $hp =~ /^\w+:/;
298 $values{home_page} = $hp;
300 $opt->{submit_url} ||= 'https://secure.itransact.com/cgi-bin/rc/ord.cgi';
304 #::logDebug("sending query: " . ::uneval(\%values));
306 my $thing = post_data($opt, \%values);
307 my $header_string = $thing->{header_string};
308 my $result_page = $thing->{result_page};
313 #::logDebug("request returned: $result_page");
315 if ($header_string =~ m/^Location: success/mi) {
316 $result{MStatus} = 'success';
317 $result{'order-id'} = $opt->{order_id};
320 if ($result_page =~ m/BEGIN ERROR DESCRIPTION --\>(.*)\<\!-- END ERROR DESCRIPTION/s) {
322 $error =~ s/\<.*?\>//g;
323 $error =~ s/[^-A-Za-z_0-9 ]//g;
325 elsif($result_page =~ m{<title>\s*error\s*</title>}i) {
326 $error = $result_page;
327 $error =~ s/.*?<body.*?>//is;
328 $error =~ s/<.*?>//g;
334 ## something very bad happened
335 $error = ::errmsg("Unknown error");
338 #::logDebug("iTransact Error: " . $error);
339 $result{MStatus} = 'denied';
340 $result{MErrMsg} = $error;
347 package Vend::Payment::iTransact;