Pass Cf1/Cf2 for voids and refunds as well
[Business-OnlinePayment-vSecureProcessing.git] / lib / Business / OnlinePayment / vSecureProcessing.pm
index e7514a3..f7d8b9d 100644 (file)
@@ -1,35 +1,66 @@
 package Business::OnlinePayment::vSecureProcessing;
 
 use strict;
+use vars qw($VERSION $DEBUG @ISA);
 use Carp;
-use Template;
+use XML::Writer;
 use XML::Simple;
 use Data::Dumper;
-
 use Business::OnlinePayment;
 use Business::OnlinePayment::HTTPS;
-#use Net::SSLeay qw(post_http post_https make_headers make_form);
-use vars qw($VERSION $DEBUG @ISA $me);
 
 @ISA = qw(Business::OnlinePayment::HTTPS);
 $DEBUG = 0;
-$VERSION = '0.01';
-$me = 'Business::OnlinePayment::vSecureProcessing';
-
-
-# $server: http://dvrotsos2.kattare.com
+$VERSION = '0.09';
+
+sub _info {
+  'info_compat'       => '0.01',
+  'gateway_name'      => 'vSecure Processing',
+  'gateway_url'       => 'http://www.vsecureprocessing.com/',
+  'module_version'    => $VERSION,
+  'supported_types'   => [qw( CC )],
+  'token_support'     => 0,
+  'test_transaction'  => 1,
+  'partial_auth'      => 1,
+  'supported_actions' => [
+                           'Normal Authorization',
+                           #'Authorization Only',
+                           #'Post Authorization',
+                           'Reverse Authorization',
+                           'Void',
+                           'Credit',
+                         ],
+}
 
 # mapping out all possible endpoints
 # but this version will only be building out "charge", "void", & "credit"
 my %payment_actions = (
     'charge' => {
         path      => '/vsg2/processpayment',
+        process   => 'ProcessPayment',
+        fields    => [qw/
+          Amount Trk1 Trk2 TypeOfSale Cf1 Cf2 Cf3 AccountNumber
+          ExpirationMonth ExpirationYear Cvv
+          CardHolderFirstName CardHolderLastName AvsZip AvsStreet
+          IndustryType ApplicationId Recurring
+        /],
     },
     'void' => {
         path      => '/vsg2/processvoid',
+        process   => 'ProcessVoid',
+        fields    => [qw(
+          Amount Cf1 Cf2 Cf3 AccountNumber
+          ExpirationMonth ExpirationYear ReferenceNumber
+          TransactionDate IndustryType ApplicationId
+        )],
     },
     'refund' => {
         path      => '/vsg2/processrefund',
+        process   => 'ProcessRefund',
+        fields    => [qw(
+          Amount Cf1 Cf2 Cf3 AccountNumber
+          ExpirationMonth ExpirationYear ApplicationId
+        )],
     },
     'authorize' => {
         path      => '/vsg2/processauth',
@@ -77,27 +108,23 @@ sub set_defaults {
                            result_code
                            error_message
                            server
-                           port
                            path
                            server_response/;
                            
     # B::OP creates the following accessors:
-    #     server, port, path, test_transaction, transaction_type,
+    #     server, path, test_transaction, transaction_type,
     #     server_response, is_success, authorization,
     #     result_code, error_message,
     
     $self->build_subs(qw/
-            env platform userid gid tid appid action reference_number cvv_response
-            avs_response risk_score txn_amount txn_date response_code
+            platform tid appid
+            action reference_number cvv2_response avs_code response_code
+            risk_score txn_amount txn_date partial_auth_amount
     /);
     
     $DEBUG = exists($options{debug}) ? $options{debug} : $DEBUG;
     
-    
-    
-    $self->server($options{'server'});
-    
-    $self->gid($options{'gid'});
+    $self->server('svr1.vsecureprocessing.com');
     
     $self->tid($options{'tid'});
     
@@ -105,13 +132,10 @@ sub set_defaults {
     
     $self->appid($options{'appid'});
     
-    $self->env((defined($options{'env'})) ? $options{'env'} : 'live'); # 'live'/'test'
-    
     $self->port(443);
+    
 }
 
-
-
 sub clean_content {
     my ($self,$content) = @_;
     my %content = $self->content();
@@ -125,15 +149,25 @@ sub clean_content {
             $content{card_number} =~ s/\D//g;
         }
         
+        if ($content{'description'} && length($content{'description'}) >20) {
+            $content{'description'} = substr($content{'description'},0,20);
+        }
+        
         # separate month and year values for expiry_date
         if ( $content{expiration} ) {
-            ($content{exp_month}, $content{exp_year}) = split /\//, $content{expiration};
+            ($content{exp_month}, $content{exp_year}) =
+              split /\//, $content{expiration};
             $content{exp_month} = sprintf "%02d", $content{exp_month};
-            $content{exp_year}  = substr($content{exp_year},0,2) if ($content{exp_year} > 99);
+            $content{exp_year}  = substr($content{exp_year},0,2)
+              if ($content{exp_year} > 99);
         }
         
-        if (!$content{'first_name'} || !$content{'last_name'} && $content{'name'}) {
-            ($content{'first_name'}, $content{'last_name'}) = split(' ', $content{'name'}, 2);
+        if (    !$content{'first_name'}
+             || !$content{'last_name'} && $content{'name'}
+           )
+        {
+            ($content{'first_name'}, $content{'last_name'}) =
+              split(' ', $content{'name'}, 2);
         }
         
         if ($content{'address'} =~ m/[\D ]*(\d+)\D/) {
@@ -148,7 +182,10 @@ sub process_content {
     my $self = shift;
     $self->clean_content();
     my %content = $self->content();
-    $self->action(($action_mapping{lc $content{'action'}}) ? $action_mapping{lc $content{'action'}} : lc $content{'action'});
+    $self->action( ($action_mapping{lc $content{'action'}})
+                     ? $action_mapping{lc $content{'action'}}
+                     : lc $content{'action'}
+                 );
     $self->path($payment_actions{ $self->action }{path})
       unless length($self->path);
     $self->appid($content{appid}) if (!$self->appid && $content{appid});
@@ -168,6 +205,10 @@ sub submit {
     $self->process_content();
     my %content = $self->content;
     my $action = $self->action();
+
+    if ( $self->test_transaction ) {
+      $self->server('dvrotsos2.kattare.com');
+    }
     
     my @acceptable_actions = ('charge', 'refund', 'void');
     
@@ -175,98 +216,99 @@ sub submit {
         croak "'$action' is not supported at this time.";
     }
     
-    # fill out the template vars
-    my $template_vars = {
-        
+    # fill in the xml vars
+    my $xml_vars = {
         auth => {
-            platform    => $self->platform,
-            userid      => $self->userid,
-            gid         => $self->gid,
-            tid         => $self->tid
+            Platform    => $self->platform,
+            UserId      => $content{'login'},
+            GID         => $content{'password'},
+            Tid         => $self->tid || '01',
         },
         
         payment => {
-            amount          => $content{'amount'},
-            track1          => ($content{'track1'}) ? $content{'track1'} : '',
-            track2          => ($content{'track2'}) ? $content{'track2'} : '',
-            type            => ($content{'description'}) ? $content{'description'} : '',
-            cf1             => ($content{'UDField1'}) ? $content{'UDField1'} : '',
-            cf2             => ($content{'UDField2'}) ? $content{'UDField2'} : '',
-            cf3             => '',
-            account_number  => ($content{'card_number'}) ? $content{'card_number'} : '',
-            exp_month       => $content{'exp_month'},
-            exp_year        => $content{'exp_year'},
-            cvv             => ($content{'cvv'}) ? $content{'cvv'} : ($content{'cvv2'}) ? $content{'cvv2'} : '',
-            first_name      => ($content{'first_name'}) ? $content{'first_name'} : '',
-            last_name       => ($content{'last_name'}) ? $content{'last_name'} : '',
-            postal_code     => ($content{'zip'}) ? $content{'zip'} : '',
-            street_address  => ($content{'street_number'}) ? $content{'street_number'} : '',
-            industry_type   => ($content{'IndustryInfo'} && lc($content{'IndustryInfo'}) eq 'ecommerce') ? 'ecom_3' : '',
-            invoice_num     => ($content{'invoice_number'}) ? $content{'invoice_number'} : '',
-            appid           => $self->appid(),
-            recurring       => ($content{'recurring_billing'} && $content{'recurring_billing'} eq 'YES' ) ? 1 : 0,
-            response_code   => ($content{'response_code'}) ? $content{'response_code'} : '',
-            reference_number=> ($content{'ref_num'}) ? $content{'ref_num'} : '',
-            token           => ($content{'token'}) ? $content{'token'} : '',
-            receipt         => ($content{'receipt'}) ? $content{'receipt'} : '',
-            transaction_date=> ($content{'txn_date'}) ? $content{'txn_date'} : '',
-            merchant_data   => ($content{'merchant_data'}) ? $content{'merchant_data'} : '',
-        },
-        
-        # we won't be using level2 nor level3.  So I'm leaving them blank for now.
-        level2 => {
-            card_type             => '',
-            purchase_code         => '',
-            country_code          => '',
-            ship_tp_postal_code   => '',
-            ship_from_postal_code => '',
-            sales_tax             => '',
-            product_description1  => '',
-            product_description2  => '',
-            product_description3  => '',
-            product_description4  => ''
-        },
-        
-        level3 => {
-            purchase_order_num    => '',
-            order_date            => '',
-            duty_amount           => '',
-            alt_tax_amount        => '',
-            discount_amount       => '',
-            freight_amount        => '',
-            tax_exempt            => '',
-            line_item_count       => '',
-            purchase_items        => $self->_parse_line_items()
+            Amount          => $content{'amount'},
+            Trk1            => ($content{'track1'}) ? $content{'track1'} : '',
+            Trk2            => ($content{'track2'}) ? $content{'track2'} : '',
+            TypeOfSale      => ($content{'description'}) ? $content{'description'} : '',
+            Cf1             => ($content{'invoice_number'}) ? $content{'invoice_number'} : '',
+            Cf2             => ($content{'customer_id'}) ? $content{'customer_id'} : '',
+            Cf3             => '',
+            AccountNumber   => ($content{'card_number'}) ? $content{'card_number'} : '',
+            ExpirationMonth => $content{'exp_month'},
+            ExpirationYear  => $content{'exp_year'},
+            Cvv             => ($content{'cvv'}) ? $content{'cvv'} : ($content{'cvv2'}) ? $content{'cvv2'} : '',
+            CardHolderFirstName => ($content{'first_name'}) ? $content{'first_name'} : '',
+            CardHolderLastName => ($content{'last_name'}) ? $content{'last_name'} : '',
+            AvsZip          => ($content{'zip'}) ? $content{'zip'} : '',
+            AvsStreet       => ($content{'street_number'}) ? $content{'street_number'} : '',
+#            IndustryType    =>  { 
+#                                IndType => ($content{'IndustryInfo'} && lc($content{'IndustryInfo'}) eq 'ecommerce') ? 'ecom_3' : '',
+#                                IndInvoice => ($content{'invoice_number'}) ? $content{'invoice_number'} : ''
+#                                },
+            ApplicationId   => $self->appid(),
+            Recurring       => ($content{'recurring_billing'} && $content{'recurring_billing'} eq 'YES' ) ? 1 : 0,
+            ReferenceNumber => ($content{'ref_num'}) ? $content{'ref_num'} : '',
+            Token           => ($content{'token'}) ? $content{'token'} : '',
+            Receipt         => ($content{'receipt'}) ? $content{'receipt'} : '',
+            TransactionDate => ($content{'txn_date'}) ? $content{'txn_date'} : ''
         }
+        # we won't be using level2 nor level3.  So I'm leaving them out for now.
     };
-    
   
     # create the list of required fields based on the action
-    my @required_fields = qw/ amount /;
+    my @required_fields = qw/ Amount /;
     if ($action eq 'charge') {
-        push(@required_fields, $_) foreach (qw/ account_number cvv exp_month exp_year /);
+        push @required_fields, $_
+          foreach (qw/ AccountNumber ExpirationMonth ExpirationYear /);
     }elsif ($action eq 'void') {
-        push(@required_fields, $_) foreach (qw/ reference_number transaction_date /);
+        push @required_fields, $_
+          foreach (qw/ ReferenceNumber /);
     }elsif ($action eq 'refund') {
-        push(@required_fields, $_) foreach (qw/ amount account_number exp_month exp_year /);
+        push @required_fields, $_
+          foreach (qw/ Amount AccountNumber ExpirationMonth ExpirationYear /);
     }
     
     # check the requirements are met.
     my @missing_fields;
     foreach my $field (@required_fields) {
-        push(@missing_fields, $field) if (!$template_vars->{payment}{$field});
+        push(@missing_fields, $field) if (!$xml_vars->{payment}{$field});
     }
     if (scalar(@missing_fields)) {
         croak "Missing required fields: ".join(', ', @missing_fields);
     }
     
-    # read in the appropriate xml template
-    my $xml_template = _get_xml_template( $action );
-    # create a template object.
-    my $tt = Template->new();
-    # populate the XML template.
+    my $process_action = $action;
+    $process_action =~ s/\b([a-z])/\u$1/g;
+    $process_action = 'Process'.$process_action;
     my $xml_data;
-    $tt->process( \$xml_template, $template_vars, \$xml_data ) || croak $tt->error();
+    my $writer = new XML::Writer( OUTPUT      => \$xml_data,
+                                  DATA_MODE   => 0,
+                                  DATA_INDENT => 0,
+                                  ENCODING    => 'utf-8',
+                                );
+    $writer->xmlDecl();
+    $writer->startTag('Request');
+    $writer->startTag('MerchantData');
+    foreach my $key ( keys ( %{$xml_vars->{auth}} ) ) {
+        $writer->dataElement( $key, $xml_vars->{auth}{$key} );
+    }
+    $writer->endTag('MerchantData');
+    $writer->startTag($payment_actions{ $self->action }{process});
+    foreach my $key ( @{$payment_actions{ $self->action }{fields}} ) {
+        next if (!$xml_vars->{payment}{$key});
+        if (ref $xml_vars->{payment}{$key} eq '') {
+            $writer->dataElement( $key, $xml_vars->{payment}{$key}); 
+        }else {
+            $writer->startTag($key);
+            foreach my $key2 (keys %{$xml_vars->{payment}{$key}}) {
+              $writer->dataElement( $key2, $xml_vars->{payment}{$key}{$key2} ); 
+            }
+            $writer->endTag($key);
+        }
+    }
+    $writer->endTag($payment_actions{ $self->action }{process});
+    $writer->endTag('Request');
+    $writer->end();
     
     warn "XML:\n$xml_data\n" if $DEBUG > 2;
     
@@ -286,18 +328,52 @@ sub submit {
     # conform to RFC standards
     $content =~ s/\n/\r\n/gs;
 
-    my ( $page, $server_response, %headers ) = $self->https_post( $opts, $content );
+    my ( $page, $server_response, %headers ) =
+      $self->https_post( $opts, $content );
   
     # store the server response.
     $self->server_response($server_response);
     # parse the result page.
     $self->parse_response($page);
+
+    if ( $self->is_success && $self->response_code == 10 ) { #partial auth
+
+      if ( $content{'partial_auth'} ) {
+
+        $self->partial_auth_amount( $self->txn_amount );
+
+      } else {
+        #XXX reverse auth if i was an auth only...
+        my $void = new Business::OnlinePayment(
+                         'vSecureProcessing',
+                         map { $_ -> $self->$_() } qw( platform appid tid )
+                   );
+
+        $void->content(
+          'action'           => 'Void',
+          'amount'           => $self->txn_amount,
+          'test_transaction' => $self->test_transaction,
+          'authorization'    => $self->authorization,
+          map { $_ => $content{$_} } qw( login password card_number expiration )
+        );
+      
+        $void->submit;
+
+        if ( !$void->is_success ) {
+          #XXX now what??? at least this is better than return is_success 0 or 1
+          die "Couldn't void partial auth";
+        } else {
+          $self->is_success(0);
+        }
+
+      }
+
+    }
     
     if (!$self->is_success() && !$self->error_message() ) {
         if ( $DEBUG ) {
-            #additional logging information, possibly too sensitive for an error msg
-            # (vSecureProcessing seems to have a failure mode where they return the full
-            #  original request including card number)
+            #additional logging information, possibly too sensitive for an error
             $self->error_message(
               "(HTTPS response: ".$server_response.") ".
               "(HTTPS headers: ".
@@ -323,237 +399,39 @@ sub parse_response {
 
     if ($self->server_response =~ /^200/) {
         my $response = XMLin($page);
+        warn "Response:\n".Dumper($response)."\n" if $DEBUG > 2;
         $self->result_code($response->{Status}); # 0 /1
         $self->response_code($response->{ResponseCode}); # see documentation for translation
-        $self->avs_response($response->{AvsResponse}); # Y / N
-        $self->cvv_response($response->{CvvResponse}); # P / F
+        $self->avs_code($response->{AvsResponse}); # Y / N
+
+        #weird (missing?) gateway responses turn into a hashref screwing up Card Fortress
+        $self->cvv2_response( $response->{CvvResponse} =~ /^\w$/
+                                ? $response->{CvvResponse}
+                                : ''
+                            );
+
         $self->txn_date($response->{TransactionDate}); # MMDDhhmmss
         $self->txn_amount($response->{TransactionAmount} / 100); # 00000003500 / 100
         $self->reference_number($response->{ReferenceNumber});
         
         $self->is_success($self->result_code() eq '0' ? 1 : 0);
         if ($self->is_success()) {
-            $self->authorization($response->{AuthIdentificationResponse});
-        }
-        # fill in error_message if there is is an error
-        if ( !$self->is_success && exists($response->{AdditionalResponseData})) {
-            $self->error_message('Error '.$response->{ResponseCode}.': '.$response->{AdditionalResponseData});
-        }elsif ( !$self->is_success && exists($response->{Receipt}) ) {
-            $self->error_message('Error '.$response->{ResponseCode}.': '.(exists($response->{Receipt})) ? $response->{Receipt} : '');
+            $self->authorization($response->{ReferenceNumber});
+        } else { # fill in error_message if there is is an error
+            $self->error_message( 'Error '.$response->{ResponseCode}.': '.
+                                    (    $response->{AdditionalResponseData}
+                                      || $response->{Receipt}
+                                      || $response->{ResultCode}
+                                    )
+                                );
         }
         
-    }else {
-        $self->is_success(0);
-        $self->error_message('Error communicating with vSecureProcessing server');
-        return;
-    }
-    
-    
-}
-
-sub _get_xml_template {
-    my $action = shift;
-    
-    my $xml_template = q|<Request >
-    <MerchantData> 
-        <Platform>[% auth.platform %]</Platform>
-        <UserId>[% auth.userid %]</UserId> 
-        <GID>[% auth.gid %]</GID>
-        <Tid>[% auth.tid %]</Tid>
-    </MerchantData>
-    |;
-    
-    if ($action eq 'charge') {
-        $xml_template .= _get_xml_template_charge();
-    }elsif($action eq 'void') {
-        $xml_template .= _get_xml_template_void();
-    }elsif($action eq 'authorize') {
-        $xml_template .= _get_xml_template_auth();
-    }elsif($action eq 'authorize_cancel') {
-        $xml_template .= _get_xml_template_auth_cancel();
-    }elsif($action eq 'refund') {
-        $xml_template .= _get_xml_template_refund();
-    }elsif($action eq 'capture') {
-        $xml_template .= _get_xml_template_capture();
-    }elsif($action eq 'create_token') {
-        $xml_template .= _get_xml_template_create_token();
-    }elsif($action eq 'delete_token') {
-        $xml_template .= _get_xml_template_delete_token();
-    }elsif($action eq 'query_token') {
-        $xml_template .= _get_xml_template_query_token();
-    }elsif($action eq 'update_exp_date') {
-        $xml_template .= _get_xml_template_update_exp_date();
-    }elsif($action eq 'update_token') {
-        $xml_template .= _get_xml_template_update_token();
-    }
-    
-    $xml_template .= "</Request>";
-    $xml_template =~ s/[\n\t\s]*//g;
-    
-    return $xml_template;
-}
-
-sub _get_xml_template_charge {
-    my $xml_template = q|<ProcessPayment>
-        <Amount>[% payment.amount %]</Amount>
-        <Trk1>[% payment.track1 %]</Trk1>
-        <Trk2>[% payment.track2 %]</Trk2>
-        <TypeOfSale>[% payment.type %]</TypeOfSale>
-        <Cf1>[% payment.cf1 %]</Cf1>
-        <Cf2>[% payment.cf2 %]</Cf2>
-        <Cf3>[% payment.cf3 %]</Cf3>
-        <AccountNumber>[% payment.account_number %]</AccountNumber>
-        <ExpirationMonth>[% payment.exp_month %]</ExpirationMonth>
-        <ExpirationYear>[% payment.exp_year %]</ExpirationYear>
-        <Cvv>[% payment.cvv %]</Cvv>
-        <CardHolderFirstName>[% payment.first_name %]</CardHolderFirstName>
-        <CardHolderLastName>[% payment.last_name %]</CardHolderLastName>
-        <AvsZip>[% payment.postal_code %]</AvsZip>
-        <AvsStreet>[% payment.street_address %]</AvsStreet>
-        <IndustryType>
-            <IndType >[% payment.industry_type %]</IndType >
-            <IndInvoice>[% payment.invoice_num %]</IndInvoice>
-        </IndustryType>
-        <ApplicationId>[% payment.appid %]</ApplicationId>
-        <Recurring>[% payment.recurring %]</Recurring>
-    </ProcessPayment>|;
-    
-    # other options (that we are not using right now):    
-#     <Level2PurchaseInfo>
-#         <Level2CardType>[% level2.card_type %]</Level2CardType >
-#         <PurchaseCode>[% level2.purchase_code %]</PurchaseCode>
-#         <ShipToCountryCode>[% level2.country_code %]</ShipToCountryCode>
-#         <ShipToPostalCode>[% level2.ship_tp_postal_code %]</ShipToPostalCode>
-#         <ShipFromPostalCode>[% level2.ship_from_postal_code %]</ShipFromPostalCode>
-#         <SalesTax>[% level2.sales_tax %]</SalesTax>
-#         <ProductDescription1>[% level2.product_description1 %]</ProductDescription1>
-#         <ProductDescription2>[% level2.product_description2 %]</ProductDescription2>
-#         <ProductDescription3>[% level2.product_description3 %]</ProductDescription3>
-#         <ProductDescription4>[% level2.product_description4 %]</ProductDescription4>
-#     </Level2PurchaseInfo>
-#     <Level3PurchaseInfo>
-#         <PurchaseOrderNumber>[% level3.purchase_order_num %]</PurchaseOrderNumber>
-#         <OrderDate>[% level3.order_date %]</OrderDate>
-#         <DutyAmount>[% level3.duty_amount %]</DutyAmount>
-#         <AlternateTaxAmount>[% level3.alt_tax_amount %]</AlternateTaxAmount>
-#         <DiscountAmount>[% level3.discount_amount %]</DiscountAmount>
-#         <FreightAmount>[% level3.freight_amount %]</FreightAmount>
-#         <TaxExemptFlag>[% level3.tax_exempt %]</TaxExemptFlag>
-#         <LineItemCount>[% level3.line_item_count %]</LineItemCount>
-#         <PurchaseItems>
-#             [% level3.purchase_items %]
-#         </PurchaseItems>
-#     </Level3PurchaseInfo>
-
-    return $xml_template;
-}
-
-sub _parse_line_items {
-    my $self = shift;
-    my %content = $self->content();
-    
-    return '' if (!$content{'items'});
-    
-    my @line_items;
-    my $template = q|            <LineItem>
-                <ItemSequenceNumber>[% seq_num %]</ItemSequenceNumber>
-                <ItemCode>[% code %]</ItemCode>
-                <ItemDescription>[% desc %]</ItemDescription>
-                <ItemQuantity>[% qty %]</ItemQuantity>
-                <ItemUnitOfMeasure>[% unit %]</ItemUnitOfMeasure>
-                <ItemUnitCost>[% unit_cost %]</ItemUnitCost>
-                <ItemAmount>[% amount %]</ItemAmount>
-                <ItemDiscountAmount>[% discount_amount %]</ItemDiscountAmount>
-                <ItemTaxAmount>[% tax_amount %]</ItemTaxAmount>
-                <ItemTaxRate>[% tax_rate %]</ItemTaxRate>
-            </LineItem>|;
-    
-    
-    my @items = $content{'items'};
-    foreach my $item (@items) {
-        # fille in the slots from $template with details in $item
-        # push to @line_items
+    } else {
+        die 'Error communicating with vSecureProcessing server (server sent response: '. $self->server_response. ')';
     }
     
-    return join("\n", @line_items);
-}
-
-sub _get_xml_template_void {
-    my $xml_template = q|<ProcessVoid>
-        <Amount>[% payment.amount %]</Amount>
-        <AccountNumber>[% payment.account_number %]</AccountNumber>
-        <ExpirationMonth>[% payment.exp_month %]</ExpirationMonth>
-        <ExpirationYear>[% payment.exp_year %]</ExpirationYear>
-        <ReferenceNumber>[% payment.reference_number %]</ReferenceNumber>
-        <TransactionDate/>
-        <IndustryType1>[% payment.industry_type %]</IndustryType1>
-        <ApplicationId>[% payment.appid %]</ApplicationId>
-    </ProcessVoid>|;
-
-    return $xml_template;
-}
-
-sub _get_xml_template_refund {
-    my $xml_template = q|<ProcessRefund>
-        <Amount>[% payment.amount %]</Amount>
-        <AccountNumber>[% payment.account_number %]</AccountNumber>
-        <ExpirationMonth>[% payment.exp_month %]</ExpirationMonth>
-        <ExpirationYear>[% payment.exp_year %]</ExpirationYear>
-        <ApplicationId>[% payment.appid %]</ApplicationId>
-    </ProcessRefund>|;
-
-    return $xml_template;
-}
-
-sub _get_xml_template_auth {
-    my $xml_template = '';
-
-    return $xml_template;
-}
-
-sub _get_xml_template_auth_cancel {
-    my $xml_template = '';
-
-    return $xml_template;
-}
-
-sub _get_xml_template_capture {
-    my $xml_template = '';
-
-    return $xml_template;
-}
-
-sub _get_xml_template_create_token {
-    my $xml_template = '';
-
-    return $xml_template;
-}
-
-sub _get_xml_template_delete_token {
-    my $xml_template = '';
-
-    return $xml_template;
-}
-
-sub _get_xml_template_query_token {
-    my $xml_template = '';
-
-    return $xml_template;
-}
-
-sub _get_xml_template_update_exp_date {
-    my $xml_template = '';
-
-    return $xml_template;
 }
 
-sub _get_xml_template_update_token {
-    my $xml_template = '';
-
-    return $xml_template;
-}
-
-
 1;
 __END__
 
@@ -566,17 +444,17 @@ Business::OnlinePayment::vSecureProcessing - vSecureProcessing backend for Busin
 
   use Business::OnlinePayment;
   my %processor_info = (
-    platform    => '####',
-    gid         => 12345678901234567890,
-    tid         => 01,
-    user_id     => '####',
-    url         => 'www.####.com'
+    platform    => 'vsecure_platform',
+    appid       => 'vsecure_appid',
+    tid         => '54', #optional, defaults to 01
   );
   my $tx =
     new Business::OnlinePayment( "vSecureProcessing", %processor_info);
   $tx->content(
-      appid          => '######',
-      type           => 'VISA',
+      login          => 'vsecure@user.id',
+      password       => '12345678901234567890', #vsecure gid
+
+      type           => 'CC',
       action         => 'Normal Authorization',
       description    => 'Business::OnlinePayment test',
       amount         => '49.95',
@@ -645,15 +523,16 @@ from content(%content):
       Amount              => 'amount'
       AvsStreet           => 'address',
       AvsZip              => 'zip',
-      Cf1                 => 'UDField1',
-      Cf2                 => 'UDField2',
+      Cf1                 => 'invoice_number',
+      Cf2                 => 'customer_id',
       IndustryType        => 'IndustryInfo',
 
 =head1 NOTE
 
 =head1 COMPATIBILITY
 
-Business::OnlinePayment::vSecureProcessing uses vSecureProcessing XML Document Version: 140901 (September 1, 2014).
+Business::OnlinePayment::vSecureProcessing uses vSecureProcessing XML Document
+Version: 140901 (September 1, 2014).
 
 See http://www.vsecureprocessing.com/ for more information.
 
@@ -661,7 +540,7 @@ See http://www.vsecureprocessing.com/ for more information.
 
 Original author: Alex Brelsfoard
 
-Current maintainer: Alex Brelsfoard
+Current maintainer: Ivan Kohler <ivan-vsecureprocessing@freeside.biz>
 
 =head1 COPYRIGHT
 
@@ -676,8 +555,9 @@ the same terms as Perl itself.
 
 Need a complete, open-source back-office and customer self-service solution?
 The Freeside software includes support for credit card and electronic check
-processing with vSecureProcessing and over 50 other gateways, invoicing, integrated
-trouble ticketing, and customer signup and self-service web interfaces.
+processing with vSecureProcessing and over 60 other gateways, invoicing,
+integrated trouble ticketing, and customer signup and self-service web
+interfaces.
 
 http://freeside.biz/freeside/
 
@@ -687,4 +567,3 @@ perl(1). L<Business::OnlinePayment>.
 
 =cut
 
-