1 package Business::OnlinePayment::GlobalPayments;
6 use vars qw($VERSION $DEBUG @ISA $me);
7 use base 'Business::OnlinePayment::HTTPS';
8 use XML::Simple 'XMLin'; # for parsing reply
15 'normal authorization' => 'Sale',
16 'authorization only' => 'Auth',
17 'post authorization' => 'Force',
23 'GlobalUserName' => 'login',
24 'GlobalPassword' => 'password',
25 'TransType' => sub { my %c = @_; $trans_type{ lc($c{action}) } },
26 'CardNum' => 'card_number',
27 'ExpDate' => sub { my %c = @_; join('', split /\D/,$c{'expiration'}) },
28 'MagData' => 'track2',
29 'NameOnCard' => sub { my %c = @_; $c{'first_name'} . ' ' . $c{'last_name'} },
31 'InvNum' => 'invoice_number',
33 'Street' => 'address',
35 'PNRef' => 'order_number',
36 'ExtData' => \&ext_data,
40 my %c = @_; # = $self->{_content}
42 if($c{'authorization'}) {
43 $ext_data .= '<AuthCode>'.$c{'authorization'}.'</AuthCode>';
45 if($c{'force_duplicate'}) { # set to any true value
46 $ext_data .= '<Force>T</Force>';
51 my %required_fields = (
52 'All' => [ qw(GlobalUserName GlobalPassword TransType) ],
53 'Sale' => [ qw(CardNum ExpDate Amount) ],
54 'Auth' => [ qw(CardNum ExpDate Amount) ],
56 'Void' => [ 'PNRef' ],
58 'Return.blind' => [ qw(CardNum ExpDate Amount) ],
64 $self->path('/GlobalPay/transact.asmx/ProcessCreditCard');
65 $self->build_subs('domain', 'avs_code', 'cvv2_response' );
71 my ($self, %map) = @_;
72 my %content = $self->content();
74 foreach (keys(%map)) {
75 if(ref($map{$_}) eq 'CODE') {
76 $content{$_} = $map{$_}->(%content);
79 $content{$_} = $content{$map{$_}} if defined( $content{$map{$_}} );
83 if(lc($content{'action'}) eq 'post authorization') {
84 # GlobalPayments uses this transaction type to complete an authorized
85 # transaction, given either its PNRef (if it was authorized by an Auth
86 # transaction to the gateway) or its AuthCode (if it was authorized by
88 if(!exists($content{'PNRef'}) and !exists($content{'authorization'})) {
89 croak("missing required field(s): PNRef or AuthCode\n");
93 $self->content(%content);
99 my $content = $self->{_content};
100 $DB::single = 1 if $DEBUG;
102 $self->setup_test if $self->test_transaction();
104 die "missing required option: domain\n" if !$self->domain();
105 $self->server($self->domain() . '.globalpay.com');
107 $self->remap_fields(%cc_fields);
109 my $action = $content->{'TransType'} or
110 croak "unknown action: '".$content->{'action'}."'\n";
111 $self->required_fields(@{ $required_fields{'All'} });
112 $self->required_fields(@{ $required_fields{$action} });
114 if($action eq 'Return' and !exists($content->{'PNRef'})) {
115 # This handles the case where a credit is ordered "blind", without
116 # an order_number. Card information must be supplied. Allowing
117 # these is somewhat risky, and can be disabled at the account level
118 # by the "Require Original PNRef" flag.
119 $self->required_fields(@{ $required_fields{'Return.blind'} });
122 tie my %request, 'Tie::IxHash',
123 map { $_ => $self->{_content}->{$_} } keys(%cc_fields);
125 $Business::OnlinePayment::HTTPS::DEBUG = $DEBUG;
126 $DB::single = 1 if $DEBUG;
127 my ($page, $response, %headers) = $self->https_post(\%request);
129 $self->server_response($page);
130 $self->is_success(0);
131 if(not $response =~ /^200/) {
132 $self->error_message("Connection failed: '$response'\n");
135 my $data = XMLin($page);
136 if(!$data or !exists($data->{'Result'})) {
137 $self->error_message("Malformed server response: '$page'\n");
140 $self->result_code($data->{'Result'});
141 $self->avs_code($data->{'GetAVSResult'});
142 $self->cvv2_response($data->{'GetCVResult'});
143 if($data->{'Result'} != 0) {
144 $self->error_message($data->{'Message'});
148 $self->is_success(1);
149 $self->authorization($data->{'AuthCode'});
150 $self->order_number($data->{'PNRef'});
157 $self->domain('certapia');
158 # For test card information, see Global Transport API documentation.
164 Business::OnlinePayment::GlobalPayments - Global Transport backend for Business::OnlinePayment
168 =head2 Initialization
170 my $trans = new Business::OnlinePayment('GlobalPayments',
171 domain => 'mymerchant' # Your account rep will supply this
174 =head2 Sale transaction
178 password => 'password',
180 card_number => '5500000000000004',
181 expiration => '0211',
183 invoice_number => '123321',
185 last_name => 'Schmoe',
186 address => '123 Anystreet',
187 city => 'Sacramento',
190 action => 'normal authorization',
197 if($trans->is_approved) {
199 "Authorization: ", $trans->authorization, "\n",
200 "Order ID: ", $trans->order_number, "\n"
203 print "Failed: ".$trans->error_message;
206 =head2 Void transaction
207 (or Return (credit) for full amount of original sale)
211 password => 'password',
212 action => 'void', # or 'credit' for a Return
213 order_number => '1001245',
219 The following transaction types are supported:
226 For Post Authorization, Credit, and Void, I<order_number> should be set to
227 the order_number of the previous transaction.
229 Alternately, Post Authorization can be sent with I<authorization> set to an
230 auth code obtained by telephone. Similarly, Credit can be sent with credit
231 account information instead of an I<order_number>.
233 By default, Global Transport will reject duplicate transactions (identical
234 card number, expiration date, and amount) sent on the same day. This can be
235 overridden by setting I<force_duplicate> => 1.
239 Mark Wells <mark@freeside.biz>
243 Support for commercial users is available from Freeside Internet Services,
244 Inc. <http://www.freeside.biz>
246 =head1 COPYRIGHT & LICENSE
248 Copyright 2009 Mark Wells, all rights reserved.
250 This program is free software; you can redistribute it and/or modify it
251 under the same terms as Perl itself.
256 1; # End of Business::OnlinePayment::GlobalPayments