+package Business::OnlinePayment::FirstDataGlobalGateway;
+use base qw( Business::OnlinePayment );
+
+use warnings;
+use strict;
+use Data::Dumper;
+use Business::CreditCard;
+use SOAP::Lite +trace => 'all';
+#SOAP::Lite->import(+trace=>'debug');
+
+our $VERSION = '0.01';
+$VERSION = eval $VERSION; # modperlstyle: convert the string into a number
+
+our @alpha = ( 'a'..'z', 'A'..'Z', '0'..'9' );
+
+sub _info {
+ {
+ 'info_compat' => '0.01',
+ 'gateway_name' => 'First Data Global Gateway e4',
+ 'gateway_url' => 'https://www.firstdata.com/en_us/products/merchants/ecommerce/online-payment-processing.html',
+ 'module_version' => $VERSION,
+ 'supported_types' => [ 'CC' ], #, 'ECHECK' ],
+ #'token_support' => 1,
+ #'test_transaction' => 1,
+
+ 'supported_actions' => [ 'Normal Authorization',
+ #'Credit',
+ ],
+ };
+}
+
+sub set_defaults {
+ my $self = shift;
+ #my %opts = @_;
+
+ #$self->build_subs(qw( order_number avs_code cvv2_response
+ # response_page response_code response_headers
+ # ));
+
+ $self->build_subs(qw( avs_code ));
+
+}
+
+sub map_fields {
+ my($self) = @_;
+
+ my %content = $self->content();
+
+ # TYPE MAP
+ my %types = ( 'visa' => 'CC',
+ 'mastercard' => 'CC',
+ 'american express' => 'CC',
+ 'discover' => 'CC',
+ 'check' => 'ECHECK',
+ );
+ $content{'type'} = $types{lc($content{'type'})} || $content{'type'};
+ $self->transaction_type($content{'type'});
+
+ # ACTION MAP
+ my $action = lc($content{'action'});
+ my %actions =
+ ( 'normal authorization' => '00', # Purchase
+ 'authorization_only' => '01', #
+ 'post authorization' => '02', # Pre-Authorization Completion
+ # '' => '03', # Forced Post
+ 'credit' => '04', # Refund
+ # '' => '05', # Pre-Authorization Only
+ 'void' => '13', # Void
+ #'reverse authorization' => '',
+
+ # '' => '07', # PayPal Order
+ # '' => '32', # Tagged Pre-Authorization Completion
+ # '' => '33', # Tagged Void
+ # '' => '34', # Tagged Refund
+ # '' => '83', # CashOut (ValueLink, v9 or higher end point only)
+ # '' => '85', # Activation (ValueLink, v9 or higher end point only)
+ # '' => '86', # Balance Inquiry (ValueLink, v9 or higher end point only)
+ # '' => '88', # Reload (ValueLink, v9 or higher end point only)
+ # '' => '89', # Deactivation (ValueLink, v9 or higher end point only)
+ );
+
+ $content{'action'} = $actions{$action} || $action;
+
+ # stuff it back into %content
+ $self->content(%content);
+
+}
+
+sub remap_fields {
+ my($self,%map) = @_;
+
+ my %content = $self->content();
+ foreach(keys %map) {
+ $content{$map{$_}} = $content{$_};
+ }
+ $self->content(%content);
+}
+
+sub submit {
+ my($self) = @_;
+
+ $self->map_fields;
+
+ $self->remap_fields(
+ 'login' => 'ExactID',
+ 'password' => 'Password',
+
+ 'action' => 'TransactionType',
+
+ 'amount' => 'DollarAmount',
+ 'currency' => 'Currency',
+ 'card_number' => 'Card_Number',
+ 'track1' => 'Track1',
+ 'track2' => 'Track2',
+ 'expiration' => 'Expiry_Date',
+ 'name' => 'CardHoldersName',
+ 'cvv2' => 'VerificationStr2',
+
+ 'authorization' => 'Authorization_Num',
+ 'order_number' => 'Reference_No',
+
+ 'zip' => 'ZipCode',
+ 'tax' => 'Tax1Amount',
+ 'customer_id' => 'Customer_Ref',
+ 'customer_ip' => 'Client_IP',
+ 'email' => 'Client_Email',
+
+ #account_type => 'accountType',
+
+ );
+
+ my %content = $self->content();
+
+ #$content{'mop'} = $mop{ cardtype($content{creditCardNum}) }
+ # if $content{'type'} eq 'CC';
+
+ #if ( $self->test_transaction ) {
+ # $content{agentCode} = 'TEST88';
+ # $content{password} = 'TEST88';
+ #}
+
+ $content{Expiry_Date} =~ s/\///;
+
+ $content{country} ||= 'US';
+
+ $content{VerificationStr1} =
+ join('|', map $content{$_}, qw( address zip city state country ));
+ $content{VerificationStr1} .= '|'. $content{'phone'}
+ if $content{'type'} eq 'ECHECK';
+
+ $content{CVD_Presence_Ind} = '1' if length($content{VerificationStr2});
+
+ $content{'Reference_No'} ||= join('', map $alpha[int(rand(62))], (1..20) );
+
+ #XXX this should be exposed as a standard B:OP field, not just recurring/no
+ if ( defined($content{'recurring_billing'})
+ && $content{'recurring_billing'} =~ /^[y1]/ ) {
+ $content{'Ecommerce_Flag'} = '2';
+ } else {
+ #$content{'Ecommerce_Flag'} = '1'; 7? if there's an IP?
+ }
+
+ my $base_uri;
+ if ( $self->test_transaction ) {
+ $base_uri =
+ 'https://api.demo.globalgatewaye4.firstdata.com/transaction';
+ } else {
+ $base_uri =
+ 'https://api.globalgatewaye4.firstdata.com/vplug-in/transaction';
+ }
+
+ my $proxy = "$base_uri/v11";
+ my $uri = "$base_uri/rpc-enc";
+
+ my %transaction = map { $_ => $content{$_} } (qw(
+ ExactID Password Transaction_Type DollarAmount Card_Number Transaction_Tag
+ Track1 Track2 Authorization_Num Expiry_Date CardHoldersName
+ VerificationStr1 VerificationStr2 CVD_Presence_Ind Reference_No ZipCode
+ Tax1Amount Tax1Number Tax2Amount Tax2Number Customer_Ref Reference_3
+ Language Client_IP Client_Email user_name Currency PartialRedemption
+ CAVV XID Ecommerce_Flag
+ ));
+ #TransarmorToken CardType EAN VirtualCard CardCost FraudSuspected
+ #CheckNumber CheckType BankAccountNumber BankRoutingNumber CustomerName
+ #CustomerIDType CustomerID
+
+ #my @opts = map { SOAP::Data->name($_)->value( $data{$_} ) }
+ # keys %data;
+
+ my $result = SOAP::Lite
+ ->proxy($proxy)
+
+ ->default_ns($base_uri)
+ ->uri($uri)
+
+ ->on_action( sub { join '/', @_ } )
+ #->on_action( sub { join '', @_ } )
+ #->on_action(sub { qq("$_[0]") }) #? https://firstdata.zendesk.com/entries/407569-First-Data-Global-Gateway-e4-Web-Service-API-Sample-Code-Perl
+ ->autotype(0)
+
+ ->readable(1)
+
+ ->ns($uri,'q1')
+ ->SendAndCommit( SOAP::Data->name('Transaction')->value( \%transaction ) )
+
+ ->result();
+
+ die Dumper($result);
+
+ die Dumper($result->result) if $result->fault;
+ #die $result->fault->faultstring if $result->fault;
+
+ die Dumper($result);
+
+ #$self->is_success
+ #$self->authorization
+ #$self->avs_code
+ #$self->error_message
+ #$self->result_code
+ ##$self->failure_status
+
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+Business::OnlinePayment::FirstDataGlobalGateway - First Data Global Gateway e4 backend for Business::OnlinePayment
+
+=head1 SYNOPSIS
+
+ use Business::OnlinePayment;
+
+ my $tx =
+ new Business::OnlinePayment( 'FirstDataGlobalGateway' );
+
+ $tx->content(
+ login => 'TEST88', # ExactID
+ password => 'TEST88', #password
+
+ type => 'CC',
+ action => 'Normal Authorization',
+ amount => '1.00',
+
+ first_name => 'Tofu',
+ last_name => 'Beast',
+ address => '123 Anystreet',
+ city => 'Anywhere',
+ state => 'UT',
+ zip => '84058',
+
+ card_number => '4111111111111111',
+ expiration => '09/20',
+ cvv2 => '124',
+
+ #optional
+ customer_ip => '1.2.3.4',
+ );
+ $tx->submit();
+
+ if($tx->is_success()) {
+ print "Card processed successfully: ".$tx->authorization."\n";
+ } else {
+ print "Card was rejected: ".$tx->error_message."\n";
+ }
+
+=head1 SUPPORTED TRANSACTION TYPES
+
+=head2 CC, Visa, MasterCard, American Express, Discover
+
+Content required: type, login, action, amount, card_number, expiration.
+
+=head2 (NOT YET) Check
+
+Content required: type, login, action, amount, name, account_number, routing_code.
+
+=head1 DESCRIPTION
+
+For detailed information see L<Business::OnlinePayment>.
+
+=head1 METHODS AND FUNCTIONS
+
+See L<Business::OnlinePayment> for the complete list. The following methods either override the methods in L<Business::OnlinePayment> or provide additional functions.
+
+=head2 result_code
+
+Returns the response error code.
+
+=head2 error_message
+
+Returns the response error number.
+
+=head2 action
+
+The following actions are valid
+
+ Normal Authorization
+ Authorization Only
+ Post Authorization
+ Credit
+ Void
+
+=head1 COMPATIBILITY
+
+Business::OnlinePayment::FirstDataGlobalGateway uses the v11 version of the API
+at this time.
+
+=head1 AUTHORS
+
+Ivan Kohler <ivan-firstdataglobalgateway@freeside.biz>
+
+=head1 SEE ALSO
+
+perl(1). L<Business::OnlinePayment>.
+
+=cut
+