1

初始帖子:

我使用 sylius 版本 1.0dev。我需要一些关于结帐/完成和电子邮件确认的帮助,这个问题似乎是已知的(https://github.com/Sylius/Sylius/issues/2915),但修复对我不起作用。在这一步,付款状态似乎是已支付,而应该是 awaiting_payment。另外,订单确认邮件不应该发送,只能在payum网关付款后发送。是否有任何触发此事件的现有配置,以及如何实现它?谢谢!

问题部分解决:我实施了一种解决方法。

首先要知道:我覆盖 shopbundle 将其扩展为我自己的包:

<?php

namespace My\ShopBundle;

use Symfony\Component\HttpKernel\Bundle\Bundle;

class MyShopBundle extends Bundle
{
    public function getParent()
    {
        return 'SyliusShopBundle';
    }
}

我覆盖了 sylius.email_manager.order 服务:

# sylius service configuration
parameters:
    # override email manager for order
    sylius.myproject.order.email.manager.class:MyBundle\ShopBundle\EmailManager\OrderEmailManager
#################################################
# override service sylius.email_manager.order   #
#                                               #
# - use configurable class                      #
# - send service container in arguments         #
#                                               #
#################################################
services:
    sylius.email_manager.order:
        class: %sylius.myproject.order.email.manager.class%
        arguments:
            - @sylius.email_sender
            - @service_container

类看起来像这样:

<?php

namespace My\ShopBundle\EmailManager;

use Sylius\Bundle\CoreBundle\Mailer\Emails;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Mailer\Sender\SenderInterface;
use My\ShopBundle\Mailer\Emails as MyEmails;

/**
 * @author I
 */
class OrderEmailManager
{
    /**
     * @var SenderInterface
     */
    protected $emailSender;
    /**
     *
     */
    protected $container ;

    /**
     * @param SenderInterface $emailSender
     */
    public function __construct( SenderInterface $emailSender, $container )
    {
        $this->emailSender = $emailSender;
        $this->container = $container ;
    }

    /**
     * @param OrderInterface $order
     * Issue : sent on checkout/complete (payment is not yet done on gateway)
     */
    public function sendConfirmationEmail(OrderInterface $order)
    {
        // sylius.shop.email.bcc is array parameter: expected bcc as array variable
        if( $this->container->hasParameter( 'sylius.shop.email.bcc' ) ){
            $this->emailSender->send( Emails::ORDER_CONFIRMATION, [$order->getCustomer()->getEmail()], ['order' => $order], $this->container->getParameter( 'sylius.shop.email.bcc' ) ) ;
        }else{
            // no bcc defined
            $this->emailSender->send( Emails::ORDER_CONFIRMATION, [$order->getCustomer()->getEmail()], ['order' => $order] ) ;
        }
    }

    /**
     * function used on gateway payment
     * here we use MyEmails to define the template (as it is done for the default confimration mail)
     */
    public function sendPaymentConfirmationEmail(OrderInterface $order)
    {
        // sylius.shop.email.bcc is array parameter: expected bcc as array variable
        if( $this->container->hasParameter( 'sylius.shop.email.bcc' ) ){
            $this->emailSender->send( MyEmails::ORDER_PAID, [$order->getCustomer()->getEmail()], ['order' => $order], $this->container->getParameter( 'sylius.shop.email.bcc' ) ) ;
        }else{
            // no bcc defined
            $this->emailSender->send( MyEmails::ORDER_PAID, [$order->getCustomer()->getEmail()], ['order' => $order] ) ;
        }
    }
}

/**
 *
 * (c) I
 *
 */

namespace My\ShopBundle\Mailer;

/**
 * @author I
 */
class Emails
{
    const ORDER_PAID = 'order_paid';
}

模板按预期定位:Resources/views/Email/orderPaid.html.twig,配置如下:

sylius_mailer:
    emails:
        order_paid:
            subject: "The email subject"
            template: "MyShopBundle:Email:orderPaid.html.twig"

要禁用默认确认邮件,请配置状态机:

winzou_state_machine:
    # disable order confirmation email on checkout/complete (we prefer on thank you action, see order.yml configuration in MyShopBundle to override the thankYouAction)
    sylius_order:
        callbacks:
            after:
                sylius_order_confirmation_email:
                    disabled: true

要在thankYou 操作上触发确认邮件(用例网关支付成功完成),在我的包(Resources/config/routing/order.yml)中:

sylius_shop_order_pay:
    path: /{lastNewPaymentId}/pay
    methods: [GET]
    defaults:
        _controller: sylius.controller.payum:prepareCaptureAction
        _sylius:
            redirect:
                route: sylius_shop_order_after_pay

sylius_shop_order_after_pay:
    path: /after-pay
    methods: [GET]
    defaults:
        _controller: sylius.controller.payum:afterCaptureAction

sylius_shop_order_thank_you:
    path: /thank-you
    methods: [GET]
    defaults:
        # OVERRIDE (add: send mail success confirmation + standard controller because this one is not a service and must not be)
        _controller: MyShopBundle:Payment:thankYou
        _sylius:
            template: MyShopBundle:Checkout:thankYou.html.twig

sylius_shop_order_show_details:
    path: /{tokenValue}
    methods: [GET]
    defaults:
        _controller: sylius.controller.order:showAction
        _sylius:
            template: SyliusShopBundle:Checkout:orderDetails.html.twig
            grid: sylius_shop_account_order
            section: shop_account
            repository:
                method: findOneBy
                arguments:
                    [tokenValue: $tokenValue]

最后我们使用标准的 symfony 控制器覆盖thankYouAction,如下:

<?php

namespace My\ShopBundle\Controller ;

// use Doctrine\ORM\EntityManager;
// use FOS\RestBundle\View\View;
// use Payum\Core\Registry\RegistryInterface;
// use Sylius\Bundle\ResourceBundle\Controller\RequestConfiguration;
// use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
// use Sylius\Component\Order\Context\CartContextInterface;
// use Sylius\Component\Order\Model\OrderInterface;
// use Sylius\Component\Order\SyliusCartEvents;
// use Sylius\Component\Resource\ResourceActions;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Webmozart\Assert\Assert;

// Carefull using ResourceController extending, cause this is a service and not a controller (different constructor)
class PaymentController extends Controller
{

    /**
     * @param Request $request
     *
     * @return Response
     */
    public function thankYouAction(Request $request = null)
    {
        // old implementation (get parameters from custom configuration, more heavy and difficult to maintain)
        //$configuration = $this->requestConfigurationFactory->create($this->metadata, $request);

        // default value for order
        $order = null ;
        // if session variable sylius_order_id exist : deal with order
        if( $request->getSession()->has( 'sylius_order_id' ) ){
            $orderId = $request->getSession()->get( 'sylius_order_id', null ) ;
            // old behaviour based on custom configuration in case session variable does not exist anymore: does a homepage redirect
            // if (null === $orderId) {
            //     return $this->redirectHandler->redirectToRoute(
            //         $configuration,
            //         $configuration->getParameters()->get('after_failure[route]', 'sylius_shop_homepage', true),
            //         $configuration->getParameters()->get('after_failure[parameters]', [], true)
            //     );
            // }

            $request->getSession()->remove( 'sylius_order_id' ) ;
            // prefer call repository service in controller (previously repository came from custom configuration)
            $orderRepository = $this->get( 'sylius.repository.order' ) ;
            $order = $orderRepository->find( $orderId ) ;


            Assert::notNull($order);
            // send email confirmation via sylius.email_manager.order service
            $this->sendEmailConfirmation( $order ) ;
            // old rendering from tankyouAction in Sylius\Bundle\CoreBundle\Controller\OrderController
            // $view = View::create()
            //     ->setData([
            //         'order' => $order
            //     ])
            //     ->setTemplate($configuration->getParameters()->get('template'))
            // ;
            // return $this->viewHandler->handle($configuration, $view);

            // prefer symfony rendering (controller knows its view, execute a controller creation with command line, your template will be defined inside)
            $response = $this->render( 'MyShopBundle:Checkout:thankYou.html.twig', array( 'order' => $order ) ) ;
            // deal with http cache expiration duration
            $response->setSharedMaxAge( 3600 ) ;
        }else{
            // redirect to home page
            $response = $this->redirect( $this->generateUrl( 'sylius_shop_homepage' ) ) ;
        }
        return $response ;
    }

    /**
     *
     */
    private function sendEmailConfirmation( $order ){
        $emailService = $this->container->get( 'sylius.email_manager.order' ) ;
        $emailService->sendPaymentConfirmationEmail( $order ) ;
    }
}

这是一种解决方法,这里的问题没有完全解决,并且是关于使用状态机做同样的事情。默认配置邮件似乎在结帐完成时发送,而它应该关注付款状态。

谢谢 !

4

0 回答 0