1 package Business::OnlinePayment::IATSPayments;
2 use base qw( Business::OnlinePayment );
7 use Business::CreditCard;
9 #SOAP::Lite->import(+trace=>'debug');
11 our $VERSION = '0.03_01';
12 $VERSION = eval $VERSION; # modperlstyle: convert the string into a number
16 'info_compat' => '0.01',
17 'gateway_name' => 'IATS Payments',
18 'gateway_url' => 'http://home.iatspayments.com/',
19 'module_version' => $VERSION,
20 'supported_types' => [ 'CC', 'ECHECK' ],
21 #'token_support' => 1,
22 'test_transaction' => 1,
24 'supported_actions' => [ 'Normal Authorization',
34 #$self->build_subs(qw( order_number avs_code cvv2_response
35 # response_page response_code response_headers
38 $self->build_subs(qw( avs_code ));
45 my %content = $self->content();
48 my %types = ( 'visa' => 'CC',
50 'american express' => 'CC',
54 $content{'type'} = $types{lc($content{'type'})} || $content{'type'};
55 $self->transaction_type($content{'type'});
58 my $action = lc($content{'action'});
60 ( 'normal authorization' => 'ProcessCreditCardV1',
61 'credit' => 'ProcessCreditCardRefundWithTransactionIdV1',
64 ( 'normal authorization' => 'ProcessACHEFTV1',
65 'credit' => 'ProcessACHEFTRefundWithTransactionIdV1',
68 if ($self->transaction_type eq 'CC') {
69 $content{'action'} = $actions{$action} || $action;
70 } elsif ($self->transaction_type eq 'ECHECK') {
72 $content{'action'} = $check_actions{$action} || $action;
75 my %account_types = ('personal checking' => 'CHECKING',
76 'personal savings' => 'SAVINGS',
77 'business checking' => 'CHECKING',
78 'business savings' => 'SAVINGS',
79 #not technically B:OP valid i guess?
80 'checking' => 'CHECKING',
81 'savings' => 'SAVINGS',
83 $content{'account_type'} = $account_types{lc($content{'account_type'})}
84 || $content{'account_type'};
87 # stuff it back into %content
88 $self->content(%content);
95 my %content = $self->content();
97 $content{$map{$_}} = $content{$_};
99 $self->content(%content);
102 # NA: VISA, MC, AMX, DSC
103 # UK: VISA, MC, AMX, MAESTR
105 'VISA card' => 'VISA',
106 'MasterCard' => 'MC',
107 'Discover card' => 'DSC',
108 'American Express card' => 'AMEX',
109 'Switch' => 'MAESTR',
113 #https://www.iatspayments.com/english/help/rejects.html
115 '1' => 'Agent code has not been set up on the authorization system. Please call iATS at 1-888-955-5455.',
116 '2' => 'Unable to process transaction. Verify and re-enter credit card information.',
117 '3' => 'Invalid Customer Code.',
118 '4' => 'Incorrect expiration date.',
119 '5' => 'Invalid transaction. Verify and re-enter credit card information.',
120 '6' => 'Please have cardholder call the number on the back of the card.',
121 '7' => 'Lost or stolen card.',
122 '8' => 'Invalid card status.',
123 '9' => 'Restricted card status. Usually on corporate cards restricted to specific sales.',
124 '10' => 'Error. Please verify and re-enter credit card information.',
125 '11' => 'General decline code. Please have client call the number on the back of credit card',
126 '12' => 'Incorrect CVV2 or Expiry date',
127 '14' => 'The card is over the limit.',
128 '15' => 'General decline code. Please have client call the number on the back of credit card',
129 '16' => 'Invalid charge card number. Verify and re-enter credit card information.',
130 '17' => 'Unable to authorize transaction. Authorizer needs more information for approval.',
131 '18' => 'Card not supported by institution.',
132 '19' => 'Incorrect CVV2 security code',
133 '22' => 'Bank timeout. Bank lines may be down or busy. Re-try transaction later.',
134 '23' => 'System error. Re-try transaction later.',
135 '24' => 'Charge card expired.',
136 '25' => 'Capture card. Reported lost or stolen.',
137 '26' => 'Invalid transaction, invalid expiry date. Please confirm and retry transaction.',
138 '27' => 'Please have cardholder call the number on the back of the card.',
139 '32' => 'Invalid charge card number.',
140 '39' => 'Contact IATS 1-888-955-5455.',
141 '40' => 'Invalid card number. Card not supported by IATS.',
142 '41' => 'Invalid Expiry date.',
143 '42' => 'CVV2 required.',
144 '43' => 'Incorrect AVS.',
145 '45' => 'Credit card name blocked. Call iATS at 1-888-955-5455.',
146 '46' => 'Card tumbling. Call iATS at 1-888-955-5455.',
147 '47' => 'Name tumbling. Call iATS at 1-888-955-5455.',
148 '48' => 'IP blocked. Call iATS at 1-888-955-5455.',
149 '49' => 'Velocity 1 – IP block. Call iATS at 1-888-955-5455.',
150 '50' => 'Velocity 2 – IP block. Call iATS at 1-888-955-5455.',
151 '51' => 'Velocity 3 – IP block. Call iATS at 1-888-955-5455.',
152 '52' => 'Credit card BIN country blocked. Call iATS at 1-888-955-5455.',
153 '100' => 'DO NOT REPROCESS. Call iATS at 1-888-955-5455.',
154 #Timeout The system has not responded in the time allotted. Call iATS at 1-888-955-5455.
157 our %failure_status = (
164 '45' => 'blacklisted',
165 '48' => 'blacklisted',
166 '49' => 'blacklisted',
167 '50' => 'blacklisted',
168 '51' => 'blacklisted',
169 '52' => 'blacklisted',
170 #'100' => # it sounds serious. but why? it says nothing specific
179 login => 'agentCode',
180 password => 'password',
182 description => 'comment',
184 invoice_number => 'invoiceNum',
185 customer_ip => 'customerIPAddress',
187 last_name => 'lastName',
188 first_name => 'firstName',
189 address => 'address',
193 #country => 'x_Country',
195 card_number => 'creditCardNum',
196 expiration => 'creditCardExpiry',
199 authorization => 'transactionId',
201 account_type => 'accountType',
205 my %content = $self->content();
207 $content{'mop'} = $mop{ cardtype($content{creditCardNum}) }
208 if $content{'type'} eq 'CC';
210 if ( $self->test_transaction ) {
211 $content{agentCode} = 'TEST88';
212 $content{password} = 'TEST88';
216 ( ! $content{currency} || $content{currency} =~ /^(USD|CAD)$/i )
217 ? 'https://www.iatspayments.com/NetGate/'
218 : 'https://www.uk.iatspayments.com/NetGate/';
220 my $action = $content{action};
222 my $uri = $base_uri. "ProcessLink.asmx?op=$action";
224 # never "uk.iatspayments.com"
225 my $default_ns = 'https://www.iatspayments.com/NetGate/';
227 my %data = map { $_ => $content{$_} } (qw(
235 if ( $action =~ /RefundWithTransacdtionIdV[\d\.]+$/ ) {
237 $data{ $_ } = $content{$_} for qw(
243 $data{ $_ } = $content{$_} for qw(
253 if ( $content{'type'} eq 'CC' ) {
255 $data{$_} = $content{$_}
256 for qw( creditCardNum creditCardExpiry cvv2 mop );
258 } elsif ( $content{'type'} eq 'ECHECK' ) {
260 $data{'accountNum'}= $content{'routing_code'}. $content{'account_number'};
262 $data{$_} = $content{$_}
263 for qw( accountType );
269 my @opts = map { SOAP::Data->name($_)->value( $data{$_} ) }
272 my $result = SOAP::Lite
274 ->default_ns($default_ns)
275 #->on_action( sub { join '/', @_ } )
276 ->on_action( sub { join '', @_ } )
283 my $iatsresponse = $result->{IATSRESPONSE};
285 if ( $iatsresponse->{STATUS} eq 'Failure' && $iatsresponse->{ERRORS} ) {
286 die 'iATS Payments error: '. $iatsresponse->{ERRORS}. "\n";
287 } elsif ( $iatsresponse->{STATUS} ne 'Success' ) {
288 die "Couldn't parse iATS Payments response: ". Dumper($result);
291 my $processresult = $iatsresponse->{PROCESSRESULT};
293 if ( defined( $processresult->{TRANSACTIONID} ) ) {
294 $processresult->{TRANSACTIONID} =~ s/^\s+//;
295 $processresult->{TRANSACTIONID} =~ s/\s+$//;
297 $self->authorization($processresult->{TRANSACTIONID} || '');
299 if ( $processresult->{AUTHORIZATIONRESULT} =~ /^\s*OK(:\s*\d+:)?(\w)?\s*$/i ) {
300 $self->is_success(1);
301 $self->avs_code($2); #avs_code? sure looks like one
303 } elsif ( $processresult->{AUTHORIZATIONRESULT} =~ /^\s*Timeout\s*$/i ) {
304 $self->is_success(0);
305 $self->error_message('The system has not responded in the time allotted. '.
306 'Call iATS at 1-888-955-5455.');
308 } elsif ( $processresult->{AUTHORIZATIONRESULT}
309 =~ /^\s*REJ(ECT)?:\s*(\d+)\s*$/i
312 $self->is_success(0);
313 $self->result_code($2);
314 $self->error_message( $reject{$2} || $processresult->{AUTHORIZATIONRESULT});
315 $self->failure_status( $failure_status{$2} || 'decline' );
318 die "No/Unknown AUTHORIZATIONRESULT iATS Payments response: ".
319 Dumper($processresult);
330 Business::OnlinePayment::IATSPayments - IATS Payments backend for Business::OnlinePayment
334 use Business::OnlinePayment;
337 new Business::OnlinePayment( 'IATSPayments' );
340 login => 'TEST88', # agentCode
341 password => 'TEST88', #password
344 action => 'Normal Authorization',
347 first_name => 'Tofu',
348 last_name => 'Beast',
349 address => '123 Anystreet',
354 card_number => '4111111111111111',
355 expiration => '09/20',
359 description => 'Business::OnlinePayment test',
360 customer_ip => '1.2.3.4',
365 if($tx->is_success()) {
366 print "Card processed successfully: ".$tx->authorization."\n";
368 print "Card was rejected: ".$tx->error_message."\n";
371 =head1 SUPPORTED TRANSACTION TYPES
373 =head2 CC, Visa, MasterCard, American Express, Discover
375 Content required: type, login, action, amount, card_number, expiration.
379 Content required: type, login, action, amount, name, account_number, routing_code.
383 For detailed information see L<Business::OnlinePayment>.
385 =head1 METHODS AND FUNCTIONS
387 See L<Business::OnlinePayment> for the complete list. The following methods either override the methods in L<Business::OnlinePayment> or provide additional functions.
391 Returns the response error code.
395 Returns the response error number.
399 The following actions are valid
406 Business::OnlinePayment::IATSPayments uses iATS WebServices ProcessLink 4.0
407 and (for tokenization support) iATS WebServices CustomerLink 4.0.
411 Ivan Kohler <ivan-iatspayments@freeside.biz>
415 perl(1). L<Business::OnlinePayment>.