1 package Business::OnlinePayment::ElavonVirtualMerchant;
2 use base qw(Business::OnlinePayment::viaKLIX);
5 use vars qw( $VERSION %maxlength );
8 $VERSION = eval $VERSION;
12 Business::OnlinePayment::ElavonVirtualMerchant - Elavon Virtual Merchant backend for Business::OnlinePayment
16 use Business::OnlinePayment::ElavonVirtualMerchant;
18 my $tx = new Business::OnlinePayment("ElavonVirtualMerchant", { default_ssl_userid => 'whatever' });
22 password => '', #password or transaction key
23 action => 'Normal Authorization',
24 description => 'Business::OnlinePayment test',
26 invoice_number => '100100',
28 first_name => 'Jason',
29 last_name => 'Kohles',
30 address => '123 Anystreet',
34 card_number => '4007000000027',
35 expiration => '09/02',
36 cvv2 => '1234', #optional
40 if($tx->is_success()) {
41 print "Card processed successfully: ".$tx->authorization."\n";
43 print "Card was rejected: ".$tx->error_message."\n";
48 This module lets you use the Elavon (formerly Nova Information Systems) Virtual Merchant real-time payment gateway, a successor to viaKlix, from an application that uses the Business::OnlinePayment interface.
50 You need an account with Elavon. Elavon uses a three-part set of credentials to allow you to configure multiple 'virtual terminals'. Since Business::OnlinePayment only passes a login and password with each transaction, you must pass the third item, the user_id, to the constructor.
52 Elavon offers a number of transaction types, including electronic gift card operations and 'PINless debit'. Of these, only credit card transactions fit the Business::OnlinePayment model.
54 Since the Virtual Merchant API is just a newer version of the viaKlix API, this module subclasses Business::OnlinePayment::viaKlix.
56 This module does not use Elavon's XML encoding as this doesn't appear to offer any benefit over the standard encoding.
62 Sets defaults for the Virtual Merchant gateway URL.
70 $self->SUPER::set_defaults(%opts);
71 # standard B::OP methods/data
72 $self->server("www.myvirtualmerchant.com");
74 $self->path("/VirtualMerchant/process.do");
80 Converts credit card types and transaction types from the Business::OnlinePayment values to Elavon's.
87 my %content = $self->content();
91 'normal authorization' => 'CCSALE', # Authorization/Settle transaction
92 'credit' => 'CCCREDIT', # Credit (refund)
95 $content{'ssl_transaction_type'} = $actions{ lc( $content{'action'} ) }
96 || $content{'action'};
101 'mastercard' => 'CC',
102 'american express' => 'CC',
107 $content{'type'} = $types{ lc( $content{'type'} ) } || $content{'type'};
109 $self->transaction_type( $content{'type'} );
111 # stuff it back into %content
112 $self->content(%content);
117 Maps data from Business::OnlinePayment name space to Elavon's, checks that all required fields
118 for the transaction type are present, and submits the transaction. Saves the results.
123 ssl_description => 255,
124 ssl_invoice_number => 25,
125 ssl_customer_code => 17,
127 ssl_first_name => 20,
130 ssl_avs_address => 30,
134 ssl_ship_to_first_name => 20,
135 ssl_ship_to_last_name => 30,
136 ssl_ship_to_company => 50,
137 ssl_ship_to_address1 => 30,
138 ssl_ship_to_city => 30,
139 ssl_ship_to_phone => 20, #though we don't map anything to this...
145 $self->_map_fields();
147 my %content = $self->content;
150 $required{CC_CCSALE} = [ qw( ssl_transaction_type ssl_merchant_id ssl_pin
151 ssl_amount ssl_card_number ssl_exp_date
152 ssl_cvv2cvc2_indicator
154 $required{CC_CCCREDIT} = $required{CC_CCSALE};
156 $optional{CC_CCSALE} = [ qw( ssl_user_id ssl_salestax ssl_cvv2cvc2
157 ssl_description ssl_invoice_number
158 ssl_customer_code ssl_company ssl_first_name
159 ssl_last_name ssl_avs_address ssl_address2
160 ssl_city ssl_state ssl_avs_zip ssl_country
161 ssl_phone ssl_email ssl_ship_to_company
162 ssl_ship_to_first_name ssl_ship_to_last_name
163 ssl_ship_to_address1 ssl_ship_to_city
164 ssl_ship_to_state ssl_ship_to_zip
167 $optional{CC_CCCREDIT} = $optional{CC_CCSALE};
169 my $type_action = $self->transaction_type(). '_'. $content{ssl_transaction_type};
170 unless ( exists($required{$type_action}) ) {
171 $self->error_message("Elavon can't handle transaction type: ".
172 "$content{action} on " . $self->transaction_type() );
173 $self->is_success(0);
177 my $expdate_mmyy = $self->expdate_mmyy( $content{"expiration"} );
178 my $zip = $content{'zip'};
179 $zip =~ s/[^[:alnum:]]//g;
181 my $cvv2indicator = $content{"cvv2"} ? 1 : 9; # 1 = Present, 9 = Not Present
183 $self->_revmap_fields(
185 ssl_merchant_id => 'login',
186 ssl_pin => 'password',
188 ssl_amount => 'amount',
189 ssl_card_number => 'card_number',
190 ssl_exp_date => \$expdate_mmyy, # MMYY from 'expiration'
191 ssl_cvv2cvc2_indicator => \$cvv2indicator,
192 ssl_cvv2cvc2 => 'cvv2',
193 ssl_description => 'description',
194 ssl_invoice_number => 'invoice_number',
195 ssl_customer_code => 'customer_id',
197 ssl_first_name => 'first_name',
198 ssl_last_name => 'last_name',
199 ssl_company => 'company',
200 ssl_avs_address => 'address',
202 ssl_state => 'state',
203 ssl_avs_zip => \$zip, # 'zip' with non-alnums removed
204 ssl_country => 'country',
205 ssl_phone => 'phone',
206 ssl_email => 'email',
208 ssl_ship_to_first_name => 'ship_first_name',
209 ssl_ship_to_last_name => 'ship_last_name',
210 ssl_ship_to_company => 'ship_company',
211 ssl_ship_to_address1 => 'ship_address',
212 ssl_ship_to_city => 'ship_city',
213 ssl_ship_to_state => 'ship_state',
214 ssl_ship_to_zip => 'ship_zip',
215 ssl_ship_to_country => 'ship_country',
219 my %params = $self->get_fields( @{$required{$type_action}},
220 @{$optional{$type_action}},
223 $params{$_} = substr($params{$_},0,$maxlength{$_})
224 foreach grep exists($maxlength{$_}), keys %params;
226 foreach ( keys ( %{($self->{_defaults})} ) ) {
227 $params{$_} = $self->{_defaults}->{$_} unless exists($params{$_});
230 $params{ssl_test_mode}='true' if $self->test_transaction;
232 $params{ssl_show_form}='false';
233 $params{ssl_result_format}='ASCII';
235 $self->required_fields(@{$required{$type_action}});
237 warn join("\n", map{ "$_ => $params{$_}" } keys(%params)) if $self->debug > 1;
238 my ( $page, $resp, %resp_headers ) =
239 $self->https_post( %params );
241 $self->response_code( $resp );
242 $self->response_page( $page );
243 $self->response_headers( \%resp_headers );
245 warn "$page\n" if $self->debug > 1;
246 # $page should contain key/value pairs
249 my %results = map { s/\s*$//; split '=', $_, 2 } grep { /=/ } split '^', $page;
251 # AVS and CVS values may be set on success or failure
252 $self->avs_code( $results{ssl_avs_response} );
253 $self->cvv2_response( $results{ ssl_cvv2_response } );
254 $self->result_code( $status = $results{ errorCode } || $results{ ssl_result } );
255 $self->order_number( $results{ ssl_txn_id } );
256 $self->authorization( $results{ ssl_approval_code } );
257 $self->error_message( $results{ errorMessage } || $results{ ssl_result_message } );
260 if ( $resp =~ /^(HTTP\S+ )?200/ && $status eq "0" ) {
261 $self->is_success(1);
263 $self->is_success(0);
272 Business::OnlinePayment, Business::OnlinePayment::viaKlix, Elavon Virtual Merchant Developers' Guide
276 Richard Siddall, E<lt>elavon@elirion.netE<gt>
280 Duplicates code to handle deprecated 'type' codes.
282 Method for passing raw card track data is not documented by Elavon.
284 =head1 COPYRIGHT AND LICENSE
286 Copyright (C) 2009 by Richard Siddall. This module is largely based on Business::OnlinePayment::viaKlix by Jeff Finucane.
288 This library is free software; you can redistribute it and/or modify
289 it under the same terms as Perl itself, either Perl version 5.8.8 or,
290 at your option, any later version of Perl 5 you may have available.