Jump to content
Mark Evans

Official PayPal IPN Support Thread

Recommended Posts

Hello,

 

I reverted back to original IPN in RC1 package and I get the radial button to show in payment. If I upgrade to any other version, like 2.3.3 and the radial button disappears? Is it okay to use the version that came with MS2.2 RC1? I would like to upgrade and figure the problem. Any guidance what would cause the issue. I did check as mentioned above, Zones=none.

 

Thanks JR

Share this post


Link to post
Share on other sites
Hi all! I have been working on this problem and still can't get this to work properly. The transaction goes through, but I get this error (and so does the client)

 

Fatal error: Cannot redeclare class ot_subtotal in /home/.../includes/modules/order_total/ot_subtotal.php on line 13

 

Subsequently they do not get notified & get that error. Has anyone else run into this? Its driving me nuts!

 

OK, I don't know if anybody (besides me) is getting the above error AFTER changing:

 

include(DIR_WS_CLASSES . 'order_total.php');

 

to

 

require_once(DIR_WS_CLASSES . 'order_total.php');

 

to avoid the "Fatal error: Cannot redeclare class ot_subtotal in /home/.../includes/classes/order_total.php" in PayPal IPN v1.4

 

However, I tracked down the problem... it is in catalog/includes/classes/order_total.php

 

Find this:

 

		  include(DIR_WS_LANGUAGES . $language . '/modules/order_total/' . $value);
	  include(DIR_WS_MODULES . 'order_total/' . $value);

 

Change to:

 

		  require_once(DIR_WS_LANGUAGES . $language . '/modules/order_total/' . $value);
	  require_once(DIR_WS_MODULES . 'order_total/' . $value);

 

Now, the emails send, the order is recorded, etc... HOWEVER, the order status will not change from "Preparing [Paypal IPN]" to "Pending" anymore...

 

Any thoughts out there in the community?

 

Scott

Share this post


Link to post
Share on other sites

Hi all,

 

Great mod, works as expected brilliant!

 

If somebody creates an order and goes through to the paypal page, then changes their mind(for whatever reason) and clicks the 'return to store' button before making a payment, the order is set to 'preparing' which is absolutely fine. If they log off the shop/timeout or whatever then their order is left at 'preparing'. Brilliant! we have an order that is waiting payment.

 

What I want to do is to be able to allow them to pay for this order when they next login to the shop. I've got some code that seems to be working in account_history.php. I'm not a php coder and this isn't proper coding(embedded string literals, etc) but it's doing the job nicely and I might tidy it up later.

 

// Hardcoded index check, 106 is our paypal status of 'Preparing [PayPal IPN]
if ( (int)$history['orders_status']==106 ) { 
 require(DIR_WS_CLASSES . 'payment.php');
 $payment_modules = new payment('paypal_ipn']);

 require(DIR_WS_CLASSES . 'order.php');
 $order = new order($history['order_id']);

 if (is_array($payment_modules->modules)) {
   $payment_modules->pre_confirmation_check();
 }

 require(DIR_WS_CLASSES . 'shipping.php');
 $shipping_modules = new shipping($shipping);

 require(DIR_WS_CLASSES . 'order_total.php');
 $order_total_modules = new order_total;
 $order_totals = $order_total_modules->process();

 $payment_modules->update_status();
 $payment_modules->confirmation();

//if (isset($$payment->form_action_url)) {
   $form_action_url = $$payment->form_action_url;
//} else {
//	$form_action_url = tep_href_link(FILENAME_CHECKOUT_PROCESS, '', 'SSL');
//}

echo tep_draw_form('checkout_confirmation', $form_action_url, 'post');
echo $payment_modules->process_button();
echo "<br />Pay for this order by ";
echo tep_image_submit('PayPal_mark_37x23.gif', 'Pay for this order');
echo "</form>";
}

 

This seems to work ok if the user goes to account_history, but when I drop the following similar code into account_history_info.php it doesn't work.

 

if ( $order->info['orders_status_id']==106 ) {
 require(DIR_WS_CLASSES . 'payment.php');
 $payment_modules = new payment('paypal_ipn');

 // Order is already setup at top of this code about line 37.
 //require(DIR_WS_CLASSES . 'order.php');
 //$order = new order($HTTP_GET_VARS['order_id']);

 if (is_array($payment_modules->modules)) {
   $payment_modules->pre_confirmation_check(); 
 }

 require(DIR_WS_CLASSES . 'shipping.php');
 $shipping_modules = new shipping($shipping);

 //require(DIR_WS_CLASSES . 'order_total.php');
 //$order_total_modules = new order_total;
 //$order_totals = $order_total_modules->process();

 $payment_modules->update_status();
 $payment_modules->confirmation();
 //if (isset($$payment->form_action_url)) {
   $form_action_url = $$payment->form_action_url;
 //} else {
 //	$form_action_url = tep_href_link(FILENAME_CHECKOUT_PROCESS, '', 'SSL');
 //}

 echo tep_draw_form('checkout_confirmation', $form_action_url, 'post');
 echo $payment_modules->process_button();
 echo "Pay for this order by ";
 echo tep_image_submit('PayPal_mark_37x23.gif', 'Pay for this order');
 echo "</form>";
}

 

The hidden paypal form fields for the totals are 0.00 <input type="hidden" name="amount" value="0.00">, the values aren't calculated. It doesn't matter if I uncomment out the code around $order_total_modules->process(); or not.

 

Anybody know why and how to fix?

 

This would be well worthy of adding to the mod 'cos there is no way of making the payment if a customer doesn't pay the 1st time they checkout.

 

thx in advance.

Edited by TechnoBuddhist

Share this post


Link to post
Share on other sites

The ability to pay for the temporary order from osc would have been nice to have, but I have a neater solution.

 

If the customer cancels the payment whilst on the paypal site using the 'cancel and return to store' link I just delete the temporary order.

 

3 files to change;

 

includes/functions/general.php

at the end of the file add

// START DELETE TEMP PAYPAL IPN ORDER
// This is used in shopping_cart.php when a temporary order needs to be deleted 
// after it was cancelled by customer on paypal site.
 function tep_remove_order($order_id, $restock = false) {
   if ($restock == 'on') {
     $order_query = tep_db_query("select products_id, products_quantity from " . TABLE_ORDERS_PRODUCTS . " where orders_id = '" . (int)$order_id . "'");
     while ($order = tep_db_fetch_array($order_query)) {
       tep_db_query("update " . TABLE_PRODUCTS . " set products_quantity = products_quantity + " . $order['products_quantity'] . ", products_ordered = products_ordered - " . $order['products_quantity'] . " where products_id = '" . (int)$order['products_id'] . "'");
     }
   }

   tep_db_query("delete from " . TABLE_ORDERS . " where orders_id = '" . (int)$order_id . "'");
   tep_db_query("delete from " . TABLE_ORDERS_PRODUCTS . " where orders_id = '" . (int)$order_id . "'");
   tep_db_query("delete from " . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . " where orders_id = '" . (int)$order_id . "'");
   tep_db_query("delete from " . TABLE_ORDERS_STATUS_HISTORY . " where orders_id = '" . (int)$order_id . "'");
   tep_db_query("delete from " . TABLE_ORDERS_TOTAL . " where orders_id = '" . (int)$order_id . "'");
 }	
// END DELETE TEMP PAYPAL IPN ORDER

Note - function tep_remove_order is copied from functions.php in admin.

 

 

includes/modules/payment/paypal_ipn.php

replace $parameters['cancel_return'] = tep_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL');

//$parameters['cancel_return'] = tep_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL');
$parameters['cancel_return'] = tep_href_link(FILENAME_SHOPPING_CART, 'ipn=cancel_ipn&order='.$parameters['invoice'], 'SSL');

shopping_cart.php

 

after line

$breadcrumb->add(NAVBAR_TITLE, tep_href_link(FILENAME_SHOPPING_CART));

   // START DELETE PAYPAL TEMP ORDER
   // Check to see if customer has cancelled a paypal_ipn process
if ( $HTTP_GET_VARS['ipn']== 'cancel_ipn' && tep_not_null($HTTP_GET_VARS['order']) )  {
	// Make sure that this order is THIS customers' order
	// We don't want anybody to pass order numbers to here and delete other people's orders!!!!
	$delete_order_query = tep_db_query("SELECT customers_id FROM " . TABLE_ORDERS . " WHERE `orders_id`='" . (int)$HTTP_GET_VARS['order'] . "'");
   $delete_order = tep_db_fetch_array($delete_order_query);

//echo "DEBUG - delete_order=".$delete_order['customers_id']."<br />";
//echo "DEBUG - customer id in session=".$customer_id."<br />";
	if ( $delete_order['customers_id']==$customer_id ) {
		// Delete the order
//echo "DEBUG - about to delete order!!!<br />";
		tep_remove_order($HTTP_GET_VARS['order'], '');
	}
}
// END DELETE PAYPAL TEMP ORDER

 

SECURITY QUESTION??

I have added checks here to make sure that the order that is being deleted belongs to the customer who is logged in. We don't want people to be able to delete all the orders from the database by simply changing the order number!! I'm not an OSC developer, so I'm not sure if this check is 100% effective, can anybody please comment?

Edited by TechnoBuddhist

Share this post


Link to post
Share on other sites

Should i upgrade? I am using paypal ipn 2.3.3

I was getting some problems when customer gets to paypal it says that the transaction couldnt go through or something. I contacted PP and they seem to have fixed it.

 

 

Also - how can i change to a different paypal account without my OLD customers suddenly getting a notification in their inbox.

 

I changed PP accounts a while ago and customers who ordered weeks before suddenly got an email from my site saying their order was updated!

Share this post


Link to post
Share on other sites

Ive just updated to the latest ipn 2.3.4.5

 

When customers complete paypal order they are taken back to

 

checkout_payment.php

 

when they should be taken to checkout process?

 

 

Any ideas please?

Share this post


Link to post
Share on other sites
Ive just updated to the latest ipn 2.3.4.5

 

When customers complete paypal order they are taken back to

 

checkout_payment.php

 

when they should be taken to checkout process?

 

 

Any ideas please?

 

this is normally set in your actual PayPal account under Profile->Website Payment Preferences - choose AutoReturn and put in the url http://www.your-website.com/checkout_process.php

 

check that first.

 

Scott

Share this post


Link to post
Share on other sites

I have two questions about PayPal IPN.

 

1. I'm inclined to use "Per Item" mode instead of "Aggregate" because item descriptions, quantities and amounts are nicely displayed on the PayPal site when the customer checks out. However, the manual recommends using Aggregate mode due to potential problems with other add-ons. How strongly is using "Per Item" mode discouraged? What kind of problems should(could) I expect?

 

2. I see that the order acknowledgement email contains limited information (order number, link to invoice and date ordered). Is there a contribution that will allow me to add more information, such as product name(s), sub-total, shipping charge, and total amount?

 

Thanks,

 

Susan

Share this post


Link to post
Share on other sites

Hi there

Have been using PayPal_IPN_v2.3.4.5 no problems on 2.2RC2. Was using it per item and shipping was calculating correctly. Now all shows ok until reaching paypals page where option is to pay via paypal or credit/bank account. The shipping has doubled for some reason. Now if I select 2 of the same items and not mix my order in the store the shipping shows correct. Only seems to happen when choosing different items in shopping cart. When used on aggreagate shipping shows ok as it should but obviously this way shows no details of the order on the paypal side when about to pay. Has this been reported by anyone else. If so what might the fix be if there is one. Thanks

 

Site WWW.anniedays.2ya.com

Edited by markhere

Share this post


Link to post
Share on other sites
I'm using osCommerce 2.2-MS2 and Paypal IPN module v 2.1.0.0 13/01/2007.

 

The Paypal IPN module functions properly on everything, BUT, after a client checks out, the Admin is not emailed the invoice. On all other payment modules the Admin gets a copy of the invoice emailed to them.

 

What must I do to resolve this, so that the Admin gets a copy of the invoice emailed to them after the client completes a transaction?

 

Thank you,

 

Jay Hasman

 

I have this same issue. Also the customer is getting an email saying items have shipped even though I have not done so

Share this post


Link to post
Share on other sites

Good aftrenoon, everybody

 

I did a lot a searching in ths forum, but did not find the solution.

 

Problem is, that customers receive the email-notofication in the correct language, but the address-format as well as the date-format ist always UK-style.

 

Example:

Bestelldatum: Wednesday 11 February, 2009

should be:

Bestelldatum: Mittwoch, 11. Februar 2009

and:

Name Lastname

Street 24

Winterthur, CH-8406

Zürich, S

should be:

Name Lastname

Street 24

Winterthur, CH-8406

ZH, Switzerland

How do I have to change the code, that the country of the customer is used for formatting address and date automatically the correct way??

 

Also there is a blank line between every line of text.

 

Example:

Artikel

 

------------------------------------------------------

 

1 x Aufkleber 400x70mm (MEST-400) = 0.05CHF

 

------------------------------------------------------

 

Zwischensumme: 0.05CHF

 

Versandkosten nach Zonen (Versand nach: CH : 0.52 kg): 0.00CHF

 

MwSt 7.6%: 0.00CHF

 

Summe: 0.05CHF

This is not the case with the normal notification if another payment methos is chosen.

 

Thank you for your help and best regards

David

Share this post


Link to post
Share on other sites

Hello

 

I have the strange thing that the confirmation email product details' currency the standard is. Example someone chooses euro, subtotal and total are shown euro but the pruducts' prices itself in CHF :) anyone can help?

 

here an example :

 

Produits:

------------------------------------------------------

1 x IPod Nano Cover (443037) = 29.90 CHF

Auf Lager

------------------------------------------------------

Sous-Total: 19.15 EUR

Envoi Poste: 3.80 EUR

Total: 23.94 EUR

 

by the way, i implemented the stock status in the confirmation mail the status is not translated

Share this post


Link to post
Share on other sites
I had the problem where most of the orders were not marked OK, email was not sent and stock was not updated. I added the fixed file AlexStudio posted few pages back and now the module is working!

 

My new problem is this:

- someone orders the last product in stock and the "Allow Checkout" is set to false.

- after successful order and payment the customer is returned to shopping_cart.php instead of checkout_confirmation.php

- at the shopping_cart.php the red message appears on the bottom saying that the item selected is not available in the desired quantity etc.

 

Has anyone else had this problem or do you know where it could be fixed?

 

If there a fix for this yet?

Share this post


Link to post
Share on other sites

Share this post


Link to post
Share on other sites

This may have been answered (I've had a scan through some of the last 195 pages but can't see it!) but...

 

I am running Paypal IPN. I'm not overly familiar with OSC, had someone else put it together for me. The issue we have relates to the comments field.

 

When a customer enters comments in the comments field, they get appended to the 'preparing' entry. But once the IPN has been approved it is the second entry that is forwarded to the email address for processing. The only comments that get forwarded on are that the Paypal IPN has been verified, any customer entered comments are stripped off.

 

Is there any way to retain customer entered comments?

Share this post


Link to post
Share on other sites

Hello @ all,

 

I have installed the newest version: PayPal-IPN 2.3.4.6

 

Everything works fine but I have one problem - the prices and shippingcosts wouldn't be send to PayPal.

So in the PayPal-card is only shown which products a costumer want to buy but no prices, shippingcosts and also no total amount.

 

On the top of the card is standing: "please enter the price and update card"

 

I didn't get any error.

 

Has someone an idea how to solf this problem.

 

Thanks

 

 

P.S: Excuse my bad English, but it isn't my motherlanguage

Share this post


Link to post
Share on other sites
Hi there

Have been using PayPal_IPN_v2.3.4.5 no problems on 2.2RC2. Was using it per item and shipping was calculating correctly. Now all shows ok until reaching paypals page where option is to pay via paypal or credit/bank account. The shipping has doubled for some reason. Now if I select 2 of the same items and not mix my order in the store the shipping shows correct. Only seems to happen when choosing different items in shopping cart. When used on aggreagate shipping shows ok as it should but obviously this way shows no details of the order on the paypal side when about to pay. Has this been reported by anyone else. If so what might the fix be if there is one. Thanks

 

Site WWW.anniedays.2ya.com

Think i fixed it. Now total is being calculated correct. "Per item" AND "move tax to total" are completely working in newer versions. next uploader please remove the admin warning ;)

 

fix to your problem:

includes/modules/payment/paypal_ipn.php

line ~330

$virtual_items = 1;

this must be set to 0 like in older versions and then it works fine. someone changed this for some reason in this newer versions and this caused this trouble. have tested several ways and didn't get any errors

Share this post


Link to post
Share on other sites

Hi guys,

 

 

Our orders just suddenly stopped working, we have not changed anything on the site for ages so not sure whats caused it. Basically now when a customer hits the 'confirm' button, they are taken to the paypal site and instead of getting a order page, it just takes them to the home page https://www.paypal.com/cgi-bin/webscr which is a bit weird.

 

I got an IPN invalid process email which is essentially blank

$_POST:

 

 

$_GET:

 

Any pointers on what might be causing this? Im digging at the moment but not coming up with much, have upgraded to latest version, but its a weird thing to just stop.

 

Interestingly the last 3 orders through paypal (we dont do many due to the nature of product, its mainly pickup and cheque).

Last one on 27th Feb, went through fine.

18th feb, registered as 'Awaiting Paypal Clearance' and nothing after that, no return to site or IPN confirmation

12 Jan, went through fine.

 

This is very strange.


Feel free to ask me for help

beep... beep....My Pager

Share this post


Link to post
Share on other sites

This only occurs when there is a "Special" item in the shopping cart.

 

Anyone shed some light on this problem?

Has anyone had experience with this error. Is there a fix available?

 

"The totals of the cart item amounts do not match order amounts."

 

In function: before_process()

Response from PayPal:

 

[security] = N/A

[RequesterCredentials]

[0]

[Credentials]

[0]

[username] = N/A

[Password] = N/A

[subject] = N/A

 

[DoExpressCheckoutPaymentResponse]

[0]

[Timestamp] = 2008-09-14T06:24:15Z

[Ack] = FailureWithWarning

[CorrelationID] = 2fd540f051c55

[Errors]

[0]

[shortMessage] = Invalid Data

[LongMessage] = Handling total is invalid.

[ErrorCode] = 10428

[severityCode] = Error

 

[1]

[shortMessage] = Transaction refused because of an invalid argument. See additional error messages for details.

[LongMessage] = The totals of the cart item amounts do not match order amounts.

[ErrorCode] = 10413

[severityCode] = Warning

 

[Version] = 2.0

[build] = 690663

[DoExpressCheckoutPaymentResponseDetails]

[0]

[PaymentInfo]

[0]

[TransactionType] = none

[PaymentType] = none

[PaymentStatus] = None

[PendingReason] = none

[ReasonCode] = none

 

From this request: (WARNING!!) DO NOT expose your API Username/Password to the public!!

 

[?xml version="1.0" encoding="utf-8"?]

[soap:Envelope xmlns:soap=http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema]

[soap:Header]

[RequesterCredentials xmlns=urn:ebay:api:PayPalAPI]

[Credentials xmlns=urn:ebay:apis:eBLBaseComponents]

[username]snipped[/username]

[Password]snipped[/Password]

[/Credentials]

[/RequesterCredentials]

[/soap:Header]

[soap:Body]

[DoExpressCheckoutPaymentReq xmlns=urn:ebay:api:PayPalAPI]

[DoExpressCheckoutPaymentRequest]

[Version xmlns=urn:ebay:apis:eBLBaseComponents]2.0[/Version]

[DoExpressCheckoutPaymentRequestDetails xmlns=urn:ebay:apis:eBLBaseComponents]

[PaymentAction]Sale[/PaymentAction]

[Token]snipped[/Token]

[PayerID]snipped[/PayerID]

[PaymentDetails]

[OrderTotal currencyID=USD]111.09[/OrderTotal]

[OrderDescription]Order placed on September 14, 2008, 1:22 am snipped[/OrderDescription]

[itemTotal currencyID=USD]106.4[/itemTotal]

[shippingTotal currencyID=USD]4.8[/shippingTotal]

 

[HandlingTotal currencyID=USD]-0.11[/HandlingTotal]

 

[TaxTotal currencyID=USD]0[/TaxTotal]

[NotifyURL]https://snipped paypal_ec/ipn.php?language=english[/NotifyURL]

[Custom]Phone: -- Email:snipped[/Custom]

[shipToAddress]

[Name][/Name]

[street1][/street1]

[street2][/street2]

[CityName][/CityName]

[stateOrProvince][/stateOrProvince]

[PostalCode][/PostalCode]

[Country][/Country]

[/shipToAddress]

[snipped]

[/PaymentDetails]

[/DoExpressCheckoutPaymentRequestDetails]

[/DoExpressCheckoutPaymentRequest]

[/DoExpressCheckoutPaymentReq]

[/soap:Body]

[/soap:Envelope]

Share this post


Link to post
Share on other sites
I would love help added this. I'm using the Quantity Discount module (order total module) and it's not sending to PayPal. I have no problem getting down and dirty in code but I just can't figure out where it should go? (How to manually install the code to make sure the discount gets sent to PayPal.

 

Any help would be much appreciated... also I'm looking for a good programmer to do a few simple things like this for me (a paying gig!)

 

Thanks,

Steve

steve [at] askmedia [dot] net

 

I'm using 'discount_quant_v1' and was having the same problem. Changed the sort order in Admin/Modules/Order Total and IPN Transaction Type to Aggregate. My Sub-Total sort order was 1 and discount contrib was 2. Changed discount contrib to sort order 1 and Sub-total to sort order 2. The correct order total now shows up on PayPal. This does not work unless the IPN Transaction Type is set to Aggregate.

Share this post


Link to post
Share on other sites

hey every one,

 

this is a intergration of mvs(multi vendor shipping) and paypal ipn v2.3.4.6

this is modified from on of the lads on the forum that did most of the work im trying to jump start this for the community as there are loads of posts on the forum everywhere for this so

this is what we have so far it does'nt load the order into vendor orders and it does'nt clear the cart after processing the order through paypal which I have read may be normal

I'm not sure about the email bit yet( to be tested)

 

/includes/modules/payment/paypal_ipn.php

<?php
/*
  $Id: paypal_ipn.php,v 2.3.3.0 11/17/2007 11:15:28 alexstudio Exp $

  Copyright (c) 2004 osCommerce
  Released under the GNU General Public License
  
  Original Authors: Harald Ponce de Leon, Mark Evans 
  Updates by PandA.nl, Navyhost, Zoeticlight, David, gravyface, AlexStudio, windfjf and Terra
  v2.3 Updated by AlexStudio
    
*/

  class paypal_ipn {
    var $code, $title, $description, $enabled, $identifier;

// class constructor
    function paypal_ipn() {
      global $order;

      $this->code = 'paypal_ipn';
      $this->title = MODULE_PAYMENT_PAYPAL_IPN_TEXT_TITLE;
      $this->description = MODULE_PAYMENT_PAYPAL_IPN_TEXT_DESCRIPTION;
      $this->sort_order = MODULE_PAYMENT_PAYPAL_IPN_SORT_ORDER;
      $this->enabled = ((MODULE_PAYMENT_PAYPAL_IPN_STATUS == 'True') ? true : false);
      $this->email_footer = MODULE_PAYMENT_PAYPAL_IPN_TEXT_EMAIL_FOOTER;
      $this->identifier = 'osCommerce PayPal IPN v2.3.3';
      // BOF Additional show text added by AlexStudio
      $this->show = MODULE_PAYMENT_PAYPAL_IPN_TEXT_SELECTION;
      $this->last_confirm = MODULE_PAYMENT_PAYPAL_IPN_TEXT_LAST_CONFIRM;
      // EOF Additional show text added by AlexStudio

      if ((int)MODULE_PAYMENT_PAYPAL_IPN_PREPARE_ORDER_STATUS_ID > 0) {
        $this->order_status = MODULE_PAYMENT_PAYPAL_IPN_PREPARE_ORDER_STATUS_ID;
      }

      if (is_object($order)) $this->update_status();

      if (MODULE_PAYMENT_PAYPAL_IPN_GATEWAY_SERVER == 'Live') {
        $this->form_action_url = 'https://www.paypal.com/cgi-bin/webscr';
      } else {
        $this->form_action_url = 'https://www.sandbox.paypal.com/cgi-bin/webscr';
      }
    }

// class methods
    function update_status() {
      global $order;

      if ( ($this->enabled == true) && ((int)MODULE_PAYMENT_PAYPAL_IPN_ZONE > 0) ) {
        $check_flag = false;
        $check_query = tep_db_query("select zone_id from " . TABLE_ZONES_TO_GEO_ZONES . " where geo_zone_id = '" . MODULE_PAYMENT_PAYPAL_IPN_ZONE . "' and zone_country_id = '" . $order->billing['country']['id'] . "' order by zone_id");
        while ($check = tep_db_fetch_array($check_query)) {
          if ($check['zone_id'] < 1) {
            $check_flag = true;
            break;
          } elseif ($check['zone_id'] == $order->billing['zone_id']) {
            $check_flag = true;
            break;
          }
        }

        if ($check_flag == false) {
          $this->enabled = false;
        }
      }
    }

    function javascript_validation() {
      return false;
    }

    function selection() {
      return array('id' => $this->code,
                   // BOF Additional show text addedby AlexStudio
                   'module' => $this->show);
                   // EOF Additional show text added by AlexStudio
    }

    function pre_confirmation_check() {
      return false;
    }

    function confirmation() {
      global $cartID, $cart_PayPal_IPN_ID, $customer_id, $languages_id, $order, $order_total_modules;

     // if (tep_session_is_registered('cartID')) {
     // PandA.nl: register_globals fix
     if (array_key_exists('cartID', $_SESSION)) {
        $insert_order = false;

        if (tep_session_is_registered('cart_PayPal_IPN_ID')) {
          $order_id = substr($cart_PayPal_IPN_ID, strpos($cart_PayPal_IPN_ID, '-')+1);

          $curr_check = tep_db_query("select currency from " . TABLE_ORDERS . " where orders_id = '" . (int)$order_id . "'");
          $curr = tep_db_fetch_array($curr_check);

           //if ( ($curr['currency'] != $order->info['currency']) || ($cartID != substr($cart_PayPal_IPN_ID, 0, strlen($cartID))) ) {
            //$check_query = tep_db_query('select orders_id from ' . TABLE_ORDERS_STATUS_HISTORY . ' where orders_id = "' . (int)$order_id . '" limit 1'); 
            $check_query = tep_db_query('select orders_id from ' . TABLE_ORDERS_STATUS_HISTORY . ' where orders_id = "' . (int)$order_id . '" limit 2');  //1.4
            $update_order = false;//1.4
            
            //if (tep_db_num_rows($check_query) < 1) {
              //tep_db_query('delete from ' . TABLE_ORDERS . ' where orders_id = "' . (int)$order_id . '"');
            if (tep_db_num_rows($check_query) == 1) { //1.4
              $update_order = true; //1.4
              tep_db_query('delete from ' . TABLE_ORDERS_TOTAL . ' where orders_id = "' . (int)$order_id . '"');
              tep_db_query('delete from ' . TABLE_ORDERS_STATUS_HISTORY . ' where orders_id = "' . (int)$order_id . '"');
              tep_db_query('delete from ' . TABLE_ORDERS_PRODUCTS . ' where orders_id = "' . (int)$order_id . '"');
              tep_db_query('delete from ' . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . ' where orders_id = "' . (int)$order_id . '"');
              tep_db_query('delete from ' . TABLE_ORDERS_PRODUCTS_DOWNLOAD . ' where orders_id = "' . (int)$order_id . '"');
            }

            $insert_order = true;
          //}    
        } else {
          $insert_order = true;
        }

        if ($insert_order == true) {
          $order_totals = array();
          if (is_array($order_total_modules->modules)) {
            reset($order_total_modules->modules);
            while (list(, $value) = each($order_total_modules->modules)) {
              $class = substr($value, 0, strrpos($value, '.'));
              if ($GLOBALS[$class]->enabled) {
                for ($i=0, $n=sizeof($GLOBALS[$class]->output); $i<$n; $i++) {
                  if (tep_not_null($GLOBALS[$class]->output[$i]['title']) && tep_not_null($GLOBALS[$class]->output[$i]['text'])) {
                    $order_totals[] = array('code' => $GLOBALS[$class]->code,
                                            'title' => $GLOBALS[$class]->output[$i]['title'],
                                            'text' => $GLOBALS[$class]->output[$i]['text'],
                                            'value' => $GLOBALS[$class]->output[$i]['value'],
                                            'sort_order' => $GLOBALS[$class]->sort_order);
                  }
                }
              }
            }
          }

          $sql_data_array = array('customers_id' => $customer_id,
                                  'customers_name' => $order->customer['firstname'] . ' ' . $order->customer['lastname'],
                                  'customers_company' => $order->customer['company'],
                                  'customers_street_address' => $order->customer['street_address'],
                                  'customers_suburb' => $order->customer['suburb'],
                                  'customers_city' => $order->customer['city'],
                                  'customers_postcode' => $order->customer['postcode'],
                                  'customers_state' => $order->customer['state'],
                                  'customers_country' => $order->customer['country']['title'],
                                  'customers_telephone' => $order->customer['telephone'],
                                  'customers_email_address' => $order->customer['email_address'],
                                  'customers_address_format_id' => $order->customer['format_id'],
                                  'delivery_name' => $order->delivery['firstname'] . ' ' . $order->delivery['lastname'],
                                  'delivery_company' => $order->delivery['company'],
                                  'delivery_street_address' => $order->delivery['street_address'],
                                  'delivery_suburb' => $order->delivery['suburb'],
                                  'delivery_city' => $order->delivery['city'],
                                  'delivery_postcode' => $order->delivery['postcode'],
                                  'delivery_state' => $order->delivery['state'],
                                  'delivery_country' => $order->delivery['country']['title'],
                                  'delivery_address_format_id' => $order->delivery['format_id'],
                                  'billing_name' => $order->billing['firstname'] . ' ' . $order->billing['lastname'],
                                  'billing_company' => $order->billing['company'],
                                  'billing_street_address' => $order->billing['street_address'],
                                  'billing_suburb' => $order->billing['suburb'],
                                  'billing_city' => $order->billing['city'],
                                  'billing_postcode' => $order->billing['postcode'],
                                  'billing_state' => $order->billing['state'],
                                  'billing_country' => $order->billing['country']['title'],
                                  'billing_address_format_id' => $order->billing['format_id'],
                                  'payment_method' => $order->info['payment_method'],
                                  'cc_type' => $order->info['cc_type'],
                                  'cc_owner' => $order->info['cc_owner'],
                                  'cc_number' => $order->info['cc_number'],
                                  'cc_expires' => $order->info['cc_expires'],
                                  'date_purchased' => 'now()',
                                  'orders_status' => $order->info['order_status'],
                                  'currency' => $order->info['currency'],
                                  'currency_value' => $order->info['currency_value']);

          //+1.4
          if ( $update_order ){  
            tep_db_perform(TABLE_ORDERS, $sql_data_array, 'update', 'orders_id = "' . (int)$order_id . '"');
            $insert_id = (int)$order_id;
          } else { 
          //-1.4
          tep_db_perform(TABLE_ORDERS, $sql_data_array);

          $insert_id = tep_db_insert_id();
          }//1.4

          for ($i=0, $n=sizeof($order_totals); $i<$n; $i++) {
            $sql_data_array = array('orders_id' => $insert_id,
                                    'title' => $order_totals[$i]['title'],
                                    'text' => $order_totals[$i]['text'],
                                    'value' => $order_totals[$i]['value'],
                                    'class' => $order_totals[$i]['code'],
                                    'sort_order' => $order_totals[$i]['sort_order']);

            tep_db_perform(TABLE_ORDERS_TOTAL, $sql_data_array);
          }
          //+1.4
          $sql_data_array = array('orders_id' => $insert_id, 
                                    'orders_status_id' => $order->info['order_status'], 
                                    'date_added' => 'now()', 
                         'customer_notified' => '0', 

                                    'comments' => $order->info['comments']);

          tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);

          

//MVS - added insert for new orders_shipping table

        $shipping_array = $shipping['vendor'];

  foreach ((array)$shipping_array as $vendors_id => $shipping_data) {

    $vendors_query = tep_db_query("select vendors_name

                                   from " . TABLE_VENDORS . "

                                   where vendors_id = '" . (int)$vendors_id . "'"

                                 );

    $vendors_name = 'Unknown';

    if ($vendors = tep_db_fetch_array($vendors_query)) {

      $vendors_name = $vendors['vendors_name'];

    }

                $shipping_method_array = explode ('_', $shipping_data['id']);

                if ($shipping_method_array[0] == 'fedex1') {

                        $shipping_method = 'Federal Express';

                        } elseif ($shipping_method_array[0] == 'upsxml') {

                        $shipping_method = 'UPS';

                        } elseif ($shipping_method_array[0] == 'usps') {

                        $shipping_method = 'USPS';

                        } else {

                    $shipping_method = $shipping_method_array[0];

                    }

    $sql_data_array = array('orders_id' => $insert_id,

                            'vendors_id' => $vendors_id,

                            'shipping_module' => $shipping_method,

                            'shipping_method' => $shipping_data['title'],

                            'shipping_cost' => $shipping_data['cost'],

                            'shipping_tax' =>  $shipping_data['ship_tax'],

                            'vendors_name' => $vendors_name,

                            'vendor_order_sent' => 'no'

                           );

    tep_db_perform(TABLE_ORDERS_SHIPPING, $sql_data_array);

  }

//MVS End

          //-1.4



          for ($i=0, $n=sizeof($order->products); $i<$n; $i++) {

            //MVS start - added 'vendors_id' => ...

    $sql_data_array = array('orders_id' => $insert_id,

                            'products_id' => tep_get_prid($order->products[$i]['id']),

                            'products_model' => $order->products[$i]['model'],

                            'products_name' => $order->products[$i]['name'],

                            'products_price' => $order->products[$i]['price'],

                            'final_price' => $order->products[$i]['final_price'],

                            'products_tax' => $order->products[$i]['tax'],

                            'products_quantity' => $order->products[$i]['qty'],

                            'vendors_id' => $order->products[$i]['vendors_id']

                           ); //MVS end



            tep_db_perform(TABLE_ORDERS_PRODUCTS, $sql_data_array);



            $order_products_id = tep_db_insert_id();

            $attributes_exist = '0';
            if (isset($order->products[$i]['attributes'])) {
              $attributes_exist = '1';
              for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) {
                if (DOWNLOAD_ENABLED == 'true') {
                  $attributes_query = "select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix, pad.products_attributes_maxdays, pad.products_attributes_maxcount , pad.products_attributes_filename
                                       from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa
                                       left join " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad
                                       on pa.products_attributes_id=pad.products_attributes_id
                                       where pa.products_id = '" . $order->products[$i]['id'] . "'
                                       and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "'
                                       and pa.options_id = popt.products_options_id
                                       and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "'
                                       and pa.options_values_id = poval.products_options_values_id
                                       and popt.language_id = '" . $languages_id . "'
                                       and poval.language_id = '" . $languages_id . "'";
                  $attributes = tep_db_query($attributes_query);
                } else {
                  $attributes = tep_db_query("select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa where pa.products_id = '" . $order->products[$i]['id'] . "' and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "' and pa.options_id = popt.products_options_id and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "' and pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . $languages_id . "' and poval.language_id = '" . $languages_id . "'");
                }
                $attributes_values = tep_db_fetch_array($attributes);

                $sql_data_array = array('orders_id' => $insert_id,
                                        'orders_products_id' => $order_products_id,
                                        'products_options' => $attributes_values['products_options_name'],
                                        'products_options_values' => $attributes_values['products_options_values_name'],
                                        'options_values_price' => $attributes_values['options_values_price'],
                                        'price_prefix' => $attributes_values['price_prefix']);

                tep_db_perform(TABLE_ORDERS_PRODUCTS_ATTRIBUTES, $sql_data_array);

                if ((DOWNLOAD_ENABLED == 'true') && isset($attributes_values['products_attributes_filename']) && tep_not_null($attributes_values['products_attributes_filename'])) {
                  $sql_data_array = array('orders_id' => $insert_id,
                                          'orders_products_id' => $order_products_id,
                                          'orders_products_filename' => $attributes_values['products_attributes_filename'],
                                          'download_maxdays' => $attributes_values['products_attributes_maxdays'],
                                          'download_count' => $attributes_values['products_attributes_maxcount']);

                  tep_db_perform(TABLE_ORDERS_PRODUCTS_DOWNLOAD, $sql_data_array);
                }
              }
            }

          }



        // FS start

        $GLOBALS['cart_PayPal_IPN_ID'] = $cartID . '-' . $insert_id;

        // FS stop

        tep_session_register('cart_PayPal_IPN_ID');

        // FS start

        // Terra register globals fix

        //$_SESSION['cart_PayPal_IPN_ID'] = $cartID . '-' . $insert_id;

        // FS stop

          

        }

      }

      // BOF Confirmation Info added by AlexStudio

      $confirmation = array('title' => MODULE_PAYMENT_PAYPAL_IPN_TEXT_LAST_CONFIRM, 'fields' => array());
      return $confirmation;
      // EOF Confirmation Info added by AlexStudio
    }

    function process_button() {
      global $customer_id, $order, $languages_id, $currencies, $currency, $cart_PayPal_IPN_ID, $shipping, $order_total_modules;

      if (MODULE_PAYMENT_PAYPAL_IPN_CURRENCY == 'Selected Currency') {
        $my_currency = $currency;
      } else {
        $my_currency = substr(MODULE_PAYMENT_PAYPAL_IPN_CURRENCY, 5);
      }

      

      if (!in_array($my_currency, array('AUD', 'CAD', 'CHF', 'CZK', 'DKK', 'EUR', 'GBP', 'HKD', 'HUF', 'JPY', 'NOK', 'NZD', 'PLN', 'SEK', 'SGD', 'USD'))) {

        $my_currency = 'EUR';

      }



      // BOF Per Item mode fix by alexstudio

      $order_totals = array();
      if (is_array($order_total_modules->modules)) {
        reset($order_total_modules->modules);
        while (list(, $value) = each($order_total_modules->modules)) {
          $class = substr($value, 0, strrpos($value, '.'));
          if ($GLOBALS[$class]->enabled) {
            for ($i=0, $n=sizeof($GLOBALS[$class]->output); $i<$n; $i++) {
              if (tep_not_null($GLOBALS[$class]->output[$i]['title']) && tep_not_null($GLOBALS[$class]->output[$i]['text'])) {
                $order_totals[] = array('code' => $GLOBALS[$class]->code,
                                        'title' => $GLOBALS[$class]->output[$i]['title'],
                                        'text' => $GLOBALS[$class]->output[$i]['text'],
                                        'value' => $GLOBALS[$class]->output[$i]['value'],
                                        'sort_order' => $GLOBALS[$class]->sort_order);
              }
            }
          }
        }
      }
      foreach ($order_totals as $ot) {
        $order_total[$ot['code']] = $ot['value'];
      }
      $subtotal = $order_total['ot_subtotal'];
      if (DISPLAY_PRICE_WITH_TAX == 'true') $subtotal -= $order->info['tax'];
      // EOF Per Item mode fix by alexstudio
      
      $parameters = array();

      if ( (MODULE_PAYMENT_PAYPAL_IPN_TRANSACTION_TYPE == 'Per Item')/* && (MODULE_PAYMENT_PAYPAL_IPN_EWP_STATUS == 'False') // removed by AlexStudio*/) {
        $parameters['cmd'] = '_cart';
        $parameters['upload'] = '1';

        // Decide how many items are virtual (no shipping)
        $shipping_count = 0;
        $shipping_added = 0;

        $handling_added = 0;

        $item_tax = 0;

        $virtual_items = 1;

        for ($y=0; $y<sizeof($order->products); $y++) {

          if (is_array($order->products[$y]['attributes'])) {

            while (list($key, $value) = each($order->products[$y]['attributes'])) {

              $z = $key;
              $attributes_query = "select pad.products_attributes_filename
                                   from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval,
                                   " . TABLE_PRODUCTS_ATTRIBUTES . " pa left join " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad
                                   on pa.products_attributes_id=pad.products_attributes_id
                                   where pa.products_id = '" . $order->products[$y]['id'] . "'
                                   and pa.options_id = '" . $order->products[$y]['attributes'][$z]['option_id'] . "'
                                   and pa.options_id = popt.products_options_id
                                   and pa.options_values_id = '" . $order->products[$y]['attributes'][$z]['value_id'] . "'
                                   and pa.options_values_id = poval.products_options_values_id";
              $attributes = tep_db_query($attributes_query);
              $attributes_values = tep_db_fetch_array($attributes);
              if (tep_not_null($attributes_values['products_attributes_filename'])) $virtual_items++;
            }
          }
        }
        
        for ($i=0, $n=sizeof($order->products); $i<$n; $i++) {
          $item = $i+1;

          $tax_value = ($order->products[$i]['tax'] / 100) * $order->products[$i]['final_price'];

          $parameters['item_name_' . $item] = $order->products[$i]['name'];
          $parameters['item_number_' . $item] = $order->products[$i]['model'];
          // BOF Tax pre item fix by AlexStudio
          if(MOVE_TAX_TO_TOTAL_AMOUNT == 'True') $parameters['amount_' . $item] = number_format(($order->products[$i]['final_price'] + $tax_value) * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
          else {
            $parameters['amount_' . $item] = number_format($order->products[$i]['final_price'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
            $parameters['tax_' . $item] = number_format($tax_value * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
          }
          $item_tax += number_format($tax_value * $order->products[$i]['qty'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
          // EOF Tax pre item fix by AlexStudio
          $parameters['quantity_' . $item] = $order->products[$i]['qty'];

          // BOF shipping & handling fix by AlexStudio
          $item_has_shipping = true;
          // EOF shipping & handling fix by AlexStudio
          if (isset($order->products[$i]['attributes'])) {
            for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) {
              if (DOWNLOAD_ENABLED == 'true') {
                $attributes_query = "select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix, pad.products_attributes_maxdays, pad.products_attributes_maxcount , pad.products_attributes_filename
                                     from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa
                                     left join " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad
                                     on pa.products_attributes_id=pad.products_attributes_id
                                     where pa.products_id = '" . $order->products[$i]['id'] . "'
                                     and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "'
                                     and pa.options_id = popt.products_options_id
                                     and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "'
                                     and pa.options_values_id = poval.products_options_values_id
                                     and popt.language_id = '" . $languages_id . "'
                                     and poval.language_id = '" . $languages_id . "'";
                $attributes = tep_db_query($attributes_query);
              } else {
                $attributes = tep_db_query("select popt.products_options_name, poval.products_options_values_name, pa.options_values_price, pa.price_prefix from " . TABLE_PRODUCTS_OPTIONS . " popt, " . TABLE_PRODUCTS_OPTIONS_VALUES . " poval, " . TABLE_PRODUCTS_ATTRIBUTES . " pa where pa.products_id = '" . $order->products[$i]['id'] . "' and pa.options_id = '" . $order->products[$i]['attributes'][$j]['option_id'] . "' and pa.options_id = popt.products_options_id and pa.options_values_id = '" . $order->products[$i]['attributes'][$j]['value_id'] . "' and pa.options_values_id = poval.products_options_values_id and popt.language_id = '" . $languages_id . "' and poval.language_id = '" . $languages_id . "'");
              }
              $attributes_values = tep_db_fetch_array($attributes);
              // BOF shipping & handling fix by AlexStudio
              if (tep_not_null($attributes_values['products_attributes_filename'])) $item_has_shipping = false;
              // EOF shipping & handling fix by AlexStudio

// Unfortunately PayPal only accepts two attributes per product, so the
// third attribute onwards will not be shown at PayPal
              $parameters['on' . $j . '_' . $item] = $attributes_values['products_options_name'];
              $parameters['os' . $j . '_' . $item] = $attributes_values['products_options_values_name'];
            }
          }
          // BOF shipping & handling fix by AlexStudio
          $handling = $order_total['ot_loworderfee'];
          if ($n == 1 || $item < $n) {
            $parameters['handling_' . $item] = number_format($handling/$n * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
            $handling_added += $parameters['handling_' . $item];
          } else {
            $parameters['handling_' . $item] = number_format($handling * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency)) - $handling_added;
          }
          if ($item_has_shipping) {
            $shipping_count++;
            $shipping_items = $n - $virtual_items;
            if ($shipping_items == 1 || $shipping_count < $shipping_items) {
              $parameters['shipping_' . $item] = number_format(($order_total['ot_shipping']/$shipping_items) * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
              $shipping_added += $parameters['shipping_' . $item];
            } else {
              $parameters['shipping_' . $item] = number_format($order_total['ot_shipping'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency)) - $shipping_added;
            }
          }
          // EOF shipping & handling fix by AlexStudio
        }
        // BOF Tax pre item fix by AlexStudio
        $tax_total = number_format($order->info['tax'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
        if ($tax_total > $item_tax && DISPLAY_PRICE_WITH_TAX != 'true') {
          $item++;
          $parameters['item_name_' . $item] = 'Shipping Tax';
          $parameters['amount_' . $item] = $tax_total - $item_tax;
          $parameters['quantity_' . $item] = 1;
        }
        // EOF Tax pre item fix by AlexStudio

        if(MOVE_TAX_TO_TOTAL_AMOUNT == 'True') {
          // BOF Tax pre item fix by AlexStudio
          $parameters['amount'] = number_format(($subtotal + $order->info['tax']) * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
        } else {
          // default
          $parameters['amount'] = number_format($subtotal * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
          // EOF Tax pre item fix by AlexStudio
        }

      } else {
        $parameters['cmd'] = '_ext-enter';
        $parameters['redirect_cmd'] = '_xclick';
        $parameters['item_name'] = STORE_NAME;
        // BOF shipping & handling fix by AlexStudio
        if(MOVE_TAX_TO_TOTAL_AMOUNT == 'True') {
          $parameters['amount'] = number_format(($subtotal + $order->info['tax']) * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
        } else {
          // default
          $parameters['amount'] = number_format($subtotal * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
          $parameters['tax'] = number_format($order->info['tax'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
        }
        if ($order->content_type != 'virtual') {
          $parameters['shipping'] = number_format($order_total['ot_shipping'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
        }
        $parameters['handling'] = number_format($order_total['ot_loworderfee'] * $currencies->get_value($my_currency), $currencies->get_decimal_places($my_currency));
        // EOF shipping & handling fix by AlexStudio
      }

     // BOF billing address fix by AlexStudio
      if ($order->content_type != 'virtual') {
        $state_abbr = tep_get_zone_code($order->delivery['country']['id'], $order->delivery['zone_id'], $order->delivery['state']);
      } else {
        $state_abbr = tep_get_zone_code($order->billing['country']['id'], $order->billing['zone_id'], $order->billing['state']);
      }
      if (empty($state_abbr)) $state_abbr = 'none';
      // EOF billing address fix by AlexStudio

      $parameters['business'] = MODULE_PAYMENT_PAYPAL_IPN_ID;
      
      // let's check what has been defined in the shop admin for the shipping address
// BOF parameters fix by AlexStudio
      if ($order->content_type != 'virtual') {
        $parameters['address_override'] = '1';
        $parameters['no_shipping'] = '2';
        $parameters['night_phone_b'] = $order->customer['telephone'];
        $parameters['first_name'] = $order->delivery['firstname'];
        $parameters['last_name'] = $order->delivery['lastname'];
        $parameters['address1'] = $order->delivery['street_address'];
        $parameters['address2'] = $order->delivery['suburb'];
        $parameters['city'] = $order->delivery['city'];
        $parameters['zip'] = $order->delivery['postcode'];
        $parameters['state'] = $state_abbr;
        $parameters['country'] = $order->delivery['country']['iso_code_2'];
        $parameters['email'] = $order->customer['email_address'];
      } else {
        $parameters['no_shipping'] = '1';
        $parameters['night_phone_b'] = $order->customer['telephone'];
        $parameters['first_name'] = $order->billing['firstname'];
        $parameters['last_name'] = $order->billing['lastname'];
        $parameters['address1'] = $order->billing['street_address'];
        $parameters['address2'] = $order->billing['suburb'];
        $parameters['city'] = $order->billing['city'];
        $parameters['zip'] = $order->billing['postcode'];
        $parameters['state'] = $state_abbr;
        $parameters['country'] = $order->billing['country']['iso_code_2'];
        $parameters['email'] = $order->customer['email_address'];
      }
      /********************************************************************************
*************
      *    Currently these are the supported charsets:                                             *
      *    big5, euc-jp, euc-kr, euc-tw, gb2312, hz-gb-2312, ibm-862, iso-2022-cn, iso-2022-jp,    *
      *    iso-2022-kr, iso-8859-1, iso-8859-2, iso-8859-3, iso-8859-4, iso-8859-5, iso-8859-6,    *
      *    iso-8859-7, iso-8859-8, iso-8859-9, iso-8859-13, iso-8859-15, ko18-r, shift_jis,        *
      *    utf-7, utf-8, utf-16, utf-16be, utf-16le, utf-16_platformendian, utf-16_oppositeendian, *
      *    utf-32, utf-32be, utf-32le, utf-32_platformendian, utf-32_oppositeendian, usa-ascii,    *
      *    windows-1250, windows-1251, windows-1252, windows-1253, windows-1254, windows-1255,     *
      *    windows-1256, windows-1257, windows-1258, windows-874, windows-949, x-mac-greek,        *

      *    x-mac-turkish, x-mac-centraleurroman, x-mac-cyrillic, ebcdic-cp-us, ibm-1047            *

      ***************************************************************************
*******************/

      $parameters['charset'] = "iso-8859-2"; // Modify this line if you have problems with the character set.

// EOF parameters fix by AlexStudio

      

      $parameters['currency_code'] = $my_currency;

      $parameters['invoice'] = substr($cart_PayPal_IPN_ID, strpos($cart_PayPal_IPN_ID, '-')+1);
      $parameters['custom'] = $customer_id;
      $parameters['no_note'] = '1';
      $parameters['notify_url'] = tep_href_link('ext/modules/payment/paypal_ipn/ipn.php', 'language=' . $_SESSION['language'], 'SSL', false, false);

      $parameters['cbt'] = CONFIRMATION_BUTTON_TEXT;  

      $parameters['return'] = tep_href_link(FILENAME_CHECKOUT_PROCESS, '', 'SSL');

//      $parameters['cancel_return'] = tep_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL');

      $parameters['cancel_return'] = tep_href_link(FILENAME_SHOPPING_CART, 'ipn=cancel_ipn&order='.$parameters['invoice'], 'SSL');

      $parameters['bn'] = $this->identifier;

      $parameters['lc'] = $order->customer['country']['iso_code_2'];

      

      if (tep_not_null(MODULE_PAYMENT_PAYPAL_IPN_PAGE_STYLE)) {
        $parameters['page_style'] = MODULE_PAYMENT_PAYPAL_IPN_PAGE_STYLE;
      }

      if (MODULE_PAYMENT_PAYPAL_IPN_EWP_STATUS == 'True') {
        $parameters['cert_id'] = MODULE_PAYMENT_PAYPAL_IPN_EWP_CERT_ID;

        $random_string = rand(100000, 999999) . '-' . $customer_id . '-';

        $data = '';
        reset($parameters);
        while (list($key, $value) = each($parameters)) {
          $data .= $key . '=' . $value . "\n";
        }

        $fp = fopen(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt', 'w');
        fwrite($fp, $data);
        fclose($fp);

        unset($data);

        if (function_exists('openssl_pkcs7_sign') && function_exists('openssl_pkcs7_encrypt')) {
          openssl_pkcs7_sign(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt', MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt', file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_PUBLIC_KEY), file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_PRIVATE_KEY), array('From' => MODULE_PAYMENT_PAYPAL_IPN_ID), PKCS7_BINARY);

          unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt');

// remove headers from the signature
          $signed = file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt');
          $signed = explode("\n\n", $signed);
          $signed = base64_decode($signed[1]);

          $fp = fopen(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt', 'w');
          fwrite($fp, $signed);
          fclose($fp);

          unset($signed);

          openssl_pkcs7_encrypt(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt', MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt', file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_PAYPAL_KEY), array('From' => MODULE_PAYMENT_PAYPAL_IPN_ID), PKCS7_BINARY);

          unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt');

// remove headers from the encrypted result
          $data = file_get_contents(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt');
          $data = explode("\n\n", $data);
          $data = '-----BEGIN PKCS7-----' . "\n" . $data[1] . "\n" . '-----END PKCS7-----';

          unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt');
        } else {
          exec(MODULE_PAYMENT_PAYPAL_IPN_EWP_OPENSSL . ' smime -sign -in ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt -signer ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_PUBLIC_KEY . ' -inkey ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_PRIVATE_KEY . ' -outform der -nodetach -binary > ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt');
          unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'data.txt');

          exec(MODULE_PAYMENT_PAYPAL_IPN_EWP_OPENSSL . ' smime -encrypt -des3 -binary -outform pem ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_PAYPAL_KEY . ' < ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt > ' . MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt');
          unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'signed.txt');

          $fh = fopen(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt', 'rb');
          $data = fread($fh, filesize(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt'));
          fclose($fh);

          unlink(MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY . '/' . $random_string . 'encrypted.txt');
        }

        $process_button_string = tep_draw_hidden_field('cmd', '_s-xclick') .
                                 tep_draw_hidden_field('encrypted', $data);

        unset($data);
      } else {
        reset($parameters);
        while (list($key, $value) = each($parameters)) {
          $process_button_string .= tep_draw_hidden_field($key, $value);
        }
      }
      return $process_button_string;
    }



    function before_process() {

      global $cart;



      $cart->reset(true);



// unregister session variables used during checkout

      tep_session_unregister('sendto');
      tep_session_unregister('billto');
      tep_session_unregister('shipping');
      tep_session_unregister('payment');
      tep_session_unregister('comments');

      tep_session_unregister('cart_PayPal_IPN_ID');

      tep_redirect(tep_href_link(FILENAME_CHECKOUT_SUCCESS, '', 'SSL'));
    }

    function after_process() {
      return false;
    }

    function output_error() {
      return false;
    }

    function check() {
      if (!isset($this->_check)) {
        $check_query = tep_db_query("select configuration_value from " . TABLE_CONFIGURATION . " where configuration_key = 'MODULE_PAYMENT_PAYPAL_IPN_STATUS'");
        $this->_check = tep_db_num_rows($check_query);
      }
      return $this->_check;
    }

    function install() {
      $check_query = tep_db_query("select orders_status_id from " . TABLE_ORDERS_STATUS . " where orders_status_name = 'Preparing [PayPal IPN]' limit 1");

      if (tep_db_num_rows($check_query) < 1) {
        $status_query = tep_db_query("select max(orders_status_id) as status_id from " . TABLE_ORDERS_STATUS);
        $status = tep_db_fetch_array($status_query);

        $status_id = $status['status_id']+1;

        $languages = tep_get_languages();

        foreach ($languages as $lang) {
          tep_db_query("insert into " . TABLE_ORDERS_STATUS . " (orders_status_id, language_id, orders_status_name) values ('" . $status_id . "', '" . $lang['id'] . "', 'Preparing [PayPal IPN]')");
        }
      } else {
        $check = tep_db_fetch_array($check_query);

        $status_id = $check['orders_status_id'];
      }

      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable PayPal IPN Module', 'MODULE_PAYMENT_PAYPAL_IPN_STATUS', 'False', 'Do you want to accept PayPal IPN payments?', '6', '1', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Gateway Server', 'MODULE_PAYMENT_PAYPAL_IPN_GATEWAY_SERVER', 'Testing', 'Use the testing (sandbox) or live gateway server for transactions?', '6', '2', 'tep_cfg_select_option(array(\'Testing\',\'Live\'), ', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Sort order of display.', 'MODULE_PAYMENT_PAYPAL_IPN_SORT_ORDER', '0', 'Sort order of display. Lowest is displayed first.', '6', '3', now())");            
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('E-Mail Address', 'MODULE_PAYMENT_PAYPAL_IPN_ID', '', 'The e-mail address to use for the PayPal IPN service', '6', '5', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Transaction Currency', 'MODULE_PAYMENT_PAYPAL_IPN_CURRENCY', 'Selected Currency', 'The currency to use for transactions', '6', '10', 'tep_cfg_select_option(array(\'Selected Currency\',\'Only USD\',\'Only GBP\',\'Only AUD\',\'Only CAD\',\'Only CHF\',\'Only CZK\',\'Only DKK\',\'Only EUR\',\'Only HKD\',\'Only HUF\',\'Only JPY\',\'Only NOK\',\'Only NZD\',\'Only PLN\',\'Only SEK\',\'Only SGD\'), ', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, use_function, set_function, date_added) values ('Payment Zone', 'MODULE_PAYMENT_PAYPAL_IPN_ZONE', '0', 'If a zone is selected, only enable this payment method for that zone.', '6', '11', 'tep_get_zone_class_title', 'tep_cfg_pull_down_zone_classes(', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set Preparing Order Status', 'MODULE_PAYMENT_PAYPAL_IPN_PREPARE_ORDER_STATUS_ID', '" . $status_id . "', 'Set the status of prepared orders made with this payment module to this value', '6', '12', 'tep_cfg_pull_down_order_statuses(', 'tep_get_order_status_name', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set PayPal Acknowledged Order Status', 'MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID', '0', 'Set the status of orders made with this payment module to this value', '6', '13', 'tep_cfg_pull_down_order_statuses(', 'tep_get_order_status_name', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, use_function, date_added) values ('Set PayPal Completed Order Status', 'MODULE_PAYMENT_PAYPAL_IPN_COMP_ORDER_STATUS_ID', '0', 'Set the status of orders which are confirmed as paid (completed) to this value', '6', '13', 'tep_cfg_pull_down_order_statuses(', 'tep_get_order_status_name', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Transaction Type', 'MODULE_PAYMENT_PAYPAL_IPN_TRANSACTION_TYPE', 'Aggregate', 'Send individual items to PayPal or aggregate all as one total item?', '6', '14', 'tep_cfg_select_option(array(\'Per Item\',\'Aggregate\'), ', now())");
      // bof PandA.nl move tax to total amount
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Move tax to total amount', 'MOVE_TAX_TO_TOTAL_AMOUNT', 'True', 'Do you want to move the tax to the total amount? If true PayPal will allways show the total amount including tax. (needs Aggregate instead of Per Item to function)', '6', '15', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
      // eof PandA.nl move tax to total amount      
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Page Style', 'MODULE_PAYMENT_PAYPAL_IPN_PAGE_STYLE', '', 'The page style to use for the transaction procedure (defined at your PayPal Profile page)', '6', '20', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Debug E-Mail Address', 'MODULE_PAYMENT_PAYPAL_IPN_DEBUG_EMAIL', '', 'All parameters of an Invalid IPN notification will be sent to this email address if one is entered.', '6', '21', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('cURL Proxy server', 'MODULE_PAYMENT_PAYPAL_IPN_PROXY_SERVER', '', 'If curl transactions need to go through a proxy, type the address here starting with http://. Otherwise, leave it blank. The current GoDaddy proxy address is http://proxy.shr.secureserver.net:3128', '6', '22', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, set_function, date_added) values ('Enable Encrypted Web Payments', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_STATUS', 'False', 'Do you want to enable Encrypted Web Payments?', '6', '30', 'tep_cfg_select_option(array(\'True\', \'False\'), ', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Your Private Key', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_PRIVATE_KEY', '', 'The location of your Private Key to use for signing the data. (*.pem)', '6', '31', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Your Public Certificate', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_PUBLIC_KEY', '', 'The location of your Public Certificate to use for signing the data. (*.pem)', '6', '32', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('PayPals Public Certificate', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_PAYPAL_KEY', '', 'The location of the PayPal Public Certificate for encrypting the data.', '6', '33', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Your PayPal Public Certificate ID', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_CERT_ID', '', 'The Certificate ID to use from your PayPal Encrypted Payment Settings Profile.', '6', '34', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('Working Directory', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY', '', 'The working directory to use for temporary files. (trailing slash needed)', '6', '35', now())");
      tep_db_query("insert into " . TABLE_CONFIGURATION . " (configuration_title, configuration_key, configuration_value, configuration_description, configuration_group_id, sort_order, date_added) values ('OpenSSL Location', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_OPENSSL', '/usr/bin/openssl', 'The location of the openssl binary file.', '6', '36', now())");

    }

    function remove() {
      tep_db_query("delete from " . TABLE_CONFIGURATION . " where configuration_key in ('" . implode("', '", $this->keys()) . "')");
    }

   function keys() {
    // PandA.nl move tax to total amount added: ", 'MOVE_TAX_TO_TOTAL_AMOUNT'"
     return array('MODULE_PAYMENT_PAYPAL_IPN_STATUS', 'MODULE_PAYMENT_PAYPAL_IPN_GATEWAY_SERVER', 'MODULE_PAYMENT_PAYPAL_IPN_ID', 'MODULE_PAYMENT_PAYPAL_IPN_SORT_ORDER', 'MODULE_PAYMENT_PAYPAL_IPN_CURRENCY', 'MODULE_PAYMENT_PAYPAL_IPN_ZONE', 'MODULE_PAYMENT_PAYPAL_IPN_PREPARE_ORDER_STATUS_ID', 'MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID', 'MODULE_PAYMENT_PAYPAL_IPN_COMP_ORDER_STATUS_ID', 'MODULE_PAYMENT_PAYPAL_IPN_TRANSACTION_TYPE', 'MOVE_TAX_TO_TOTAL_AMOUNT', 'MODULE_PAYMENT_PAYPAL_IPN_PAGE_STYLE', 'MODULE_PAYMENT_PAYPAL_IPN_DEBUG_EMAIL', 'MODULE_PAYMENT_PAYPAL_IPN_PROXY_SERVER', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_STATUS', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_PRIVATE_KEY', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_PUBLIC_KEY', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_PAYPAL_KEY', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_CERT_ID', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_WORKING_DIRECTORY', 'MODULE_PAYMENT_PAYPAL_IPN_EWP_OPENSSL');
   }
  }
?>

/ext/modules/payment/paypal_ipn/ipn.php

<?php
/*
  $Id: paypal_ipn.php,v 2.3.0.0 10/09/2007 11:58:21 alexstudio Exp $

  Copyright (c) 2004 osCommerce
  Released under the GNU General Public License
  
  Original Authors: Harald Ponce de Leon, Mark Evans 
  Updates by PandA.nl, Navyhost, Zoeticlight, David, gravyface, AlexStudio, windfjf, Monika in Germany and Terra
  v2.3 updated by AlexStudio
    
*/



  chdir('../../../../');

  require('includes/application_top.php');

  include(DIR_WS_LANGUAGES . $language . '/' . FILENAME_CHECKOUT_PROCESS);

  // BOF configuration keys fix by AlexStudio

  require(DIR_WS_CLASSES . 'payment.php');

  $payment_modules = new payment(paypal_ipn);

  // EOF configuration keys fix by AlexStudio

//MVS start

    // load the selected shipping module

   if (($total_weight > 0 ) || (SELECT_VENDOR_SHIPPING == 'true')){

        include(DIR_WS_CLASSES . 'vendor_shipping.php');

      } elseif (($total_weight > 0 ) || (SELECT_VENDOR_SHIPPING == 'false')){

        include(DIR_WS_CLASSES . 'shipping.php');

      }

      $shipping_modules = new shipping($shipping);

      //MVS End

  $parameters = 'cmd=_notify-validate';



  foreach ($_POST as $key => $value) {

    $parameters .= '&' . $key . '=' . urlencode(stripslashes($value));
  }

  if (MODULE_PAYMENT_PAYPAL_IPN_GATEWAY_SERVER == 'Live') {
    $server = 'www.paypal.com';
  } else {
    $server = 'www.sandbox.paypal.com';
  }

  $fsocket = false;
  $curl = false;
  $result = false;

  if ( (PHP_VERSION >= 4.3) && ($fp = @fsockopen('ssl://' . $server, 443, $errno, $errstr, 30)) ) {
    $fsocket = true;
  } elseif (function_exists('curl_exec')) {
    $curl = true;
  } elseif ($fp = @fsockopen($server, 80, $errno, $errstr, 30)) {
    $fsocket = true;
  }

  if ($fsocket == true) {
    $header = 'POST /cgi-bin/webscr HTTP/1.0' . "\r\n" .
              'Host: ' . $server . "\r\n" .
              'Content-Type: application/x-www-form-urlencoded' . "\r\n" .
              'Content-Length: ' . strlen($parameters) . "\r\n" .
              'Connection: close' . "\r\n\r\n";

    @fputs($fp, $header . $parameters);

    $string = '';
    while (!@feof($fp)) {
      $res = @fgets($fp, 1024);
      $string .= $res;

      if ( ($res == 'VERIFIED') || ($res == 'INVALID') ) {
        $result = $res;
        break;
      }
    }

    @fclose($fp);
  } elseif ($curl == true) {
    $ch = curl_init();

    // BOF add by AlexStudio
    // For the poor souls on GoDaddy and the like, set the connection to go through their proxy
    if (trim(MODULE_PAYMENT_PAYPAL_IPN_PROXY_SERVER) != '') {
      curl_setopt($ch, CURLOPT_PROXYTYPE, CURLPROXY_HTTP);
      curl_setopt($ch, CURLOPT_PROXY, MODULE_PAYMENT_PAYPAL_IPN_PROXY_SERVER);
    }
    // Eof add by AlexStudio
    curl_setopt($ch, CURLOPT_URL, 'https://' . $server . '/cgi-bin/webscr');
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $parameters);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HEADER, false);
    curl_setopt($ch, CURLOPT_TIMEOUT, 30);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);

    $result = curl_exec($ch);

    curl_close($ch);
  }

  if ($result == 'VERIFIED') {
    if (isset($_POST['invoice']) && is_numeric($_POST['invoice']) && ($_POST['invoice'] > 0)) {
      $order_query = tep_db_query("select currency, currency_value from " . TABLE_ORDERS . " where orders_id = '" . $_POST['invoice'] . "' and customers_id = '" . (int)$_POST['custom'] . "'");
      if (tep_db_num_rows($order_query) > 0) {
        $order_db = tep_db_fetch_array($order_query);

        // let's re-create the required arrays
        require(DIR_WS_CLASSES . 'order.php');
        $order = new order($_POST['invoice']);

        // let's update the order status
        $total_query = tep_db_query("select value from " . TABLE_ORDERS_TOTAL . " where orders_id = '" . $_POST['invoice'] . "' and class = 'ot_total' limit 1");
        $total = tep_db_fetch_array($total_query);

        $comment_status = 'payment status: ' . $_POST['payment_status'] . ' (' . ucfirst($_POST['payer_status']) . '; ' . $currencies->format($_POST['mc_gross'], false, $_POST['mc_currency']) . ')';

        if ($_POST['payment_status'] == 'Pending') {
          $comment_status .= '; ' . $_POST['pending_reason'];
        } elseif ( ($_POST['payment_status'] == 'Reversed') || ($_POST['payment_status'] == 'Refunded') ) {
          $comment_status .= '; ' . $_POST['reason_code'];
        } elseif ( ($_POST['payment_status'] == 'Completed') && (tep_not_null($_POST['address_street'])) ) {
          $comment_status .= ", \n" . PAYPAL_ADDRESS . ": " . $_POST['address_name'] . ", " . $_POST['address_street'] . ", " . $_POST['address_city'] . ", " . $_POST['address_zip'] . ", " . $_POST['address_state'] . ", " . $_POST['address_country'] . ", " . $_POST['address_country_code'] . ", " . $_POST['address_status'];
        } 

        $order_status_id = DEFAULT_ORDERS_STATUS_ID;

// modified AlexStudio's Rounding error bug fix 
// variances of up to 0.05 on either side (plus / minus) are ignored
        if ((((number_format($total['value'] * $order_db['currency_value'], $currencies->get_decimal_places($order_db['currency']))) -  $_POST['mc_gross']) <= 0.05)  
          &&
          (((number_format($total['value'] * $order_db['currency_value'], $currencies->get_decimal_places($order_db['currency']))) -  $_POST['mc_gross']) >= -0.05)) {

// Terra -> modified update. If payment status is "completed" than a completed order status is chosen based on the admin settings 
          if ( (MODULE_PAYMENT_PAYPAL_IPN_COMP_ORDER_STATUS_ID > 0) && ($_POST['payment_status'] == 'Completed') ) {
            $order_status_id = MODULE_PAYMENT_PAYPAL_IPN_COMP_ORDER_STATUS_ID;
          } elseif (MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID > 0) {
            $order_status_id = MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID;
          }
        }

        // Let's see what the PayPal payment status is and set the notification accordingly
        // more info: https://www.paypal.com/IntegrationCenter/ic_ipn-pdt-variable-reference.html
        if ( ($_POST['payment_status'] == 'Pending') || ($_POST['payment_status'] == 'Completed')) {
          $customer_notified = '1'; 
        } else {
          $customer_notified = '0'; 
        }

        tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . $order_status_id . "', last_modified = now() where orders_id = '" . $_POST['invoice'] . "'");

        $sql_data_array = array('orders_id' => $_POST['invoice'],
                                'orders_status_id' => $order_status_id,
                                'date_added' => 'now()',
                                'customer_notified' => $customer_notified,
                                'comments' => 'PayPal IPN Verified [' . $comment_status . ']');



        tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);

        

//MVS - added insert for new orders_shipping table

        $shipping_array = $shipping['vendor'];

  foreach ($shipping_array as $vendors_id => $shipping_data) {

    $vendors_query = tep_db_query("select vendors_name

                                   from " . TABLE_VENDORS . "

                                   where vendors_id = '" . (int)$vendors_id . "'"

                                 );

    $vendors_name = 'Unknown';

    if ($vendors = tep_db_fetch_array($vendors_query)) {

      $vendors_name = $vendors['vendors_name'];

    }

                $shipping_method_array = explode ('_', $shipping_data['id']);

                if ($shipping_method_array[0] == 'fedex1') {

                        $shipping_method = 'Federal Express';

                        } elseif ($shipping_method_array[0] == 'upsxml') {

                        $shipping_method = 'UPS';

                        } elseif ($shipping_method_array[0] == 'usps') {

                        $shipping_method = 'USPS';

                        } else {

                    $shipping_method = $shipping_method_array[0];

                    }

    $sql_data_array = array('orders_id' => $insert_id,

                            'vendors_id' => $vendors_id,

                            'shipping_module' => $shipping_method,

                            'shipping_method' => $shipping_data['title'],

                            'shipping_cost' => $shipping_data['cost'],

                            'shipping_tax' =>  $shipping_data['ship_tax'],

                            'vendors_name' => $vendors_name,

                            'vendor_order_sent' => 'no'

                           );

    tep_db_perform(TABLE_ORDERS_SHIPPING, $sql_data_array);

  }

//MVS End



// If the order is completed, then we want to send the order email and update the stock

        if ($_POST['payment_status'] == 'Completed') { // START STATUS == COMPLETED LOOP


// initialized for the email confirmation
          $products_ordered = '';
          $total_tax = 0;

// let's update the stock  
#######################################################
          for ($i=0, $n=sizeof($order->products); $i<$n; $i++) { // PRODUCT LOOP STARTS HERE
// Stock Update - Joao Correia
            if (STOCK_LIMITED == 'true') {
              if (DOWNLOAD_ENABLED == 'true') {
                $stock_query_raw = "SELECT products_quantity, pad.products_attributes_filename 
                                    FROM " . TABLE_PRODUCTS . " p
                                    LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES . " pa
                                    ON p.products_id=pa.products_id
                                    LEFT JOIN " . TABLE_PRODUCTS_ATTRIBUTES_DOWNLOAD . " pad
                                    ON pa.products_attributes_id=pad.products_attributes_id
                                    WHERE p.products_id = '" . tep_get_prid($order->products[$i]['id']) . "'";
// Will work with only one option for downloadable products
// otherwise, we have to build the query dynamically with a loop
                $products_attributes = $order->products[$i]['attributes'];
                if (is_array($products_attributes)) {
                  $stock_query_raw .= " AND pa.options_id = '" . $products_attributes[0]['option_id'] . "' AND pa.options_values_id = '" . $products_attributes[0]['value_id'] . "'";
                }
                $stock_query = tep_db_query($stock_query_raw);
              } else {
                $stock_query = tep_db_query("select products_quantity from " . TABLE_PRODUCTS . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
              }
              if (tep_db_num_rows($stock_query) > 0) {
                $stock_values = tep_db_fetch_array($stock_query);
// do not decrement quantities if products_attributes_filename exists
                if ((DOWNLOAD_ENABLED != 'true') || (!$stock_values['products_attributes_filename'])) {
                  $stock_left = $stock_values['products_quantity'] - $order->products[$i]['qty'];
                } else {
                  $stock_left = $stock_values['products_quantity'];
                }
                tep_db_query("update " . TABLE_PRODUCTS . " set products_quantity = '" . $stock_left . "' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
                if ( ($stock_left < 1) && (STOCK_ALLOW_CHECKOUT == 'false') ) {
                  tep_db_query("update " . TABLE_PRODUCTS . " set products_status = '0' where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");
                }
              }
            }

// Update products_ordered (for bestsellers list)
            tep_db_query("update " . TABLE_PRODUCTS . " set products_ordered = products_ordered + " . sprintf('%d', $order->products[$i]['qty']) . " where products_id = '" . tep_get_prid($order->products[$i]['id']) . "'");

// Let's get all the info together for the email
            $total_weight += ($order->products[$i]['qty'] * $order->products[$i]['weight']);
            $total_tax += tep_calculate_tax($total_products_price, $products_tax) * $order->products[$i]['qty'];
            $total_cost += $total_products_price;

// Let's get the attributes
            $products_ordered_attributes = '';
            if ( (isset($order->products[$i]['attributes'])) && (sizeof($order->products[$i]['attributes']) > 0) ) {
              for ($j=0, $n2=sizeof($order->products[$i]['attributes']); $j<$n2; $j++) {
                $products_ordered_attributes .= "\n\t" . $order->products[$i]['attributes'][$j]['option'] . ' ' . $order->products[$i]['attributes'][$j]['value'];
              }
            } 

// Let's format the products model       
            $products_model = '';      
            if ( !empty($order->products[$i]['model']) ) {
              $products_model = ' (' . $order->products[$i]['model'] . ')';
            } 



// Let's put all the product info together into a string

            //MVS begin

     if (SELECT_VENDOR_EMAIL_OPTION == 'false') {

     $products_ordered .= $order->products[$i]['qty'] . ' x ' . $order->products[$i]['name'] . ' (' . $order->products[$i]['model'] . ') = ' . $currencies->display_price($order->products[$i]['final_price'], $order->products[$i]['tax'], $order->products[$i]['qty']) . $products_ordered_attributes . "\n";

    }

    }

    if (SELECT_VENDOR_EMAIL_OPTION == 'true') {

   $order_id = $insert_id;

       require(DIR_WS_INCLUDES . 'vendor_order_data.php');

           }

function vendors_email($vendors_id, $oID, $status, $vendor_order_sent) {

       $vendor_order_sent =  false;

   $debug='no';

   $vendor_order_sent = 'no';

$index2 = 0;

              //let's get the Vendors

              $vendor_data_query = tep_db_query("select v.vendors_id, v.vendors_name, v.vendors_email, v.vendors_contact, v.vendor_add_info, v.vendor_street, v.vendor_city, v.vendor_state, v.vendors_zipcode, v.vendor_country, v.account_number, v.vendors_status_send, os.shipping_module, os.shipping_method, os.shipping_cost, os.shipping_tax, os.vendor_order_sent from " . TABLE_VENDORS . " v,  " . TABLE_ORDERS_SHIPPING . " os where v.vendors_id=os.vendors_id and v.vendors_id='" . $vendors_id . "' and os.orders_id='" . (int)$oID . "' and v.vendors_status_send='" . $status . "'");

           while ($vendor_order = tep_db_fetch_array($vendor_data_query)) {

$vendor_products[$index2] = array('Vid' => $vendor_order['vendors_id'],

                             'Vname' => $vendor_order['vendors_name'],

                             'Vemail' => $vendor_order['vendors_email'],

                             'Vcontact' => $vendor_order['vendors_contact'],

                             'Vaccount' => $vendor_order['account_number'],

                             'Vstreet' => $vendor_order['vendor_street'],

                             'Vcity' => $vendor_order['vendor_city'],

                             'Vstate' => $vendor_order['vendor_state'],

                             'Vzipcode' => $vendor_order['vendors_zipcode'],

                             'Vcountry' => $vendor_order['vendor_country'],

                             'Vaccount' => $vendor_order['account_number'],                               'Vinstructions' => $vendor_order['vendor_add_info'],

                             'Vmodule' => $vendor_order['shipping_module'],                               'Vmethod' => $vendor_order['shipping_method']);

if ($debug == 'yes') {

    echo 'The vendor query: ' . $vendor_order['vendors_id'] . '<br>';

      }

                                   $index = 0;

    $vendor_orders_products_query = tep_db_query("select o.orders_id, o.orders_products_id, o.products_model, o.products_id, o.products_quantity, o.products_name, p.vendors_id,  p.vendors_prod_comments, p.vendors_prod_id, p.vendors_product_price from " . TABLE_ORDERS_PRODUCTS . " o, " . TABLE_PRODUCTS . " p where p.vendors_id='" . (int)$vendor_order['vendors_id'] . "' and o.products_id=p.products_id and o.orders_id='" . $oID . "' order by o.products_name");

        while ($vendor_orders_products = tep_db_fetch_array($vendor_orders_products_query)) {

      $vendor_products[$index2]['vendor_orders_products'][$index] = array(

                                      'Pqty' => $vendor_orders_products['products_quantity'],

                                      'Pname' => $vendor_orders_products['products_name'],

                                      'Pmodel' => $vendor_orders_products['products_model'],

                                      'Pprice' => $vendor_orders_products['products_price'],

                                      'Pvendor_name' => $vendor_orders_products['vendors_name'],

                                      'Pcomments' => $vendor_orders_products['vendors_prod_comments'],

                                      'PVprod_id' => $vendor_orders_products['vendors_prod_id'],

                                      'PVprod_price' => $vendor_orders_products['vendors_product_price'],

                                      'spacer' => '-');

                                   //MVS end

                   if ($debug == 'yes') {

echo 'The products query: ' . $vendor_orders_products['products_name'] . '<br>';

}

        $subindex = 0;

      $vendor_attributes_query = tep_db_query("select products_options, products_options_values, options_values_price, price_prefix from " . TABLE_ORDERS_PRODUCTS_ATTRIBUTES . " where orders_id = '" . (int)$oID . "' and orders_products_id = '" . (int)$vendor_orders_products['orders_products_id'] . "'");

        if (tep_db_num_rows($vendor_attributes_query)) {

          while ($vendor_attributes = tep_db_fetch_array($vendor_attributes_query)) {

          $vendor_products[$index2]['vendor_orders_products'][$index]['vendor_attributes'][$subindex] = array('option' => $vendor_attributes['products_options'],

                                                                     'value' => $vendor_attributes['products_options_values'],

                                                                     'prefix' => $vendor_attributes['price_prefix'],

                                                                     'price' => $vendor_attributes['options_values_price']);



            $subindex++;

          }

        }

        $index++;

      }

     $index2++;

    // let's build the email

   // Get the delivery address

  $delivery_address_query = tep_db_query("select distinct delivery_company, delivery_name, delivery_street_address, delivery_city, delivery_state, delivery_postcode from " . TABLE_ORDERS . " where orders_id='" . $oID ."'");

  $vendor_delivery_address_list = tep_db_fetch_array($delivery_address_query);



if ($debug == 'yes') {

    echo 'The number of vendors: ' . sizeof($vendor_products) . '<br>';

     }

    $email='';

for ($l=0, $m=sizeof($vendor_products); $l<$m; $l++) {



    $vendor_country = tep_get_country_name($vendor_products[$l]['Vcountry']);

    $order_number= $oID;

    $vendors_id=$vendor_products[$l]['Vid'];

    $the_email=$vendor_products[$l]['Vemail'];

    $the_name=$vendor_products[$l]['Vname'];

    $the_contact=$vendor_products[$l]['Vcontact'];

$email=  '<b>To: ' . $the_contact . '  <br>' . $the_name . '<br>' . $the_email . '<br>' .

    $vendor_products[$l]['Vstreet'] .'<br>' .

    $vendor_products[$l]['Vcity'] .', ' .

    $vendor_products[$l]['Vstate'] .'  ' .

    $vendor_products[$l]['Vzipcode'] . ' ' . $vendor_country . '<br>' . '<br>' . EMAIL_SEPARATOR . '<br>' . 'Special Comments or Instructions:  ' . $vendor_products[$l]['Vinstructions'] .'<br>' . '<br>' . EMAIL_SEPARATOR . '<br>' . 'From: ' . STORE_OWNER . '<br>' . STORE_NAME_ADDRESS . '<br>' . 'Accnt #: ' . $vendor_products[$l]['Vaccount'] . '<br>' . EMAIL_SEPARATOR . '<br>' . EMAIL_TEXT_ORDER_NUMBER . ' ' . $oID . '<br>' .  EMAIL_SEPARATOR . '<br>' . '<br> Shipping Method: ' .  $vendor_products[$l]['Vmodule'] . ' -- '  .  $vendor_products[$l]['Vmethod'] .  '<br>' .  EMAIL_SEPARATOR . '<br>' . '<br>Dropship deliver to:<br>' .

    $vendor_delivery_address_list['delivery_company'] .'<br>' .

    $vendor_delivery_address_list['delivery_name'] .'<br>' .

    $vendor_delivery_address_list['delivery_street_address'] .'<br>' .

    $vendor_delivery_address_list['delivery_city'] .', ' .

    $vendor_delivery_address_list['delivery_state'] . ' ' . $vendor_delivery_address_list['delivery_postcode'] . '<br><br>';

    $email = $email .  '<table width="75%" border=1 cellspacing="0" cellpadding="3">

    <tr><td>Qty:</td><td>Product Name:</td><td>Item Code/Number:</td><td>Product Model:</td><td>Per Unit Price:</td><td>Item Comments: </td></tr>';

           for ($i=0, $n=sizeof($vendor_products[$l]['vendor_orders_products']); $i<$n; $i++) {

      $product_attribs ='';

      if (isset($vendor_products[$l]['vendor_orders_products'][$i]['vendor_attributes']) && (sizeof($vendor_products[$l]['vendor_orders_products'][$i]['vendor_attributes']) > 0)) {



        for ($j = 0, $k = sizeof($vendor_products[$l]['vendor_orders_products'][$i]['vendor_attributes']); $j < $k; $j++) {

         $product_attribs .= '  ' . $vendor_products[$l]['vendor_orders_products'][$i]['vendor_attributes'][$j]['option'] . ': ' .  $vendor_products[$l]['vendor_orders_products'][$i]['vendor_attributes'][$j]['value'] . '<br>';

        }

        }

        $email = $email . '<tr><td> ' . $vendor_products[$l]['vendor_orders_products'][$i]['Pqty'] .

     '</td><td> ' . $vendor_products[$l]['vendor_orders_products'][$i]['Pname'] . '<br>  <i>Option<br> ' . $product_attribs .

     '</td><td> ' . $vendor_products[$l]['vendor_orders_products'][$i]['PVprod_id'] .

     '</td><td> ' . $vendor_products[$l]['vendor_orders_products'][$i]['Pmodel'] .

     '</td><td> ' . $vendor_products[$l]['vendor_orders_products'][$i]['PVprod_price'] . '</td><td>' .

     $vendor_products[$l]['vendor_orders_products'][$i]['Pcomments'] . '</b></td></tr>';



      }

    }

    $email = $email . '</table><br><HR><br>';



    tep_mail($the_name, $the_email, EMAIL_TEXT_ORDER_NUMBER . ' ' . $oID ,  $email .  '<br>', STORE_NAME, STORE_OWNER_EMAIL_ADDRESS) ;

     $vendor_order_sent = 'yes';



     tep_db_query("update " . TABLE_ORDERS_SHIPPING . " set vendor_order_sent = '" . tep_db_input($vendor_order_sent) . "' where orders_id = '" . (int)$oID . "'  and vendors_id = '" . (int)$vendors_id . "'");



     if ($debug == 'yes') {

           echo 'The $email(including headers:<br>Vendor Email Addy' . $the_email . '<br>Vendor Name' . $the_name . '<br>Vendor Contact' . $the_contact . '<br>Body--<br>' . $email . '<br>';

           }

  }



  return true;

} //MVS end        // PRODUCT LOOP ENDS HERE

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



// lets start with the email confirmation

// BOF content type fix by AlexStudio
            $content_type = '';
            $content_count = 0;
            // BOF order comment fix
            $comment_query = tep_db_query("select comments from " . TABLE_ORDERS_STATUS_HISTORY . " where orders_id = '" . $_POST['invoice'] . "'");
            $comment_array = tep_db_fetch_array($comment_query);
            $comments = $comment_array['comments'];
            // EOF order comment fix

            if (DOWNLOAD_ENABLED == 'true') {
              $content_query = tep_db_query("select * from " . TABLE_ORDERS_PRODUCTS_DOWNLOAD . " where orders_id = '" . (int)$_POST['invoice'] . "'");
              $content_count = tep_db_num_rows($content_query);
              if ($content_count > 0) {
                $content_type = 'virtual';
              }
            }
            switch ($content_type) {
              case 'virtual':
                if ($content_count != sizeof($order->products)) $content_type = 'mixed'; 
                break;
              default:
                $content_type = 'physical';
                break;
            }

// EOF content type fix by AlexStudio

// $order variables have been changed from checkout_process to work with the variables from the function query () instead of cart () in the order class

          $email_order = STORE_NAME . "\n" . 

                         EMAIL_SEPARATOR . "\n" . 

                         EMAIL_TEXT_ORDER_NUMBER . ' ' . $_POST['invoice'] . "\n" .

                         EMAIL_TEXT_INVOICE_URL . ' ' . tep_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $_POST['invoice'], 'SSL', false) . "\n" .

                         EMAIL_TEXT_DATE_ORDERED . ' ' . strftime(DATE_FORMAT_LONG) . "\n\n";



          // BOF order comment fix by AlexStudio

          if ($comments) {

            $email_order .= $comments . "\n\n";

          }

          // EOF order comment fix by AlexStudio



          $email_order .= EMAIL_TEXT_PRODUCTS . "\n" . 

                          EMAIL_SEPARATOR . "\n" . 

                          $products_ordered . 

                          EMAIL_SEPARATOR . "\n";



          for ($i=0, $n=sizeof($order->totals); $i<$n; $i++) {

            $email_order .= strip_tags($order->totals[$i]['title']) . ' ' . strip_tags($order->totals[$i]['text']) . "\n";

          }

          // BOF content type fix by AlexStudio
          if ($content_type != 'virtual') {
          // EOF content type fix by AlexStudio
            $email_order .= "\n" . EMAIL_TEXT_DELIVERY_ADDRESS . "\n" . 
                            EMAIL_SEPARATOR . "\n" .
                            tep_address_format($order->delivery['format_id'], $order->delivery,  0, '', "\n") . "\n";
          }

          $email_order .= "\n" . EMAIL_TEXT_BILLING_ADDRESS . "\n" .
                          EMAIL_SEPARATOR . "\n" .
                          tep_address_format($order->billing['format_id'], $order->billing, 0, '', "\n") . "\n\n";
          if (is_object($$payment)) {
            $email_order .= EMAIL_TEXT_PAYMENT_METHOD . "\n" . 
                            EMAIL_SEPARATOR . "\n";
            $payment_class = $$payment;
            $email_order .= $payment_class->title . "\n\n";
            if ($payment_class->email_footer) { 
              $email_order .= $payment_class->email_footer . "\n\n";

            }

          }

          tep_mail($order->customer['name'], $order->customer['email_address'], EMAIL_TEXT_SUBJECT, nl2br($email_order), STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);



// send emails to other people

          if (SEND_EXTRA_ORDER_EMAILS_TO != '') {

            tep_mail('', SEND_EXTRA_ORDER_EMAILS_TO, EMAIL_TEXT_SUBJECT, nl2br($email_order), STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);

          }

          //MVS start

    if (SELECT_VENDOR_EMAIL_WHEN == 'Catalog' || SELECT_VENDOR_EMAIL_WHEN == 'Both') {

            $status=$order->info['order_status'];

             if (isset($status)) {

  $order_sent_query = tep_db_query("select vendor_order_sent, vendors_id from " . TABLE_ORDERS_SHIPPING . " where orders_id = '" . $insert_id . "'");

       while ($order_sent_data = tep_db_fetch_array($order_sent_query)) {

     $order_sent_ckeck = $order_sent_data['vendor_order_sent'];

     $vendors_id = $order_sent_data['vendors_id'];

    //   echo $order_sent_check . ' The order sent check<br>';

    //          echo $insert_id . 'The order number<br>';

      if ($order_sent_ckeck == 'no') {

         $status='';

         $oID=$insert_id;

         $vendor_order_sent = false;

         $status=$order->info['order_status'];



         vendors_email($vendors_id, $oID, $status, $vendor_order_sent);

            }// if order check

          }// while

        }// if isset

         //  echo 'Email sent? ' . $vendor_order_sent . '<br>';

     }// if enabled

     //MVS end this file is complete

        } // END STATUS == COMPLETED LOOP



        if ($_POST['payment_status'] == 'Pending') { // START STATUS == PENDING LOOP


          $email_order = STORE_NAME . "\n" . 
                         EMAIL_SEPARATOR . "\n" . 
                         EMAIL_TEXT_ORDER_NUMBER . ' ' . $_POST['invoice'] . "\n" .
                         EMAIL_TEXT_INVOICE_URL . ' ' . tep_href_link(FILENAME_ACCOUNT_HISTORY_INFO, 'order_id=' . $_POST['invoice'], 'SSL', false) . "\n" .
                         EMAIL_TEXT_DATE_ORDERED . ' ' . strftime(DATE_FORMAT_LONG) . "\n\n" . 
                         EMAIL_SEPARATOR . "\n" .
                         EMAIL_PAYPAL_PENDING_NOTICE . "\n\n"; 

          tep_mail($order->customer['name'], $order->customer['email_address'], EMAIL_TEXT_SUBJECT, $email_order, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);

// send emails to other people
          if (SEND_EXTRA_ORDER_EMAILS_TO != '') {

            tep_mail('', SEND_EXTRA_ORDER_EMAILS_TO, EMAIL_TEXT_SUBJECT, $email_order, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);

          } 

          //MVS start

    if (SELECT_VENDOR_EMAIL_WHEN == 'Catalog' || SELECT_VENDOR_EMAIL_WHEN == 'Both') {

            $status=$order->info['order_status'];

             if (isset($status)) {

  $order_sent_query = tep_db_query("select vendor_order_sent, vendors_id from " . TABLE_ORDERS_SHIPPING . " where orders_id = '" . $insert_id . "'");

       while ($order_sent_data = tep_db_fetch_array($order_sent_query)) {

     $order_sent_ckeck = $order_sent_data['vendor_order_sent'];

     $vendors_id = $order_sent_data['vendors_id'];

    //   echo $order_sent_check . ' The order sent check<br>';

    //          echo $insert_id . 'The order number<br>';

      if ($order_sent_ckeck == 'no') {

         $status='';

         $oID=$insert_id;

         $vendor_order_sent = false;

         $status=$order->info['order_status'];



         vendors_email($vendors_id, $oID, $status, $vendor_order_sent);

            }// if order check

          }// while

        }// if isset

         //  echo 'Email sent? ' . $vendor_order_sent . '<br>';

     }// if enabled

     //MVS end this file is complete

        } // END STATUS == PENDING LOOP

//emptying cart for everyone! by Monika in Germany

        tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET . " where customers_id = '" . (int)$_POST['custom'] . "'");

        tep_db_query("delete from " . TABLE_CUSTOMERS_BASKET_ATTRIBUTES . " where customers_id = '" . (int)$_POST['custom'] . "'");
//end emptying cart for everyone
      }
    }
  } else {
    if (tep_not_null(MODULE_PAYMENT_PAYPAL_IPN_DEBUG_EMAIL)) {
      $email_body = '$_POST:' . "\n\n";
      foreach ($_POST as $key => $value) {
        $email_body .= $key . '=' . $value . "\n";
      }
      $email_body .= "\n" . '$_GET:' . "\n\n";
      foreach ($_GET as $key => $value) {
        $email_body .= $key . '=' . $value . "\n";
      }
      tep_mail('', MODULE_PAYMENT_PAYPAL_IPN_DEBUG_EMAIL, 'PayPal IPN Invalid Process', $email_body, STORE_OWNER, STORE_OWNER_EMAIL_ADDRESS);
    }

    if (isset($_POST['invoice']) && is_numeric($_POST['invoice']) && ($_POST['invoice'] > 0)) {
      $check_query = tep_db_query("select orders_id from " . TABLE_ORDERS . " where orders_id = '" . $_POST['invoice'] . "' and customers_id = '" . (int)$_POST['custom'] . "'");
      if (tep_db_num_rows($check_query) > 0) {
        $comment_status = $_POST['payment_status'];

        if ($_POST['payment_status'] == 'Pending') {
          $comment_status .= '; ' . $_POST['pending_reason'];
        } elseif ( ($_POST['payment_status'] == 'Reversed') || ($_POST['payment_status'] == 'Refunded') ) {
          $comment_status .= '; ' . $_POST['reason_code'];
        }

        tep_db_query("update " . TABLE_ORDERS . " set orders_status = '" . ((MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID > 0) ? MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID : DEFAULT_ORDERS_STATUS_ID) . "', last_modified = now() where orders_id = '" . $_POST['invoice'] . "'");

        $sql_data_array = array('orders_id' => $_POST['invoice'],
                                'orders_status_id' => (MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID > 0) ? MODULE_PAYMENT_PAYPAL_IPN_ORDER_STATUS_ID : DEFAULT_ORDERS_STATUS_ID,
                                'date_added' => 'now()',
                                'customer_notified' => '0',
                                'comments' => 'PayPal IPN Invalid [' . $comment_status . ']');



        tep_db_perform(TABLE_ORDERS_STATUS_HISTORY, $sql_data_array);

        

//MVS - added insert for new orders_shipping table

        $shipping_array = $shipping['vendor'];

  foreach ($shipping_array as $vendors_id => $shipping_data) {

    $vendors_query = tep_db_query("select vendors_name

                                   from " . TABLE_VENDORS . "

                                   where vendors_id = '" . (int)$vendors_id . "'"

                                 );

    $vendors_name = 'Unknown';

    if ($vendors = tep_db_fetch_array($vendors_query)) {

      $vendors_name = $vendors['vendors_name'];

    }

                $shipping_method_array = explode ('_', $shipping_data['id']);

                if ($shipping_method_array[0] == 'fedex1') {

                        $shipping_method = 'Federal Express';

                        } elseif ($shipping_method_array[0] == 'upsxml') {

                        $shipping_method = 'UPS';

                        } elseif ($shipping_method_array[0] == 'usps') {

                        $shipping_method = 'USPS';

                        } else {

                    $shipping_method = $shipping_method_array[0];

                    }

    $sql_data_array = array('orders_id' => $insert_id,

                            'vendors_id' => $vendors_id,

                            'shipping_module' => $shipping_method,

                            'shipping_method' => $shipping_data['title'],

                            'shipping_cost' => $shipping_data['cost'],

                            'shipping_tax' =>  $shipping_data['ship_tax'],

                            'vendors_name' => $vendors_name,

                            'vendor_order_sent' => 'no'

                           );

    tep_db_perform(TABLE_ORDERS_SHIPPING, $sql_data_array);

  }

//MVS End

      }

    }

  }


  require('includes/application_bottom.php');
?>

 

 

anyone can help with this would be greatly appreciated

alman

Share this post


Link to post
Share on other sites

The data for the MVS orders_shipping table is inserted in checkout_process.php. If Paypal IPN does not return to this page, the MVS code from checkout_process.php must be added to the Paypal return page. This needs to be after the data is inserted into the orders table so that the $orders_id is valid, and before the shipping data is destroyed (if it is.)

 

The shopping cart can be cleared by calling

$cart->reset(true);

You probably also want to unregister the session variables. This is all done at the bottom of checkout_process.php.

 

Regards

Jim


See my profile for a list of my addons and ways to get support.

Share this post


Link to post
Share on other sites

Hello :)

 

I've noticed in the file ipn.php in /html/ext/modules/payment/paypal_ipn

 

the following line as in checkout.process.php:

 

$products_ordered .= $order->products[$i]['qty'] . ' x ' . $order->products[$i]['name'] . $products_model . ' = ' . $currencies->display_price($order->products[$i]['final_price'], $order->products[$i]['tax'], $order->products[$i]['qty']) . $products_ordered_attributes . "\n";

 

Unfortunately the $products_ordered in the confirmation email has always the default currency and not the currency used by the customer. Any Help?

 

Very appreciated :)

Share this post


Link to post
Share on other sites

lads this bit of code in paypal_ipn.php

$parameters['return'] = tep_href_link(FILENAME_CHECKOUT_PROCESS, '', 'SSL');

//	  $parameters['cancel_return'] = tep_href_link(FILENAME_CHECKOUT_PAYMENT, '', 'SSL');

  $parameters['cancel_return'] = tep_href_link(FILENAME_SHOPPING_CART, 'ipn=cancel_ipn&order='.$parameters['invoice'], 'SSL');

if you cancel the order in should go to shopping_cart and if it is processed checkout_process

 

but in my case it is going to shopping cart each time even though the order went through successfully

any pointers or ideas?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×