Перенаправление пользовательского способа повторяющейся оплаты на платежный шлюз после размещения заказа в Magento 1


Я пытаюсь реализовать пользовательский модуль повторяющихся платежей для Magento 1.9.

Я следую учебнику из Блога Modulesgarden в сочетании с Paypal Express.

Мне удалось создать новый способ оплаты, который отображается при оформлении заказа только для повторяющихся продуктов. Если я создам только поддельный запрос на тестирование, как в учебнике, все работает хорошо, заказы созданы, профиль создан, я могу отменить или приостановить профиль из Моего аккаунта.

Проблема в том, что я не знаю, как перенаправить на страницу шлюза после размещения заказа. До сих пор я пытался добавить в свою платежную модель метод getOrderPlaceRedirectUrl(), который вызывается в методе saveOrder(), но это не работает, потому что метод выглядит так:

public function saveOrder()
{
    $this->validate();
    $isNewCustomer = false;
    switch ($this->getCheckoutMethod()) {
        case self::METHOD_GUEST:
            $this->_prepareGuestQuote();
            break;
        case self::METHOD_REGISTER:
            $this->_prepareNewCustomerQuote();
            $isNewCustomer = true;
            break;
        default:
            $this->_prepareCustomerQuote();
            break;
    }

    $service = Mage::getModel('sales/service_quote', $this->getQuote());
    $service->submitAll();

    if ($isNewCustomer) {
        try {
            $this->_involveNewCustomer();
        } catch (Exception $e) {
            Mage::logException($e);
        }
    }

    $this->_checkoutSession->setLastQuoteId($this->getQuote()->getId())
        ->setLastSuccessQuoteId($this->getQuote()->getId())
        ->clearHelperData();

    $order = $service->getOrder();
    if ($order) {
        Mage::dispatchEvent('checkout_type_onepage_save_order_after',
            array('order'=>$order, 'quote'=>$this->getQuote()));

        /**
         * a flag to set that there will be redirect to third party after confirmation
         * eg: paypal standard ipn
         */
        $redirectUrl = $this->getQuote()->getPayment()->getOrderPlaceRedirectUrl();
        /**
         * we only want to send to customer about new order when there is no redirect to third party
         */
        if (!$redirectUrl && $order->getCanSendNewEmailFlag()) {
            try {
                $order->queueNewOrderEmail();
            } catch (Exception $e) {
                Mage::logException($e);
            }
        }

        // add order information to the session
        $this->_checkoutSession->setLastOrderId($order->getId())
            ->setRedirectUrl($redirectUrl)
            ->setLastRealOrderId($order->getIncrementId());

        // as well a billing agreement can be created
        $agreement = $order->getPayment()->getBillingAgreement();
        if ($agreement) {
            $this->_checkoutSession->setLastBillingAgreementId($agreement->getId());
        }
    }

    // add recurring profiles information to the session
    $profiles = $service->getRecurringPaymentProfiles();
    if ($profiles) {
        $ids = array();
        foreach ($profiles as $profile) {
            $ids[] = $profile->getId();
        }
        $this->_checkoutSession->setLastRecurringProfileIds($ids);
        // TODO: send recurring profile emails
    }

    Mage::dispatchEvent(
        'checkout_submit_all_after',
        array('order' => $order, 'quote' => $this->getQuote(), 'recurring_profiles' => $profiles)
    );

    return $this;
}

Метод вызывается только в том случае, если есть порядок, но его нет, потому что при использовании повторяющихся профилей порядок создается позже, поэтому выполняется только код внутри if ($profiles) {}, и нет redirectUrl.

Затем я попытался использовать метод getCheckoutRedirectUrl(), как он используется в PayPal Express. Теперь я перенаправлен на платежный шлюз, но проблема в том, что этот метод вызывается в savePaymentAction(), и это означает, что я перенаправлен перед этапом проверки заказа.

Можно ли перенаправить на платежный шлюз только после размещения заказа, где-нибудь в методе submitRecurringProfile()? Я не хочу удалять этап проверки заказа, потому что клиенты должны принять условия и положения.

Спасибо вам!

Author: Ciprian, 2019-06-26

2 answers

Итак, после нескольких дней исследований и отладки я только что нашел простое решение.

Во-первых, поскольку мы не можем изменять файлы ядра, я просто копирую Onepage.php из ядра:

App/code/core/Mage/Checkout/Model/Type/Onepage.php

Кому:

App/code/local/Mage/Checkout/Model/Type/Onepage.php

И я внес некоторые изменения в метод saveOrder(). Теперь этот метод выглядит так:

public function saveOrder()
{
    $this->validate();
    $isNewCustomer = false;
    switch ($this->getCheckoutMethod()) {
        case self::METHOD_GUEST:
            $this->_prepareGuestQuote();
            break;
        case self::METHOD_REGISTER:
            $this->_prepareNewCustomerQuote();
            $isNewCustomer = true;
            break;
        default:
            $this->_prepareCustomerQuote();
            break;
    }

    $service = Mage::getModel('sales/service_quote', $this->getQuote());
    $service->submitAll();

    if ($isNewCustomer) {
        try {
            $this->_involveNewCustomer();
        } catch (Exception $e) {
            Mage::logException($e);
        }
    }

    $this->_checkoutSession->setLastQuoteId($this->getQuote()->getId())
        ->setLastSuccessQuoteId($this->getQuote()->getId())
        ->clearHelperData();

    $order = $service->getOrder();
    /**
     * a flag to set that there will be redirect to third party after confirmation
     * eg: paypal standard ipn
     */
    $redirectUrl = $this->getQuote()->getPayment()->getOrderPlaceRedirectUrl();

    if ($order) {
        Mage::dispatchEvent('checkout_type_onepage_save_order_after',
            array('order'=>$order, 'quote'=>$this->getQuote()));

        /**
         * we only want to send to customer about new order when there is no redirect to third party
         */
        if (!$redirectUrl && $order->getCanSendNewEmailFlag()) {
            try {
                $order->queueNewOrderEmail();
            } catch (Exception $e) {
                Mage::logException($e);
            }
        }

        // add order information to the session
        $this->_checkoutSession->setLastOrderId($order->getId())
            ->setRedirectUrl($redirectUrl)
            ->setLastRealOrderId($order->getIncrementId());

        // as well a billing agreement can be created
        $agreement = $order->getPayment()->getBillingAgreement();
        if ($agreement) {
            $this->_checkoutSession->setLastBillingAgreementId($agreement->getId());
        }
    }

    // add recurring profiles information to the session
    $profiles = $service->getRecurringPaymentProfiles();
    if ($profiles) {
        $this->_checkoutSession->setRedirectUrl($redirectUrl);

        $ids = array();
        foreach ($profiles as $profile) {
            $ids[] = $profile->getId();
        }

        $this->_checkoutSession->setLastRecurringProfileIds($ids);
        // TODO: send recurring profile emails
    }

    Mage::dispatchEvent(
        'checkout_submit_all_after',
        array('order' => $order, 'quote' => $this->getQuote(), 'recurring_profiles' => $profiles)
    );

    return $this;
}

Различия заключаются в том, что я определил $redirectUrl даже если заказа нет, и я устанавливаю его в $checkoutSession в обоих случаях, если существует заказ или повторяющийся профиль. Вы можете сравнить методы saveOrder() из моего вопроса и моего ответа, чтобы увидеть различия.

После этого вы должны создать метод getOrderPlaceRedirectUrl() в своей платежной модели, и все должно работать идеально.

Надеюсь, это поможет другим разработчикам!

 0
Author: Ciprian, 2019-07-02 13:51:41

Я столкнулся с точно такой же проблемой и подошел к ней по-другому.

Я создал наблюдателя для события checkout_submit_all_after и внутри наблюдателя я проверяю, были ли добавлены какие-либо повторяющиеся профили в данные события. Если это так, то я принудительно перенаправляю свое действие.

Вот код метода наблюдателя

public function checkoutSubmitAllFunction(Varien_Event_Observer $observer){
Mage::log(__FUNCTION__, Zend_Log::DEBUG, $this->logFileName);

if(0 < sizeof($observer->getEvent()->getData()['recurring_profiles'])){
  $recurringProfileId = $observer->getEvent()->getData()['recurring_profiles'][0]['profile_id'];

  if($recurringProfileId){
    /* Construct the redirect URL. */
    $redirectUrl = Mage::getUrl('module/controller/action', ['_query' => ['profileId' => $recurringProfileId]]);
    /* Set the redirect URL. */
    Mage::getSingleton('checkout/session')->setRedirectUrl($redirectUrl);
  }
}
return $this;
}

Надеюсь, это поможет. :)

 0
Author: Cosmin, 2019-12-09 13:27:06