public function applyRule(ISC_QUOTE $quote) { if (!customerIsSignedIn()) { return null; } $customerId = getClass('ISC_CUSTOMER')->getCustomerId(); $query = " SELECT COUNT(*) FROM [|PREFIX|]orders WHERE ordcustid='".$customerId."' AND ordstatus > 0 AND deleted = 0 LIMIT 1 "; $orderCount = $GLOBALS['ISC_CLASS_DB']->fetchOne($query); // Discount does not apply if($orderCount <= $this->orders) { return false; } $items = $quote->getItems(); $totalDiscount = 0; // The discount needs to come off each item, so that tax is also affected. foreach($items as $item) { $discountAmount = $item->getDiscountedBaseTotal() * ($this->amount / 100); $item->addDiscount($this->getDbId(), $discountAmount); $totalDiscount += $discountAmount; } $quote->addDiscount($this->getDbId(), $totalDiscount); $this->banners[] = sprintf(getLang($this->getName().'DiscountMessage'), $this->amount); return true; }
/** * Create the pending order in the database with the customers selected payment details, etc. * * @return array An array containing information about what needs to be done next. */ public function SavePendingOrder() { $provider = null; $verifyPaymentProvider = true; $redirectToFinishOrder = false; $providerId = ''; $pendingOrderResult = array(); $creditUsed = 0; $giftCertificates = array(); $orderTotal = $this->getQuote()->getGrandTotal(); // store the discounted subtotal in the session for affiliate tracking $incTax = (getConfig('taxDefaultTaxDisplayOrders') == TAX_PRICES_DISPLAY_INCLUSIVE); $_SESSION['LAST_ORDER_DISCOUNTED_SUBTOTAL'] = $this->getQuote()->getDiscountedSubTotal($incTax); // Find out what currency we are using. We'll need this later to display their previous orders in the currency that they have selected $selectedCurrency = GetCurrencyById($GLOBALS['CurrentCurrency']); $giftCertificates = $this->getQuote()->getAppliedGiftCertificates(); if(!empty($giftCertificates)) { $badCertificates = array(); $remainingBalance = 0; $totalWithoutCertificates = $this->getQuote()->getGrandTotalWithoutGiftCertificates(); $giftCertificateAmount = $this->getQuote()->getGiftCertificateTotal(); getClass('ISC_GIFTCERTIFICATES') ->giftCertificatesApplicableToOrder( $totalWithoutCertificates, $giftCertificates, $remainingBalance, $badCertificates); // One or more gift certificates were invalid so this order is now invalid if(!empty($badCertificates)) { $badCertificatesList = '<strong>'.GetLang('BadGiftCertificates').'</strong><ul>'; foreach($badCertificates as $code => $reason) { if(is_array($reason) && $reason[0] == "expired") { $reason = sprintf(GetLang('BadGiftCertificateExpired'), CDate($reason[1])); } else { $reason = GetLang('BadGiftCertificate'.ucfirst($reason)); } $badCertificatesList .= sprintf("<li>%s - %s", isc_html_escape($code), $reason); } $badCertificatesList .= "</ul>"; $pendingOrderResult = array( 'error' => GetLang('OrderContainedInvalidGiftCertificates'), 'errorDetails' => $badCertificatesList ); return $pendingOrderResult; } // This order was entirely paid for using gift certificates but the totals don't add up else if($totalWithoutCertificates == $giftCertificateAmount && $remainingBalance > 0) { $pendingOrderResult = array( 'error' => GetLang('OrderTotalStillRemainingCertificates') ); return $pendingOrderResult; } // Order was entirely paid for using gift certificates else if($totalWithoutCertificates == $giftCertificateAmount) { $providerId = 'giftcertificate'; $verifyPaymentProvider = false; $redirectToFinishOrder = true; } } // If the order total is 0, then we just forward the user on to the "Thank You" page and set the payment provider to '' if($orderTotal == 0) { $providerId = ''; $verifyPaymentProvider = false; $redirectToFinishOrder = true; } $selected_provider = ''; if($verifyPaymentProvider) { $candidate = ''; if (isset($_POST['checkout_provider']) && $_POST['checkout_provider'] != '') { $candidate = $_POST['checkout_provider']; } else if (isset($_POST['credit_checkout_provider']) && $_POST['credit_checkout_provider'] != '') { // used by paypal $candidate = $_POST['credit_checkout_provider']; } // Check if the chosen checkout method is valid $providers = GetCheckoutModulesThatCustomerHasAccessTo(true); foreach ($providers as $p) { if ($p['id'] == $candidate) { $selected_provider = $candidate; } } // If there's only one payment provider, then they're paying via that if($selected_provider == '' && count($providers) == 1) { $selected_provider = $providers[0]['object']->GetId(); } // Are we using our store credit? $customer = getClass('ISC_CUSTOMER')->getCustomerDataByToken(); if (isset($_POST['store_credit']) && $_POST['store_credit'] == 1 && $customer['custstorecredit'] > 0) { // User has not chosen a payment provider and can't afford this order using only store credit, throw back as error if ($selected_provider == '' && $customer['custstorecredit'] < $orderTotal) { return false; } // Otherwise we can use the store credit. // Subtract store credit from users account and send them to the finished page else { $onlyCredit = false; $updateExtra = ''; // If we're only using store credit $creditToUse = $orderTotal; if ($customer['custstorecredit'] >= $creditToUse) { // Set the checkout provider $providerId = 'storecredit'; $verifyPaymentProvider = false; $redirectToFinishOrder = true; $creditUsed = $creditToUse; $onlyCredit = true; } else { // Using all of our store credit to pay for this order and we owe more. $creditUsed = $customer['custstorecredit']; } } } } $orderStatus = ORDER_STATUS_INCOMPLETE; // Now with round 2, do we still need to verify the payment provider? if($verifyPaymentProvider) { // If there's more than one provider and one wasn't selected on the order confirmation screen then there's a problem if ((count($providers) == 0 || (count($providers) > 1 && $selected_provider == '')) && !isset($_SESSION['CHECKOUT']['ProviderListHTML'])) { return false; } // Is the payment provider selected actually valid? if (!GetModuleById('checkout', $provider, $selected_provider)) { return false; } $providerId = $provider->GetId(); } if(isset($_COOKIE['SHOP_TOKEN'])) { $customerToken = $_COOKIE['SHOP_TOKEN']; } else { $customerToken = ''; } $orderComments = ''; if(isset($_REQUEST['ordercomments'])) { $orderComments = $_POST['ordercomments']; } // Set up the order to be created $this->getQuote() ->setAppliedStoreCredit($creditUsed) ->setCustomerMessage($orderComments); ; $newOrder = array( 'orderpaymentmodule' => $providerId, 'ordcurrencyid' => $selectedCurrency['currencyid'], 'ordcurrencyexchangerate' => $selectedCurrency['currencyexchangerate'], 'ordipaddress' => getIp(), 'ordstatus' => $orderStatus, 'extraInfo' => array(), 'quote' => $this->getQuote(), ); // OK, we're successful down to here - do they want to create an account? If so then assign it to // a session so we can create the actual record on a successful order if(!empty($_SESSION['CHECKOUT']['CREATE_ACCOUNT']) || !customerIsSignedIn() && getConfig('GuestCheckoutCreateAccounts')) { $createAccount = array( 'addresses' => array() ); if(!empty($_SESSION['CHECKOUT']['CREATE_ACCOUNT'])) { $createAccount['password'] = $_SESSION['CHECKOUT']['CREATE_ACCOUNT']['password']; $createAccount['customFormFields'] = $_SESSION['CHECKOUT']['CREATE_ACCOUNT']['customFields']; } else { $createAccount['autoCreated'] = 1; } // Handle saving of addresses for new customers foreach($this->getQuote()->getAllAddresses() as $address) { if($address->getSaveAddress()) { $customerAddress = $address->getAsArray(); $customFields = $address->getCustomFields(); if(!empty($customFields)) { $customerAddress['customFormFields'] = $customFields; // Shipping fields need to be mapped back to billing so they can be stored if($address->getType() == ISC_QUOTE_ADDRESS::TYPE_SHIPPING) { $newCustomFields = array(); $map = $GLOBALS['ISC_CLASS_FORM']->mapAddressFieldList(FORMFIELDS_FORM_SHIPPING, array_keys($customFields)); foreach($map as $oldId => $newId) { $newCustomFields[$newId] = $customFields[$oldId]; } $customerAddress['customFormFields'] = $newCustomFields; } } $createAccount['addresses'][] = $customerAddress; } } $newOrder['extraInfo']['createAccount'] = $createAccount; } // Did they agree to signup to any mailing lists? if (isset($_POST['join_mailing_list'])) { $newOrder['extraInfo']['join_mailing_list'] = true; } if (isset($_POST['join_order_list'])) { $newOrder['extraInfo']['join_order_list'] = true; } if (isset($_POST['join_mailing_list']) || isset($_POST['join_order_list'])) { if (isset($_POST['mail_format_preference'])) { $newOrder['extraInfo']['mail_format_preference'] = (int)$_POST['mail_format_preference']; } else { $newOrder['extraInfo']['mail_format_preference'] = Interspire_EmailIntegration_Subscription::FORMAT_PREF_NONE; } $newOrder['extraInfo']['join_order_list'] = true; } if(isset($_POST['ordermessage'])) { $newOrder['ordermessage'] = $_POST['ordermessage']; } else { $newOrder['ordermessage'] = ''; } $entity = new ISC_ENTITY_ORDER(); $orderId = $entity->add($newOrder); // Failed to create the order if(!$orderId) { return false; } $order = getOrder($orderId); // Persist the pending order token as a cookie for 24 hours ISC_SetCookie("SHOP_ORDER_TOKEN", $order['ordtoken'], time() + (3600*24), true); $_COOKIE['SHOP_ORDER_TOKEN'] = $order['ordtoken']; // Redirecting to finish order page? if($redirectToFinishOrder) { return array( 'redirectToFinishOrder' => true ); } // Otherwise, the gateway want's to do something $orderData = LoadPendingOrdersByToken($order['ordtoken']); $provider->SetOrderData($orderData); // Is this an online payment provider? It would like to do something if($provider->GetPaymentType() == PAYMENT_PROVIDER_ONLINE || method_exists($provider, "ShowPaymentForm")) { // Call the checkout process for the selected provider if(method_exists($provider, "ShowPaymentForm")) { return array( 'provider' => $provider, 'showPaymentForm' => true ); } else { return array( 'provider' => $provider ); } } // If an offline method, we throw them to the "Thank you for your order" page else { return array( 'provider' => $provider ); } }
/** * Save the billing address for a customer checking out via express checkout. */ public function saveExpressCheckoutBillingAddress() { // If the customer is not logged in and guest checkout is enabled, then don't go any further if(!customerIsSignedIn() && !getConfig('GuestCheckoutEnabled') && empty($_POST['createAccount'])) { $response = array( 'status' => 0, 'changeStep' => 'AccountDetails', 'errorMessage' => getLang('GuestCheckoutDisabledError') ); echo isc_json_encode($response); exit; } $addressDetails = null; $shipToBilling = false; // If the customer isn't signed in then they've just entered an address that we need to validate if(isset($_REQUEST['BillingAddressType']) && $_REQUEST['BillingAddressType'] == 'new') { $errors = array(); // An invalid address was entered, show the form again $addressDetails = getClass('ISC_CHECKOUT')->validateGuestCheckoutAddress('billing', $errors); if(!$addressDetails) { $response = array( 'status' => 0, 'changeStep' => 'BillingAddress', 'errorMessage' => implode("\n", $errors) ); echo isc_json_encode($response); exit; } // Make sure the email address isn't already in use if the customer is // creating a new account. // Plus if it's guess checkout and creation of account after the checkout process is enabled if(!customerIsSignedIn() && (!empty($_POST['createAccount']) || (getConfig('GuestCheckoutEnabled') && getConfig('GuestCheckoutCreateAccounts')))) { $emailField = $GLOBALS['ISC_CLASS_FORM']->getFormField(FORMFIELDS_FORM_ACCOUNT, '1', '', true); $email = $emailField->getValue(); // Check that this email address isn't already in use by a customer $customer = GetClass('ISC_CUSTOMER'); if($customer->AccountWithEmailAlreadyExists($email)) { $response = array( 'status' => 0, 'changeStep' => 'BillingAddress', 'errorMessage' => getLang('CheckoutEmailAddressInUseAjax'), 'focus' => '#'.$emailField->getFieldId(), ); echo isc_json_encode($response); exit; } } if(!empty($_POST['ship_to_billing_new'])) { $shipToBilling = true; } } else { // We've just selected an address if(isset($_POST['sel_billing_address'])) { $addressDetails = (int)$_POST['sel_billing_address']; } if(!empty($_POST['ship_to_billing_existing'])) { $shipToBilling = true; } } // There was a problem saving the selected billing address if(!getClass('ISC_CHECKOUT')->setOrderBillingAddress($addressDetails)) { $response = array( 'status' => 0, 'changeStep' => 'BillingAddress', 'errorMessage' => getLang('UnableSaveOrderBillingAddress'), ); echo isc_json_encode($response); exit; } if(!empty($_POST['save_billing_address'])) { getCustomerQuote()->getBillingAddress()->setSaveAddress(true); } $completedSteps = array( array( 'id' => 'BillingAddress', 'message' => $this->getCheckoutAddressPreview( getCustomerQuote()->getBillingAddress() ), ) ); // If creating an account, store the account creation fields unset($_SESSION['CHECKOUT']['CREATE_ACCOUNT']); if(!empty($_POST['createAccount'])) { $accountFields = $GLOBALS['ISC_CLASS_FORM']->getFormFields(FORMFIELDS_FORM_ACCOUNT, true); $accountSession = array( 'customFields' => array() ); foreach($accountFields as $fieldId => $formField) { if($formField->record['formfieldprivateid'] == 'Password') { $accountSession['password'] = $formField->getValue(); } // Apart from the password, only interested in CUSTOM fields else if(!$formField->record['formfieldprivateid']) { $accountSession['customFields'][$fieldId] = $formField->getValue(); } } $_SESSION['CHECKOUT']['CREATE_ACCOUNT'] = $accountSession; } // If a digital order, skip right to the order confirmation if(getCustomerQuote()->isDigital()) { $this->getExpressCheckoutConfirmation($completedSteps); exit; } // Otherwise, proceed with shipping // Shipping to the billing address so save it as well if($shipToBilling) { if(!getClass('ISC_CHECKOUT')->setOrderShippingAddress($addressDetails, true)) { $response = array( 'status' => 0, 'changeStep' => 'ShippingAddress', 'errorMessage' => getLang('UnableSaveOrderShippingAddress'), ); echo isc_json_encode($response); exit; } // If we're shipping to the billing address, then reload the shipping address // quote block, because it could contain updated values. $stepContent = array(array( 'id' => 'ShippingAddress', 'content' => getClass('ISC_CHECKOUT')->expressCheckoutChooseAddress('shipping', true), )); $this->getExpressCheckoutShippers($completedSteps, $stepContent); exit; } $response = array( 'status' => 1, 'changeStep' => 'ShippingAddress', 'completedSteps' => $completedSteps, 'resetSteps' => true, ); echo isc_json_encode($response); exit; }