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.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',
33 my %content = $self->content();
36 my %types = ( 'visa' => 'CC',
38 'american express' => 'CC',
42 $content{'type'} = $types{lc($content{'type'})} || $content{'type'};
43 $self->transaction_type($content{'type'});
46 my $action = lc($content{'action'});
48 ( 'normal authorization' => 'ProcessCreditCardV1',
49 'credit' => 'ProcessCreditCardRefundWithTransactionIdV1',
52 ( 'normal authorization' => 'ProcessACHEFTV1',
53 'credit' => 'ProcessACHEFTRefundWithTransactionIdV1',
56 if ($self->transaction_type eq 'CC') {
57 $content{'action'} = $actions{$action} || $action;
58 } elsif ($self->transaction_type eq 'ECHECK') {
60 $content{'action'} = $check_actions{$action} || $action;
63 my %account_types = ('personal checking' => 'CHECKING',
64 'personal savings' => 'SAVINGS',
65 'business checking' => 'CHECKING',
66 'business savings' => 'SAVINGS',
67 #not technically B:OP valid i guess?
68 'checking' => 'CHECKING',
69 'savings' => 'SAVINGS',
71 $content{'account_type'} = $account_types{lc($content{'account_type'})}
72 || $content{'account_type'};
75 # stuff it back into %content
76 $self->content(%content);
83 my %content = $self->content();
85 $content{$map{$_}} = $content{$_};
87 $self->content(%content);
90 # NA: VISA, MC, AMX, DSC
91 # UK: VISA, MC, AMX, MAESTR
93 'VISA card' => 'VISA',
95 'Discover card' => 'DSC',
96 'American Express card' => 'AMEX',
101 #https://www.iatspayments.com/english/help/rejects.html
103 '1' => 'Agent code has not been set up on the authorization system. Please call iATS at 1-888-955-5455.',
104 '2' => 'Unable to process transaction. Verify and re-enter credit card information.',
105 '3' => 'Invalid Customer Code.',
106 '4' => 'Incorrect expiration date.',
107 '5' => 'Invalid transaction. Verify and re-enter credit card information.',
108 '6' => 'Please have cardholder call the number on the back of the card.',
109 '7' => 'Lost or stolen card.',
110 '8' => 'Invalid card status.',
111 '9' => 'Restricted card status. Usually on corporate cards restricted to specific sales.',
112 '10' => 'Error. Please verify and re-enter credit card information.',
113 '11' => 'General decline code. Please have client call the number on the back of credit card',
114 '12' => 'Incorrect CVV2 or Expiry date',
115 '14' => 'The card is over the limit.',
116 '15' => 'General decline code. Please have client call the number on the back of credit card',
117 '16' => 'Invalid charge card number. Verify and re-enter credit card information.',
118 '17' => 'Unable to authorize transaction. Authorizer needs more information for approval.',
119 '18' => 'Card not supported by institution.',
120 '19' => 'Incorrect CVV2 security code',
121 '22' => 'Bank timeout. Bank lines may be down or busy. Re-try transaction later.',
122 '23' => 'System error. Re-try transaction later.',
123 '24' => 'Charge card expired.',
124 '25' => 'Capture card. Reported lost or stolen.',
125 '26' => 'Invalid transaction, invalid expiry date. Please confirm and retry transaction.',
126 '27' => 'Please have cardholder call the number on the back of the card.',
127 '32' => 'Invalid charge card number.',
128 '39' => 'Contact IATS 1-888-955-5455.',
129 '40' => 'Invalid card number. Card not supported by IATS.',
130 '41' => 'Invalid Expiry date.',
131 '42' => 'CVV2 required.',
132 '43' => 'Incorrect AVS.',
133 '45' => 'Credit card name blocked. Call iATS at 1-888-955-5455.',
134 '46' => 'Card tumbling. Call iATS at 1-888-955-5455.',
135 '47' => 'Name tumbling. Call iATS at 1-888-955-5455.',
136 '48' => 'IP blocked. Call iATS at 1-888-955-5455.',
137 '49' => 'Velocity 1 – IP block. Call iATS at 1-888-955-5455.',
138 '50' => 'Velocity 2 – IP block. Call iATS at 1-888-955-5455.',
139 '51' => 'Velocity 3 – IP block. Call iATS at 1-888-955-5455.',
140 '52' => 'Credit card BIN country blocked. Call iATS at 1-888-955-5455.',
141 '100' => 'DO NOT REPROCESS. Call iATS at 1-888-955-5455.',
142 #Timeout The system has not responded in the time allotted. Call iATS at 1-888-955-5455.
145 our %failure_status = (
152 '45' => 'blacklisted',
153 '48' => 'blacklisted',
154 '49' => 'blacklisted',
155 '50' => 'blacklisted',
156 '51' => 'blacklisted',
157 '52' => 'blacklisted',
158 #'100' => # it sounds serious. but why? it says nothing specific
167 login => 'agentCode',
168 password => 'password',
170 description => 'comment',
172 invoice_number => 'invoiceNum',
173 customer_ip => 'customerIPAddress',
175 last_name => 'lastName',
176 first_name => 'firstName',
177 address => 'address',
181 #country => 'x_Country',
183 card_number => 'creditCardNum',
184 expiration => 'creditCardExpiry',
187 authorization => 'transactionId',
189 account_type => 'accountType',
193 my %content = $self->content();
195 $content{'mop'} = $mop{ cardtype($content{creditCardNum}) }
196 if $content{'type'} eq 'CC';
198 if ( $self->test_transaction ) {
199 $content{agentCode} = 'TEST88';
200 $content{password} = 'TEST88';
204 ( ! $content{currency} || $content{currency} =~ /^(USD|CAD)$/i )
205 ? 'https://www.iatspayments.com/NetGate/'
206 : 'https://www.uk.iatspayments.com/NetGate/';
208 my $action = $content{action};
210 my $uri = $base_uri. "ProcessLink.asmx?op=$action";
212 my %data = map { $_ => $content{$_} } (qw(
220 if ( $action =~ /RefundWithTransacdtionIdV[\d\.]+$/ ) {
222 $data{ $_ } = $content{$_} for qw(
228 $data{ $_ } = $content{$_} for qw(
238 if ( $content{'type'} eq 'CC' ) {
240 $data{$_} = $content{$_}
241 for qw( creditCardNum creditCardExpiry cvv2 mop );
243 } elsif ( $content{'type'} eq 'ECHECK' ) {
245 $data{'accountNum'}= $content{'routing_code'}. $content{'account_number'};
247 $data{$_} = $content{$_}
248 for qw( accountType );
254 my @opts = map { SOAP::Data->name($_)->value( $data{$_} ) }
257 my $result = SOAP::Lite
259 ->default_ns($base_uri)
260 #->on_action( sub { join '/', @_ } )
261 ->on_action( sub { join '', @_ } )
268 my $iatsresponse = $result->{IATSRESPONSE};
270 if ( $iatsresponse->{STATUS} eq 'Failure' && $iatsresponse->{ERRORS} ) {
271 die 'iATS Payments error: '. $iatsresponse->{ERRORS}. "\n";
272 } elsif ( $iatsresponse->{STATUS} ne 'Success' ) {
273 die "Couldn't parse iATS Payments response: ". Dumper($result);
276 my $processresult = $iatsresponse->{PROCESSRESULT};
278 $self->authorization($processresult->{TRANSACTIONID} || '');
280 if ( $processresult->{AUTHORIZATIONRESULT} =~ /^\s*OK(:\s*\d+)?(:(\w))?\s*$/i ) {
281 $self->is_success(1);
282 $self->avs_code($3); #avs_code? sure looks like one
284 } elsif ( $processresult->{AUTHORIZATIONRESULT} =~ /^\s*Timeout\s*$/i ) {
285 $self->is_success(0);
286 $self->error_message('The system has not responded in the time allotted. '.
287 'Call iATS at 1-888-955-5455.');
289 } elsif ( $processresult->{AUTHORIZATIONRESULT}
290 =~ /^\s*REJ(ECT)?:\s*(\d+)\s*$/i
293 $self->is_success(0);
294 $self->error_message( $reject{$2} || $processresult->{AUTHORIZATIONRESULT});
295 $self->failure_status( $failure_status{$2} || 'decline' );
298 die "No/Unknown AUTHORIZATIONRESULT iATS Payments response: ".
299 Dumper($processresult);
310 Business::OnlinePayment::IATSPayments - IATS Payments backend for Business::OnlinePayment
314 use Business::OnlinePayment;
317 new Business::OnlinePayment( 'IATSPayments' );
320 login => 'TEST88', # agentCode
321 password => 'TEST88', #password
324 action => 'Normal Authorization',
327 first_name => 'Tofu',
328 last_name => 'Beast',
329 address => '123 Anystreet',
334 card_number => '4111111111111111',
335 expiration => '09/20',
339 description => 'Business::OnlinePayment test',
340 customer_ip => '1.2.3.4',
345 if($tx->is_success()) {
346 print "Card processed successfully: ".$tx->authorization."\n";
348 print "Card was rejected: ".$tx->error_message."\n";
351 =head1 SUPPORTED TRANSACTION TYPES
353 =head2 CC, Visa, MasterCard, American Express, Discover
355 Content required: type, login, action, amount, card_number, expiration.
359 Content required: type, login, action, amount, name, account_number, routing_code.
363 For detailed information see L<Business::OnlinePayment>.
365 =head1 METHODS AND FUNCTIONS
367 See L<Business::OnlinePayment> for the complete list. The following methods either override the methods in L<Business::OnlinePayment> or provide additional functions.
371 Returns the response error code.
375 Returns the response error number.
379 The following actions are valid
386 Business::OnlinePayment::IATSPayments uses iATS WebServices ProcessLink 4.0
387 and (for tokenization support) iATS WebServices CustomerLink 4.0.
391 Ivan Kohler <ivan-iatspayments@freeside.biz>
395 perl(1). L<Business::OnlinePayment>.