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, 'order_number' should be set to
227 the order_number of the previous transaction.
229 Alternately, Post Authorization can be sent with 'authorization' set to an
230 auth code obtained by telephone. Similarly, Credit can be sent with credit
231 account information instead of an 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 '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