$versions{'PayPalIPN-order_lib.pl'} = '06.6.00.0000';
#
# PayPal order library for the 'PayPal Standard with IPN' Payment Gateway
# Requires AgoraCart version 06.6.00.000 or above.
#
# Previous Contributions: Mister Ed, Andy Smith, Bonnie Scott
# Redesigned by Mister Ed at AgoraCart - September 2018 for version 6.6+
#
#####################################################################
#
# AgoraCart and all associated files, except where noted, are
# Copyright 2001 to Present jointly by K-Factor Technologies, Inc.
# and by C E Mayo (aka Mister Ed) at AgoraCart.com & K-Factor.net
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

# http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# This copyright notice may not be removed or altered in any way.
#
#######################################################################
#                    Order Form Definition Variables
#######################################################################
$sc_order_response_vars{'PayPalIPN'} = 'PayPalIPN';

add_codehook( 'printSubmitPage', 'print_PayPalIPN_SubmitPage' );
add_codehook( 'set_form_required_fields', 'PayPalIPN_fields' );
add_codehook( 'gateway_response',  'check_for_PayPalIPN_response' );
add_codehook( 'open_for_business',  'check_for_PayPalIPN_submit' );

#######################################################################
sub check_for_PayPalIPN_submit {
    if ( form_check('submit_order_form_button') ) {
        if ( $form_data{'gateway'} eq 'PayPalIPN' && $mc_mgr_gateways_enabled =~ /PayPalIPN/i ) {
            PayPalIPN_response_prep();
        }
    }
}
#######################################################################
sub PayPalIPN_check_and_load {
    local ($myname) = 'PayPalIPN';
    if ( $mc_mgr_gateways_enabled =~ /$myname/ ) {
        require_supporting_libraries( __FILE__, __LINE__, "$sc_userpay_conf_dir/$myname-user_lib.pl" );
    }
}
#######################################################################
sub check_for_PayPalIPN_response {

    if ( $ENV{'QUERY_STRING'} =~ /PayPalIPN/ && $mc_mgr_gateways_enabled =~ /PayPalIPN/i ) {
        # Read post from PayPal system and add 'cmd'
        my $query = $ENV{'QUERY_STRING'};
        $query =~ s/^\?//;
        # split posted variables into key/value pairs
        @pairs = split(/&/, $query);
        foreach $pair (@pairs) {
            ($key, $value) = split(/=/, $pair);
            $value =~ tr/+/ /;
            $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
            $form_data{$key} = $value;
        }
    }

    if ( $form_data{'cart_id'} && $form_data{'cinvoice'} && $form_data{'gateway'} =~ /PayPalIPN/ && $mc_mgr_gateways_enabled =~ /PayPalIPN/i ) {
        $cart_id = $form_data{'cart_id'};
        #set_sc_cart_path();
        PayPalIPN_check_and_load();
        codehook( 'PayPalIPN_order' );
        if ( $sc_header_printed ne 1 ) {
            &print_agora_http_headers();
        }
        if ($form_data{'ppcancel'} eq 'yes') {
            &cancel_PayPalIPN_screen();
        }
        else {
            process_PayPalIPN_Order();
        }
        exit(0);
    }

}
#######################################################################
sub PayPalIPN_response_prep {
    # use this code hooks to check for more variables / default values
    codehook('PayPalIPN_response_prep_bottom');
}
#######################################################################
sub PayPalIPN_fields {
    local ($myname) = 'PayPalIPN';

    if ( !( $form_data{'gateway'} eq $myname ) || $mc_mgr_gateways_enabled !~ /PayPalIPN/i ) { return; }

    set_order_form_array();

    @sc_order_form_required_fields = (
        'Ecom_BillTo_Postal_Name_First',    'Ecom_BillTo_Postal_Name_Last',
        'Ecom_BillTo_Postal_Street_Line1',  'Ecom_BillTo_Postal_City',
        'Ecom_BillTo_Postal_StateProv',     'Ecom_BillTo_Postal_PostalCode',
        'Ecom_BillTo_Telecom_Phone_Number', 'Ecom_BillTo_Online_Email'
    );

    # override if in donation mode
    if ( $sc_donation_mode eq 'yes' && $sc_donation_orderform_name  ) {
        @sc_order_form_required_fields = @sc_donation_form_required_fields;
    }

    if ( $sc_display_checkout_tos =~ /yes/i ) {
        push( @sc_order_form_required_fields, 'Ecom_tos' );
    }

    # use this codehook to change the above arrays for required fields and such
    codehook('PayPalIPN_fields_bottom');

}
#######################################################################
sub PayPalIPN_order_form_prep {    # load the customer info ...
    PayPalIPN_check_and_load();
    if ( $sc_PayPalIPN_form_prep == 0  && $mc_mgr_gateways_enabled =~ /PayPalIPN/i ) {
        if ( -f "$sc_verify_order_path" ) {
            read_verify_file();
        }
        else {
            codehook('load_customer_info');
        }
        $sc_PayPalIPN_form_prep = 1;
    }
    return '';
}
#######################################################################
sub PayPalIPN_table_setup {

    #
    # To use this, put this in the email_text in the manager for HTML:
    #
    #	<!--agorascript-pre
    #	  return $PayPalIPN_cart_table;
    #	-->
    #
    # or for text in an email:
    #
    #	<!--agorascript-pre
    #	  return $PayPalIPN_prod_in_cart;
    #	-->
    #

    local ( @my_cart_fields, $my_cart_row_number, $result );
    local ( $count, $price, $product_id, $quantity, $total_cost, $total_qty ) = 0;
    local ( $name, $cost );

    $PayPalIPN_prod_in_cart = q{};
    $PayPalIPN_cart_table   = q{};
    $result                = q{};

    if ( $mc_mgr_gateways_enabled !~ /PayPalIPN/i ) { return; }

    open( CART, "$sc_cart_path" ) || file_open_error(
        "$sc_cart_path", 'display_cart_contents_in_header',__FILE__, __LINE__ );
    while (<CART>) {
        $count++;
        chop;
        @my_cart_fields = split( /\|/, $_ );
        $my_cart_row_number = pop(@my_cart_fields);
        push( @my_cart_fields, $my_cart_row_number );
        $quantity   = $my_cart_fields[0];
        $product_id = $my_cart_fields[1];
        $price      = $my_cart_fields[$sc_cart_index_of_price_after_options];
        $name       = $my_cart_fields[ $cart{'name'} ];
        $name       = substr( $name, 0, 35 );
        $cost       = format_price( $quantity * $price );
        $total_cost = $total_cost + $quantity * $price;
        $total_qty  = $total_qty + $quantity;
        $options    = $my_cart_fields[ $cart{'options'} ];
        $options =~ s/<br>/ /g;

        if ( $result eq '' ) {
            $result .= '<table cellpadding=0 cellspacing=0 border=0 width=425>';
            $result .= "<tr><td>Items Ordered:</td></tr><tr><td>\n";
            $result .=
              "<table cellpadding=3 cellspacing=0 border=1 width=100%>\n";
            $result .= "<tr><th>QTY</th><th>ID #</th><th>Description</th>";
            $result .= "<th>Cost</th></tr>\n";
            $PayPalIPN_prod_in_cart .= "  --PRODUCT INFORMATION--\n\n";
        }
        $result .= "<tr><td>$quantity</td><td>$product_id</td>\n";
        $result .= "<td>$name</td><td>$cost</td>";
        $result .= '</tr>\n';
        $PayPalIPN_prod_in_cart .= cart_textinfo(*my_cart_fields);
    }    # End of while (<CART>)
    close(CART);
    if ( $result ne '' ) {
        $result .= '</table></td></tr></table>\n';
    }

    # use this to change $result
    codehook('PayPalIPN_table_setup_bottom');

    $PayPalIPN_cart_table = $result;

}
#######################################################################
sub print_PayPalIPN_SubmitPage {

    local ( $myname ) = 'PayPalIPN';
    if ( !( $form_data{'gateway'} eq $myname ) || $mc_mgr_gateways_enabled !~ /$myname/i ) { return; }

    local ( $invoice_number, $customer_number, $displayTotal );
    local ( $test_mode, $zemail_text );
    local ( $my_message, $my_desc,$my_verify_top_message );
    local ( $HREF_FIELDS ) = make_hidden_fields();
    my $PP_server_sandbox = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
    my $PP_server = 'https://www.paypal.com/cgi-bin/webscr'; # production

    &PayPalIPN_check_and_load;

    if ( $PayPalIPN_set_to_test eq 'yes' ) {
        $PP_server = $PP_server_sandbox;
    }

    if ( $PayPalIPN_submit eq '' ) {
        $PayPalIPN_submit = q{https://www.paypalobjects.com/en_US/i/btn/btn_buynowCC_LG.gif};
    }

    $invoice_number  = $current_verify_inv_no;
    $customer_number = $cart_id;
    $customer_number =~ s/_/./g;
    $my_desc    = script_and_substitute($PayPalIPN_order_name);
    $my_verify_top_message = script_and_substitute($order_ok_final_msg_tbl);
    $discounted_subtotal = format_price( $subtotal - $zfinal_discount );
    $zfinal_shipping = format_price($zfinal_shipping);
    $zfinal_sales_tax =
      $zfinal_sales_tax +
      $zfinal_extra_tax1 +
      $zfinal_extra_tax2 +
      $zfinal_extra_tax3;
    $zfinal_sales_tax = format_price($zfinal_sales_tax);
    $zfinal_buySafe   = format_price($zfinal_buySafe);
    $displayTotal = display_price($discounted_subtotal);
    $my_message = script_and_substitute($PayPalIPN_verify_message);


    if ( $PayPalIPN_username eq '' ) {
        $PayPalIPN_username = $sc_admin_email;
    }

    $my_ShipTo_Postal_Street = $form_data{'Ecom_ShipTo_Postal_Street_Line1'};
    if ( $form_data{'Ecom_ShipTo_Postal_Street_Line2'} ) {
        $my_ShipTo_Postal_Street .=  "<br>$form_data{'Ecom_ShipTo_Postal_Street_Line2'}";
    }

    if ( $form_data{'Ecom_ShipTo_Postal_Street_Line3'} ) {
        $my_ShipTo_Postal_Street .= "<br>$form_data{'Ecom_ShipTo_Postal_Street_Line3'}";
    }

    $my_BillTo_Postal_Street = $form_data{'Ecom_BillTo_Postal_Street_Line1'};
    if ( $form_data{'Ecom_BillTo_Postal_Street_Line2'} ) {
        $my_BillTo_Postal_Street .=  "<br>$form_data{'Ecom_BillTo_Postal_Street_Line2'}";
    }

    if ( $form_data{'Ecom_BillTo_Postal_Street_Line3'} ) {
        $my_BillTo_Postal_Street .= "<br>$form_data{'Ecom_BillTo_Postal_Street_Line3'}";
    }

    my $temp_URL_extend = "cart_id=$customer_number&cinvoice=$invoice_number&gateway=PayPalIPN";
    my $temp_cancel_URL_extend = '&ppcancel=yes';
    print <<ENDOFTEXT;
<form action="$PP_server" method="post">
<input type="hidden" name="cmd" value="_xclick">
<input type="hidden" name="business" value="$PayPalIPN_username">
<input type="hidden" name="notify_url" value="$PayPalIPN_order_notify_url">
<input type="hidden" name="return" value="$PayPalIPN_order_return_url$temp_URL_extend">
<input type="hidden" name="rm" value="2">
<input type="hidden" name="bn" value="AgoraCart_ShoppingCart_WPS_US">
<input type="hidden" name="cancel_return" value="$PayPalIPN_order_return_url$temp_URL_extend$temp_cancel_URL_extend">
ENDOFTEXT

        if ( $PayPalIPN_image_url ) {
            print <<ENDOFTEXT;
<input type="hidden" name="image_url" value="$PayPalIPN_image_url">
ENDOFTEXT
        }

        print <<ENDOFTEXT;
<!--Financial Data-->
<input type="hidden" name="currency_code" value="$PayPalIPN_currency_id">
<input type="hidden" name="amount" value="$discounted_subtotal">
<input type="hidden" name="shipping" value="$zfinal_shipping">
<input type="hidden" name="tax" value="$zfinal_sales_tax">
<input type="hidden" name="handling" value="$zfinal_buySafe">
<!--Cart Order Data-->
<input type="hidden" name="no_shipping" value="1">
<input type="hidden" name="custom" value="$cart_id">
<input type="hidden" name="invoice" value="$invoice_number">
<input type="hidden" name="item_name" value="$PayPalIPN_order_name: $invoice_number">
<!--Auto Populate Address-->
<input type="hidden" name="address_override" value="1">
<input type="hidden" name="first_name" value="$eform_data{'Ecom_BillTo_Postal_Name_First'}">
<input type="hidden" name="last_name" value="$eform_data{'Ecom_BillTo_Postal_Name_Last'}">
<input type="hidden" name="address1" value="$eform_data{'Ecom_BillTo_Postal_Street_Line1'}">
<input type="hidden" name="city" value="$eform_data{'Ecom_BillTo_Postal_City'}">
<input type="hidden" name="state" value="$eform_data{'Ecom_BillTo_Postal_StateProv'}">
<input type="hidden" name="zip" value="$eform_data{'Ecom_BillTo_Postal_PostalCode'}">
<input type="hidden" name="country" value="$eform_data{'Ecom_BillTo_Postal_CountryCode'}">
<input type="hidden" name="email" value="$eform_data{'Ecom_BillTo_Online_Email'}">
ENDOFTEXT

    if ( $PayPalIPN_verifytable eq '' ) {
        $PayPalIPN_verifytable = 'verifyTable_PayPalIPN.inc';
    }
    require_supporting_libraries( __FILE__, __LINE__, "$sc_cartverifyplates_dir/$PayPalIPN_verifytable" );

    print $sc_verifytable_at_checkout;
}

#######################################################################

sub cancel_PayPalIPN_screen {
    if ( $mc_mgr_gateways_enabled !~ /PayPalIPN/i ) { return; }
    # print store header
    standard_page_header();
    CheckoutStoreHeader();

    if ( $template_override_ppipn_cancel_page eq 'yes' ) {
        &codehook('ppipn_cancel_page_content');
    }
    else {
        print $sc_template_spacing_line01;
        print '<h4>' . $messages{'paypalipn_canceled'} . '<h4>';
        print $sc_template_spacing_line01;
    }

    CheckoutStoreFooter();
}

#######################################################################
# confirmation tables/displays no longer shown.
# confirmation done via emails in IPN functions.

sub process_PayPalIPN_Order {

    local ( %orderLoggingHash );
    local ( $pp_orderline_found ) = q{};
    #$sc_paypalipn_troubleshoot = 'yes'; # for dev convenience only

    if ( $mc_mgr_gateways_enabled !~ /PayPalIPN/i ) { return; }

    ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst ) = localtime(time);
    $year += 1900;
    $month = "$short_months[$mon]";

    local $logfile = $sc_ppipn_log_path . "/" . $year . '_' . $month . '_ppipn.log';


    # print store header
    standard_page_header();
    CheckoutStoreHeader();
    $sc_thankyou_page_header_title_box =~ s/\[\[verify_page_header_text\]\]/$agora_thankyou_page_title_text/g;
    $sc_thankyou_page_header_title_box =~ s/\[\[name\]\]//g;
    print $sc_thankyou_page_header_title_box;

    print "<h4$ppipn_thankyou_page_confirm_title_class>Confirming your payment ";

    my $sleep_seconds = 7;
    my $sleeper = 0;


    while ( $sleeper < $sleep_seconds ) {
        print ' . ';
        sleep(1);
        $sleeper++;
    }

    print ' Done!</h4>';

    if (-e $logfile ) {
        # check to see if previously processed.
        # <:encoding(utf8)
        open(IPNLOGCHECK, "<", "$logfile") or file_open_error("$logfile", "Opening $logfile for reading", __FILE__, __LINE__);
        while (<IPNLOGCHECK>) {
            if ( $pp_orderline_found eq '' ) {
                (
                    $cart_invoiceNumber, # $form_data{'invoice'} - cart invoice
                    $pp_cart_id, # $form_data{'custom'} -  cart id
                    $pp_txn_id,
                    $pp_child_txn_id,
                    $payment_date, # HH:MM:SS Mmm DD, YYYY PDT
                    $pp_mc_gross, # $form_data{'mc_gross'} - total of order (or adjustment/refund)
                    $pp_mc_fee,
                    $pp_memo,
                    $pp_payment_type, # $form_data{'payment_type'}
                    $pp_payment_status, # $form_data{'payment_status'}
                    $pp_pending_reason, # $form_data{'pending_reason'} - set only if payment_status is set to pending
                    $pp_reason_code,
                    $pp_echeck_time_processed,
                    $pp_exchange_rate,
                    $pp_payer_status,
                    $pp_case_id
                ) = split( /\t/, $_ );

                if ( ( $cart_invoiceNumber =~ /$form_data{'cinvoice'}/ ) && ( $pp_cart_id =~ /$form_data{'cart_id'}/ ) ) {
                    $pp_orderline_found = 1;
                }
            } # End of if ( $pp_orderline_found eq '' )
        } # End of while $file
        close(IPNLOGCHECK);
    } # End of if ( -e $logfile )

    codehook('process-order-display-thankyou-page');

    if ( $PayPalIPN_thankstable eq '' ) {
        $PayPalIPN_thankstable = 'thanksTable_PayPalIPN.inc';
    }
    require_supporting_libraries( __FILE__, __LINE__,"$sc_thankyouplates_dir/$PayPalIPN_thankstable" );

    print $sc_thankstable_after_checkout;
    print qq{<br><br>$sc_affiliate_image_call};

    CheckoutStoreFooter();

    undef %form_data;

    set_agora('AGORA_ORDER_COMPLETED', 'yes');
    agora_cookie_save();

}

#######################################################################

#######################################################################
#                       Cancel PayPalIPN Pending Order
#######################################################################
# for PP IPN Listener script

sub cancel_PayPalIPN_pending_order {

    if ( $mc_mgr_gateways_enabled !~ /PayPalIPN/i ) { return; }

    local (
        $subtotal,                $total_quantity,
        $total_measured_quantity, $text_of_cart,
        $weight,                  $required_fields_filled_in,
        $product,                 $quantity,
        $options, $temp_message_subject,   $text_of_cart_to_send
    );
    $cart_id = $form_data{'custom'};
    $cart_id =~ /^([\w\-\=\+\/]+)\.(\w+)/;
    $cart_id = "$1.$2";
    &set_sc_cart_path;
    require_supporting_libraries( __FILE__, __LINE__, "$sc_userpay_conf_dir/PayPalIPN-user_lib.pl" );
    &load_order_libs;
    &load_cart_libs;

    if ( $PayPalIPN_admin_email_cancel_template eq '' ) {
        $PayPalIPN_admin_email_cancel_template = 'admin_emailPlate_text_PP_Canceled_default01.inc';
    }
    if ( $PayPalIPN_email_cancel_template eq '' ) {
        $PayPalIPN_email_cancel_template = 'emailPlate_text_PP_Canceled_default01.inc';
    }

    my $new_file = $sc_verify_order_path;
    my $new_file2 = $sc_cart_path;
    $new_file =~ s/VERIFY/PENDING_VERIFY/;
    $new_file2 =~ s/cart/PENDING_cart/;
    if (-e "$new_file") {
        # move files back to original state.
        eval("move(\"$new_file\", \"$sc_verify_order_path\");");
        eval("move(\"$new_file2\", \"$sc_cart_path\");");
    }

    read_verify_file();
    $orderDate = get_date();
    populate_orderlogging_hash();
    $orderLoggingHash{'orderDate'}   = "$orderDate";
    $orderLoggingHash{'GatewayUsed'} = 'PayPalIPN';
    $orderLoggingHash{'cart_and_order_id'} = "$eform_cart_id";
    $orderLoggingHash{'cart_invoiceNumber'}  = "$sc_verify_inv_no";

    open( CART, "$sc_cart_path" ) || file_open_error( "$sc_cart_path", 'process_PayPalIPN_ipn_response', __FILE__,__LINE__ );
    while (<CART>) {
        $cartData++;
        @cart_fields   = split( /\|/, $_ );
        $quantity      = $cart_fields[0];
        $product_price = $cart_fields[3];
        $product       = $cart_fields[4];
        $weight        = $cart_fields[6];
        $options       = $cart_fields[ $cart{'options'} ];
        $options =~ s/<br>/ /g;
        $text_of_cart  .= cart_textinfo(*cart_fields);
        if ($sc_use_html_customer_emails =~ /yes/i)  {
            $html_of_cart .= cart_html_textinfo(*cart_fields);
        }
        $stevo_shipping_thing .= "|$quantity\*$weight";
        $stevo_shipping_names .= "|$product\($options\)";
        codehook("process-cart-item");
    }
    close(CART);

    if ( ( $sc_send_order_to_email =~ /yes/i ) ) {
        $text_of_cart_to_send = replace_email_template_tokens($PayPalIPN_admin_email_cancel_template);
        $temp_message_subject = $messages{'ordcnf_14'} . $form_data{'payment_status'};
        send_mail($sc_admin_email, $sc_order_email, $temp_message_subject, $text_of_cart_to_send);
    }

    if ( $cartData && $eform_Ecom_BillTo_Online_Email ) {
        $text_of_cart_to_send = replace_email_template_tokens($PayPalIPN_email_cancel_template);
        $temp_message_subject = $messages{'ordcnf_13'} . $form_data{'payment_status'};
        #$eform_Ecom_BillTo_Online_Email,
        send_mail(
            $sc_admin_email, $sc_admin_email,
            $temp_message_subject, "$text_of_cart_to_send"
        );
    }

    # Delete Cart and Verify files.
    eval("unlink  \"$sc_verify_order_path\";");
    eval("unlink  \"$sc_cart_path\";");

}

#######################################################################
#                       Cancel PayPalIPN Pending Order
#######################################################################
# for PP IPN Listener script

sub payPalIPN_payment_status_update {

    if ( $mc_mgr_gateways_enabled !~ /PayPalIPN/i ) { return; }

    local ( $temp_message_subject, $text_of_cart_to_send );

    require_supporting_libraries( __FILE__, __LINE__, "$sc_userpay_conf_dir/PayPalIPN-user_lib.pl" );
    &load_order_libs;

    if ( $PayPalIPN_admin_email_payment_status_update_template  eq '' ) {
        $PayPalIPN_admin_email_payment_status_update_template = 'admin_emailPlate_text_PP_Reversed_default01.inc';
    }

    $orderLoggingHash{'cart_and_order_id'} = "$form_data{'custom'}";
    $orderLoggingHash{'cart_invoiceNumber'} = "$form_data{'invoice'}";
    $orderLoggingHash{'fullName'} = "$form_data{'address_name'}";

    if ( ( $sc_send_order_to_email =~ /yes/i ) ) {
        $text_of_cart_to_send = replace_email_template_tokens($PayPalIPN_admin_email_payment_status_update_template );
        $temp_message_subject = $messages{'ordcnf_15'} . $form_data{'payment_status'};
        send_mail($sc_admin_email, $sc_order_email, $temp_message_subject, $text_of_cart_to_send);
    }

}

#######################################################################
#                       Ready to Process PayPal IPN Order
#######################################################################
# for PP IPN Listener script

sub ready_to_process_PayPalIPN_order {

    if ( $lib_process_order_ok ne 'yes' ) { return; }
    $cart_id = $form_data{'custom'};
    $cart_id =~ /^([\w\-\=\+\/]+)\.(\w+)/;
    $cart_id = "$1.$2";
    &set_sc_cart_path;
    require_supporting_libraries( __FILE__, __LINE__, "$sc_userpay_conf_dir/PayPalIPN-user_lib.pl" );
    &load_order_libs;
    &load_cart_libs;
    #codehook( 'PayPalIPN_order' );
    &process_PayPalIPN_ipn_response;

}

#######################################################################
#                       Process PayPalIPN IPN Response
#######################################################################
# for PP IPN Listener script

sub process_PayPalIPN_ipn_response {

    if ( $mc_mgr_gateways_enabled !~ /PayPalIPN/i || $lib_process_order_ok ne 'yes' ) { return; }

    local (
        $subtotal,                $total_quantity,
        $total_measured_quantity, $text_of_cart,
        $weight,                  $required_fields_filled_in,
        $product,                 $quantity,
        $options,                 $text_of_confirm_email,
        $text_of_admin_email
    );

    local ( $stevo_shipping_thing, $contentTest, $tempString, $text_of_cart_to_send ) = q{};
    local ( $stevo_shipping_names ) = q{};
    local ( $order_ok_final_msg, $order_ok_final_msg_tbl );
    local ( $ship_thing_too, $ship_instructions );
    local ( $verification ) = q{};
    local ( %zip_list );
    local ( %zip_names_list );
    my ( $ipndata, $invaliddata, $IPN_verified_form_warning, $IPN_form_string ) = q{};
    my $running_total = $form_data{'mc_gross'};
    my $new_file = $sc_verify_order_path;
    my $new_file2 = $sc_cart_path;
    my $temp_admin_email_template = $PayPalIPN_admin_email_template;
    my $temp_email_template = $PayPalIPN_email_template;

    if ( $temp_admin_email_template eq '' ) {
        $temp_admin_email_template = 'admin_emailPlate_text_default01.inc';
    }

    if ( $temp_email_template eq '' ) {
        $temp_email_template = 'emailPlate_text_default01.inc';
    }

    if ( $form_data{'payment_status'} =~ /Pending/ ) {
        $temp_email_template = 'emailPlate_text_PP_Pending_default01.inc';
        $temp_admin_email_template = 'admin_emailPlate_text_PP_Pending_default01.inc';
    }

    # move PENDING files back to _cart and _VERIFY files so we can complete the order.
    $new_file =~ s/VERIFY/PENDING_VERIFY/;
    $new_file2 =~ s/cart/PENDING_cart/;
    if (-e "$new_file") {
        # move files back to original state in non-fatal way
        eval("move('$new_file', '$sc_verify_order_path');");
        eval("move('$new_file2', '$sc_cart_path');");
    }

    codehook('process-order-routine-top');

    read_verify_file(); # reads file without deleting it

    $orderDate = get_date();

    # default data entered at cart order form converted here, if exists.
    populate_orderlogging_hash();

    $orderLoggingHash{'orderDate'}   = "$orderDate";
    $orderLoggingHash{'GatewayUsed'} = 'PayPalIPN';

    if ( $eform_cart_id ne $form_data{'custom'} ) {
        $IPN_verified_ok = 'no';
        $IPN_verified_form_warning = $agora_paypal_ipnCartidMismatch . qq{\n$agora_paypal_expected $eform_cart_id $agora_paypal_received form_data{'custom'}\n\n};
    }
    $sc_verify_grand_total = format_price($sc_verify_grand_total);
    if ( $sc_verify_grand_total ne $form_data{'mc_gross'} ) {
        $IPN_verified_ok = 'no';
        $IPN_verified_form_warning = $agora_paypal_ipnTotalMismatch . qq{\n$agora_paypal_expected $sc_verify_grand_total $agora_paypal_received $form_data{'mc_gross'}\n\n};
    }
    if ( $PayPalIPN_currency_id ne $form_data{'mc_currency'} ) {
        $IPN_verified_ok = 'no';
        $IPN_verified_form_warning = $agora_paypal_ipnCurrencyMismatch . qq{\n$agora_paypal_expected $PayPalIPN_currency_id $agora_paypal_received $form_data{'mc_currency'}\n\n};
    }
    if ( $PayPalIPN_username =~ /$form_data{'receiver_email'}|$form_data{'business'}/ ) {
        $IPN_verified_form_warning = $agora_paypal_ipnEmailMismatch . qq{\n\n};
    }
    if ( $form_data{'payer_email'} ne $eform_Ecom_BillTo_Online_Email ) {
        $IPN_verified_form_warning = $agora_paypal_ipnEmailMismatch . qq{\n\n};
    }


    if ( $IPN_verified_ok eq 'no' ) {
        $IPN_form_string = "$IPN_verified_form_warning";
    }


    # $form_data{'address_country'}
    $IPN_form_string .= <<ENDOFTEXT;

#########################################################################
PayPal HTTP_USER_AGENT:  $ENV{'HTTP_USER_AGENT'}
PayPal IP (REMOTE_ADDR): $ENV{'REMOTE_ADDR'}
Host Name (REMOTE_HOST): $ENV{'REMOTE_HOST'}

#########################################################################
PAYMENT/ORDER DETAILS: PayPal IPN vs your AgoraCart Store
#########################################################################

Cart ID passed back from PayPal:  $form_data{'custom'}  Expected by AgoraCart: $eform_cart_id
Cart Invoice passed back from PayPal:  $form_data{'invoice'}  Expected by AgoraCart: $
Item reported back from PayPal: $form_data{'item_name'}

PayPal Payment date: $form_data{'payment_date'}  AgoraCart Date:
Transaction ID reported from PayPal: $form_data{'txn_id'}
PayPal Discount Total:  $form_data{'discount'}  Expected by AgoraCart: $sc_verify_discount
PayPal Shipping Total:  $form_data{'shipping'}  Expected by AgoraCart: $sc_verify_shipping
PayPal Tax Total:  $form_data{'tax'}  Expected by AgoraCart: $$sc_verify_tax
PayPal Order Total:  $form_data{'mc_gross'}  Expected by AgoraCart: $sc_verify_grand_total
PayPal Currency Type: $form_data{'mc_currency'}  Expected by AgoraCart: $PayPalIPN_currency_id
Your PayPal Email Address passed back from PayPal: $form_data{'business'}  Expected by AgoraCart: $$PayPalIPN_username

Customer Name passed back from PayPal: $form_data{'address_name'}  Expected by AgoraCart: $$eform_Ecom_BillTo_Postal_Name_First $eform_Ecom_BillTo_Postal_Name_Last
Customer Street Address passed back from PayPal: $form_data{'address_street'}  Expected by AgoraCart: $eform_Ecom_ShipTo_Postal_Street_Line1
Customer City passed back from PayPal: $form_data{'address_city'}  Expected by AgoraCart: $eform_Ecom_ShipTo_Postal_City
Customer State passed back from PayPal: $form_data{'address_state'}  Expected by AgoraCart: $eform_Ecom_ShipTo_Postal_StateProv
Customer Postal Code (Zipcode) passed back from PayPal: $form_data{'address_zip'}  Expected by AgoraCart: $eform_Ecom_ShipTo_Postal_PostalCode
Customer Country passed back from PayPal: $form_data{'address_country_code'}  Expected by AgoraCart: $eform_Ecom_ShipTo_Postal_CountryCode

ENDOFTEXT

    if ( $sc_set_paypal_notify_script_to_test eq 'yes' ) {
        send_mail( $sc_admin_email, $sc_admin_email, 'PayPal IPN Test Submission Report', $IPN_form_string );
    }
    elsif ( $IPN_verified_ok eq 'no' ) {
        send_mail( $sc_admin_email, $sc_admin_email, 'PayPal IPN Order Processing Errors Report', $IPN_form_string );
    }

    if ( $sc_use_html_customer_emails =~ /yes/i )  {
        $html_of_cart_header = cart_html_headerinfo();
    }

    open( CART, "$sc_cart_path" ) || file_open_error( "$sc_cart_path", 'process_PayPalIPN_ipn_response', __FILE__,__LINE__ );
    while (<CART>) {
        $cartData++;
        @cart_fields   = split( /\|/, $_ );
        $quantity      = $cart_fields[0];
        $product_price = $cart_fields[3];
        $product       = $cart_fields[4];
        $weight        = $cart_fields[6];
        $options       = $cart_fields[ $cart{'options'} ];
        $options =~ s/<br>/ /g;
        $text_of_cart         .= cart_textinfo(*cart_fields);
        if ($sc_use_html_customer_emails =~ /yes/i)  {
            $html_of_cart .= cart_html_textinfo(*cart_fields);
        }
        $stevo_shipping_thing .= "|$quantity\*$weight";
        $stevo_shipping_names .= "|$product\($options\)";
        codehook("process-cart-item");
    }
    close(CART);

    PayPalIPN_response_prep();

    $sc_orderlib_use_SBW_for_ship_ins = $sc_use_SBW;

    codehook('orderlib-ship-instructions');

    if ( $sc_orderlib_use_SBW_for_ship_ins =~ /yes/i ) {
        ( $ship_thing_too, $ship_instructions ) = ship_put_in_boxes(
            $stevo_shipping_thing, $stevo_shipping_names,
            $sc_verify_Origin_ZIP, $sc_verify_boxes_max_wt
        );
    }

    $orderLoggingHash{'shippingMessages'} = "$ship_instructions";
    $orderLoggingHash{'shippingMessages'} =~ s/\n/<br>/g;
    $orderLoggingHash{'cart_and_order_id'} = "$eform_cart_id";
    $orderLoggingHash{'cart_invoiceNumber'}  = "$sc_verify_inv_no";

    codehook('process-order-pre-xcomments');

    $orderLoggingHash{'adminMessages'} .=
      "$verification<br><br>$XCOMMENTS_ADMIN";
    $orderLoggingHash{'adminMessages'} .=
        qq|\nPAYMENT INFORMATION --------------\nMETHOD: Paypal IPN $form_data{'payment_type'}\nTransaction ID: $form_data{'txn_id'}\nTransaction Fee: \$ $form_data{'mc_fee'}\nCustomer Billing Address: $form_data{'address_status'}\nPayment Status: $form_data{'payment_status'}\nPayer Status:  $form_data{'payer_status'}\nName on PayPal Account:  $form_data{'first_name'} $form_data{'last_name'}\n--------------------------------------------\n|;
    $orderLoggingHash{'xcomments'} = "$XCOMMENTS";

    $x_description = $PayPalIPN_order_name . ' - ' . $sc_verify_inv_no;
    if ( $form_data{'payment_status'} =~ /Pending/ ) {
        $x_description = $PayPalIPN_pending_order_subject_line . ': ' . $sc_verify_inv_no;
        $messages{'ordcnf_08'} .= $messages{'ordcnf_12'};
    }

    if ( ( $sc_send_order_to_email =~ /yes/i ) ) {
        $text_of_cart_to_send = replace_email_template_tokens($temp_admin_email_template);
        codehook('admin_mailtosend');
        send_mail($sc_admin_email, $sc_order_email, $x_description, $text_of_cart_to_send);
    }

    if ( $cartData && $form_data{'payer_email'} ) {
        if ($sc_use_html_customer_emails =~ /yes/i)  {
            $sc_email_content_type = 'text/html';
        }
        $xcomments_html = $orderLoggingHash{'xcomments'};
        $xcomments_html =~ s/\n/<br>/g;
        $text_of_cart_to_send = replace_email_template_tokens($temp_email_template);
        send_mail(
            $sc_admin_email, $form_data{'payer_email'},
            $messages{'ordcnf_08'}, "$text_of_cart_to_send"
        );
        if ( !( $form_data{'payer_email'} =~ /$eform_Ecom_BillTo_Online_Email/i ) ) {
            my $temp_email_title = $messages{'ordcnf_11'} . $eform_Ecom_BillTo_Online_Email;
            send_mail(
                $sc_admin_email, $eform_Ecom_BillTo_Online_Email,
                $temp_email_title, "$text_of_cart_to_send"
            );
        }
    }

    $orderLoggingHash{'adminMessages'} =~ s/\n/<br>/g;
    $orderLoggingHash{'adminMessages'} =~ s/\t/ /g;
    $orderLoggingHash{'xcomments'}     =~ s/\n/<br>/g;
    $orderLoggingHash{'adminMessages'} =~ s/\t/ /g;

    if ( $form_data{'payment_status'} =~ /Pending/ ) {
        # move _cart and _VERIFY files so they are not erased/removed (by cart automation) during pending period, in non-fatal way.
        eval("move('$sc_verify_order_path', '$new_file');");
        if ($@) {
            send_mail($sc_admin_email, $sc_admin_email, 'file move error', "$@");
        }
        eval("move('$sc_cart_path', '$new_file2');");
        if ($@) {
            send_mail($sc_admin_email, $sc_admin_email, 'file move error', "$@");
        }

    }
    else {
        log_order( $sc_verify_inv_no, $eform_cart_id );
        eval("unlink  \"$sc_verify_order_path\";");
        eval("unlink  \"$sc_cart_path\";");
    }

    # free up memory & for additional security, just in case
    undef %orderLoggingHash;
    undef %zip_list;
    undef %zip_names_list;

}
#######################################################################
1;
