初始职位:

我使用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 ) ;
    }
}

This is a workaround, issue here is not fully solved, and is about doing same thing using state machine. Default configuration mail seems to be sent on checkout complete whereas it shoud take care about payment status instead.

谢谢 !