public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown', $message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false, $secure_key = false, Shop $shop = null)
 {
     if (self::DEBUG_MODE) {
         PrestaShopLogger::addLog('PaymentModule::validateOrder - Function called', 1, null, 'Cart', (int) $id_cart, true);
     }
     if (!isset($this->context)) {
         $this->context = Context::getContext();
     }
     $this->context->cart = new Cart($id_cart);
     $this->context->customer = new Customer($this->context->cart->id_customer);
     // The tax cart is loaded before the customer so re-cache the tax calculation method
     $this->context->cart->setTaxCalculationMethod();
     $this->context->language = new Language($this->context->cart->id_lang);
     $this->context->shop = $shop ? $shop : new Shop($this->context->cart->id_shop);
     ShopUrl::resetMainDomainCache();
     $id_currency = $currency_special ? (int) $currency_special : (int) $this->context->cart->id_currency;
     $this->context->currency = new Currency($id_currency, null, $this->context->shop->id);
     if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') {
         $context_country = $this->context->country;
     }
     $order_status = new OrderState((int) $id_order_state, (int) $this->context->language->id);
     if (!Validate::isLoadedObject($order_status)) {
         PrestaShopLogger::addLog('PaymentModule::validateOrder - Order Status cannot be loaded', 3, null, 'Cart', (int) $id_cart, true);
         throw new PrestaShopException('Can\'t load Order status');
     }
     if (!$this->active) {
         PrestaShopLogger::addLog('PaymentModule::validateOrder - Module is not active', 3, null, 'Cart', (int) $id_cart, true);
         die(Tools::displayError());
     }
     // Does order already exists ?
     if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists() == false) {
         if ($secure_key !== false && $secure_key != $this->context->cart->secure_key) {
             PrestaShopLogger::addLog('PaymentModule::validateOrder - Secure key does not match', 3, null, 'Cart', (int) $id_cart, true);
             die(Tools::displayError());
         }
         // For each package, generate an order
         $delivery_option_list = $this->context->cart->getDeliveryOptionList();
         $package_list = $this->context->cart->getPackageList();
         $cart_delivery_option = $this->context->cart->getDeliveryOption();
         // If some delivery options are not defined, or not valid, use the first valid option
         foreach ($delivery_option_list as $id_address => $package) {
             if (!isset($cart_delivery_option[$id_address]) || !array_key_exists($cart_delivery_option[$id_address], $package)) {
                 foreach ($package as $key => $val) {
                     $cart_delivery_option[$id_address] = $key;
                     break;
                 }
             }
         }
         $order_list = array();
         $order_detail_list = array();
         do {
             $reference = Order::generateReference();
         } while (Order::getByReference($reference)->count());
         $this->currentOrderReference = $reference;
         $order_creation_failed = false;
         $cart_total_paid = (double) Tools::ps_round((double) $this->context->cart->getOrderTotal(true, Cart::BOTH), 2);
         foreach ($cart_delivery_option as $id_address => $key_carriers) {
             foreach ($delivery_option_list[$id_address][$key_carriers]['carrier_list'] as $id_carrier => $data) {
                 foreach ($data['package_list'] as $id_package) {
                     // Rewrite the id_warehouse
                     $package_list[$id_address][$id_package]['id_warehouse'] = (int) $this->context->cart->getPackageIdWarehouse($package_list[$id_address][$id_package], (int) $id_carrier);
                     $package_list[$id_address][$id_package]['id_carrier'] = $id_carrier;
                 }
             }
         }
         // Make sure CartRule caches are empty
         CartRule::cleanCache();
         $cart_rules = $this->context->cart->getCartRules();
         foreach ($cart_rules as $cart_rule) {
             if (($rule = new CartRule((int) $cart_rule['obj']->id)) && Validate::isLoadedObject($rule)) {
                 if ($error = $rule->checkValidity($this->context, true, true)) {
                     $this->context->cart->removeCartRule((int) $rule->id);
                     if (isset($this->context->cookie) && isset($this->context->cookie->id_customer) && $this->context->cookie->id_customer && !empty($rule->code)) {
                         if (Configuration::get('PS_ORDER_PROCESS_TYPE') == 1) {
                             Tools::redirect('index.php?controller=order-opc&submitAddDiscount=1&discount_name=' . urlencode($rule->code));
                         }
                         Tools::redirect('index.php?controller=order&submitAddDiscount=1&discount_name=' . urlencode($rule->code));
                     } else {
                         $rule_name = isset($rule->name[(int) $this->context->cart->id_lang]) ? $rule->name[(int) $this->context->cart->id_lang] : $rule->code;
                         $error = Tools::displayError(sprintf('CartRule ID %1s (%2s) used in this cart is not valid and has been withdrawn from cart', (int) $rule->id, $rule_name));
                         PrestaShopLogger::addLog($error, 3, '0000002', 'Cart', (int) $this->context->cart->id);
                     }
                 }
             }
         }
         foreach ($package_list as $id_address => $packageByAddress) {
             foreach ($packageByAddress as $id_package => $package) {
                 $order = new Order();
                 $order->product_list = $package['product_list'];
                 if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') {
                     $address = new Address($id_address);
                     $this->context->country = new Country($address->id_country, $this->context->cart->id_lang);
                     if (!$this->context->country->active) {
                         throw new PrestaShopException('The delivery address country is not active.');
                     }
                 }
                 $carrier = null;
                 if (!$this->context->cart->isVirtualCart() && isset($package['id_carrier'])) {
                     $carrier = new Carrier($package['id_carrier'], $this->context->cart->id_lang);
                     $order->id_carrier = (int) $carrier->id;
                     $id_carrier = (int) $carrier->id;
                 } else {
                     $order->id_carrier = 0;
                     $id_carrier = 0;
                 }
                 $order->id_customer = (int) $this->context->cart->id_customer;
                 $order->id_address_invoice = (int) $this->context->cart->id_address_invoice;
                 $order->id_address_delivery = (int) $id_address;
                 $order->id_currency = $this->context->currency->id;
                 $order->id_lang = (int) $this->context->cart->id_lang;
                 $order->id_cart = (int) $this->context->cart->id;
                 $order->reference = $reference;
                 $order->id_shop = (int) $this->context->shop->id;
                 $order->id_shop_group = (int) $this->context->shop->id_shop_group;
                 $order->secure_key = $secure_key ? pSQL($secure_key) : pSQL($this->context->customer->secure_key);
                 $order->payment = $payment_method;
                 if (isset($this->name)) {
                     $order->module = $this->name;
                 }
                 $order->recyclable = $this->context->cart->recyclable;
                 $order->gift = (int) $this->context->cart->gift;
                 $order->gift_message = $this->context->cart->gift_message;
                 $order->mobile_theme = $this->context->cart->mobile_theme;
                 $order->conversion_rate = $this->context->currency->conversion_rate;
                 $amount_paid = !$dont_touch_amount ? Tools::ps_round((double) $amount_paid, 2) : $amount_paid;
                 $order->total_paid_real = 0;
                 $order->total_products = (double) $this->context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier);
                 $order->total_products_wt = (double) $this->context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier);
                 $order->total_discounts_tax_excl = (double) abs($this->context->cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier));
                 $order->total_discounts_tax_incl = (double) abs($this->context->cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier));
                 $order->total_discounts = $order->total_discounts_tax_incl;
                 $order->total_shipping_tax_excl = (double) $this->context->cart->getPackageShippingCost((int) $id_carrier, false, null, $order->product_list);
                 $order->total_shipping_tax_incl = (double) $this->context->cart->getPackageShippingCost((int) $id_carrier, true, null, $order->product_list);
                 $order->total_shipping = $order->total_shipping_tax_incl;
                 if (!is_null($carrier) && Validate::isLoadedObject($carrier)) {
                     $order->carrier_tax_rate = $carrier->getTaxesRate(new Address($this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));
                 }
                 $order->total_wrapping_tax_excl = (double) abs($this->context->cart->getOrderTotal(false, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier));
                 $order->total_wrapping_tax_incl = (double) abs($this->context->cart->getOrderTotal(true, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier));
                 $order->total_wrapping = $order->total_wrapping_tax_incl;
                 $order->total_paid_tax_excl = (double) Tools::ps_round((double) $this->context->cart->getOrderTotal(false, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_);
                 $order->total_paid_tax_incl = (double) Tools::ps_round((double) $this->context->cart->getOrderTotal(true, Cart::BOTH, $order->product_list, $id_carrier), _PS_PRICE_COMPUTE_PRECISION_);
                 $order->total_paid = $order->total_paid_tax_incl;
                 $order->round_mode = Configuration::get('PS_PRICE_ROUND_MODE');
                 $order->invoice_date = '0000-00-00 00:00:00';
                 $order->delivery_date = '0000-00-00 00:00:00';
                 if (self::DEBUG_MODE) {
                     PrestaShopLogger::addLog('PaymentModule::validateOrder - Order is about to be added', 1, null, 'Cart', (int) $id_cart, true);
                 }
                 // Creating order
                 $result = $order->add();
                 if (!$result) {
                     PrestaShopLogger::addLog('PaymentModule::validateOrder - Order cannot be created', 3, null, 'Cart', (int) $id_cart, true);
                     throw new PrestaShopException('Can\'t save Order');
                 }
                 // Amount paid by customer is not the right one -> Status = payment error
                 // We don't use the following condition to avoid the float precision issues : http://www.php.net/manual/en/language.types.float.php
                 // if ($order->total_paid != $order->total_paid_real)
                 // We use number_format in order to compare two string
                 if ($order_status->logable && number_format($cart_total_paid, _PS_PRICE_COMPUTE_PRECISION_) != number_format($amount_paid, _PS_PRICE_COMPUTE_PRECISION_)) {
                     $id_order_state = Configuration::get('PS_OS_ERROR');
                 }
                 $order_list[] = $order;
                 if (self::DEBUG_MODE) {
                     PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderDetail is about to be added', 1, null, 'Cart', (int) $id_cart, true);
                 }
                 // Insert new Order detail list using cart for the current order
                 $order_detail = new OrderDetail(null, null, $this->context);
                 $order_detail->createList($order, $this->context->cart, $id_order_state, $order->product_list, 0, true, $package_list[$id_address][$id_package]['id_warehouse']);
                 $order_detail_list[] = $order_detail;
                 if (self::DEBUG_MODE) {
                     PrestaShopLogger::addLog('PaymentModule::validateOrder - OrderCarrier is about to be added', 1, null, 'Cart', (int) $id_cart, true);
                 }
                 // Adding an entry in order_carrier table
                 if (!is_null($carrier)) {
                     $order_carrier = new OrderCarrier();
                     $order_carrier->id_order = (int) $order->id;
                     $order_carrier->id_carrier = (int) $id_carrier;
                     $order_carrier->weight = (double) $order->getTotalWeight();
                     $order_carrier->shipping_cost_tax_excl = (double) $order->total_shipping_tax_excl;
                     $order_carrier->shipping_cost_tax_incl = (double) $order->total_shipping_tax_incl;
                     $order_carrier->add();
                 }
             }
         }
         // The country can only change if the address used for the calculation is the delivery address, and if multi-shipping is activated
         if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery') {
             $this->context->country = $context_country;
         }
         if (!$this->context->country->active) {
             PrestaShopLogger::addLog('PaymentModule::validateOrder - Country is not active', 3, null, 'Cart', (int) $id_cart, true);
             throw new PrestaShopException('The order address country is not active.');
         }
         if (self::DEBUG_MODE) {
             PrestaShopLogger::addLog('PaymentModule::validateOrder - Payment is about to be added', 1, null, 'Cart', (int) $id_cart, true);
         }
         // Register Payment only if the order status validate the order
         if ($order_status->logable) {
             // $order is the last order loop in the foreach
             // The method addOrderPayment of the class Order make a create a paymentOrder
             //     linked to the order reference and not to the order id
             if (isset($extra_vars['transaction_id'])) {
                 $transaction_id = $extra_vars['transaction_id'];
             } else {
                 $transaction_id = null;
             }
             if (!$order->addOrderPayment($amount_paid, null, $transaction_id)) {
                 PrestaShopLogger::addLog('PaymentModule::validateOrder - Cannot save Order Payment', 3, null, 'Cart', (int) $id_cart, true);
                 throw new PrestaShopException('Can\'t save Order Payment');
             }
         }
         // Next !
         $only_one_gift = false;
         $cart_rule_used = array();
         $products = $this->context->cart->getProducts();
         // Make sure CarRule caches are empty
         CartRule::cleanCache();
         foreach ($order_detail_list as $key => $order_detail) {
             $order = $order_list[$key];
             if (!$order_creation_failed && isset($order->id)) {
                 if (!$secure_key) {
                     $message .= '<br />' . Tools::displayError('Warning: the secure key is empty, check your payment account before validation');
                 }
                 // Optional message to attach to this order
                 if (isset($message) & !empty($message)) {
                     $msg = new Message();
                     $message = strip_tags($message, '<br>');
                     if (Validate::isCleanHtml($message)) {
                         if (self::DEBUG_MODE) {
                             PrestaShopLogger::addLog('PaymentModule::validateOrder - Message is about to be added', 1, null, 'Cart', (int) $id_cart, true);
                         }
                         $msg->message = $message;
                         $msg->id_order = (int) $order->id;
                         $msg->private = 1;
                         $msg->add();
                     }
                 }
                 // Insert new Order detail list using cart for the current order
                 //$orderDetail = new OrderDetail(null, null, $this->context);
                 //$orderDetail->createList($order, $this->context->cart, $id_order_state);
                 // Construct order detail table for the email
                 $products_list = '';
                 $virtual_product = true;
                 $ppropertiessmartprice_hook1 = null;
                 $product_var_tpl_list = array();
                 foreach ($order->product_list as $product) {
                     PP::smartyPPAssign(array('cart' => $product, 'currency' => $this->context->currency));
                     $price = Product::getPriceStatic((int) $product['id_product'], false, $product['id_product_attribute'] ? (int) $product['id_product_attribute'] : null, 6, null, false, true, array($product['cart_quantity'], $product['cart_quantity_fractional']), false, (int) $order->id_customer, (int) $order->id_cart, (int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
                     $price_wt = Product::getPriceStatic((int) $product['id_product'], true, $product['id_product_attribute'] ? (int) $product['id_product_attribute'] : null, 2, null, false, true, array($product['cart_quantity'], $product['cart_quantity_fractional']), false, (int) $order->id_customer, (int) $order->id_cart, (int) $order->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
                     $ppropertiessmartprice_hook2 = '';
                     $product_var_tpl = array('reference' => $product['reference'], 'name' => $product['name'] . (isset($product['attributes']) ? ' - ' . $product['attributes'] : '') . PP::smartyDisplayProductName(array('name' => '')) . $ppropertiessmartprice_hook2, 'unit_price' => PP::smartyDisplayPrice(array('price' => Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt)), 'price' => PP::smartyDisplayPrice(array('price' => Product::getTaxCalculationMethod() == PS_TAX_EXC ? $product['total'] : $product['total_wt'], 'quantity' => (int) $product['cart_quantity'], 'm' => 'total')), 'quantity' => PP::smartyDisplayQty(array('quantity' => (int) $product['cart_quantity'])), 'customization' => array());
                     $customized_datas = Product::getAllCustomizedDatas((int) $order->id_cart);
                     $productHasCustomizedDatas = Product::hasCustomizedDatas($product, $customized_datas);
                     if ($productHasCustomizedDatas && isset($customized_datas[$product['id_product']][$product['id_product_attribute']])) {
                         $product_var_tpl['customization'] = array();
                         foreach ($customized_datas[$product['id_product']][$product['id_product_attribute']][$order->id_address_delivery] as $customization) {
                             if ($product['id_cart_product'] == $customization['id_cart_product']) {
                                 $customization_text = '';
                                 if (isset($customization['datas'][Product::CUSTOMIZE_TEXTFIELD])) {
                                     foreach ($customization['datas'][Product::CUSTOMIZE_TEXTFIELD] as $text) {
                                         $customization_text .= $text['name'] . ': ' . $text['value'] . '<br />';
                                     }
                                 }
                                 if (isset($customization['datas'][Product::CUSTOMIZE_FILE])) {
                                     $customization_text .= sprintf(Tools::displayError('%d image(s)'), count($customization['datas'][Product::CUSTOMIZE_FILE])) . '<br />';
                                 }
                                 $customization_quantity = (int) $product['customization_quantity'];
                                 $product_var_tpl['customization'][] = array('customization_text' => $customization_text, 'customization_quantity' => PP::smartyDisplayQty(array('quantity' => $customization_quantity)), 'quantity' => PP::smartyDisplayPrice(array('price' => Product::getTaxCalculationMethod() == PS_TAX_EXC ? $product['total_customization'] : $product['total_customization_wt'], 'm' => 'total')));
                             }
                         }
                     }
                     $product_var_tpl_list[] = $product_var_tpl;
                     // Check if is not a virutal product for the displaying of shipping
                     if (!$product['is_virtual']) {
                         $virtual_product &= false;
                     }
                 }
                 // end foreach ($products)
                 PP::smartyPPAssign();
                 $product_list_txt = '';
                 $product_list_html = '';
                 if (count($product_var_tpl_list) > 0) {
                     $product_list_txt = $this->getEmailTemplateContent('order_conf_product_list.txt', Mail::TYPE_TEXT, $product_var_tpl_list);
                     $product_list_html = $this->getEmailTemplateContent('order_conf_product_list.tpl', Mail::TYPE_HTML, $product_var_tpl_list);
                 }
                 $cart_rules_list = array();
                 $total_reduction_value_ti = 0;
                 $total_reduction_value_tex = 0;
                 foreach ($cart_rules as $cart_rule) {
                     $package = array('id_carrier' => $order->id_carrier, 'id_address' => $order->id_address_delivery, 'products' => $order->product_list);
                     $values = array('tax_incl' => $cart_rule['obj']->getContextualValue(true, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package), 'tax_excl' => $cart_rule['obj']->getContextualValue(false, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package));
                     // If the reduction is not applicable to this order, then continue with the next one
                     if (!$values['tax_excl']) {
                         continue;
                     }
                     // IF
                     //     This is not multi-shipping
                     //     The value of the voucher is greater than the total of the order
                     //     Partial use is allowed
                     //     This is an "amount" reduction, not a reduction in % or a gift
                     // THEN
                     //     The voucher is cloned with a new value corresponding to the remainder
                     if (count($order_list) == 1 && $values['tax_incl'] > $order->total_products_wt - $total_reduction_value_ti && $cart_rule['obj']->partial_use == 1 && $cart_rule['obj']->reduction_amount > 0) {
                         // Create a new voucher from the original
                         $voucher = new CartRule($cart_rule['obj']->id);
                         // We need to instantiate the CartRule without lang parameter to allow saving it
                         unset($voucher->id);
                         // Set a new voucher code
                         $voucher->code = empty($voucher->code) ? Tools::substr(md5($order->id . '-' . $order->id_customer . '-' . $cart_rule['obj']->id), 0, 16) : $voucher->code . '-2';
                         if (preg_match('/\\-([0-9]{1,2})\\-([0-9]{1,2})$/', $voucher->code, $matches) && $matches[1] == $matches[2]) {
                             $voucher->code = preg_replace('/' . $matches[0] . '$/', '-' . (int) ($matches[1] + 1), $voucher->code);
                         }
                         // Set the new voucher value
                         if ($voucher->reduction_tax) {
                             $voucher->reduction_amount = $total_reduction_value_ti + $values['tax_incl'] - $order->total_products_wt;
                             // Add total shipping amout only if reduction amount > total shipping
                             if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_incl) {
                                 $voucher->reduction_amount -= $order->total_shipping_tax_incl;
                             }
                         } else {
                             $voucher->reduction_amount = $total_reduction_value_tex + $values['tax_excl'] - $order->total_products;
                             // Add total shipping amout only if reduction amount > total shipping
                             if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_excl) {
                                 $voucher->reduction_amount -= $order->total_shipping_tax_excl;
                             }
                         }
                         if ($voucher->reduction_amount <= 0) {
                             continue;
                         }
                         $voucher->id_customer = $order->id_customer;
                         $voucher->quantity = 1;
                         $voucher->quantity_per_user = 1;
                         $voucher->free_shipping = 0;
                         if ($voucher->add()) {
                             // If the voucher has conditions, they are now copied to the new voucher
                             CartRule::copyConditions($cart_rule['obj']->id, $voucher->id);
                             $params = array('{voucher_amount}' => Tools::displayPrice($voucher->reduction_amount, $this->context->currency, false), '{voucher_num}' => $voucher->code, '{firstname}' => $this->context->customer->firstname, '{lastname}' => $this->context->customer->lastname, '{id_order}' => $order->reference, '{order_name}' => $order->getUniqReference());
                             Mail::Send((int) $order->id_lang, 'voucher', sprintf(Mail::l('New voucher for your order %s', (int) $order->id_lang), $order->reference), $params, $this->context->customer->email, $this->context->customer->firstname . ' ' . $this->context->customer->lastname, null, null, null, null, _PS_MAIL_DIR_, false, (int) $order->id_shop);
                         }
                         $values['tax_incl'] = $order->total_products_wt - $total_reduction_value_ti;
                         $values['tax_excl'] = $order->total_products - $total_reduction_value_tex;
                     }
                     $total_reduction_value_ti += $values['tax_incl'];
                     $total_reduction_value_tex += $values['tax_excl'];
                     $order->addCartRule($cart_rule['obj']->id, $cart_rule['obj']->name, $values, 0, $cart_rule['obj']->free_shipping);
                     if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && !in_array($cart_rule['obj']->id, $cart_rule_used)) {
                         $cart_rule_used[] = $cart_rule['obj']->id;
                         // Create a new instance of Cart Rule without id_lang, in order to update its quantity
                         $cart_rule_to_update = new CartRule($cart_rule['obj']->id);
                         $cart_rule_to_update->quantity = max(0, $cart_rule_to_update->quantity - 1);
                         $cart_rule_to_update->update();
                     }
                     $cart_rules_list[] = array('voucher_name' => $cart_rule['obj']->name, 'voucher_reduction' => ($values['tax_incl'] != 0.0 ? '-' : '') . Tools::displayPrice($values['tax_incl'], $this->context->currency, false));
                 }
                 $cart_rules_list_txt = '';
                 $cart_rules_list_html = '';
                 if (count($cart_rules_list) > 0) {
                     $cart_rules_list_txt = $this->getEmailTemplateContent('order_conf_cart_rules.txt', Mail::TYPE_TEXT, $cart_rules_list);
                     $cart_rules_list_html = $this->getEmailTemplateContent('order_conf_cart_rules.tpl', Mail::TYPE_HTML, $cart_rules_list);
                 }
                 // Specify order id for message
                 $old_message = Message::getMessageByCartId((int) $this->context->cart->id);
                 if ($old_message) {
                     $update_message = new Message((int) $old_message['id_message']);
                     $update_message->id_order = (int) $order->id;
                     $update_message->update();
                     // Add this message in the customer thread
                     $customer_thread = new CustomerThread();
                     $customer_thread->id_contact = 0;
                     $customer_thread->id_customer = (int) $order->id_customer;
                     $customer_thread->id_shop = (int) $this->context->shop->id;
                     $customer_thread->id_order = (int) $order->id;
                     $customer_thread->id_lang = (int) $this->context->language->id;
                     $customer_thread->email = $this->context->customer->email;
                     $customer_thread->status = 'open';
                     $customer_thread->token = Tools::passwdGen(12);
                     $customer_thread->add();
                     $customer_message = new CustomerMessage();
                     $customer_message->id_customer_thread = $customer_thread->id;
                     $customer_message->id_employee = 0;
                     $customer_message->message = $update_message->message;
                     $customer_message->private = 0;
                     if (!$customer_message->add()) {
                         $this->errors[] = Tools::displayError('An error occurred while saving message');
                     }
                 }
                 if (self::DEBUG_MODE) {
                     PrestaShopLogger::addLog('PaymentModule::validateOrder - Hook validateOrder is about to be called', 1, null, 'Cart', (int) $id_cart, true);
                 }
                 // Hook validate order
                 Hook::exec('actionValidateOrder', array('cart' => $this->context->cart, 'order' => $order, 'customer' => $this->context->customer, 'currency' => $this->context->currency, 'orderStatus' => $order_status));
                 foreach ($this->context->cart->getProducts() as $product) {
                     if ($order_status->logable) {
                         ProductSale::addProductSale((int) $product['id_product'], (int) $product['cart_quantity']);
                     }
                 }
                 if (self::DEBUG_MODE) {
                     PrestaShopLogger::addLog('PaymentModule::validateOrder - Order Status is about to be added', 1, null, 'Cart', (int) $id_cart, true);
                 }
                 // Set the order status
                 $new_history = new OrderHistory();
                 $new_history->id_order = (int) $order->id;
                 $new_history->changeIdOrderState((int) $id_order_state, $order, true);
                 $new_history->addWithemail(true, $extra_vars);
                 // Switch to back order if needed
                 if (Configuration::get('PS_STOCK_MANAGEMENT') && $order_detail->getStockState()) {
                     $history = new OrderHistory();
                     $history->id_order = (int) $order->id;
                     $history->changeIdOrderState(Configuration::get($order->valid ? 'PS_OS_OUTOFSTOCK_PAID' : 'PS_OS_OUTOFSTOCK_UNPAID'), $order, true);
                     $history->addWithemail();
                 }
                 unset($order_detail);
                 // Order is reloaded because the status just changed
                 $order = new Order($order->id);
                 // Send an e-mail to customer (one order = one email)
                 if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && $this->context->customer->id) {
                     $invoice = new Address($order->id_address_invoice);
                     $delivery = new Address($order->id_address_delivery);
                     $delivery_state = $delivery->id_state ? new State($delivery->id_state) : false;
                     $invoice_state = $invoice->id_state ? new State($invoice->id_state) : false;
                     $data = array('{firstname}' => $this->context->customer->firstname, '{lastname}' => $this->context->customer->lastname, '{email}' => $this->context->customer->email, '{delivery_block_txt}' => $this->_getFormatedAddress($delivery, "\n"), '{invoice_block_txt}' => $this->_getFormatedAddress($invoice, "\n"), '{delivery_block_html}' => $this->_getFormatedAddress($delivery, '<br />', array('firstname' => '<span style="font-weight:bold;">%s</span>', 'lastname' => '<span style="font-weight:bold;">%s</span>')), '{invoice_block_html}' => $this->_getFormatedAddress($invoice, '<br />', array('firstname' => '<span style="font-weight:bold;">%s</span>', 'lastname' => '<span style="font-weight:bold;">%s</span>')), '{delivery_company}' => $delivery->company, '{delivery_firstname}' => $delivery->firstname, '{delivery_lastname}' => $delivery->lastname, '{delivery_address1}' => $delivery->address1, '{delivery_address2}' => $delivery->address2, '{delivery_city}' => $delivery->city, '{delivery_postal_code}' => $delivery->postcode, '{delivery_country}' => $delivery->country, '{delivery_state}' => $delivery->id_state ? $delivery_state->name : '', '{delivery_phone}' => $delivery->phone ? $delivery->phone : $delivery->phone_mobile, '{delivery_other}' => $delivery->other, '{invoice_company}' => $invoice->company, '{invoice_vat_number}' => $invoice->vat_number, '{invoice_firstname}' => $invoice->firstname, '{invoice_lastname}' => $invoice->lastname, '{invoice_address2}' => $invoice->address2, '{invoice_address1}' => $invoice->address1, '{invoice_city}' => $invoice->city, '{invoice_postal_code}' => $invoice->postcode, '{invoice_country}' => $invoice->country, '{invoice_state}' => $invoice->id_state ? $invoice_state->name : '', '{invoice_phone}' => $invoice->phone ? $invoice->phone : $invoice->phone_mobile, '{invoice_other}' => $invoice->other, '{order_name}' => $order->getUniqReference(), '{date}' => Tools::displayDate(date('Y-m-d H:i:s'), null, 1), '{carrier}' => $virtual_product || !isset($carrier->name) ? Tools::displayError('No carrier') : $carrier->name, '{payment}' => Tools::substr($order->payment, 0, 32), '{products}' => $product_list_html, '{products_txt}' => $product_list_txt, '{discounts}' => $cart_rules_list_html, '{discounts_txt}' => $cart_rules_list_txt, '{total_paid}' => Tools::displayPrice($order->total_paid, $this->context->currency, false), '{total_products}' => Tools::displayPrice($order->total_paid - $order->total_shipping - $order->total_wrapping + $order->total_discounts, $this->context->currency, false), '{total_discounts}' => Tools::displayPrice($order->total_discounts, $this->context->currency, false), '{total_shipping}' => Tools::displayPrice($order->total_shipping, $this->context->currency, false), '{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $this->context->currency, false), '{total_tax_paid}' => Tools::displayPrice($order->total_products_wt - $order->total_products + ($order->total_shipping_tax_incl - $order->total_shipping_tax_excl), $this->context->currency, false));
                     if (is_array($extra_vars)) {
                         $data = array_merge($data, $extra_vars);
                     }
                     // Join PDF invoice
                     if ((int) Configuration::get('PS_INVOICE') && $order_status->invoice && $order->invoice_number) {
                         $pdf = new PDF($order->getInvoicesCollection(), PDF::TEMPLATE_INVOICE, $this->context->smarty);
                         $file_attachement = array();
                         $file_attachement['content'] = $pdf->render(false);
                         $file_attachement['name'] = Configuration::get('PS_INVOICE_PREFIX', (int) $order->id_lang, null, $order->id_shop) . sprintf('%06d', $order->invoice_number) . '.pdf';
                         $file_attachement['mime'] = 'application/pdf';
                     } else {
                         $file_attachement = null;
                     }
                     if (self::DEBUG_MODE) {
                         PrestaShopLogger::addLog('PaymentModule::validateOrder - Mail is about to be sent', 1, null, 'Cart', (int) $id_cart, true);
                     }
                     if (Validate::isEmail($this->context->customer->email)) {
                         Mail::Send((int) $order->id_lang, 'order_conf', Mail::l('Order confirmation', (int) $order->id_lang), $data, $this->context->customer->email, $this->context->customer->firstname . ' ' . $this->context->customer->lastname, null, null, $file_attachement, null, _PS_MAIL_DIR_, false, (int) $order->id_shop);
                     }
                 }
                 // updates stock in shops
                 if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT')) {
                     $product_list = $order->getProducts();
                     foreach ($product_list as $product) {
                         // if the available quantities depends on the physical stock
                         if (StockAvailable::dependsOnStock($product['product_id'])) {
                             // synchronizes
                             StockAvailable::synchronize($product['product_id'], $order->id_shop);
                         }
                     }
                 }
             } else {
                 $error = Tools::displayError('Order creation failed');
                 PrestaShopLogger::addLog($error, 4, '0000002', 'Cart', (int) $order->id_cart);
                 die($error);
             }
         }
         // End foreach $order_detail_list
         // Update Order Details Tax in case cart rules have free shipping
         foreach ($order->getOrderDetailList() as $detail) {
             $order_detail = new OrderDetail($detail['id_order_detail']);
             $order_detail->updateTaxAmount($order);
         }
         // Use the last order as currentOrder
         if (isset($order) && $order->id) {
             $this->currentOrder = (int) $order->id;
         }
         if (self::DEBUG_MODE) {
             PrestaShopLogger::addLog('PaymentModule::validateOrder - End of validateOrder', 1, null, 'Cart', (int) $id_cart, true);
         }
         return true;
     } else {
         $error = Tools::displayError('Cart cannot be loaded or an order has already been placed using this cart');
         PrestaShopLogger::addLog($error, 4, '0000001', 'Cart', (int) $this->context->cart->id);
         die($error);
     }
 }
Exemple #2
0
    /**
     * @param bool $autodate Optional
     * @param array $template_vars Optional
     * @param Context $context Optional
     * @return bool
     */
    public function addWithemail($autodate = true, $template_vars = false, Context $context = null)
    {
        if (!$context) {
            $context = Context::getContext();
        }
        $order = new Order($this->id_order);
        if (!$this->add($autodate)) {
            return false;
        }
        $result = Db::getInstance()->getRow('
			SELECT osl.`template`, c.`lastname`, c.`firstname`, osl.`name` AS osname, c.`email`, os.`module_name`, os.`id_order_state`
			FROM `' . _DB_PREFIX_ . 'order_history` oh
				LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON oh.`id_order` = o.`id_order`
				LEFT JOIN `' . _DB_PREFIX_ . 'customer` c ON o.`id_customer` = c.`id_customer`
				LEFT JOIN `' . _DB_PREFIX_ . 'order_state` os ON oh.`id_order_state` = os.`id_order_state`
				LEFT JOIN `' . _DB_PREFIX_ . 'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = o.`id_lang`)
			WHERE oh.`id_order_history` = ' . (int) $this->id . ' AND os.`send_email` = 1');
        if (isset($result['template']) && Validate::isEmail($result['email'])) {
            ShopUrl::cacheMainDomainForShop($order->id_shop);
            $topic = $result['osname'];
            $data = array('{lastname}' => $result['lastname'], '{firstname}' => $result['firstname'], '{id_order}' => (int) $this->id_order, '{order_name}' => $order->getUniqReference());
            if ($template_vars) {
                $data = array_merge($data, $template_vars);
            }
            if ($result['module_name']) {
                $module = Module::getInstanceByName($result['module_name']);
                if (Validate::isLoadedObject($module) && isset($module->extra_mail_vars) && is_array($module->extra_mail_vars)) {
                    $data = array_merge($data, $module->extra_mail_vars);
                }
            }
            $data['{total_paid}'] = Tools::displayPrice((double) $order->total_paid, new Currency((int) $order->id_currency), false);
            $data['{order_name}'] = $order->getUniqReference();
            if (Validate::isLoadedObject($order)) {
                // Join PDF invoice if order state is "payment accepted"
                if ((int) $result['id_order_state'] === 2 && (int) Configuration::get('PS_INVOICE') && $order->invoice_number) {
                    $context = Context::getContext();
                    $pdf = new PDF($order->getInvoicesCollection(), PDF::TEMPLATE_INVOICE, $context->smarty);
                    $file_attachement['content'] = $pdf->render(false);
                    $file_attachement['name'] = Configuration::get('PS_INVOICE_PREFIX', (int) $order->id_lang, null, $order->id_shop) . sprintf('%06d', $order->invoice_number) . '.pdf';
                    $file_attachement['mime'] = 'application/pdf';
                } else {
                    $file_attachement = null;
                }
                Mail::Send((int) $order->id_lang, $result['template'], $topic, $data, $result['email'], $result['firstname'] . ' ' . $result['lastname'], null, null, $file_attachement, null, _PS_MAIL_DIR_, false, (int) $order->id_shop);
            }
            ShopUrl::resetMainDomainCache();
        }
        return true;
    }
Exemple #3
0
    /**
     * return the link elements for the CMS object
     *
     * @param array  $link_sitemap contain all the links for the Google Sitemap file to be generated
     * @param string $lang         the language of link to add
     * @param int    $index        the index of the current Google Sitemap file
     * @param int    $i            the count of elements added to sitemap main array
     * @param int    $id_cms       the CMS object identifier
     *
     * @return bool
     */
    private function _getCmsLink(&$link_sitemap, $lang, &$index, &$i, $id_cms = 0)
    {
        $link = new Link();
        if (method_exists('ShopUrl', 'resetMainDomainCache')) {
            ShopUrl::resetMainDomainCache();
        }
        $cmss_id = Db::getInstance()->ExecuteS('SELECT c.`id_cms` FROM `' . _DB_PREFIX_ . 'cms` c INNER JOIN `' . _DB_PREFIX_ . 'cms_lang` cl ON c.`id_cms` = cl.`id_cms` ' . ($this->tableColumnExists(_DB_PREFIX_ . 'supplier_shop') ? 'INNER JOIN `' . _DB_PREFIX_ . 'cms_shop` cs ON c.`id_cms` = cs.`id_cms` ' : '') . 'INNER JOIN `' . _DB_PREFIX_ . 'cms_category` cc ON c.id_cms_category = cc.id_cms_category AND cc.active = 1
				WHERE c.`active` =1 AND c.`id_cms` > ' . (int) $id_cms . ($this->tableColumnExists(_DB_PREFIX_ . 'supplier_shop') ? ' AND cs.id_shop = ' . (int) $this->context->shop->id : '') . ' AND cl.`id_lang` = ' . (int) $lang['id_lang'] . ' ORDER BY c.`id_cms` ASC');
        foreach ($cmss_id as $cms_id) {
            $cms = new CMS((int) $cms_id['id_cms'], $lang['id_lang']);
            $cms->link_rewrite = urlencode(is_array($cms->link_rewrite) ? $cms->link_rewrite[(int) $lang['id_lang']] : $cms->link_rewrite);
            $url = $link->getCMSLink($cms, null, null, $lang['id_lang']);
            if (!$this->_addLinkToSitemap($link_sitemap, array('type' => 'cms', 'page' => 'cms', 'link' => $url, 'image' => false), $lang['iso_code'], $index, $i, $cms_id['id_cms'])) {
                return false;
            }
        }
        return true;
    }
    public function sendEmail($order, $template_vars = false)
    {
        $result = Db::getInstance()->getRow('
			SELECT osl.`template`, c.`lastname`, c.`firstname`, osl.`name` AS osname, c.`email`, os.`module_name`, os.`id_order_state`, os.`pdf_invoice`, os.`pdf_delivery`
			FROM `' . _DB_PREFIX_ . 'order_history` oh
				LEFT JOIN `' . _DB_PREFIX_ . 'orders` o ON oh.`id_order` = o.`id_order`
				LEFT JOIN `' . _DB_PREFIX_ . 'customer` c ON o.`id_customer` = c.`id_customer`
				LEFT JOIN `' . _DB_PREFIX_ . 'order_state` os ON oh.`id_order_state` = os.`id_order_state`
				LEFT JOIN `' . _DB_PREFIX_ . 'order_state_lang` osl ON (os.`id_order_state` = osl.`id_order_state` AND osl.`id_lang` = o.`id_lang`)
			WHERE oh.`id_order_history` = ' . (int) $this->id . ' AND os.`send_email` = 1');
        if (isset($result['template']) && Validate::isEmail($result['email'])) {
            ShopUrl::cacheMainDomainForShop($order->id_shop);
            $topic = $result['osname'];
            $data = array('{lastname}' => $result['lastname'], '{firstname}' => $result['firstname'], '{id_order}' => (int) $this->id_order, '{order_name}' => $order->getUniqReference());
            if ($result['module_name']) {
                $module = Module::getInstanceByName($result['module_name']);
                if (Validate::isLoadedObject($module) && isset($module->extra_mail_vars) && is_array($module->extra_mail_vars)) {
                    $data = array_merge($data, $module->extra_mail_vars);
                }
            }
            if ($template_vars) {
                $data = array_merge($data, $template_vars);
            }
            $data['{total_paid}'] = Tools::displayPrice((double) $order->total_paid, new Currency((int) $order->id_currency), false);
            if (Validate::isLoadedObject($order)) {
                // Attach invoice and / or delivery-slip if they exists and status is set to attach them
                if ($result['pdf_invoice'] || $result['pdf_delivery']) {
                    $context = Context::getContext();
                    $invoice = $order->getInvoicesCollection();
                    $file_attachement = array();
                    if ($result['pdf_invoice'] && (int) Configuration::get('PS_INVOICE') && $order->invoice_number) {
                        Hook::exec('actionPDFInvoiceRender', array('order_invoice_list' => $invoice));
                        $pdf = new PDF($invoice, PDF::TEMPLATE_INVOICE, $context->smarty);
                        $file_attachement['invoice']['content'] = $pdf->render(false);
                        $file_attachement['invoice']['name'] = Configuration::get('PS_INVOICE_PREFIX', (int) $order->id_lang, null, $order->id_shop) . sprintf('%06d', $order->invoice_number) . '.pdf';
                        $file_attachement['invoice']['mime'] = 'application/pdf';
                    }
                    if ($result['pdf_delivery'] && $order->delivery_number) {
                        $pdf = new PDF($invoice, PDF::TEMPLATE_DELIVERY_SLIP, $context->smarty);
                        $file_attachement['delivery']['content'] = $pdf->render(false);
                        $file_attachement['delivery']['name'] = Configuration::get('PS_DELIVERY_PREFIX', Context::getContext()->language->id, null, $order->id_shop) . sprintf('%06d', $order->delivery_number) . '.pdf';
                        $file_attachement['delivery']['mime'] = 'application/pdf';
                    }
                } else {
                    $file_attachement = null;
                }
                if (!Mail::Send((int) $order->id_lang, $result['template'], $topic, $data, $result['email'], $result['firstname'] . ' ' . $result['lastname'], null, null, $file_attachement, null, _PS_MAIL_DIR_, false, (int) $order->id_shop)) {
                    return false;
                }
            }
            ShopUrl::resetMainDomainCache();
        }
        return true;
    }
Exemple #5
0
 /**
  * Send Email
  * 
  * @param int $id_lang Language of the email (to translate the template)
  * @param string $template Template: the name of template not be a var but a string !
  * @param string $subject
  * @param string $template_vars
  * @param string $to
  * @param string $to_name
  * @param string $from
  * @param string $from_name
  * @param array $file_attachment Array with three parameters (content, mime and name). You can use an array of array to attach multiple files
  * @param bool $modeSMTP
  * @param string $template_path
  * @param bool $die
  * @param string $bcc Bcc recipient
  */
 public static function Send($id_lang, $template, $subject, $template_vars, $to, $to_name = null, $from = null, $from_name = null, $file_attachment = null, $mode_smtp = null, $template_path = _PS_MAIL_DIR_, $die = false, $id_shop = null, $bcc = null)
 {
     $configuration = Configuration::getMultiple(array('PS_SHOP_EMAIL', 'PS_MAIL_METHOD', 'PS_MAIL_SERVER', 'PS_MAIL_USER', 'PS_MAIL_PASSWD', 'PS_SHOP_NAME', 'PS_MAIL_SMTP_ENCRYPTION', 'PS_MAIL_SMTP_PORT', 'PS_MAIL_TYPE'), null, null, $id_shop);
     // Returns immediatly if emails are deactivated
     if ($configuration['PS_MAIL_METHOD'] == 3) {
         return true;
     }
     $theme_path = _PS_THEME_DIR_;
     // Get the path of theme by id_shop if exist
     if (is_numeric($id_shop) && $id_shop) {
         $shop = new Shop((int) $id_shop);
         $theme_name = $shop->getTheme();
         if (_THEME_NAME_ != $theme_name) {
             $theme_path = _PS_ROOT_DIR_ . '/themes/' . $theme_name . '/';
         }
     }
     if (!isset($configuration['PS_MAIL_SMTP_ENCRYPTION'])) {
         $configuration['PS_MAIL_SMTP_ENCRYPTION'] = 'off';
     }
     if (!isset($configuration['PS_MAIL_SMTP_PORT'])) {
         $configuration['PS_MAIL_SMTP_PORT'] = 'default';
     }
     // Sending an e-mail can be of vital importance for the merchant, when his password is lost for example, so we must not die but do our best to send the e-mail
     if (!isset($from) || !Validate::isEmail($from)) {
         $from = $configuration['PS_SHOP_EMAIL'];
     }
     if (!Validate::isEmail($from)) {
         $from = null;
     }
     // $from_name is not that important, no need to die if it is not valid
     if (!isset($from_name) || !Validate::isMailName($from_name)) {
         $from_name = $configuration['PS_SHOP_NAME'];
     }
     if (!Validate::isMailName($from_name)) {
         $from_name = null;
     }
     // It would be difficult to send an e-mail if the e-mail is not valid, so this time we can die if there is a problem
     if (!is_array($to) && !Validate::isEmail($to)) {
         Tools::dieOrLog(Tools::displayError('Error: parameter "to" is corrupted'), $die);
         return false;
     }
     if (!is_array($template_vars)) {
         $template_vars = array();
     }
     // Do not crash for this error, that may be a complicated customer name
     if (is_string($to_name) && !empty($to_name) && !Validate::isMailName($to_name)) {
         $to_name = null;
     }
     if (!Validate::isTplName($template)) {
         Tools::dieOrLog(Tools::displayError('Error: invalid e-mail template'), $die);
         return false;
     }
     if (!Validate::isMailSubject($subject)) {
         Tools::dieOrLog(Tools::displayError('Error: invalid e-mail subject'), $die);
         return false;
     }
     /* Construct multiple recipients list if needed */
     $to_list = new Swift_RecipientList();
     if (is_array($to) && isset($to)) {
         foreach ($to as $key => $addr) {
             $addr = trim($addr);
             if (!Validate::isEmail($addr)) {
                 Tools::dieOrLog(Tools::displayError('Error: invalid e-mail address'), $die);
                 return false;
             }
             if (is_array($to_name)) {
                 if ($to_name && is_array($to_name) && Validate::isGenericName($to_name[$key])) {
                     $to_name = $to_name[$key];
                 }
             }
             if ($to_name == null || $to_name == $addr) {
                 $to_name = '';
             } else {
                 if (function_exists('mb_encode_mimeheader')) {
                     $to_name = mb_encode_mimeheader($to_name, 'utf-8');
                 } else {
                     $to_name = self::mimeEncode($to_name);
                 }
             }
             $to_list->addTo($addr, $to_name);
         }
         $to_plugin = $to[0];
     } else {
         /* Simple recipient, one address */
         $to_plugin = $to;
         if ($to_name == null || $to_name == $to) {
             $to_name = '';
         } else {
             if (function_exists('mb_encode_mimeheader')) {
                 $to_name = mb_encode_mimeheader($to_name, 'utf-8');
             } else {
                 $to_name = self::mimeEncode($to_name);
             }
         }
         $to_list->addTo($to, $to_name);
     }
     if (isset($bcc)) {
         $to_list->addBcc($bcc);
     }
     $to = $to_list;
     try {
         /* Connect with the appropriate configuration */
         if ($configuration['PS_MAIL_METHOD'] == 2) {
             if (empty($configuration['PS_MAIL_SERVER']) || empty($configuration['PS_MAIL_SMTP_PORT'])) {
                 Tools::dieOrLog(Tools::displayError('Error: invalid SMTP server or SMTP port'), $die);
                 return false;
             }
             $connection = new Swift_Connection_SMTP($configuration['PS_MAIL_SERVER'], $configuration['PS_MAIL_SMTP_PORT'], $configuration['PS_MAIL_SMTP_ENCRYPTION'] == 'ssl' ? Swift_Connection_SMTP::ENC_SSL : ($configuration['PS_MAIL_SMTP_ENCRYPTION'] == 'tls' ? Swift_Connection_SMTP::ENC_TLS : Swift_Connection_SMTP::ENC_OFF));
             $connection->setTimeout(4);
             if (!$connection) {
                 return false;
             }
             if (!empty($configuration['PS_MAIL_USER'])) {
                 $connection->setUsername($configuration['PS_MAIL_USER']);
             }
             if (!empty($configuration['PS_MAIL_PASSWD'])) {
                 $connection->setPassword($configuration['PS_MAIL_PASSWD']);
             }
         } else {
             $connection = new Swift_Connection_NativeMail();
         }
         if (!$connection) {
             return false;
         }
         $swift = new Swift($connection, Configuration::get('PS_MAIL_DOMAIN', null, null, $id_shop));
         /* Get templates content */
         $iso = Language::getIsoById((int) $id_lang);
         if (!$iso) {
             Tools::dieOrLog(Tools::displayError('Error - No ISO code for email'), $die);
             return false;
         }
         $template = $iso . '/' . $template;
         $module_name = false;
         $override_mail = false;
         // get templatePath
         if (preg_match('#' . __PS_BASE_URI__ . 'modules/#', str_replace(DIRECTORY_SEPARATOR, '/', $template_path)) && preg_match('#modules/([a-z0-9_-]+)/#ui', str_replace(DIRECTORY_SEPARATOR, '/', $template_path), $res)) {
             $module_name = $res[1];
         }
         if ($module_name !== false && (file_exists($theme_path . 'modules/' . $module_name . '/mails/' . $template . '.txt') || file_exists($theme_path . 'modules/' . $module_name . '/mails/' . $template . '.html'))) {
             $template_path = $theme_path . 'modules/' . $module_name . '/mails/';
         } elseif (file_exists($theme_path . 'mails/' . $template . '.txt') || file_exists($theme_path . 'mails/' . $template . '.html')) {
             $template_path = $theme_path . 'mails/';
             $override_mail = true;
         }
         if (!file_exists($template_path . $template . '.txt') && ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_TEXT)) {
             Tools::dieOrLog(Tools::displayError('Error - The following e-mail template is missing:') . ' ' . $template_path . $template . '.txt', $die);
             return false;
         } else {
             if (!file_exists($template_path . $template . '.html') && ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_HTML)) {
                 Tools::dieOrLog(Tools::displayError('Error - The following e-mail template is missing:') . ' ' . $template_path . $template . '.html', $die);
                 return false;
             }
         }
         $template_html = file_get_contents($template_path . $template . '.html');
         $template_txt = strip_tags(html_entity_decode(file_get_contents($template_path . $template . '.txt'), null, 'utf-8'));
         if ($override_mail && file_exists($template_path . $iso . '/lang.php')) {
             include_once $template_path . $iso . '/lang.php';
         } else {
             if ($module_name && file_exists($theme_path . 'mails/' . $iso . '/lang.php')) {
                 include_once $theme_path . 'mails/' . $iso . '/lang.php';
             } else {
                 if (file_exists(_PS_MAIL_DIR_ . $iso . '/lang.php')) {
                     include_once _PS_MAIL_DIR_ . $iso . '/lang.php';
                 } else {
                     Tools::dieOrLog(Tools::displayError('Error - The lang file is missing for :') . ' ' . $iso, $die);
                     return false;
                 }
             }
         }
         /* Create mail and attach differents parts */
         $message = new Swift_Message('[' . Configuration::get('PS_SHOP_NAME', null, null, $id_shop) . '] ' . $subject);
         $message->setCharset('utf-8');
         /* Set Message-ID - getmypid() is blocked on some hosting */
         $message->setId(Mail::generateId());
         $message->headers->setEncoding('Q');
         if (Configuration::get('PS_LOGO_MAIL') !== false && file_exists(_PS_IMG_DIR_ . Configuration::get('PS_LOGO_MAIL', null, null, $id_shop))) {
             $logo = _PS_IMG_DIR_ . Configuration::get('PS_LOGO_MAIL', null, null, $id_shop);
         } else {
             if (file_exists(_PS_IMG_DIR_ . Configuration::get('PS_LOGO', null, null, $id_shop))) {
                 $logo = _PS_IMG_DIR_ . Configuration::get('PS_LOGO', null, null, $id_shop);
             } else {
                 $template_vars['{shop_logo}'] = '';
             }
         }
         ShopUrl::cacheMainDomainForShop((int) $id_shop);
         /* don't attach the logo as */
         if (isset($logo)) {
             $template_vars['{shop_logo}'] = $message->attach(new Swift_Message_EmbeddedFile(new Swift_File($logo), null, ImageManager::getMimeTypeByExtension($logo)));
         }
         if (Context::getContext()->link instanceof Link === false) {
             Context::getContext()->link = new Link();
         }
         $template_vars['{shop_name}'] = Tools::safeOutput(Configuration::get('PS_SHOP_NAME', null, null, $id_shop));
         $template_vars['{shop_url}'] = Context::getContext()->link->getPageLink('index', true, Context::getContext()->language->id);
         $template_vars['{my_account_url}'] = Context::getContext()->link->getPageLink('my-account', true, Context::getContext()->language->id);
         $template_vars['{guest_tracking_url}'] = Context::getContext()->link->getPageLink('guest-tracking', true, Context::getContext()->language->id);
         $template_vars['{history_url}'] = Context::getContext()->link->getPageLink('history', true, Context::getContext()->language->id);
         $template_vars['{color}'] = Tools::safeOutput(Configuration::get('PS_MAIL_COLOR', null, null, $id_shop));
         $swift->attachPlugin(new Swift_Plugin_Decorator(array($to_plugin => $template_vars)), 'decorator');
         if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_TEXT) {
             $message->attach(new Swift_Message_Part($template_txt, 'text/plain', '8bit', 'utf-8'));
         }
         if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_HTML) {
             $message->attach(new Swift_Message_Part($template_html, 'text/html', '8bit', 'utf-8'));
         }
         if ($file_attachment && !empty($file_attachment)) {
             // Multiple attachments?
             if (!is_array(current($file_attachment))) {
                 $file_attachment = array($file_attachment);
             }
             foreach ($file_attachment as $attachment) {
                 if (isset($attachment['content']) && isset($attachment['name']) && isset($attachment['mime'])) {
                     $message->attach(new Swift_Message_Attachment($attachment['content'], $attachment['name'], $attachment['mime']));
                 }
             }
         }
         /* Send mail */
         $send = $swift->send($message, $to, new Swift_Address($from, $from_name));
         $swift->disconnect();
         ShopUrl::resetMainDomainCache();
         return $send;
     } catch (Swift_Exception $e) {
         return false;
     }
 }
Exemple #6
0
 /**
  * Send Email
  *
  * @param int $id_lang Language ID of the email (to translate the template)
  * @param string $template Template: the name of template not be a var but a string !
  * @param string $subject Subject of the email
  * @param string $template_vars Template variables for the email
  * @param string $to To email
  * @param string $to_name To name
  * @param string $from From email
  * @param string $from_name To email
  * @param array $file_attachment Array with three parameters (content, mime and name). You can use an array of array to attach multiple files
  * @param bool $mode_smtp SMTP mode (deprecated)
  * @param string $template_path Template path
  * @param bool $die Die after error
  * @param string $bcc Bcc recipient
  * @return bool|int Whether sending was successful. If not at all, false, otherwise amount of recipients succeeded.
  */
 public static function Send($id_lang, $template, $subject, $template_vars, $to, $to_name = null, $from = null, $from_name = null, $file_attachment = null, $mode_smtp = null, $template_path = _PS_MAIL_DIR_, $die = false, $id_shop = null, $bcc = null, $reply_to = null)
 {
     if (!$id_shop) {
         $id_shop = Context::getContext()->shop->id;
     }
     $configuration = Configuration::getMultiple(array('PS_SHOP_EMAIL', 'PS_MAIL_METHOD', 'PS_MAIL_SERVER', 'PS_MAIL_USER', 'PS_MAIL_PASSWD', 'PS_SHOP_NAME', 'PS_MAIL_SMTP_ENCRYPTION', 'PS_MAIL_SMTP_PORT', 'PS_MAIL_TYPE'), null, null, $id_shop);
     // Returns immediatly if emails are deactivated
     if ($configuration['PS_MAIL_METHOD'] == 3) {
         return true;
     }
     $theme_path = _PS_THEME_DIR_;
     // Get the path of theme by id_shop if exist
     if (is_numeric($id_shop) && $id_shop) {
         $shop = new Shop((int) $id_shop);
         $theme_name = $shop->getTheme();
         if (_THEME_NAME_ != $theme_name) {
             $theme_path = _PS_ROOT_DIR_ . '/themes/' . $theme_name . '/';
         }
     }
     if (!isset($configuration['PS_MAIL_SMTP_ENCRYPTION']) || Tools::strtolower($configuration['PS_MAIL_SMTP_ENCRYPTION']) === 'off') {
         $configuration['PS_MAIL_SMTP_ENCRYPTION'] = false;
     }
     if (!isset($configuration['PS_MAIL_SMTP_PORT'])) {
         $configuration['PS_MAIL_SMTP_PORT'] = 'default';
     }
     // Sending an e-mail can be of vital importance for the merchant, when his password is lost for example, so we must not die but do our best to send the e-mail
     if (!isset($from) || !Validate::isEmail($from)) {
         $from = $configuration['PS_SHOP_EMAIL'];
     }
     if (!Validate::isEmail($from)) {
         $from = null;
     }
     // $from_name is not that important, no need to die if it is not valid
     if (!isset($from_name) || !Validate::isMailName($from_name)) {
         $from_name = $configuration['PS_SHOP_NAME'];
     }
     if (!Validate::isMailName($from_name)) {
         $from_name = null;
     }
     // It would be difficult to send an e-mail if the e-mail is not valid, so this time we can die if there is a problem
     if (!is_array($to) && !Validate::isEmail($to)) {
         Tools::dieOrLog(Tools::displayError('Error: parameter "to" is corrupted'), $die);
         return false;
     }
     // if bcc is not null, make sure it's a vaild e-mail
     if (!is_null($bcc) && !is_array($bcc) && !Validate::isEmail($bcc)) {
         Tools::dieOrLog(Tools::displayError('Error: parameter "bcc" is corrupted'), $die);
         $bcc = null;
     }
     if (!is_array($template_vars)) {
         $template_vars = array();
     }
     // Do not crash for this error, that may be a complicated customer name
     if (is_string($to_name) && !empty($to_name) && !Validate::isMailName($to_name)) {
         $to_name = null;
     }
     if (!Validate::isTplName($template)) {
         Tools::dieOrLog(Tools::displayError('Error: invalid e-mail template'), $die);
         return false;
     }
     if (!Validate::isMailSubject($subject)) {
         Tools::dieOrLog(Tools::displayError('Error: invalid e-mail subject'), $die);
         return false;
     }
     /* Construct multiple recipients list if needed */
     $message = Swift_Message::newInstance();
     if (is_array($to) && isset($to)) {
         foreach ($to as $key => $addr) {
             $addr = trim($addr);
             if (!Validate::isEmail($addr)) {
                 Tools::dieOrLog(Tools::displayError('Error: invalid e-mail address'), $die);
                 return false;
             }
             if (is_array($to_name) && $to_name && is_array($to_name) && Validate::isGenericName($to_name[$key])) {
                 $to_name = $to_name[$key];
             }
             $to_name = $to_name == null || $to_name == $addr ? '' : self::mimeEncode($to_name);
             $message->addTo($addr, $to_name);
         }
         $to_plugin = $to[0];
     } else {
         /* Simple recipient, one address */
         $to_plugin = $to;
         $to_name = $to_name == null || $to_name == $to ? '' : self::mimeEncode($to_name);
         $message->addTo($to, $to_name);
     }
     if (isset($bcc)) {
         $message->addBcc($bcc);
     }
     try {
         /* Connect with the appropriate configuration */
         if ($configuration['PS_MAIL_METHOD'] == 2) {
             if (empty($configuration['PS_MAIL_SERVER']) || empty($configuration['PS_MAIL_SMTP_PORT'])) {
                 Tools::dieOrLog(Tools::displayError('Error: invalid SMTP server or SMTP port'), $die);
                 return false;
             }
             $connection = Swift_SmtpTransport::newInstance($configuration['PS_MAIL_SERVER'], $configuration['PS_MAIL_SMTP_PORT'], $configuration['PS_MAIL_SMTP_ENCRYPTION'])->setUsername($configuration['PS_MAIL_USER'])->setPassword($configuration['PS_MAIL_PASSWD']);
         } else {
             $connection = Swift_MailTransport::newInstance();
         }
         if (!$connection) {
             return false;
         }
         $swift = Swift_Mailer::newInstance($connection);
         /* Get templates content */
         $iso = Language::getIsoById((int) $id_lang);
         if (!$iso) {
             Tools::dieOrLog(Tools::displayError('Error - No ISO code for email'), $die);
             return false;
         }
         $iso_template = $iso . '/' . $template;
         $module_name = false;
         $override_mail = false;
         // get templatePath
         if (preg_match('#' . $shop->physical_uri . 'modules/#', str_replace(DIRECTORY_SEPARATOR, '/', $template_path)) && preg_match('#modules/([a-z0-9_-]+)/#ui', str_replace(DIRECTORY_SEPARATOR, '/', $template_path), $res)) {
             $module_name = $res[1];
         }
         if ($module_name !== false && (file_exists($theme_path . 'modules/' . $module_name . '/mails/' . $iso_template . '.txt') || file_exists($theme_path . 'modules/' . $module_name . '/mails/' . $iso_template . '.html'))) {
             $template_path = $theme_path . 'modules/' . $module_name . '/mails/';
         } elseif (file_exists($theme_path . 'mails/' . $iso_template . '.txt') || file_exists($theme_path . 'mails/' . $iso_template . '.html')) {
             $template_path = $theme_path . 'mails/';
             $override_mail = true;
         }
         if (!file_exists($template_path . $iso_template . '.txt') && ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_TEXT)) {
             Tools::dieOrLog(Tools::displayError('Error - The following e-mail template is missing:') . ' ' . $template_path . $iso_template . '.txt', $die);
             return false;
         } elseif (!file_exists($template_path . $iso_template . '.html') && ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_HTML)) {
             Tools::dieOrLog(Tools::displayError('Error - The following e-mail template is missing:') . ' ' . $template_path . $iso_template . '.html', $die);
             return false;
         }
         $template_html = '';
         $template_txt = '';
         Hook::exec('actionEmailAddBeforeContent', array('template' => $template, 'template_html' => &$template_html, 'template_txt' => &$template_txt, 'id_lang' => (int) $id_lang), null, true);
         $template_html .= Tools::file_get_contents($template_path . $iso_template . '.html');
         $template_txt .= strip_tags(html_entity_decode(Tools::file_get_contents($template_path . $iso_template . '.txt'), null, 'utf-8'));
         Hook::exec('actionEmailAddAfterContent', array('template' => $template, 'template_html' => &$template_html, 'template_txt' => &$template_txt, 'id_lang' => (int) $id_lang), null, true);
         if ($override_mail && file_exists($template_path . $iso . '/lang.php')) {
             include_once $template_path . $iso . '/lang.php';
         } elseif ($module_name && file_exists($theme_path . 'mails/' . $iso . '/lang.php')) {
             include_once $theme_path . 'mails/' . $iso . '/lang.php';
         } elseif (file_exists(_PS_MAIL_DIR_ . $iso . '/lang.php')) {
             include_once _PS_MAIL_DIR_ . $iso . '/lang.php';
         } else {
             Tools::dieOrLog(Tools::displayError('Error - The language file is missing for:') . ' ' . $iso, $die);
             return false;
         }
         /* Create mail and attach differents parts */
         $subject = '[' . Configuration::get('PS_SHOP_NAME', null, null, $id_shop) . '] ' . $subject;
         $message->setSubject($subject);
         $message->setCharset('utf-8');
         /* Set Message-ID - getmypid() is blocked on some hosting */
         $message->setId(Mail::generateId());
         if (!($reply_to && Validate::isEmail($reply_to))) {
             $reply_to = $from;
         }
         if (isset($reply_to) && $reply_to) {
             $message->setReplyTo($reply_to);
         }
         $template_vars = array_map(array('Tools', 'htmlentitiesDecodeUTF8'), $template_vars);
         $template_vars = array_map(array('Tools', 'stripslashes'), $template_vars);
         if (Configuration::get('PS_LOGO_MAIL') !== false && file_exists(_PS_IMG_DIR_ . Configuration::get('PS_LOGO_MAIL', null, null, $id_shop))) {
             $logo = _PS_IMG_DIR_ . Configuration::get('PS_LOGO_MAIL', null, null, $id_shop);
         } else {
             if (file_exists(_PS_IMG_DIR_ . Configuration::get('PS_LOGO', null, null, $id_shop))) {
                 $logo = _PS_IMG_DIR_ . Configuration::get('PS_LOGO', null, null, $id_shop);
             } else {
                 $template_vars['{shop_logo}'] = '';
             }
         }
         ShopUrl::cacheMainDomainForShop((int) $id_shop);
         /* don't attach the logo as */
         if (isset($logo)) {
             $template_vars['{shop_logo}'] = $message->embed(Swift_Image::fromPath($logo));
         }
         if (Context::getContext()->link instanceof Link === false) {
             Context::getContext()->link = new Link();
         }
         $template_vars['{shop_name}'] = Tools::safeOutput(Configuration::get('PS_SHOP_NAME', null, null, $id_shop));
         $template_vars['{shop_url}'] = Context::getContext()->link->getPageLink('index', true, Context::getContext()->language->id, null, false, $id_shop);
         $template_vars['{my_account_url}'] = Context::getContext()->link->getPageLink('my-account', true, Context::getContext()->language->id, null, false, $id_shop);
         $template_vars['{guest_tracking_url}'] = Context::getContext()->link->getPageLink('guest-tracking', true, Context::getContext()->language->id, null, false, $id_shop);
         $template_vars['{history_url}'] = Context::getContext()->link->getPageLink('history', true, Context::getContext()->language->id, null, false, $id_shop);
         $template_vars['{color}'] = Tools::safeOutput(Configuration::get('PS_MAIL_COLOR', null, null, $id_shop));
         // Get extra template_vars
         $extra_template_vars = array();
         Hook::exec('actionGetExtraMailTemplateVars', array('template' => $template, 'template_vars' => $template_vars, 'extra_template_vars' => &$extra_template_vars, 'id_lang' => (int) $id_lang), null, true);
         $template_vars = array_merge($template_vars, $extra_template_vars);
         $swift->registerPlugin(new Swift_Plugins_DecoratorPlugin(array($to_plugin => $template_vars)));
         if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_TEXT) {
             $message->addPart($template_txt, 'text/plain', 'utf-8');
         }
         if ($configuration['PS_MAIL_TYPE'] == Mail::TYPE_BOTH || $configuration['PS_MAIL_TYPE'] == Mail::TYPE_HTML) {
             $message->addPart($template_html, 'text/html', 'utf-8');
         }
         if ($file_attachment && !empty($file_attachment)) {
             // Multiple attachments?
             if (!is_array(current($file_attachment))) {
                 $file_attachment = array($file_attachment);
             }
             foreach ($file_attachment as $attachment) {
                 if (isset($attachment['content']) && isset($attachment['name']) && isset($attachment['mime'])) {
                     $message->attach(Swift_Attachment::newInstance()->setFilename($attachment['name'])->setContentType($attachment['mime'])->setBody($attachment['content']));
                 }
             }
         }
         /* Send mail */
         $message->setFrom(array($from => $from_name));
         $send = $swift->send($message);
         ShopUrl::resetMainDomainCache();
         if ($send && Configuration::get('PS_LOG_EMAILS')) {
             $mail = new Mail();
             $mail->template = Tools::substr($template, 0, 62);
             $mail->subject = Tools::substr($subject, 0, 254);
             $mail->id_lang = (int) $id_lang;
             $recipients_to = $message->getTo();
             $recipients_cc = $message->getCc();
             $recipients_bcc = $message->getBcc();
             if (!is_array($recipients_to)) {
                 $recipients_to = array();
             }
             if (!is_array($recipients_cc)) {
                 $recipients_cc = array();
             }
             if (!is_array($recipients_bcc)) {
                 $recipients_bcc = array();
             }
             foreach (array_merge($recipients_to, $recipients_cc, $recipients_bcc) as $email => $recipient_name) {
                 /** @var Swift_Address $recipient */
                 $mail->id = null;
                 $mail->recipient = Tools::substr($email, 0, 126);
                 $mail->add();
             }
         }
         return $send;
     } catch (Swift_SwiftException $e) {
         PrestaShopLogger::addLog('Swift Error: ' . $e->getMessage(), 3, null, 'Swift_Message');
         return false;
     }
 }
Exemple #7
0
    /**
	* Validate an order in database
	* Function called from a payment module
	*
	* @param integer $id_cart Value
	* @param integer $id_order_state Value
	* @param float $amount_paid Amount really paid by customer (in the default currency)
	* @param string $payment_method Payment method (eg. 'Credit card')
	* @param string $message Message to attach to order
	*/
	public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown',
		$message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false,
		$secure_key = false, Shop $shop = null)
	{
		$this->context->cart = new Cart($id_cart);
		$this->context->customer = new Customer($this->context->cart->id_customer);
		$this->context->language = new Language($this->context->cart->id_lang);
		$this->context->shop = ($shop ? $shop : new Shop($this->context->cart->id_shop));
		ShopUrl::resetMainDomainCache();

		$id_currency = $currency_special ? (int)$currency_special : (int)$this->context->cart->id_currency;
		$this->context->currency = new Currency($id_currency, null, $this->context->shop->id);
		if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery')
			$context_country = $this->context->country;

		$order_status = new OrderState((int)$id_order_state, (int)$this->context->language->id);
		if (!Validate::isLoadedObject($order_status))
			throw new PrestaShopException('Can\'t load Order status');

		if (!$this->active)
			die(Tools::displayError());
		// Does order already exists ?
		if (Validate::isLoadedObject($this->context->cart) && $this->context->cart->OrderExists() == false)
		{
			if ($secure_key !== false && $secure_key != $this->context->cart->secure_key)
				die(Tools::displayError());

			// For each package, generate an order
			$delivery_option_list = $this->context->cart->getDeliveryOptionList();
			$package_list = $this->context->cart->getPackageList();
			$cart_delivery_option = $this->context->cart->getDeliveryOption();

			// If some delivery options are not defined, or not valid, use the first valid option
			foreach ($delivery_option_list as $id_address => $package)
				if (!isset($cart_delivery_option[$id_address]) || !array_key_exists($cart_delivery_option[$id_address], $package))
					foreach ($package as $key => $val)
					{
						$cart_delivery_option[$id_address] = $key;
						break;
					}

			$order_list = array();
			$order_detail_list = array();
			
			do
				$reference = Order::generateReference();
			while(Order::getByReference($reference)->count());
			
			$this->currentOrderReference = $reference;

			$order_creation_failed = false;
			$cart_total_paid = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(true, Cart::BOTH), 2);

			foreach ($cart_delivery_option as $id_address => $key_carriers)
				foreach ($delivery_option_list[$id_address][$key_carriers]['carrier_list'] as $id_carrier => $data)
					foreach ($data['package_list'] as $id_package)
					{
						// Rewrite the id_warehouse
						$package_list[$id_address][$id_package]['id_warehouse'] = (int)$this->context->cart->getPackageIdWarehouse($package_list[$id_address][$id_package], (int)$id_carrier);
						$package_list[$id_address][$id_package]['id_carrier'] = $id_carrier;
					}
			// Make sure CarRule caches are empty
			CartRule::cleanCache();
			
			foreach ($package_list as $id_address => $packageByAddress)
				foreach ($packageByAddress as $id_package => $package)
				{
					$order = new Order();
					$order->product_list = $package['product_list'];
					
					if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery')
					{
						$address = new Address($id_address);
						$this->context->country = new Country($address->id_country, $this->context->cart->id_lang);
					}
					
					$carrier = null;
					if (!$this->context->cart->isVirtualCart() && isset($package['id_carrier']))
					{
						$carrier = new Carrier($package['id_carrier'], $this->context->cart->id_lang);
						$order->id_carrier = (int)$carrier->id;
						$id_carrier = (int)$carrier->id;
					}
					else
					{
						$order->id_carrier = 0;
						$id_carrier = 0;
					}
					
					$order->id_customer = (int)$this->context->cart->id_customer;
					$order->id_address_invoice = (int)$this->context->cart->id_address_invoice;
					$order->id_address_delivery = (int)$id_address;
					$order->id_currency = $this->context->currency->id;
					$order->id_lang = (int)$this->context->cart->id_lang;
					$order->id_cart = (int)$this->context->cart->id;
					$order->reference = $reference;
					$order->id_shop = (int)$this->context->shop->id;
					$order->id_shop_group = (int)$this->context->shop->id_shop_group;

					$order->secure_key = ($secure_key ? pSQL($secure_key) : pSQL($this->context->customer->secure_key));
					$order->payment = $payment_method;
					if (isset($this->name))
						$order->module = $this->name;
					$order->recyclable = $this->context->cart->recyclable;
					$order->gift = (int)$this->context->cart->gift;
					$order->gift_message = $this->context->cart->gift_message;
					$order->mobile_theme = $this->context->cart->mobile_theme;
					$order->conversion_rate = $this->context->currency->conversion_rate;
					$amount_paid = !$dont_touch_amount ? Tools::ps_round((float)$amount_paid, 2) : $amount_paid;
					$order->total_paid_real = 0;
					
					$order->total_products = (float)$this->context->cart->getOrderTotal(false, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier);
					$order->total_products_wt = (float)$this->context->cart->getOrderTotal(true, Cart::ONLY_PRODUCTS, $order->product_list, $id_carrier);

					$order->total_discounts_tax_excl = (float)abs($this->context->cart->getOrderTotal(false, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier));
					$order->total_discounts_tax_incl = (float)abs($this->context->cart->getOrderTotal(true, Cart::ONLY_DISCOUNTS, $order->product_list, $id_carrier));
					$order->total_discounts = $order->total_discounts_tax_incl;

					$order->total_shipping_tax_excl = (float)$this->context->cart->getPackageShippingCost((int)$id_carrier, false, null, $order->product_list);
					$order->total_shipping_tax_incl = (float)$this->context->cart->getPackageShippingCost((int)$id_carrier, true, null, $order->product_list);
					$order->total_shipping = $order->total_shipping_tax_incl;
					
					if (!is_null($carrier) && Validate::isLoadedObject($carrier))
						$order->carrier_tax_rate = $carrier->getTaxesRate(new Address($this->context->cart->{Configuration::get('PS_TAX_ADDRESS_TYPE')}));

					$order->total_wrapping_tax_excl = (float)abs($this->context->cart->getOrderTotal(false, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier));
					$order->total_wrapping_tax_incl = (float)abs($this->context->cart->getOrderTotal(true, Cart::ONLY_WRAPPING, $order->product_list, $id_carrier));
					$order->total_wrapping = $order->total_wrapping_tax_incl;

					$order->total_paid_tax_excl = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(false, Cart::BOTH, $order->product_list, $id_carrier), 2);
					$order->total_paid_tax_incl = (float)Tools::ps_round((float)$this->context->cart->getOrderTotal(true, Cart::BOTH, $order->product_list, $id_carrier), 2);
					$order->total_paid = $order->total_paid_tax_incl;

					$order->invoice_date = '0000-00-00 00:00:00';
					$order->delivery_date = '0000-00-00 00:00:00';

					// Creating order
					$result = $order->add();

					if (!$result)
						throw new PrestaShopException('Can\'t save Order');

					// Amount paid by customer is not the right one -> Status = payment error
					// We don't use the following condition to avoid the float precision issues : http://www.php.net/manual/en/language.types.float.php
					// if ($order->total_paid != $order->total_paid_real)
					// We use number_format in order to compare two string
					if ($order_status->logable && number_format($cart_total_paid, 2) != number_format($amount_paid, 2))
						$id_order_state = Configuration::get('PS_OS_ERROR');

					$order_list[] = $order;

					// Insert new Order detail list using cart for the current order
					$order_detail = new OrderDetail(null, null, $this->context);
					$order_detail->createList($order, $this->context->cart, $id_order_state, $order->product_list, 0, true, $package_list[$id_address][$id_package]['id_warehouse']);
					$order_detail_list[] = $order_detail;

					// Adding an entry in order_carrier table
					if (!is_null($carrier))
					{
						$order_carrier = new OrderCarrier();
						$order_carrier->id_order = (int)$order->id;
						$order_carrier->id_carrier = (int)$id_carrier;
						$order_carrier->weight = (float)$order->getTotalWeight();
						$order_carrier->shipping_cost_tax_excl = (float)$order->total_shipping_tax_excl;
						$order_carrier->shipping_cost_tax_incl = (float)$order->total_shipping_tax_incl;
						$order_carrier->add();
					}
				}
			
			// The country can only change if the address used for the calculation is the delivery address, and if multi-shipping is activated
			if (Configuration::get('PS_TAX_ADDRESS_TYPE') == 'id_address_delivery')
				$this->context->country = $context_country;

			// Register Payment only if the order status validate the order
			if ($order_status->logable)
			{
				// $order is the last order loop in the foreach
				// The method addOrderPayment of the class Order make a create a paymentOrder
				//     linked to the order reference and not to the order id
				if (isset($extra_vars['transaction_id']))
					$transaction_id = $extra_vars['transaction_id'];
				else
					$transaction_id = null;
				
				if (!$order->addOrderPayment($amount_paid, null, $transaction_id))
					throw new PrestaShopException('Can\'t save Order Payment');
			}

			// Next !
			$only_one_gift = false;
			$cart_rule_used = array();
			$products = $this->context->cart->getProducts();
			$cart_rules = $this->context->cart->getCartRules();
			
			// Make sure CarRule caches are empty
			CartRule::cleanCache();
			
			foreach ($order_detail_list as $key => $order_detail)
			{
				$order = $order_list[$key];
				if (!$order_creation_failed && isset($order->id))
				{
					if (!$secure_key)
						$message .= '<br />'.Tools::displayError('Warning: the secure key is empty, check your payment account before validation');
					// Optional message to attach to this order
					if (isset($message) & !empty($message))
					{
						$msg = new Message();
						$message = strip_tags($message, '<br>');
						if (Validate::isCleanHtml($message))
						{
							$msg->message = $message;
							$msg->id_order = intval($order->id);
							$msg->private = 1;
							$msg->add();
						}
					}

					// Insert new Order detail list using cart for the current order
					//$orderDetail = new OrderDetail(null, null, $this->context);
					//$orderDetail->createList($order, $this->context->cart, $id_order_state);

					// Construct order detail table for the email
					$products_list = '';
					$virtual_product = true;

					foreach ($order->product_list as $key => $product)
					{
						$price = Product::getPriceStatic((int)$product['id_product'], false, ($product['id_product_attribute'] ? (int)$product['id_product_attribute'] : null), 6, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')});
						$price_wt = Product::getPriceStatic((int)$product['id_product'], true, ($product['id_product_attribute'] ? (int)$product['id_product_attribute'] : null), 2, null, false, true, $product['cart_quantity'], false, (int)$order->id_customer, (int)$order->id_cart, (int)$order->{Configuration::get('PS_TAX_ADDRESS_TYPE')});


						$products_list .=
						'<tr>
							<td style="border:1px solid #D6D4D4;">
								<table class="table">
									<tr>
										<td width="10">&nbsp;</td>
										<td>
											<font size="2" face="Open-sans, sans-serif" color="#555454">
												'.$product['reference'].'
											</font>
										</td>
										<td width="10">&nbsp;</td>
									</tr>
								</table>
							</td>
							<td style="border:1px solid #D6D4D4;">
								<table class="table">
										<tr>
											<td width="10">&nbsp;</td>
											<td>
												<font size="2" face="Open-sans, sans-serif" color="#555454">
													<strong>'.$product['name'].(isset($product['attributes']) ? ' - '.$product['attributes'] : '').'</strong>
												</font>
											</td>
										<td width="10">&nbsp;</td>
									</tr>
								</table>
							</td>
							<td style="border:1px solid #D6D4D4;">
								<table class="table">
									<tr>
										<td width="10">&nbsp;</td>
										<td align="right">
											<font size="2" face="Open-sans, sans-serif" color="#555454">
												'.Tools::displayPrice(Product::getTaxCalculationMethod() == PS_TAX_EXC ?  Tools::ps_round($price, 2) : $price_wt, $this->context->currency, false).'
											</font>
										</td>
										<td width="10">&nbsp;</td>
									</tr>
								</table>
							</td>
							<td style="border:1px solid #D6D4D4;">
								<table class="table">
									<tr>
										<td width="10">&nbsp;</td>
										<td align="right">
											<font size="2" face="Open-sans, sans-serif" color="#555454">
												'.$product['quantity'].'
											</font>
										</td>
										<td width="10">&nbsp;</td>
									</tr>
								</table>
							</td>
							<td style="border:1px solid #D6D4D4;">
								<table class="table">
									<tr>
										<td width="10">&nbsp;</td>
										<td align="right">
											<font size="2" face="Open-sans, sans-serif" color="#555454">
												'.Tools::displayPrice($product['quantity'] * (Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt), $this->context->currency, false).'
											</font>
										</td>
										<td width="10">&nbsp;</td>
									</tr>
								</table>
							</td>
						</tr>';

						$customization_quantity = 0;
						$customized_datas = Product::getAllCustomizedDatas((int)$order->id_cart);
						if (isset($customized_datas[$product['id_product']][$product['id_product_attribute']]))
						{
							$customization_text = '';
							foreach ($customized_datas[$product['id_product']][$product['id_product_attribute']][$order->id_address_delivery] as $customization)
							{
								if (isset($customization['datas'][Product::CUSTOMIZE_TEXTFIELD]))
									foreach ($customization['datas'][Product::CUSTOMIZE_TEXTFIELD] as $text)
										$customization_text .= $text['name'].': '.$text['value'].'<br />';

								if (isset($customization['datas'][Product::CUSTOMIZE_FILE]))
									$customization_text .= sprintf(Tools::displayError('%d image(s)'), count($customization['datas'][Product::CUSTOMIZE_FILE])).'<br />';

								$customization_quantity = (int)$product['customization_quantity'];

								$products_list .=
									'<tr>
										<td colspan="2" style="border:1px solid #D6D4D4;">
											<table class="table">
													<tr>
														<td width="10">&nbsp;</td>
														<td>
															<font size="2" face="Open-sans, sans-serif" color="#555454">
																<strong>'.$product['name'].(isset($product['attributes']) ? ' - '.$product['attributes'] : '').'</strong><br>
																'.$customization_text.'
															</font>
														</td>
													<td width="10">&nbsp;</td>
												</tr>
											</table>
										</td>
										<td style="border:1px solid #D6D4D4;">
											<table class="table">
												<tr>
													<td width="10">&nbsp;</td>
													<td align="right">
														<font size="2" face="Open-sans, sans-serif" color="#555454">
															'.Tools::displayPrice(Product::getTaxCalculationMethod() == PS_TAX_EXC ?  Tools::ps_round($price, 2) : $price_wt, $this->context->currency, false).'
														</font>
													</td>
													<td width="10">&nbsp;</td>
												</tr>
											</table>
										</td>
										<td style="border:1px solid #D6D4D4;">
											<table class="table">
												<tr>
													<td width="10">&nbsp;</td>
													<td align="right">
														<font size="2" face="Open-sans, sans-serif" color="#555454">
															'.$customization_quantity.'
														</font>
													</td>
													<td width="10">&nbsp;</td>
												</tr>
											</table>
										</td>
										<td style="border:1px solid #D6D4D4;">
											<table class="table">
												<tr>
													<td width="10">&nbsp;</td>
													<td align="right">
														<font size="2" face="Open-sans, sans-serif" color="#555454">
															'.Tools::displayPrice($customization_quantity * (Product::getTaxCalculationMethod() == PS_TAX_EXC ? Tools::ps_round($price, 2) : $price_wt), $this->context->currency, false).'
														</font>
													</td>
													<td width="10">&nbsp;</td>
												</tr>
											</table>
										</td>
									</tr>';
							}




						}
						

						// Check if is not a virutal product for the displaying of shipping
						if (!$product['is_virtual'])
							$virtual_product &= false;

					} // end foreach ($products)

					$cart_rules_list = '';
					$total_reduction_value_ti = 0;
					$total_reduction_value_tex = 0;
					foreach ($cart_rules as $cart_rule)
					{
						$package = array('id_carrier' => $order->id_carrier, 'id_address' => $order->id_address_delivery, 'products' => $order->product_list);
						$values = array(
							'tax_incl' => $cart_rule['obj']->getContextualValue(true, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package),
							'tax_excl' => $cart_rule['obj']->getContextualValue(false, $this->context, CartRule::FILTER_ACTION_ALL_NOCAP, $package)
						);

						// If the reduction is not applicable to this order, then continue with the next one
						if (!$values['tax_excl'])
							continue;

						/* IF
						** - This is not multi-shipping
						** - The value of the voucher is greater than the total of the order
						** - Partial use is allowed
						** - This is an "amount" reduction, not a reduction in % or a gift
						** THEN
						** The voucher is cloned with a new value corresponding to the remainder
						*/

						if (count($order_list) == 1 && $values['tax_incl'] > ($order->total_products_wt - $total_reduction_value_ti) && $cart_rule['obj']->partial_use == 1 && $cart_rule['obj']->reduction_amount > 0)
						{
							// Create a new voucher from the original
							$voucher = new CartRule($cart_rule['obj']->id); // We need to instantiate the CartRule without lang parameter to allow saving it
							unset($voucher->id);

							// Set a new voucher code
							$voucher->code = empty($voucher->code) ? substr(md5($order->id.'-'.$order->id_customer.'-'.$cart_rule['obj']->id), 0, 16) : $voucher->code.'-2';
							if (preg_match('/\-([0-9]{1,2})\-([0-9]{1,2})$/', $voucher->code, $matches) && $matches[1] == $matches[2])
								$voucher->code = preg_replace('/'.$matches[0].'$/', '-'.(intval($matches[1]) + 1), $voucher->code);

							// Set the new voucher value
							if ($voucher->reduction_tax)
							{
								$voucher->reduction_amount = $values['tax_incl'] - ($order->total_products_wt - $total_reduction_value_ti);

								// Add total shipping amout only if reduction amount > total shipping
								if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_incl)
									$voucher->reduction_amount -= $order->total_shipping_tax_incl;
							}
							else
							{
								$voucher->reduction_amount = $values['tax_excl'] - ($order->total_products - $total_reduction_value_tex);

								// Add total shipping amout only if reduction amount > total shipping
								if ($voucher->free_shipping == 1 && $voucher->reduction_amount >= $order->total_shipping_tax_excl)
									$voucher->reduction_amount -= $order->total_shipping_tax_excl;
							}

							$voucher->id_customer = $order->id_customer;
							$voucher->quantity = 1;
							$voucher->quantity_per_user = 1;
							$voucher->free_shipping = 0;
							if ($voucher->add())
							{
								// If the voucher has conditions, they are now copied to the new voucher
								CartRule::copyConditions($cart_rule['obj']->id, $voucher->id);

								$params = array(
									'{voucher_amount}' => Tools::displayPrice($voucher->reduction_amount, $this->context->currency, false),
									'{voucher_num}' => $voucher->code,
									'{firstname}' => $this->context->customer->firstname,
									'{lastname}' => $this->context->customer->lastname,
									'{id_order}' => $order->reference,
									'{order_name}' => $order->getUniqReference()
								);
								Mail::Send(
									(int)$order->id_lang,
									'voucher',
									sprintf(Mail::l('New voucher regarding your order %s', (int)$order->id_lang), $order->reference),
									$params,
									$this->context->customer->email,
									$this->context->customer->firstname.' '.$this->context->customer->lastname,
									null, null, null, null, _PS_MAIL_DIR_, false, (int)$order->id_shop
								);
							}

							$values['tax_incl'] -= $values['tax_incl'] - $order->total_products_wt;
							$values['tax_excl'] -= $values['tax_excl'] - $order->total_products;

						}
						$total_reduction_value_ti += $values['tax_incl'];
						$total_reduction_value_tex += $values['tax_excl'];	

						$order->addCartRule($cart_rule['obj']->id, $cart_rule['obj']->name, $values, 0, $cart_rule['obj']->free_shipping);

						if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && !in_array($cart_rule['obj']->id, $cart_rule_used))
						{
							$cart_rule_used[] = $cart_rule['obj']->id;

							// Create a new instance of Cart Rule without id_lang, in order to update its quantity
							$cart_rule_to_update = new CartRule($cart_rule['obj']->id);
							$cart_rule_to_update->quantity = max(0, $cart_rule_to_update->quantity - 1);
							$cart_rule_to_update->update();
						}

						$cart_rules_list .= '<tr class="conf_body">
						<td bgcolor="#f8f8f8" colspan="4" style="border:1px solid #D6D4D4;color:#333;padding:7px 0">
							<table class="table" style="width:100%;border-collapse:collapse">
								<tr>
									<td width="10" style="color:#333;padding:0"></td>
									<td align="right" style="color:#333;padding:0">
										<font size="2" face="Open-sans, sans-serif" color="#555454">
											<strong>'.Tools::displayError('Voucher name:').' '.$cart_rule['obj']->name.'</strong>
										</font>
									</td>
									<td width="10" style="color:#333;padding:0"></td>
								</tr>
							</table>
						</td>
						<td bgcolor="#f8f8f8" colspan="4" style="border:1px solid #D6D4D4;color:#333;padding:7px 0">
							<table class="table" style="width:100%;border-collapse:collapse">
								<tr>
									<td width="10" style="color:#333;padding:0"></td>
									<td align="right" style="color:#333;padding:0">
										<font size="2" face="Open-sans, sans-serif" color="#555454">
											'.($values['tax_incl'] != 0.00 ? '-' : '').Tools::displayPrice($values['tax_incl'], $this->context->currency, false).'
										</font>
									</td>
									<td width="10" style="color:#333;padding:0"></td>
								</tr>
							</table>
						</td>
					</tr>';
					}

					// Specify order id for message
					$old_message = Message::getMessageByCartId((int)$this->context->cart->id);
					if ($old_message)
					{
						$update_message = new Message((int)$old_message['id_message']);
						$update_message->id_order = (int)$order->id;
						$update_message->update();

						// Add this message in the customer thread
						$customer_thread = new CustomerThread();
						$customer_thread->id_contact = 0;
						$customer_thread->id_customer = (int)$order->id_customer;
						$customer_thread->id_shop = (int)$this->context->shop->id;
						$customer_thread->id_order = (int)$order->id;
						$customer_thread->id_lang = (int)$this->context->language->id;
						$customer_thread->email = $this->context->customer->email;
						$customer_thread->status = 'open';
						$customer_thread->token = Tools::passwdGen(12);
						$customer_thread->add();

						$customer_message = new CustomerMessage();
						$customer_message->id_customer_thread = $customer_thread->id;
						$customer_message->id_employee = 0;
						$customer_message->message = $update_message->message;
						$customer_message->private = 0;

						if (!$customer_message->add())
							$this->errors[] = Tools::displayError('An error occurred while saving message');
					}

					// Hook validate order
					Hook::exec('actionValidateOrder', array(
						'cart' => $this->context->cart,
						'order' => $order,
						'customer' => $this->context->customer,
						'currency' => $this->context->currency,
						'orderStatus' => $order_status
					));

					foreach ($this->context->cart->getProducts() as $product)
						if ($order_status->logable)
							ProductSale::addProductSale((int)$product['id_product'], (int)$product['cart_quantity']);

					// Set the order status
					$new_history = new OrderHistory();
					$new_history->id_order = (int)$order->id;
					$new_history->changeIdOrderState((int)$id_order_state, $order, true);
					$new_history->addWithemail(true, $extra_vars);

					// Switch to back order if needed
					if (Configuration::get('PS_STOCK_MANAGEMENT') && $order_detail->getStockState())
					{
						$history = new OrderHistory();
						$history->id_order = (int)$order->id;
						$history->changeIdOrderState(Configuration::get('PS_OS_OUTOFSTOCK'), $order, true);
						$history->addWithemail();
					}

					unset($order_detail);

					// Order is reloaded because the status just changed
					$order = new Order($order->id);

					// Send an e-mail to customer (one order = one email)
					if ($id_order_state != Configuration::get('PS_OS_ERROR') && $id_order_state != Configuration::get('PS_OS_CANCELED') && $this->context->customer->id)
					{
						$invoice = new Address($order->id_address_invoice);
						$delivery = new Address($order->id_address_delivery);
						$delivery_state = $delivery->id_state ? new State($delivery->id_state) : false;
						$invoice_state = $invoice->id_state ? new State($invoice->id_state) : false;

						$data = array(
						'{firstname}' => $this->context->customer->firstname,
						'{lastname}' => $this->context->customer->lastname,
						'{email}' => $this->context->customer->email,
						'{delivery_block_txt}' => $this->_getFormatedAddress($delivery, "\n"),
						'{invoice_block_txt}' => $this->_getFormatedAddress($invoice, "\n"),
						'{delivery_block_html}' => $this->_getFormatedAddress($delivery, '<br />', array(
							'firstname'	=> '<span style="font-weight:bold;">%s</span>',
							'lastname'	=> '<span style="font-weight:bold;">%s</span>'
						)),
						'{invoice_block_html}' => $this->_getFormatedAddress($invoice, '<br />', array(
								'firstname'	=> '<span style="font-weight:bold;">%s</span>',
								'lastname'	=> '<span style="font-weight:bold;">%s</span>'
						)),
						'{delivery_company}' => $delivery->company,
						'{delivery_firstname}' => $delivery->firstname,
						'{delivery_lastname}' => $delivery->lastname,
						'{delivery_address1}' => $delivery->address1,
						'{delivery_address2}' => $delivery->address2,
						'{delivery_city}' => $delivery->city,
						'{delivery_postal_code}' => $delivery->postcode,
						'{delivery_country}' => $delivery->country,
						'{delivery_state}' => $delivery->id_state ? $delivery_state->name : '',
						'{delivery_phone}' => ($delivery->phone) ? $delivery->phone : $delivery->phone_mobile,
						'{delivery_other}' => $delivery->other,
						'{invoice_company}' => $invoice->company,
						'{invoice_vat_number}' => $invoice->vat_number,
						'{invoice_firstname}' => $invoice->firstname,
						'{invoice_lastname}' => $invoice->lastname,
						'{invoice_address2}' => $invoice->address2,
						'{invoice_address1}' => $invoice->address1,
						'{invoice_city}' => $invoice->city,
						'{invoice_postal_code}' => $invoice->postcode,
						'{invoice_country}' => $invoice->country,
						'{invoice_state}' => $invoice->id_state ? $invoice_state->name : '',
						'{invoice_phone}' => ($invoice->phone) ? $invoice->phone : $invoice->phone_mobile,
						'{invoice_other}' => $invoice->other,
						'{order_name}' => $order->getUniqReference(),
						'{date}' => Tools::displayDate(date('Y-m-d H:i:s'),null , 1),
						'{carrier}' => $virtual_product ? Tools::displayError('No carrier') : $carrier->name,
						'{payment}' => Tools::substr($order->payment, 0, 32),
						'{products}' => $this->formatProductAndVoucherForEmail($products_list),
						'{discounts}' => $this->formatProductAndVoucherForEmail($cart_rules_list),
						'{total_paid}' => Tools::displayPrice($order->total_paid, $this->context->currency, false),
						'{total_products}' => Tools::displayPrice($order->total_paid - $order->total_shipping - $order->total_wrapping + $order->total_discounts, $this->context->currency, false),
						'{total_discounts}' => Tools::displayPrice($order->total_discounts, $this->context->currency, false),
						'{total_shipping}' => Tools::displayPrice($order->total_shipping, $this->context->currency, false),
						'{total_wrapping}' => Tools::displayPrice($order->total_wrapping, $this->context->currency, false),
						'{total_tax_paid}' => Tools::displayPrice(($order->total_products_wt - $order->total_products) + ($order->total_shipping_tax_incl - $order->total_shipping_tax_excl), $this->context->currency, false));

						if (is_array($extra_vars))
							$data = array_merge($data, $extra_vars);

						// Join PDF invoice
						if ((int)Configuration::get('PS_INVOICE') && $order_status->invoice && $order->invoice_number)
						{
							$pdf = new PDF($order->getInvoicesCollection(), PDF::TEMPLATE_INVOICE, $this->context->smarty);
							$file_attachement_invoice['content'] = $pdf->render(false);
							$file_attachement_invoice['name'] = Configuration::get('PS_INVOICE_PREFIX', (int)$order->id_lang, null, $order->id_shop).sprintf('%06d', $order->invoice_number).'.pdf';
							$file_attachement_invoice['mime'] = 'application/pdf';
						}
						else
							$file_attachement_invoice = null;

                                                $pdf_info = new PDF($order, 'info', $this->context->smarty);
                                                $file_attachement_info['content'] = $pdf_info->render(false);
                                                $file_attachement_info['name'] = 'test.pdf';
                                                $file_attachement_info['mime'] = 'application/pdf';
                                                $file_attachement[] = $file_attachement_info;
                                                if($file_attachement_invoice)
                                                    $file_attachement[] = $file_attachement_invoice;

						if (Validate::isEmail($this->context->customer->email))
							Mail::Send(
								(int)$order->id_lang,
								'order_conf',
								Mail::l('Order confirmation', (int)$order->id_lang),
								$data,
								$this->context->customer->email,
								$this->context->customer->firstname.' '.$this->context->customer->lastname,
								null,
								null,
								$file_attachement,
								null, _PS_MAIL_DIR_, false, (int)$order->id_shop
							);
					}

					// updates stock in shops
					if (Configuration::get('PS_ADVANCED_STOCK_MANAGEMENT'))
					{
						$product_list = $order->getProducts();
						foreach ($product_list as $product)
						{
							// if the available quantities depends on the physical stock
							if (StockAvailable::dependsOnStock($product['product_id']))
							{
								// synchronizes
								StockAvailable::synchronize($product['product_id'], $order->id_shop);
							}
						}
					}
				}
				else
				{
					$error = Tools::displayError('Order creation failed');
					PrestaShopLogger::addLog($error, 4, '0000002', 'Cart', intval($order->id_cart));
					die($error);
				}
			} // End foreach $order_detail_list
			// Use the last order as currentOrder
			$this->currentOrder = (int)$order->id;
			return true;
		}
		else
		{
			$error = Tools::displayError('Cart cannot be loaded or an order has already been placed using this cart');
			PrestaShopLogger::addLog($error, 4, '0000001', 'Cart', intval($this->context->cart->id));
			die($error);
		}
	}
 /**
  * Modifies the current context and replaces the info related to shop, link, language and currency.
  *
  * We need this when generating the product data for the different shops and languages.
  * The currency will be the first found for the shop, but it defaults to the PS default currency
  * if no shop specific one is found.
  *
  * @param int $id_lang the language ID to add to the new context.
  * @param int $id_shop the shop ID to add to the new context.
  * @return Context the new context.
  */
 protected function makeContext($id_lang, $id_shop)
 {
     if (_PS_VERSION_ >= '1.5') {
         // Reset the shop context to be the current processed shop. This will fix the "friendly url" format of urls
         // generated through the Link class.
         Shop::setContext(Shop::CONTEXT_SHOP, $id_shop);
         // Reset the dispatcher singleton instance so that the url rewrite setting is check on a shop basis when
         // generating product urls. This will fix the issue of incorrectly formatted urls when one shop has the
         // rewrite setting enabled and another does not.
         Dispatcher::$instance = null;
         if (method_exists('ShopUrl', 'resetMainDomainCache')) {
             // Reset the shop url domain cache so that it is re-initialized on a shop basis when generating product
             // image urls. This will fix the issue of the image urls having an incorrect shop base url when the
             // shops are configured to use different domains.
             ShopUrl::resetMainDomainCache();
         }
         foreach (Currency::getCurrenciesByIdShop($id_shop) as $row) {
             if ($row['deleted'] === '0' && $row['active'] === '1') {
                 $currency = new Currency($row['id_currency']);
                 break;
             }
         }
     }
     $context = Context::getContext();
     $context->language = new Language($id_lang);
     $context->shop = new Shop($id_shop);
     $context->link = new Link('http://', 'http://');
     $context->currency = isset($currency) ? $currency : Currency::getDefaultCurrency();
     return $context;
 }