예제 #1
0
 /**
  * Returns an array of two HTML representations of the Attributes and
  * their respective options specified by the array given
  *
  * One of these representation may be used anywhere the matching Product
  * is viewed.  The first (at index 0) is the long form best used in the
  * cart view, the second (at index 1) is suitable for the JSCart in the
  * sidebar.
  * Attributes with an empty list of option IDs will not be included in
  * the string produced.  Invalid IDs are silently skipped.
  * Note that the format of the string can be easily customized by editing
  * the following language entries:
  *  TXT_SHOP_OPTION_LONG_FORMAT
  *  TXT_SHOP_OPTION_LONG_FORMAT_JOINER
  *  TXT_SHOP_ATTRIBUTE_LONG_FORMAT
  *  TXT_SHOP_ATTRIBUTE_LONG_FORMAT_JOINER
  *  TXT_SHOP_OPTION_CART_FORMAT
  *  TXT_SHOP_OPTION_CART_FORMAT_JOINER
  *  TXT_SHOP_ATTRIBUTE_CART_FORMAT
  *  TXT_SHOP_ATTRIBUTE_CART_FORMAT_JOINER
  * The array parameter must have the form
  *  array(
  *    Attribute ID => array(
  *      option ID,
  *      [...]
  *    ),
  *    [...],
  *  )
  * @global  array   $_ARRAYLANG
  * @param   array   $arrAttributesOptions   The array of Attribute and
  *                                          option IDs
  * @param   float   $options_price          The sum of all option prices,
  *                                          by reference
  * @return  array                           The array of two HTML
  *                                          representations of
  *                                          the Attributes and options
  *                                          present in the parameter array
  */
 static function getAsStrings($arrAttributesOptions, &$options_price = NULL)
 {
     global $_ARRAYLANG;
     //DBG::log("Attributes::getAsStrings(".var_export($arrAttributesOptions, true).", $options_price)");
     $options_price = 0;
     if (!is_array($arrAttributesOptions) || empty($arrAttributesOptions)) {
         return array('', '');
     }
     $attributes_long = $attributes_cart = array();
     foreach ($arrAttributesOptions as $attribute_id => $arrOptionIds) {
         //DBG::log("Attributes::getAsStrings(): Attribute ID $attribute_id");
         if (empty($arrOptionIds)) {
             continue;
         }
         $objAttribute = Attribute::getById($attribute_id);
         if (!$objAttribute) {
             continue;
         }
         //DBG::log("Attributes::getAsStrings(): Attribute ".var_export($objAttribute, true));
         $options_long = $options_cart = array();
         $arrOptions = $objAttribute->getOptionArray();
         foreach ($arrOptionIds as $option_id) {
             //DBG::log("Attributes::getAsStrings(): Option ID $option_id");
             $option_name = '';
             // Valid indices are: 'value', 'price', 'order'
             $option_price = $arrOptions[$option_id]['price'];
             // Note that this *MUST NOT* test for is_integer()
             // (which $option_id isn't -- it's either an arbitrary
             // string, or one that represents a positive integer),
             // but for a *string matching a valid ID*.
             // intval() doesn't do the job properly, as it also
             // converts "1 but true" to 1.
             // A good match would be done by is_numeric(); however,
             // this would also accept floats and scientific
             // notation...
             if (preg_match('/^[1-9][0-9]*$/', $option_id) && in_array($objAttribute->getType(), array(Attribute::TYPE_MENU_OPTIONAL, Attribute::TYPE_MENU_MANDATORY, Attribute::TYPE_RADIOBUTTON, Attribute::TYPE_CHECKBOX))) {
                 $option_name = $arrOptions[$option_id]['value'];
             } else {
                 $option_name = ShopLibrary::stripUniqidFromFilename($option_id);
                 $path = Order::UPLOAD_FOLDER . $option_id;
                 if ($option_name != $option_id && file_exists($path)) {
                     $option_name = \Html::getLink('/' . $path, $option_name, 'uploadimage');
                 }
             }
             $options_long[] = sprintf($_ARRAYLANG['TXT_SHOP_OPTION_LONG_FORMAT'], $option_name, $option_price, Currency::getActiveCurrencyCode(), Currency::getActiveCurrencySymbol());
             $options_cart[] = sprintf($_ARRAYLANG['TXT_SHOP_OPTION_CART_FORMAT'], $option_name, $option_price, Currency::getActiveCurrencyCode(), Currency::getActiveCurrencySymbol());
             $options_price += $option_price;
             //DBG::log("Attributes::getAsStrings(): Price + $option_price = $options_price");
         }
         if ($options_long) {
             $options_long = join($_ARRAYLANG['TXT_SHOP_OPTION_LONG_FORMAT_JOINER'], $options_long);
             $attributes_long[] = sprintf($_ARRAYLANG['TXT_SHOP_ATTRIBUTE_LONG_FORMAT'], $objAttribute->getName(), $options_long);
             $options_cart = join($_ARRAYLANG['TXT_SHOP_OPTION_CART_FORMAT_JOINER'], $options_cart);
             $attributes_cart[] = sprintf($_ARRAYLANG['TXT_SHOP_ATTRIBUTE_CART_FORMAT'], $objAttribute->getName(), $options_cart);
         }
     }
     if ($attributes_long) {
         $attributes_long = join($_ARRAYLANG['TXT_SHOP_ATTRIBUTE_LONG_FORMAT_JOINER'], $attributes_long);
         $attributes_cart = join($_ARRAYLANG['TXT_SHOP_ATTRIBUTE_CART_FORMAT_JOINER'], $attributes_cart);
     }
     return array($attributes_long, $attributes_cart);
 }
예제 #2
0
 /**
  * Set up the template block with the shipment terms and conditions
  *
  * Please *DO NOT* remove this method, despite the site terms and
  * conditions have been removed from the Shop!
  * This has been requested by some shopkeepers and may be used at will.
  * @global    array   $_ARRAYLANG     Language array
  * @author    Reto Kohli <*****@*****.**>
  */
 static function showShipmentTerms()
 {
     if (self::$objTemplate->blockExists('shopShipper')) {
         // TODO: Should be set by the calling view, if any
         global $_ARRAYLANG;
         self::$objTemplate->setGlobalVariable($_ARRAYLANG + array('SHOP_CURRENCY_SYMBOL' => Currency::getActiveCurrencySymbol(), 'SHOP_CURRENCY_CODE' => Currency::getActiveCurrencyCode()));
         $arrShipment = Shipment::getShipmentConditions();
         foreach ($arrShipment as $strShipperName => $arrContent) {
             $strCountries = join(', ', $arrContent['countries']);
             $arrConditions = $arrContent['conditions'];
             self::$objTemplate->setCurrentBlock('shopShipment');
             foreach ($arrConditions as $arrData) {
                 self::$objTemplate->setVariable(array('SHOP_MAX_WEIGHT' => $arrData['max_weight'], 'SHOP_COST_FREE' => $arrData['free_from'], 'SHOP_COST' => $arrData['fee']));
                 self::$objTemplate->parse('shopShipment');
             }
             self::$objTemplate->setVariable(array('SHOP_SHIPPER' => $strShipperName, 'SHOP_COUNTRIES' => $strCountries));
             self::$objTemplate->parse('shopShipper');
         }
     }
 }
예제 #3
0
 /**
  * Returns a formatted string indicating the given amount as discounted
  * due to the use of coupon codes
  * @param   float   $amount     The amount
  * @return  sting               The formatted string
  */
 static function getTotalAmountString($amount)
 {
     global $_ARRAYLANG;
     return sprintf($_ARRAYLANG['TXT_SHOP_DISCOUNT_COUPON_AMOUNT_TOTAL_STRING_FORMAT'], Currency::formatPrice($amount), Currency::getActiveCurrencyCode());
 }
 /**
  * Check in the payment processor after the payment is complete.
  * @return  mixed   For external payment methods:
  *                  The integer order ID, if known, upon success
  *                  For internal payment methods:
  *                  Boolean true, in order to make these skip the order
  *                  status update, as this has already been done.
  *                  If the order ID is unknown or upon failure:
  *                  Boolean false
  */
 static function checkIn()
 {
     //DBG::log("PaymentProcessing::checkIn(): Entered");
     //DBG::log("POST: ".var_export($_POST, true));
     //DBG::log("GET: ".var_export($_GET, true));
     $result = NULL;
     if (isset($_GET['result'])) {
         $result = abs(intval($_GET['result']));
         if ($result == 0 || $result == 2) {
             return false;
         }
     }
     if (empty($_REQUEST['handler'])) {
         return false;
     }
     switch ($_REQUEST['handler']) {
         case 'paymill_cc':
         case 'paymill_elv':
         case 'paymill_iban':
             $arrShopOrder = array('order_id' => $_SESSION['shop']['order_id'], 'amount' => intval(bcmul($_SESSION['shop']['grand_total_price'], 100, 0)), 'currency' => Currency::getActiveCurrencyCode(), 'note' => $_SESSION['shop']['note']);
             $response = \PaymillHandler::processRequest($_REQUEST['paymillToken'], $arrShopOrder);
             \DBG::log(var_export($response, true));
             if ($response['status'] === 'success') {
                 return true;
             } else {
                 \DBG::log("PaymentProcessing::checkIn(): WARNING: paymill: Payment verification failed; errors: " . var_export($response, true));
                 return false;
             }
         case 'saferpay':
             $arrShopOrder = array('ACCOUNTID' => \Cx\Core\Setting\Controller\Setting::getValue('saferpay_id', 'Shop'));
             $id = \Saferpay::payConfirm();
             if (\Cx\Core\Setting\Controller\Setting::getValue('saferpay_finalize_payment', 'Shop')) {
                 $arrShopOrder['ID'] = $id;
                 $id = \Saferpay::payComplete($arrShopOrder);
             }
             //DBG::log("Transaction: ".var_export($transaction, true));
             return (bool) $id;
         case 'paypal':
             if (empty($_POST['custom'])) {
                 //DBG::log("PaymentProcessing::checkIn(): No custom parameter, returning NULL");
                 return NULL;
             }
             $order_id = \PayPal::getOrderId();
             //                    if (!$order_id) {
             //                        $order_id = (isset($_SESSION['shop']['order_id'])
             //                            ? $_SESSION['shop']['order_id']
             //                            : (isset ($_SESSION['shop']['order_id_checkin'])
             //                                ? $_SESSION['shop']['order_id_checkin']
             //                                : NULL));
             //                    }
             $order = Order::getById($order_id);
             $amount = $currency_id = $customer_email = NULL;
             if ($order) {
                 $amount = $order->sum();
                 $currency_id = $order->currency_id();
                 $customer_id = $order->customer_id();
                 $customer = Customer::getById($customer_id);
                 if ($customer) {
                     $customer_email = $customer->email();
                 }
             }
             $currency_code = Currency::getCodeById($currency_id);
             return \PayPal::ipnCheck($amount, $currency_code, $order_id, $customer_email, \Cx\Core\Setting\Controller\Setting::getValue('paypal_account_email', 'Shop'));
         case 'yellowpay':
             $passphrase = \Cx\Core\Setting\Controller\Setting::getValue('postfinance_hash_signature_out', 'Shop');
             return \Yellowpay::checkIn($passphrase);
             //                    if (\Yellowpay::$arrError || \Yellowpay::$arrWarning) {
             //                        global $_ARRAYLANG;
             //                        echo('<font color="red"><b>'.
             //                        $_ARRAYLANG['TXT_SHOP_PSP_FAILED_TO_INITIALISE_YELLOWPAY'].
             //                        '</b><br />'.
             //                        'Errors:<br />'.
             //                        join('<br />', \Yellowpay::$arrError).
             //                        'Warnings:<br />'.
             //                        join('<br />', \Yellowpay::$arrWarning).
             //                        '</font>');
             //                    }
         //                    if (\Yellowpay::$arrError || \Yellowpay::$arrWarning) {
         //                        global $_ARRAYLANG;
         //                        echo('<font color="red"><b>'.
         //                        $_ARRAYLANG['TXT_SHOP_PSP_FAILED_TO_INITIALISE_YELLOWPAY'].
         //                        '</b><br />'.
         //                        'Errors:<br />'.
         //                        join('<br />', \Yellowpay::$arrError).
         //                        'Warnings:<br />'.
         //                        join('<br />', \Yellowpay::$arrWarning).
         //                        '</font>');
         //                    }
         case 'payrexx':
             return \PayrexxProcessor::checkIn();
             // Added 20100222 -- Reto Kohli
         // Added 20100222 -- Reto Kohli
         case 'mobilesolutions':
             // A return value of null means:  Do not change the order status
             if (empty($_POST['state'])) {
                 return null;
             }
             $result = \PostfinanceMobile::validateSign();
             if ($result) {
                 //DBG::log("PaymentProcessing::checkIn(): mobilesolutions: Payment verification successful!");
             } else {
                 DBG::log("PaymentProcessing::checkIn(): WARNING: mobilesolutions: Payment verification failed; errors: " . var_export(\PostfinanceMobile::getErrors(), true));
             }
             return $result;
             // Added 20081117 -- Reto Kohli
         // Added 20081117 -- Reto Kohli
         case 'datatrans':
             return \Datatrans::validateReturn() && \Datatrans::getPaymentResult() == 1;
             // For the remaining types, there's no need to check in, so we
             // return true and jump over the validation of the order ID
             // directly to success!
             // Note: A backup of the order ID is kept in the session
             // for payment methods that do not return it. This is used
             // to cancel orders in all cases where false is returned.
         // For the remaining types, there's no need to check in, so we
         // return true and jump over the validation of the order ID
         // directly to success!
         // Note: A backup of the order ID is kept in the session
         // for payment methods that do not return it. This is used
         // to cancel orders in all cases where false is returned.
         case 'internal':
         case 'internal_creditcard':
         case 'internal_debit':
         case 'internal_lsv':
             return true;
             // Dummy payment.
         // Dummy payment.
         case 'dummy':
             $result = '';
             if (isset($_REQUEST['result'])) {
                 $result = $_REQUEST['result'];
             }
             // Returns the order ID on success, false otherwise
             return \Dummy::commit($result);
         default:
             break;
     }
     // Anything else is wrong.
     return false;
 }
예제 #5
0
 /**
  * Returns an array with all placeholders and their values to be
  * replaced in any shop mailtemplate for the given order ID.
  *
  * You only have to set the 'substitution' index value of your MailTemplate
  * array to the array returned.
  * Customer data is not included here.  See {@see Customer::getSubstitutionArray()}.
  * Note that this method is now mostly independent of the current session.
  * The language of the mail template is determined by the browser
  * language range stored with the order.
  * @access  private
  * @static
  * @param   integer $order_id     The order ID
  * @param   boolean $create_accounts  If true, creates User accounts
  *                                    and Coupon codes.  Defaults to true
  * @return  array                 The array with placeholders as keys
  *                                and values from the order on success,
  *                                false otherwise
  */
 static function getSubstitutionArray($order_id, $create_accounts = true)
 {
     global $_ARRAYLANG;
     /*
                 $_ARRAYLANG['TXT_SHOP_URI_FOR_DOWNLOAD'].":\r\n".
                 'http://'.$_SERVER['SERVER_NAME'].
                 "/index.php?section=download\r\n";
     */
     $objOrder = Order::getById($order_id);
     if (!$objOrder) {
         // Order not found
         return false;
     }
     $lang_id = $objOrder->lang_id();
     if (!intval($lang_id)) {
         $lang_id = \FWLanguage::getLangIdByIso639_1($lang_id);
     }
     $status = $objOrder->status();
     $customer_id = $objOrder->customer_id();
     $customer = Customer::getById($customer_id);
     $payment_id = $objOrder->payment_id();
     $shipment_id = $objOrder->shipment_id();
     $arrSubstitution = array('CUSTOMER_COUNTRY_ID' => $objOrder->billing_country_id(), 'LANG_ID' => $lang_id, 'NOW' => date(ASCMS_DATE_FORMAT_DATETIME), 'TODAY' => date(ASCMS_DATE_FORMAT_DATE), 'ORDER_ID' => $order_id, 'ORDER_ID_CUSTOM' => ShopLibrary::getCustomOrderId($order_id), 'ORDER_DATE' => date(ASCMS_DATE_FORMAT_DATE, strtotime($objOrder->date_time())), 'ORDER_TIME' => date(ASCMS_DATE_FORMAT_TIME, strtotime($objOrder->date_time())), 'ORDER_STATUS_ID' => $status, 'ORDER_STATUS' => $_ARRAYLANG['TXT_SHOP_ORDER_STATUS_' . $status], 'MODIFIED' => date(ASCMS_DATE_FORMAT_DATETIME, strtotime($objOrder->modified_on())), 'REMARKS' => $objOrder->note(), 'ORDER_SUM' => sprintf('% 9.2f', $objOrder->sum()), 'CURRENCY' => Currency::getCodeById($objOrder->currency_id()));
     $arrSubstitution += $customer->getSubstitutionArray();
     if ($shipment_id) {
         $arrSubstitution += array('SHIPMENT' => array(0 => array('SHIPMENT_NAME' => sprintf('%-40s', Shipment::getShipperName($shipment_id)), 'SHIPMENT_PRICE' => sprintf('% 9.2f', $objOrder->shipment_amount()))), 'SHIPPING_ADDRESS' => array(0 => array('SHIPPING_COMPANY' => $objOrder->company(), 'SHIPPING_TITLE' => $_ARRAYLANG['TXT_SHOP_' . strtoupper($objOrder->gender())], 'SHIPPING_FIRSTNAME' => $objOrder->firstname(), 'SHIPPING_LASTNAME' => $objOrder->lastname(), 'SHIPPING_ADDRESS' => $objOrder->address(), 'SHIPPING_ZIP' => $objOrder->zip(), 'SHIPPING_CITY' => $objOrder->city(), 'SHIPPING_COUNTRY_ID' => $objOrder->country_id(), 'SHIPPING_COUNTRY' => \Cx\Core\Country\Controller\Country::getNameById($objOrder->country_id()), 'SHIPPING_PHONE' => $objOrder->phone())));
     }
     if ($payment_id) {
         $arrSubstitution += array('PAYMENT' => array(0 => array('PAYMENT_NAME' => sprintf('%-40s', Payment::getNameById($payment_id)), 'PAYMENT_PRICE' => sprintf('% 9.2f', $objOrder->payment_amount()))));
     }
     $arrItems = $objOrder->getItems();
     if (!$arrItems) {
         \Message::warning($_ARRAYLANG['TXT_SHOP_ORDER_WARNING_NO_ITEM']);
     }
     // Deduct Coupon discounts, either from each Product price, or
     // from the items total.  Mind that the Coupon has already been
     // stored with the Order, but not redeemed yet.  This is done
     // in this method, but only if $create_accounts is true.
     $coupon_code = NULL;
     $coupon_amount = 0;
     $objCoupon = Coupon::getByOrderId($order_id);
     if ($objCoupon) {
         $coupon_code = $objCoupon->code();
     }
     $orderItemCount = 0;
     $total_item_price = 0;
     // Suppress Coupon messages (see Coupon::available())
     \Message::save();
     foreach ($arrItems as $item) {
         $product_id = $item['product_id'];
         $objProduct = Product::getById($product_id);
         if (!$objProduct) {
             //die("Product ID $product_id not found");
             continue;
         }
         //DBG::log("Orders::getSubstitutionArray(): Item: Product ID $product_id");
         $product_name = substr($item['name'], 0, 40);
         $item_price = $item['price'];
         $quantity = $item['quantity'];
         // TODO: Add individual VAT rates for Products
         //            $orderItemVatPercent = $objResultItem->fields['vat_percent'];
         // Decrease the Product stock count,
         // applies to "real", shipped goods only
         $objProduct->decreaseStock($quantity);
         $product_code = $objProduct->code();
         // Pick the order items attributes
         $str_options = '';
         // Any attributes?
         if ($item['attributes']) {
             $str_options = '  ';
             // '[';
             $attribute_name_previous = '';
             foreach ($item['attributes'] as $attribute_name => $arrAttribute) {
                 //DBG::log("Attribute /$attribute_name/ => ".var_export($arrAttribute, true));
                 // NOTE: The option price is optional and may be left out
                 foreach ($arrAttribute as $arrOption) {
                     $option_name = $arrOption['name'];
                     $option_price = $arrOption['price'];
                     $item_price += $option_price;
                     // Recognize the names of uploaded files,
                     // verify their presence and use the original name
                     $option_name_stripped = ShopLibrary::stripUniqidFromFilename($option_name);
                     $path = Order::UPLOAD_FOLDER . $option_name;
                     if ($option_name != $option_name_stripped && \File::exists($path)) {
                         $option_name = $option_name_stripped;
                     }
                     if ($attribute_name != $attribute_name_previous) {
                         if ($attribute_name_previous) {
                             $str_options .= '; ';
                         }
                         $str_options .= $attribute_name . ': ' . $option_name;
                         $attribute_name_previous = $attribute_name;
                     } else {
                         $str_options .= ', ' . $option_name;
                     }
                     // TODO: Add proper formatting with sprintf() and language entries
                     if ($option_price != 0) {
                         $str_options .= ' ' . Currency::formatPrice($option_price) . ' ' . Currency::getActiveCurrencyCode();
                     }
                 }
             }
             //                $str_options .= ']';
         }
         // Product details
         $arrProduct = array('PRODUCT_ID' => $product_id, 'PRODUCT_CODE' => $product_code, 'PRODUCT_QUANTITY' => $quantity, 'PRODUCT_TITLE' => $product_name, 'PRODUCT_OPTIONS' => $str_options, 'PRODUCT_ITEM_PRICE' => sprintf('% 9.2f', $item_price), 'PRODUCT_TOTAL_PRICE' => sprintf('% 9.2f', $item_price * $quantity));
         //DBG::log("Orders::getSubstitutionArray($order_id, $create_accounts): Adding article: ".var_export($arrProduct, true));
         $orderItemCount += $quantity;
         $total_item_price += $item_price * $quantity;
         if ($create_accounts) {
             // Add an account for every single instance of every Product
             for ($instance = 1; $instance <= $quantity; ++$instance) {
                 $validity = 0;
                 // Default to unlimited validity
                 // In case there are protected downloads in the cart,
                 // collect the group IDs
                 $arrUsergroupId = array();
                 if ($objProduct->distribution() == 'download') {
                     $usergroupIds = $objProduct->usergroup_ids();
                     if ($usergroupIds != '') {
                         $arrUsergroupId = explode(',', $usergroupIds);
                         $validity = $objProduct->weight();
                     }
                 }
                 // create an account that belongs to all collected
                 // user groups, if any.
                 if (count($arrUsergroupId) > 0) {
                     // The login names are created separately for
                     // each product instance
                     $username = self::usernamePrefix . "_{$order_id}_{$product_id}_{$instance}";
                     $userEmail = $username . '-' . $arrSubstitution['CUSTOMER_EMAIL'];
                     $userpass = \User::make_password();
                     $objUser = new \User();
                     $objUser->setUsername($username);
                     $objUser->setPassword($userpass);
                     $objUser->setEmail($userEmail);
                     $objUser->setAdminStatus(false);
                     $objUser->setActiveStatus(true);
                     $objUser->setGroups($arrUsergroupId);
                     $objUser->setValidityTimePeriod($validity);
                     $objUser->setFrontendLanguage(FRONTEND_LANG_ID);
                     $objUser->setBackendLanguage(FRONTEND_LANG_ID);
                     $objUser->setProfile(array('firstname' => array(0 => $arrSubstitution['CUSTOMER_FIRSTNAME']), 'lastname' => array(0 => $arrSubstitution['CUSTOMER_LASTNAME']), 'company' => array(0 => $arrSubstitution['CUSTOMER_COMPANY']), 'address' => array(0 => $arrSubstitution['CUSTOMER_ADDRESS']), 'zip' => array(0 => $arrSubstitution['CUSTOMER_ZIP']), 'city' => array(0 => $arrSubstitution['CUSTOMER_CITY']), 'country' => array(0 => $arrSubstitution['CUSTOMER_COUNTRY_ID']), 'phone_office' => array(0 => $arrSubstitution['CUSTOMER_PHONE']), 'phone_fax' => array(0 => $arrSubstitution['CUSTOMER_FAX'])));
                     if (!$objUser->store()) {
                         \Message::error(implode('<br />', $objUser->getErrorMsg()));
                         return false;
                     }
                     if (empty($arrProduct['USER_DATA'])) {
                         $arrProduct['USER_DATA'] = array();
                     }
                     $arrProduct['USER_DATA'][] = array('USER_NAME' => $username, 'USER_PASS' => $userpass);
                 }
                 //echo("Instance $instance");
                 if ($objProduct->distribution() == 'coupon') {
                     if (empty($arrProduct['COUPON_DATA'])) {
                         $arrProduct['COUPON_DATA'] = array();
                     }
                     //DBG::log("Orders::getSubstitutionArray(): Getting code");
                     $code = Coupon::getNewCode();
                     //DBG::log("Orders::getSubstitutionArray(): Got code: $code, calling Coupon::addCode($code, 0, 0, 0, $item_price)");
                     Coupon::storeCode($code, 0, 0, 0, $item_price, 0, 0, 10000000000.0, true);
                     $arrProduct['COUPON_DATA'][] = array('COUPON_CODE' => $code);
                 }
             }
             // Redeem the *product* Coupon, if possible for the Product
             if ($coupon_code) {
                 $objCoupon = Coupon::available($coupon_code, $item_price * $quantity, $customer_id, $product_id, $payment_id);
                 if ($objCoupon) {
                     $coupon_code = NULL;
                     $coupon_amount = $objCoupon->getDiscountAmount($item_price, $customer_id);
                     if ($create_accounts) {
                         $objCoupon->redeem($order_id, $customer_id, $item_price * $quantity);
                     }
                 }
                 //\DBG::log("Orders::getSubstitutionArray(): Got Product Coupon $coupon_code");
             }
         }
         if (empty($arrSubstitution['ORDER_ITEM'])) {
             $arrSubstitution['ORDER_ITEM'] = array();
         }
         $arrSubstitution['ORDER_ITEM'][] = $arrProduct;
     }
     $arrSubstitution['ORDER_ITEM_SUM'] = sprintf('% 9.2f', $total_item_price);
     $arrSubstitution['ORDER_ITEM_COUNT'] = sprintf('% 4u', $orderItemCount);
     // Redeem the *global* Coupon, if possible for the Order
     if ($coupon_code) {
         $objCoupon = Coupon::available($coupon_code, $total_item_price, $customer_id, null, $payment_id);
         if ($objCoupon) {
             $coupon_amount = $objCoupon->getDiscountAmount($total_item_price, $customer_id);
             if ($create_accounts) {
                 $objCoupon->redeem($order_id, $customer_id, $total_item_price);
             }
         }
     }
     \Message::restore();
     // Fill in the Coupon block with proper discount and amount
     if ($objCoupon) {
         $coupon_code = $objCoupon->code();
         //\DBG::log("Orders::getSubstitutionArray(): Coupon $coupon_code, amount $coupon_amount");
     }
     if ($coupon_amount) {
         //\DBG::log("Orders::getSubstitutionArray(): Got Order Coupon $coupon_code");
         $arrSubstitution['DISCOUNT_COUPON'][] = array('DISCOUNT_COUPON_CODE' => sprintf('%-40s', $coupon_code), 'DISCOUNT_COUPON_AMOUNT' => sprintf('% 9.2f', -$coupon_amount));
     } else {
         //\DBG::log("Orders::getSubstitutionArray(): No Coupon for Order ID $order_id");
     }
     Products::deactivate_soldout();
     if (Vat::isEnabled()) {
         //DBG::log("Orders::getSubstitutionArray(): VAT amount: ".$objOrder->vat_amount());
         $arrSubstitution['VAT'] = array(0 => array('VAT_TEXT' => sprintf('%-40s', Vat::isIncluded() ? $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_INCL'] : $_ARRAYLANG['TXT_SHOP_VAT_PREFIX_EXCL']), 'VAT_PRICE' => $objOrder->vat_amount()));
     }
     return $arrSubstitution;
 }