Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Magento 1.5 Paypal Express Review Page Shipping - no quotes are available

I have a problem whereby Magento (v1.5) does not calculate shipping based on the country of the registered Paypal user based on the shipping rules also defined in the one page checkout. When using Paypal Express, after logging into Paypal, the user is redirected back to our site to confirm the order, no shipping option is selected (or selectable) and so the customer can't place the order.

This solution does not work for me: http://www.magentocommerce.com/boards/viewthread/211273/

All I get is: "Shipping Method Sorry, no quotes are available for this order at this time."

When the user presses 'Place Order' nothing happens, no doubt because it is silently complaining that there in no shipping method available. (Of course there is a shipping method available and would be automatically selected if going through the normal checkout).

Other forum posts also suggest that custom themes cause the problem. I have removed all Paypal content from my custom theme to ensure Magento is using the base/default template files and layout.

Any ideas anyone?

like image 821
Sam Avatar asked Jul 18 '11 22:07

Sam


2 Answers

The following code from Oscar Reales worked for us, and I cannot remember where I downloaded it from! The other solution is to use Paypal Standard.

/**
 * Overload of Mage_Paypal_Model_Express_Checkout to fix bug with user registration.
  *
  * Currently, when users choose "Register" in the buying process
  * And then choose "Paypal Express Checkout" as a method of payment,
  * User registration does not occur,
  * And the order is not assigned to the client, but remains "anonymous".
 * 
 * @see Mage_Paypal_Model_Express_Checkout
 * @see Mage_Checkout_Model_Type_Onepage
 * 
 * @author Oscar Reales <[email protected]>
 * @author Oscar Reales <[email protected]>
 */
class Mg_Paypal_Model_Express_Checkout extends Mage_Paypal_Model_Express_Checkout
{

    /**
     * Update quote when returned from PayPal
     * @param string $token
     */
    public function returnFromPaypal($token)
    {
        $this->_getApi();
        $this->_api->setToken($token)
            ->callGetExpressCheckoutDetails();

        //modified
        //do not import the billing address from Paypal, we use the data that the user entered in the onsite Checkout
        /*$billingAddress = $this->_quote->getBillingAddress();
        $exportedBillingAddress = $this->_api->getExportedBillingAddress();
        foreach ($exportedBillingAddress->getExportedKeys() as $key) {
            $billingAddress->setDataUsingMethod($key, $exportedBillingAddress->getData($key));
        }*/

        //modified
        //do not import the shipping address from Paypal, we use the data that the user entered in the onsite Checkout
        /*$exportedShippingAddress = $this->_api->getExportedShippingAddress();
        if (!$this->_quote->getIsVirtual()) {
            $shippingAddress = $this->_quote->getShippingAddress();
            if ($shippingAddress) {
                if ($exportedShippingAddress) {
                    foreach ($exportedShippingAddress->getExportedKeys() as $key) {
                        $shippingAddress->setDataUsingMethod($key, $exportedShippingAddress->getData($key));
                    }
                    $shippingAddress->setCollectShippingRates(true);
                }

                // 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);
                    }
                }
                $this->_quote->getPayment()->setAdditionalInformation(self::PAYMENT_INFO_TRANSPORT_SHIPPING_METHOD, $code);
            }
        }*/
        $this->_ignoreAddressValidation();

        // import payment info
        $payment = $this->_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)
        ;
        $this->_quote->collectTotals()->save();
    }



    /**
      * Override the parent because core code does not take into account whether the user
      * Has chosen to register or not. It makes no difference under checkout_method chosen by the user.
      * Simply: if the customer does not have a quote, the core code saves it as Guest, NOT_LOGGED_IN group
      * And saves the email in the billing Address along with the order.
      *
      * This behavior is not what we want. We save the customer if the user has
      * elected to register and not place the order as GUEST
     *
     * @param string $token
     * @param string $shippingMethodCode
     */
    public function place($token, $shippingMethodCode = null)
    {
        if ($shippingMethodCode) {
            $this->updateShippingMethod($shippingMethodCode);
        }

        //modified
        //check if the checkout method was chosen as a guest user or registering
        $isNewCustomer = false;
        switch ($this->_quote->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;
        }
        //fin modification

        //modified
        //this code is no longer necessary with the previous change
        /*if (!$this->_quote->getCustomerId()) {
            $this->_quote->setCustomerIsGuest(true)
                ->setCustomerGroupId(Mage_Customer_Model_Group::NOT_LOGGED_IN_ID)
                ->setCustomerEmail($this->_quote->getBillingAddress()->getEmail());
        }*/
        //fin modification

        $this->_ignoreAddressValidation();
        $this->_quote->collectTotals();
        $service = Mage::getModel('sales/service_quote', $this->_quote);
        $service->submitAll();
        $this->_quote->save();
        $this->_recurringPaymentProfiles = $service->getRecurringPaymentProfiles();
        // TODO: send recurring profile emails


        //modified
        //after saving the order and the customer, send relevant emails if this is a new customer
        if ($isNewCustomer) {
            try {
                $this->_involveNewCustomer();
            } catch (Exception $e) {
                Mage::logException($e);
            }
        }
        //fin modificacion

        $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;
    }


    /**
     * Prepare quote for guest checkout order submit
     *
     * @see Mage_Checkout_Model_Type_Onepage::_prepareGuestQuote()
     *
     * @return Mg_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
     * 
     * @see Mage_Checkout_Model_Type_Onepage::_prepareNewCustomerQuote()
     *
     */
    protected function _prepareNewCustomerQuote()
    {
        $quote      = $this->_quote;
        $billing    = $quote->getBillingAddress();
        $shipping   = $quote->isVirtual() ? null : $quote->getShippingAddress();

        //$customer = Mage::getModel('customer/customer');
        $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->setPassword($customer->decryptPassword($quote->getPasswordHash()));
        $customer->setPasswordHash($customer->hashPassword($customer->getPassword()));
        $quote->setCustomer($customer)
            ->setCustomerId(true);
    }


    /**
     * Involve new customer to system
     * 
     * @see Mage_Checkout_Model_Type_Onepage::_involveNewCustomer()
     *
     * @return Mg_Paypal_Model_Express_Checkout
     */
    protected function _involveNewCustomer()
    {
        $customer = $this->_quote->getCustomer();
        if ($customer->isConfirmationRequired()) {
            $customer->sendNewAccountEmail('confirmation');
            $url = Mage::helper('customer')->getEmailConfirmationUrl($customer->getEmail());
            Mage::getSingleton('customer/session')->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();
            Mage::getSingleton('customer/session')->loginById($customer->getId());
        }
        return $this;
    }



    /**
      *  we extend it simply because it is defined as private in the parent
      *  And if nothing changes, we have the obligation to extend to
     */
    private function _ignoreAddressValidation()
    {
        $this->_quote->getBillingAddress()->setShouldIgnoreValidation(true);
        if (!$this->_quote->getIsVirtual()) {
            $this->_quote->getShippingAddress()->setShouldIgnoreValidation(true);
        }
    }


}
like image 125
ShaunOReilly Avatar answered Oct 13 '22 17:10

ShaunOReilly


I found three problems, but got this working in the end (bounty well spent :) ). Not sure where they all came from, but suspect it is to do with upgrading Magento and various template changes in this module. The first problem was this line:

<?php if (!($_shippingRateGroups = $this->getShippingRates())): ?>

Which should read:

<?php if (!($_shippingRateGroups = $this->getShippingRateGroups())): ?>

The second problem was the $this->getUrl function, repeated in several places. I removed this entirely, hardcoding the URLs.

Finally, the $this->getCurrentShippingRate function wasn't returning the current rate. I changed the getCurrentShippingRate function in app/code/core/Mage/Paypal/Block/Express/Review.php to this:

public function getCurrentShippingRate()
{
    $this->_address = $this->_quote->getShippingAddress();
    return $this->_address->getShippingMethod();
    //return $this->_currentShippingRate;
}
like image 35
Dave Child Avatar answered Oct 13 '22 19:10

Dave Child