覆盖frontcontroller或modulefrontcontroller init()方法以进行检出

时间:2017-12-04 19:40:38

标签: php prestashop prestashop-1.6 prestashop-1.7

我的问题如下。我为prestashop 1.7创建了一个支付模块。验证订单//在启动付款时创建。这通过使用validateOrder方法在payment.php控制器中发生:

        $this->module->validateOrder(
                (int) $cartId,
                $this->module->statuses[$orderStatus],
                $prestaTotal,
                'paymentmodule',
                null,
                array(),
                null,
                false,
                $customer->secure_key
                );

因此创建了新订单,购物车现在与订单相关。并且客户被重定向到支付提供商。他们可以付钱,或按“取消”按钮。

webhook.php从付款提供商处收到订单状态,并在prestashop中更新订单状态。如果订单已付款,则会将其重定向到订单确认页面。但如果它被取消,那么购物车就不见了。

这种情况发生了,因为prestashop会检查订单是否存在。如果是这样,购物车将被删除。 FronController.php中的init()方法负责:

/* Cart already exists */
    if ((int) $this->context->cookie->id_cart) {
        if (!isset($cart)) {
            $cart = new Cart($this->context->cookie->id_cart);
        }

        if (Validate::isLoadedObject($cart) && $cart->OrderExists()) {
            PrestaShopLogger::addLog('Frontcontroller::init - Cart cannot be loaded or an order has already been placed using this cart', 1, null, 'Cart', (int) $this->context->cookie->id_cart, true);
            unset($this->context->cookie->id_cart, $cart, $this->context->cookie->checkedTOS);
            $this->context->cookie->check_cgv = false;
        }

所以我在return.php控制器中创建了一个Method来制作属于现有订单的购物车的副本,所以你有一个新的购物车:

class PaymentModuleFrontController extends ModuleFrontController
{

    public function initContent()
    {
        parent::initContent();
        $cartId = Tools::getValue('cart_id');
        $cart = new Cart((int) $cartId);
        $data['info'] = $this->module->getPaymentBy('cart_id', (int)$cartId);
                $orderId = Order::getOrderByCartId($cartId);
                $orderStatus = $data['info']['bank_status'];

                if (Validate::isLoadedObject($cart) && 
                $cart->OrderExists() && 
                $orderStatus === 'cancelled')
                {
                    $oldCart = new Cart(Order::getCartIdStatic($orderId, $this->context->customer->id));
                    $duplication = $oldCart->duplicate();
                    if (!$duplication || !Validate::isLoadedObject($duplication['cart'])) 
                    {
                        $this->errors[] = Tools::displayError('Sorry. We cannot renew your order.');
                    } 
                    elseif (!$duplication['success']) 
                    {
                        $this->errors[] = Tools::displayError('Some items are no longer available, and we are unable to renew your order.');
                    } 
                    else 
                    {
                        $this->context->cookie->id_cart = $duplication['cart']->id;
                        $context = $this->context;
                        $context->cart = $duplication['cart'];
                        CartRule::autoAddToCart($context);
                        $this->context->cookie->write();
                        if (Configuration::get('PS_ORDER_PROCESS_TYPE') == 1) 
                        {
                            Tools::redirect('index.php?controller=order-opc');
                        }
                    Tools::redirect('index.php?controller=order');
                    }   

                }
      }

将创建购物车的副本,然后将其重定向到结帐。

如此苛刻,购物车没有消失(如果购物车有订单通常会发生),他们可以选择不同的付款方式,并创建一个全新的订单。

但是,客户也可以在支付提供商页面上按下浏览器的“返回上一页”按钮。

enter image description here

他们会被重定向回结账,但在这种情况下,我的方法不会被调用,因此购物车已经消失。发生这种情况是因为调用了Frontcontroller.php中的init()方法。而且由于订单已经过验证//已创建,购物车会被删除。

所以,我在支付模块中添加了一个名为checkout的新控制器:

$this->controllers = array('payment, return, webhook, checkout');

并将checkout.php放在我的模块的文件夹controller / front中。

我扩展了类FrontController并为init()方法创建了一个覆盖。我的代码:

class PaymentModuleFrontController extends FrontController
{

    public function init()
    {

        $data = array();
        $cartId = $this->context->cart->id;
        $cart = new Cart($cartId);
        $orderId = Order::getOrderByCartId($cartId);
        $data['info'] = $this->module->getPaymentBy('cart_id', (int)$cartId); //gets payment from db. I checked it and this is correct
        $orderStatus = $data['info']['status']; //gets the status. I checked it and it's correct

        if (Validate::isLoadedObject($cart) && 
        $cart->OrderExists() && 
        $orderStatus === 'open') 
        {
            $oldCart = new Cart(Order::getCartIdStatic($orderId, $this->context->customer->id));
            $duplication = $oldCart->duplicate();
            if (!$duplication || !Validate::isLoadedObject($duplication['cart'])) 
            {
                $this->errors[] = Tools::displayError('Problem duplicating cart.');
            } 
            elseif (!$duplication['success']) 
            {
                $this->errors[] = Tools::displayError('Problem duplicating cart.');
            } 
            else 
            {
                $this->context->cookie->id_cart = $duplication['cart']->id;
                $context = $this->context;
                $context->cart = $duplication['cart'];
                CartRule::autoAddToCart($context);
                $this->context->cookie->write();
                if (Configuration::get('PS_ORDER_PROCESS_TYPE') == 1) 
                {
                Tools::redirect('index.php?controller=order-opc');
              }
              Tools::redirect('index.php?controller=order');
            }
        }
        parent::init();

    }


}

我不知道我做错了什么,因为这对我的返回控制器工作正常但如果我使用浏览器按钮返回上一页,它仍会移除购物车。

我可以在结帐/订单页面上使用的钩子中使用我的代码并将其添加到我的PaymentModule类中吗?

很重要,我想在没有为FrontController.php创建覆盖文件的情况下建立这个,所以必须使用模块控制器或我的支付模块Class。

我希望有人可以帮我解决这个问题。

2 个答案:

答案 0 :(得分:0)

您创建订单时所遵循的方法不正确。您应该根据从付款提供商处收到的回复创建订单,而不是在将用户重定向到付款提供商时创建订单。

这意味着订单仅在付款成功时生成,否则用户将在结帐页面上看到错误,购物车也会保持原样。

您正在遵循的方法风险很大,因为您要覆盖PrestaShop中每个页面上调用的方法,我的建议是您不应该这样做。

答案 1 :(得分:0)

您可以在付款网址中设置id_cart并将其放入控制器中。因此,当您创建付款选项时,请在网址查询中设置id_cart:

public function hookDisplayPayment($params){
    $externalOption = new PaymentOption();
    $externalOption->setCallToActionText('Payment Method')
          ->setAction($this->context->link->getModuleLink($this->name, 'payment', ['id_cart'=>$this->context->cart->id], true))
          ->setAdditionalInformation($plugin->description)
          ->setLogo(Media::getMediaPath(_PS_MODULE_DIR_.$this->name.'/logo.jpg'));
    return $externalOption;
}

然后在付款控制器中获取相关购物车:

class PaymentModuleFrontController extends FrontController
{

    public function init()
    {
        $cart = new Cart(Tools::getValue('id_cart'));
        //more...
    }
 }