/magento/app/code/core/Mage/Paypal/Model/Express/Checkout.php
PHP | 996 lines | 597 code | 91 blank | 308 comment | 116 complexity | 460fec8be683d9e5c2e859295ffb2e9f MD5 | raw file
Possible License(s): LGPL-3.0
- <?php
- /**
- * Magento
- *
- * NOTICE OF LICENSE
- *
- * This source file is subject to the Open Software License (OSL 3.0)
- * that is bundled with this package in the file LICENSE.txt.
- * It is also available through the world-wide-web at this URL:
- * http://opensource.org/licenses/osl-3.0.php
- * If you did not receive a copy of the license and are unable to
- * obtain it through the world-wide-web, please send an email
- * to license@magentocommerce.com so we can send you a copy immediately.
- *
- * DISCLAIMER
- *
- * Do not edit or add to this file if you wish to upgrade Magento to newer
- * versions in the future. If you wish to customize Magento for your
- * needs please refer to http://www.magentocommerce.com for more information.
- *
- * @category Mage
- * @package Mage_Paypal
- * @copyright Copyright (c) 2012 Magento Inc. (http://www.magentocommerce.com)
- * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
- */
- /**
- * Wrapper that performs Paypal Express and Checkout communication
- * Use current Paypal Express method instance
- */
- class Mage_Paypal_Model_Express_Checkout
- {
- /**
- * Cache ID prefix for "pal" lookup
- * @var string
- */
- const PAL_CACHE_ID = 'paypal_express_checkout_pal';
- /**
- * Keys for passthrough variables in sales/quote_payment and sales/order_payment
- * Uses additional_information as storage
- * @var string
- */
- const PAYMENT_INFO_TRANSPORT_TOKEN = 'paypal_express_checkout_token';
- const PAYMENT_INFO_TRANSPORT_SHIPPING_OVERRIDEN = 'paypal_express_checkout_shipping_overriden';
- const PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD = 'paypal_express_checkout_shipping_method';
- const PAYMENT_INFO_TRANSPORT_PAYER_ID = 'paypal_express_checkout_payer_id';
- const PAYMENT_INFO_TRANSPORT_REDIRECT = 'paypal_express_checkout_redirect_required';
- const PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT = 'paypal_ec_create_ba';
- /**
- * @var Mage_Sales_Model_Quote
- */
- protected $_quote = null;
- /**
- * Config instance
- * @var Mage_Paypal_Model_Config
- */
- protected $_config = null;
- /**
- * API instance
- * @var Mage_Paypal_Model_Api_Nvp
- */
- protected $_api = null;
- /**
- * Api Model Type
- *
- * @var string
- */
- protected $_apiType = 'paypal/api_nvp';
- /**
- * Payment method type
- *
- * @var unknown_type
- */
- protected $_methodType = Mage_Paypal_Model_Config::METHOD_WPP_EXPRESS;
- /**
- * State helper variables
- * @var string
- */
- protected $_redirectUrl = '';
- protected $_pendingPaymentMessage = '';
- protected $_checkoutRedirectUrl = '';
- /**
- * @var Mage_Customer_Model_Session
- */
- protected $_customerSession;
- /**
- * Redirect urls supposed to be set to support giropay
- *
- * @var array
- */
- protected $_giropayUrls = array();
- /**
- * Create Billing Agreement flag
- *
- * @var bool
- */
- protected $_isBARequested = false;
- /**
- * Customer ID
- *
- * @var int
- */
- protected $_customerId = null;
- /**
- * Recurring payment profiles
- *
- * @var array
- */
- protected $_recurringPaymentProfiles = array();
- /**
- * Billing agreement that might be created during order placing
- *
- * @var Mage_Sales_Model_Billing_Agreement
- */
- protected $_billingAgreement = null;
- /**
- * Order
- *
- * @var Mage_Sales_Model_QuoteMage_Sales_Model_Quote
- */
- protected $_order = null;
- /**
- * Set quote and config instances
- * @param array $params
- */
- public function __construct($params = array())
- {
- if (isset($params['quote']) && $params['quote'] instanceof Mage_Sales_Model_Quote) {
- $this->_quote = $params['quote'];
- } else {
- throw new Exception('Quote instance is required.');
- }
- if (isset($params['config']) && $params['config'] instanceof Mage_Paypal_Model_Config) {
- $this->_config = $params['config'];
- } else {
- throw new Exception('Config instance is required.');
- }
- $this->_customerSession = Mage::getSingleton('customer/session');
- }
- /**
- * Checkout with PayPal image URL getter
- * Spares API calls of getting "pal" variable, by putting it into cache per store view
- * @return string
- */
- public function getCheckoutShortcutImageUrl()
- {
- // get "pal" thing from cache or lookup it via API
- $pal = null;
- if ($this->_config->areButtonsDynamic()) {
- $cacheId = self::PAL_CACHE_ID . Mage::app()->getStore()->getId();
- $pal = Mage::app()->loadCache($cacheId);
- if (-1 == $pal) {
- $pal = null;
- } elseif (!$pal) {
- $pal = null;
- $this->_getApi();
- try {
- $this->_api->callGetPalDetails();
- $pal = $this->_api->getPal();
- Mage::app()->saveCache($pal, $cacheId, array(Mage_Core_Model_Config::CACHE_TAG));
- } catch (Exception $e) {
- Mage::app()->saveCache(-1, $cacheId, array(Mage_Core_Model_Config::CACHE_TAG));
- Mage::logException($e);
- }
- }
- }
- return $this->_config->getExpressCheckoutShortcutImageUrl(
- Mage::app()->getLocale()->getLocaleCode(),
- $this->_quote->getBaseGrandTotal(),
- $pal
- );
- }
- /**
- * Setter that enables giropay redirects flow
- *
- * @param string $successUrl - payment success result
- * @param string $cancelUrl - payment cancellation result
- * @param string $pendingUrl - pending payment result
- * @return Mage_Paypal_Model_Express_Checkout
- */
- public function prepareGiropayUrls($successUrl, $cancelUrl, $pendingUrl)
- {
- $this->_giropayUrls = array($successUrl, $cancelUrl, $pendingUrl);
- return $this;
- }
- /**
- * Set create billing agreement flag
- *
- * @param bool $flag
- * @return Mage_Paypal_Model_Express_Checkout
- */
- public function setIsBillingAgreementRequested($flag)
- {
- $this->_isBARequested = $flag;
- return $this;
- }
- /**
- * Setter for customer Id
- *
- * @param int $id
- * @return Mage_Paypal_Model_Express_Checkout
- * @deprecated please use self::setCustomer
- */
- public function setCustomerId($id)
- {
- $this->_customerId = $id;
- return $this;
- }
- /**
- * Setter for customer
- *
- * @param Mage_Customer_Model_Customer $customer
- * @return Mage_Paypal_Model_Express_Checkout
- */
- public function setCustomer($customer)
- {
- $this->_quote->assignCustomer($customer);
- $this->_customerId = $customer->getId();
- return $this;
- }
- /**
- * Setter for customer with billing and shipping address changing ability
- *
- * @param Mage_Customer_Model_Customer $customer
- * @param Mage_Sales_Model_Quote_Address $billingAddress
- * @param Mage_Sales_Model_Quote_Address $shippingAddress
- * @return Mage_Paypal_Model_Express_Checkout
- */
- public function setCustomerWithAddressChange($customer, $billingAddress = null, $shippingAddress = null)
- {
- $this->_quote->assignCustomerWithAddressChange($customer, $billingAddress, $shippingAddress);
- $this->_customerId = $customer->getId();
- return $this;
- }
- /**
- * Reserve order ID for specified quote and start checkout on PayPal
- *
- * @param string $returnUrl
- * @param string $cancelUrl
- * @return mixed
- */
- public function start($returnUrl, $cancelUrl)
- {
- $this->_quote->collectTotals();
- if (!$this->_quote->getGrandTotal() && !$this->_quote->hasNominalItems()) {
- Mage::throwException(Mage::helper('paypal')->__('PayPal does not support processing orders with zero amount. To complete your purchase, proceed to the standard checkout process.'));
- }
- $this->_quote->reserveOrderId()->save();
- // prepare API
- $this->_getApi();
- $this->_api->setAmount($this->_quote->getBaseGrandTotal())
- ->setCurrencyCode($this->_quote->getBaseCurrencyCode())
- ->setInvNum($this->_quote->getReservedOrderId())
- ->setReturnUrl($returnUrl)
- ->setCancelUrl($cancelUrl)
- ->setSolutionType($this->_config->solutionType)
- ->setPaymentAction($this->_config->paymentAction)
- ;
- if ($this->_giropayUrls) {
- list($successUrl, $cancelUrl, $pendingUrl) = $this->_giropayUrls;
- $this->_api->addData(array(
- 'giropay_cancel_url' => $cancelUrl,
- 'giropay_success_url' => $successUrl,
- 'giropay_bank_txn_pending_url' => $pendingUrl,
- ));
- }
- $this->_setBillingAgreementRequest();
- if ($this->_config->requireBillingAddress == Mage_Paypal_Model_Config::REQUIRE_BILLING_ADDRESS_ALL) {
- $this->_api->setRequireBillingAddress(1);
- }
- // supress or export shipping address
- if ($this->_quote->getIsVirtual()) {
- if ($this->_config->requireBillingAddress == Mage_Paypal_Model_Config::REQUIRE_BILLING_ADDRESS_VIRTUAL) {
- $this->_api->setRequireBillingAddress(1);
- }
- $this->_api->setSuppressShipping(true);
- } else {
- $address = $this->_quote->getShippingAddress();
- $isOverriden = 0;
- if (true === $address->validate()) {
- $isOverriden = 1;
- $this->_api->setAddress($address);
- }
- $this->_quote->getPayment()->setAdditionalInformation(
- self::PAYMENT_INFO_TRANSPORT_SHIPPING_OVERRIDEN, $isOverriden
- );
- $this->_quote->getPayment()->save();
- }
- // add line items
- $paypalCart = Mage::getModel('paypal/cart', array($this->_quote));
- $this->_api->setPaypalCart($paypalCart)
- ->setIsLineItemsEnabled($this->_config->lineItemsEnabled)
- ;
- // add shipping options if needed and line items are available
- if ($this->_config->lineItemsEnabled && $this->_config->transferShippingOptions && $paypalCart->getItems()) {
- if (!$this->_quote->getIsVirtual() && !$this->_quote->hasNominalItems()) {
- if ($options = $this->_prepareShippingOptions($address, true)) {
- $this->_api->setShippingOptionsCallbackUrl(
- Mage::getUrl('*/*/shippingOptionsCallback', array('quote_id' => $this->_quote->getId()))
- )->setShippingOptions($options);
- }
- }
- }
- // add recurring payment profiles information
- if ($profiles = $this->_quote->prepareRecurringPaymentProfiles()) {
- foreach ($profiles as $profile) {
- $profile->setMethodCode(Mage_Paypal_Model_Config::METHOD_WPP_EXPRESS);
- if (!$profile->isValid()) {
- Mage::throwException($profile->getValidationErrors(true, true));
- }
- }
- $this->_api->addRecurringPaymentProfiles($profiles);
- }
- $this->_config->exportExpressCheckoutStyleSettings($this->_api);
- // call API and redirect with token
- $this->_api->callSetExpressCheckout();
- $token = $this->_api->getToken();
- $this->_redirectUrl = $this->_config->getExpressCheckoutStartUrl($token);
- $this->_quote->getPayment()->unsAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT);
- $this->_quote->getPayment()->save();
- return $token;
- }
- /**
- * Update quote when returned from PayPal
- * rewrite billing address by paypal
- * save old billing address for new customer
- * export shipping address in case address absence
- *
- * @param string $token
- */
- public function returnFromPaypal($token)
- {
- $this->_getApi();
- $this->_api->setToken($token)
- ->callGetExpressCheckoutDetails();
- $quote = $this->_quote;
- $this->_ignoreAddressValidation();
- // import billing address
- $billingAddress = $quote->getBillingAddress();
- $exportedBillingAddress = $this->_api->getExportedBillingAddress();
- $quote->setCustomerEmail($billingAddress->getEmail());
- $quote->setCustomerPrefix($billingAddress->getPrefix());
- $quote->setCustomerFirstname($billingAddress->getFirstname());
- $quote->setCustomerMiddlename($billingAddress->getMiddlename());
- $quote->setCustomerLastname($billingAddress->getLastname());
- $quote->setCustomerSuffix($billingAddress->getSuffix());
- $quote->setCustomerNote($exportedBillingAddress->getData('note'));
- $this->_setExportedAddressData($billingAddress, $exportedBillingAddress);
- // import shipping address
- $exportedShippingAddress = $this->_api->getExportedShippingAddress();
- if (!$quote->getIsVirtual()) {
- $shippingAddress = $quote->getShippingAddress();
- if ($shippingAddress) {
- if ($exportedShippingAddress) {
- $this->_setExportedAddressData($shippingAddress, $exportedShippingAddress);
- $shippingAddress->setCollectShippingRates(true);
- $shippingAddress->setSameAsBilling(0);
- }
- // import shipping method
- $code = '';
- if ($this->_api->getShippingRateCode()) {
- if ($code = $this->_matchShippingMethodCode($shippingAddress, $this->_api->getShippingRateCode())) {
- // possible bug of double collecting rates :-/
- $shippingAddress->setShippingMethod($code)->setCollectShippingRates(true);
- }
- }
- $quote->getPayment()->setAdditionalInformation(
- self::PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD,
- $code
- );
- }
- }
- // import payment info
- $payment = $quote->getPayment();
- $payment->setMethod($this->_methodType);
- Mage::getSingleton('paypal/info')->importToPayment($this->_api, $payment);
- $payment->setAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_PAYER_ID, $this->_api->getPayerId())
- ->setAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_TOKEN, $token)
- ;
- $quote->collectTotals()->save();
- }
- /**
- * Check whether order review has enough data to initialize
- *
- * @param $token
- * @throws Mage_Core_Exception
- */
- public function prepareOrderReview($token = null)
- {
- $payment = $this->_quote->getPayment();
- if (!$payment || !$payment->getAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_PAYER_ID)) {
- Mage::throwException(Mage::helper('paypal')->__('Payer is not identified.'));
- }
- $this->_quote->setMayEditShippingAddress(
- 1 != $this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_SHIPPING_OVERRIDEN)
- );
- $this->_quote->setMayEditShippingMethod(
- '' == $this->_quote->getPayment()->getAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD)
- );
- $this->_ignoreAddressValidation();
- $this->_quote->collectTotals()->save();
- }
- /**
- * Return callback response with shipping options
- *
- * @param array $request
- * @return string
- */
- public function getShippingOptionsCallbackResponse(array $request)
- {
- // prepare debug data
- $logger = Mage::getModel('core/log_adapter', 'payment_' . $this->_methodType . '.log');
- $debugData = array('request' => $request, 'response' => array());
- try {
- // obtain addresses
- $this->_getApi();
- $address = $this->_api->prepareShippingOptionsCallbackAddress($request);
- $quoteAddress = $this->_quote->getShippingAddress();
- // compare addresses, calculate shipping rates and prepare response
- $options = array();
- if ($address && $quoteAddress && !$this->_quote->getIsVirtual()) {
- foreach ($address->getExportedKeys() as $key) {
- $quoteAddress->setDataUsingMethod($key, $address->getData($key));
- }
- $quoteAddress->setCollectShippingRates(true)->collectTotals();
- $options = $this->_prepareShippingOptions($quoteAddress, false, true);
- }
- $response = $this->_api->setShippingOptions($options)->formatShippingOptionsCallback();
- // log request and response
- $debugData['response'] = $response;
- $logger->log($debugData);
- return $response;
- } catch (Exception $e) {
- $logger->log($debugData);
- throw $e;
- }
- }
- /**
- * Set shipping method to quote, if needed
- * @param string $methodCode
- */
- public function updateShippingMethod($methodCode)
- {
- if (!$this->_quote->getIsVirtual() && $shippingAddress = $this->_quote->getShippingAddress()) {
- if ($methodCode != $shippingAddress->getShippingMethod()) {
- $this->_ignoreAddressValidation();
- $shippingAddress->setShippingMethod($methodCode)->setCollectShippingRates(true);
- $this->_quote->collectTotals();
- }
- }
- }
- /**
- * Update order data
- *
- * @param array $data
- */
- public function updateOrder($data)
- {
- /** @var $checkout Mage_Checkout_Model_Type_Onepage */
- $checkout = Mage::getModel('checkout/type_onepage');
- $this->_quote->setTotalsCollectedFlag(true);
- $checkout->setQuote($this->_quote);
- if (isset($data['billing'])) {
- if (isset($data['customer-email'])) {
- $data['billing']['email'] = $data['customer-email'];
- }
- $checkout->saveBilling($data['billing'], 0);
- }
- if (!$this->_quote->getIsVirtual() && isset($data['shipping'])) {
- $checkout->saveShipping($data['shipping'], 0);
- }
- if (isset($data['shipping_method'])) {
- $this->updateShippingMethod($data['shipping_method']);
- }
- $this->_quote->setTotalsCollectedFlag(false);
- $this->_quote->collectTotals();
- $this->_quote->setDataChanges(true);
- $this->_quote->save();
- }
- /**
- * Place the order and recurring payment profiles when customer returned from paypal
- * Until this moment all quote data must be valid
- *
- * @param string $token
- * @param string $shippingMethodCode
- */
- public function place($token, $shippingMethodCode = null)
- {
- if ($shippingMethodCode) {
- $this->updateShippingMethod($shippingMethodCode);
- }
- $isNewCustomer = false;
- switch ($this->getCheckoutMethod()) {
- case Mage_Checkout_Model_Type_Onepage::METHOD_GUEST:
- $this->_prepareGuestQuote();
- break;
- case Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER:
- $this->_prepareNewCustomerQuote();
- $isNewCustomer = true;
- break;
- default:
- $this->_prepareCustomerQuote();
- break;
- }
- $this->_ignoreAddressValidation();
- $this->_quote->collectTotals();
- $service = Mage::getModel('sales/service_quote', $this->_quote);
- $service->submitAll();
- $this->_quote->save();
- if ($isNewCustomer) {
- try {
- $this->_involveNewCustomer();
- } catch (Exception $e) {
- Mage::logException($e);
- }
- }
- $this->_recurringPaymentProfiles = $service->getRecurringPaymentProfiles();
- // TODO: send recurring profile emails
- $order = $service->getOrder();
- if (!$order) {
- return;
- }
- $this->_billingAgreement = $order->getPayment()->getBillingAgreement();
- // commence redirecting to finish payment, if paypal requires it
- if ($order->getPayment()->getAdditionalInformation(
- Mage_Paypal_Model_Express_Checkout::PAYMENT_INFO_TRANSPORT_REDIRECT
- )) {
- $this->_redirectUrl = $this->_config->getExpressCheckoutCompleteUrl($token);
- }
- switch ($order->getState()) {
- // even after placement paypal can disallow to authorize/capture, but will wait until bank transfers money
- case Mage_Sales_Model_Order::STATE_PENDING_PAYMENT:
- // TODO
- break;
- // regular placement, when everything is ok
- case Mage_Sales_Model_Order::STATE_PROCESSING:
- case Mage_Sales_Model_Order::STATE_COMPLETE:
- case Mage_Sales_Model_Order::STATE_PAYMENT_REVIEW:
- $order->sendNewOrderEmail();
- break;
- }
- $this->_order = $order;
- }
- /**
- * Make sure addresses will be saved without validation errors
- */
- private function _ignoreAddressValidation()
- {
- $this->_quote->getBillingAddress()->setShouldIgnoreValidation(true);
- if (!$this->_quote->getIsVirtual()) {
- $this->_quote->getShippingAddress()->setShouldIgnoreValidation(true);
- if (!$this->_config->requireBillingAddress && !$this->_quote->getBillingAddress()->getEmail()) {
- $this->_quote->getBillingAddress()->setSameAsBilling(1);
- }
- }
- }
- /**
- * Determine whether redirect somewhere specifically is required
- *
- * @return string
- */
- public function getRedirectUrl()
- {
- return $this->_redirectUrl;
- }
- /**
- * Return recurring payment profiles
- *
- * @return array
- */
- public function getRecurringPaymentProfiles()
- {
- return $this->_recurringPaymentProfiles;
- }
- /**
- * Get created billing agreement
- *
- * @return Mage_Sales_Model_Billing_Agreement|null
- */
- public function getBillingAgreement()
- {
- return $this->_billingAgreement;
- }
- /**
- * Return order
- *
- * @return Mage_Sales_Model_Order
- */
- public function getOrder()
- {
- return $this->_order;
- }
- /**
- * Get checkout method
- *
- * @return string
- */
- public function getCheckoutMethod()
- {
- if ($this->getCustomerSession()->isLoggedIn()) {
- return Mage_Checkout_Model_Type_Onepage::METHOD_CUSTOMER;
- }
- if (!$this->_quote->getCheckoutMethod()) {
- if (Mage::helper('checkout')->isAllowedGuestCheckout($this->_quote)) {
- $this->_quote->setCheckoutMethod(Mage_Checkout_Model_Type_Onepage::METHOD_GUEST);
- } else {
- $this->_quote->setCheckoutMethod(Mage_Checkout_Model_Type_Onepage::METHOD_REGISTER);
- }
- }
- return $this->_quote->getCheckoutMethod();
- }
- /**
- * Sets address data from exported address
- *
- * @param Mage_Sales_Model_Quote_Address $address
- * @param array $exportedAddress
- */
- protected function _setExportedAddressData($address, $exportedAddress)
- {
- foreach ($exportedAddress->getExportedKeys() as $key) {
- $oldData = $address->getDataUsingMethod($key);
- $isEmpty = null;
- if (is_array($oldData)) {
- foreach($oldData as $val) {
- if(!empty($val)) {
- $isEmpty = false;
- break;
- }
- $isEmpty = true;
- }
- }
- if (empty($oldData) || $isEmpty === true) {
- $address->setDataUsingMethod($key, $exportedAddress->getData($key));
- }
- }
- }
- /**
- * Set create billing agreement flag to api call
- *
- * @return Mage_Paypal_Model_Express_Checkout
- */
- protected function _setBillingAgreementRequest()
- {
- if (!$this->_customerId || $this->_quote->hasNominalItems()) {
- return $this;
- }
- $isRequested = $this->_isBARequested || $this->_quote->getPayment()
- ->getAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_BILLING_AGREEMENT);
- if (!($this->_config->allow_ba_signup == Mage_Paypal_Model_Config::EC_BA_SIGNUP_AUTO
- || $isRequested && $this->_config->shouldAskToCreateBillingAgreement())) {
- return $this;
- }
- if (!Mage::getModel('sales/billing_agreement')->needToCreateForCustomer($this->_customerId)) {
- return $this;
- }
- $this->_api->setBillingType($this->_api->getBillingAgreementType());
- return $this;
- }
- /**
- * @return Mage_Paypal_Model_Api_Nvp
- */
- protected function _getApi()
- {
- if (null === $this->_api) {
- $this->_api = Mage::getModel($this->_apiType)->setConfigObject($this->_config);
- }
- return $this->_api;
- }
- /**
- * Attempt to collect address shipping rates and return them for further usage in instant update API
- * Returns empty array if it was impossible to obtain any shipping rate
- * If there are shipping rates obtained, the method must return one of them as default.
- *
- * @param Mage_Sales_Model_Quote_Address $address
- * @param bool $mayReturnEmpty
- * @return array|false
- */
- protected function _prepareShippingOptions(
- Mage_Sales_Model_Quote_Address $address,
- $mayReturnEmpty = false, $calculateTax = false
- ) {
- $options = array(); $i = 0; $iMin = false; $min = false;
- $userSelectedOption = null;
- foreach ($address->getGroupedAllShippingRates() as $group) {
- foreach ($group as $rate) {
- $amount = (float)$rate->getPrice();
- if ($rate->getErrorMessage()) {
- continue;
- }
- $isDefault = $address->getShippingMethod() === $rate->getCode();
- $amountExclTax = Mage::helper('tax')->getShippingPrice($amount, false, $address);
- $amountInclTax = Mage::helper('tax')->getShippingPrice($amount, true, $address);
- $options[$i] = new Varien_Object(array(
- 'is_default' => $isDefault,
- 'name' => trim("{$rate->getCarrierTitle()} - {$rate->getMethodTitle()}", ' -'),
- 'code' => $rate->getCode(),
- 'amount' => $amountExclTax,
- ));
- if ($calculateTax) {
- $options[$i]->setTaxAmount(
- $amountInclTax - $amountExclTax
- + $address->getTaxAmount() - $address->getShippingTaxAmount()
- );
- }
- if ($isDefault) {
- $userSelectedOption = $options[$i];
- }
- if (false === $min || $amountInclTax < $min) {
- $min = $amountInclTax;
- $iMin = $i;
- }
- $i++;
- }
- }
- if ($mayReturnEmpty && is_null($userSelectedOption)) {
- $options[] = new Varien_Object(array(
- 'is_default' => true,
- 'name' => Mage::helper('paypal')->__('N/A'),
- 'code' => 'no_rate',
- 'amount' => 0.00,
- ));
- if ($calculateTax) {
- $options[$i]->setTaxAmount($address->getTaxAmount());
- }
- } elseif (is_null($userSelectedOption) && isset($options[$iMin])) {
- $options[$iMin]->setIsDefault(true);
- }
- // Magento will transfer only first 10 cheapest shipping options if there are more than 10 available.
- if (count($options) > 10) {
- usort($options, array(get_class($this),'cmpShippingOptions'));
- array_splice($options, 10);
- // User selected option will be always included in options list
- if (!is_null($userSelectedOption) && !in_array($userSelectedOption, $options)) {
- $options[9] = $userSelectedOption;
- }
- }
- return $options;
- }
- /**
- * Compare two shipping options based on their amounts
- *
- * This function is used as a callback comparison function in shipping options sorting process
- * @see self::_prepareShippingOptions()
- *
- * @param Varien_Object $option1
- * @param Varien_Object $option2
- * @return integer
- */
- protected static function cmpShippingOptions(Varien_Object $option1, Varien_Object $option2)
- {
- if ($option1->getAmount() == $option2->getAmount()) {
- return 0;
- }
- return ($option1->getAmount() < $option2->getAmount()) ? -1 : 1;
- }
- /**
- * Try to find whether the code provided by PayPal corresponds to any of possible shipping rates
- * This method was created only because PayPal has issues with returning the selected code.
- * If in future the issue is fixed, we don't need to attempt to match it. It would be enough to set the method code
- * before collecting shipping rates
- *
- * @param Mage_Sales_Model_Quote_Address $address
- * @param string $selectedCode
- * @return string
- */
- protected function _matchShippingMethodCode(Mage_Sales_Model_Quote_Address $address, $selectedCode)
- {
- $options = $this->_prepareShippingOptions($address, false);
- foreach ($options as $option) {
- if ($selectedCode === $option['code'] // the proper case as outlined in documentation
- || $selectedCode === $option['name'] // workaround: PayPal may return name instead of the code
- // workaround: PayPal may concatenate code and name, and return it instead of the code:
- || $selectedCode === "{$option['code']} {$option['name']}"
- ) {
- return $option['code'];
- }
- }
- return '';
- }
- /**
- * Prepare quote for guest checkout order submit
- *
- * @return Mage_Paypal_Model_Express_Checkout
- */
- protected function _prepareGuestQuote()
- {
- $quote = $this->_quote;
- $quote->setCustomerId(null)
- ->setCustomerEmail($quote->getBillingAddress()->getEmail())
- ->setCustomerIsGuest(true)
- ->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID);
- return $this;
- }
- /**
- * Prepare quote for customer registration and customer order submit
- * and restore magento customer data from quote
- *
- * @return Mage_Paypal_Model_Express_Checkout
- */
- protected function _prepareNewCustomerQuote()
- {
- $quote = $this->_quote;
- $billing = $quote->getBillingAddress();
- $shipping = $quote->isVirtual() ? null : $quote->getShippingAddress();
- $customer = $quote->getCustomer();
- /** @var $customer Mage_Customer_Model_Customer */
- $customerBilling = $billing->exportCustomerAddress();
- $customer->addAddress($customerBilling);
- $billing->setCustomerAddress($customerBilling);
- $customerBilling->setIsDefaultBilling(true);
- if ($shipping && !$shipping->getSameAsBilling()) {
- $customerShipping = $shipping->exportCustomerAddress();
- $customer->addAddress($customerShipping);
- $shipping->setCustomerAddress($customerShipping);
- $customerShipping->setIsDefaultShipping(true);
- } elseif ($shipping) {
- $customerBilling->setIsDefaultShipping(true);
- }
- /**
- * @todo integration with dynamica attributes customer_dob, customer_taxvat, customer_gender
- */
- if ($quote->getCustomerDob() && !$billing->getCustomerDob()) {
- $billing->setCustomerDob($quote->getCustomerDob());
- }
- if ($quote->getCustomerTaxvat() && !$billing->getCustomerTaxvat()) {
- $billing->setCustomerTaxvat($quote->getCustomerTaxvat());
- }
- if ($quote->getCustomerGender() && !$billing->getCustomerGender()) {
- $billing->setCustomerGender($quote->getCustomerGender());
- }
- Mage::helper('core')->copyFieldset('checkout_onepage_billing', 'to_customer', $billing, $customer);
- $customer->setEmail($quote->getCustomerEmail());
- $customer->setPrefix($quote->getCustomerPrefix());
- $customer->setFirstname($quote->getCustomerFirstname());
- $customer->setMiddlename($quote->getCustomerMiddlename());
- $customer->setLastname($quote->getCustomerLastname());
- $customer->setSuffix($quote->getCustomerSuffix());
- $customer->setPassword($customer->decryptPassword($quote->getPasswordHash()));
- $customer->setPasswordHash($customer->hashPassword($customer->getPassword()));
- $customer->save();
- $quote->setCustomer($customer);
- return $this;
- }
- /**
- * Prepare quote for customer order submit
- *
- * @return Mage_Paypal_Model_Express_Checkout
- */
- protected function _prepareCustomerQuote()
- {
- $quote = $this->_quote;
- $billing = $quote->getBillingAddress();
- $shipping = $quote->isVirtual() ? null : $quote->getShippingAddress();
- $customer = $this->getCustomerSession()->getCustomer();
- if (!$billing->getCustomerId() || $billing->getSaveInAddressBook()) {
- $customerBilling = $billing->exportCustomerAddress();
- $customer->addAddress($customerBilling);
- $billing->setCustomerAddress($customerBilling);
- }
- if ($shipping && ((!$shipping->getCustomerId() && !$shipping->getSameAsBilling())
- || (!$shipping->getSameAsBilling() && $shipping->getSaveInAddressBook()))) {
- $customerShipping = $shipping->exportCustomerAddress();
- $customer->addAddress($customerShipping);
- $shipping->setCustomerAddress($customerShipping);
- }
- if (isset($customerBilling) && !$customer->getDefaultBilling()) {
- $customerBilling->setIsDefaultBilling(true);
- }
- if ($shipping && isset($customerBilling) && !$customer->getDefaultShipping() && $shipping->getSameAsBilling()) {
- $customerBilling->setIsDefaultShipping(true);
- } elseif ($shipping && isset($customerShipping) && !$customer->getDefaultShipping()) {
- $customerShipping->setIsDefaultShipping(true);
- }
- $quote->setCustomer($customer);
- return $this;
- }
- /**
- * Involve new customer to system
- *
- * @return Mage_Paypal_Model_Express_Checkout
- */
- protected function _involveNewCustomer()
- {
- $customer = $this->_quote->getCustomer();
- if ($customer->isConfirmationRequired()) {
- $customer->sendNewAccountEmail('confirmation');
- $url = Mage::helper('customer')->getEmailConfirmationUrl($customer->getEmail());
- $this->getCustomerSession()->addSuccess(
- Mage::helper('customer')->__('Account confirmation is required. Please, check your e-mail for confirmation link. To resend confirmation email please <a href="%s">click here</a>.', $url)
- );
- } else {
- $customer->sendNewAccountEmail();
- $this->getCustomerSession()->loginById($customer->getId());
- }
- return $this;
- }
- /**
- * Get customer session object
- *
- * @return Mage_Customer_Model_Session
- */
- public function getCustomerSession()
- {
- return $this->_customerSession;
- }
- }