【问题标题】:Payum - Dispatched event on capture?Payum - 捕获时调度事件?
【发布时间】:2016-05-15 15:04:43
【问题描述】:

我想知道 Payum(或 PayumBundle)是否在捕获付款时发送事件? 目的是向客户发送确认电子邮件。

我发现什么都不是文档,我在代码源中只发现了三个事件:

  • payum.gateway.pre_execute
  • payum.gateway.execute
  • payum.gateway.post_execute

但我猜它与付款本身无关。顺便说一句,它似乎从未与 Stripe 付款一起发送。

谢谢。

【问题讨论】:

    标签: symfony events payum


    【解决方案1】:

    Payum 默认不调度任何事件。它旨在通过扩展进行扩展。例如,如果您想在实例推送通知 (Paypal IPN) 上做一些事情,您可以添加如下所述的扩展:http://payum.org/doc/1.0/Core/instant-payment-notification

    还有一个扩展名为dispatch events。您必须手动创建它并添加到 payum。

    【讨论】:

      【解决方案2】:

      我遇到了同样的问题:针对某些支付操作发送自定义事件。就我而言,我想处理 AuthorizeCapture 动作。

      我注意到Payum 请求可能会为 1 次付款操作处理多次,这就是为什么我需要将我的付款标记为已处理,以便只发送一次我的自定义事件(Payment::$customPaymentEventDispatched 的目的属性)。

      这是我的付款实体:

      <?php
      
      namespace MyApp\PaymentBundle\Entity;
      
      use Doctrine\ORM\Mapping as ORM;
      use Payum\Core\Model\Payment as BasePayment;
      
      class Payment extends BasePayment
      {
          // ...
      
          // Not persisted
          protected $payable;
          protected $customPaymentEventDispatched = false;
      
          // ...
      
          public function setPayable($payable)
          {
              $this->payable = $payable;
      
              return $this;
          }
      
          public function getPayable()
          {
              return $this->payable;
          }
      
          public function markAsCustomPaymentEventDispatched()
          {
              $this->customPaymentEventDispatched = true;
      
              return $this;
          }
      
          public function isCustomPaymentEventDispatched()
          {
              return $this->customPaymentEventDispatched;
          }
      }
      

      然后注册 Payum eventDispatcherExtension 和我的自定义监听器

      services:        
      
          payum.extension.event_dispatcher:
              class: Payum\Core\Bridge\Symfony\Extension\EventDispatcherExtension
              arguments: ["@event_dispatcher"]
              tags:
                  - { name: payum.extension, all: true, prepend: false }
      
          my_app_payment.payum.listener.payment_listener:
              class: MyApp\PaymentBundle\EventListener\PaymentListener
              arguments:
                  - "@monolog.logger.payment"
              tags:
                  - { name: kernel.event_listener, event: payum.gateway.post_execute }
      

      以及监听器的代码:

      <?php
      
      namespace MyApp\PaymentBundle\EventListener;
      
      use Payum\Core\Bridge\Symfony\Event\ExecuteEvent;
      use Payum\Core\Request\Authorize;
      use Payum\Core\Request\BaseGetStatus;
      use Payum\Core\Request\Capture;
      use Payum\Core\Model\PaymentInterface;
      use Payum\Core\Request\GetHumanStatus;
      use Psr\Log\LoggerInterface;
      use Symfony\Component\EventDispatcher\EventDispatcherInterface;
      use MyApp\PaymentBundle\Entity\Payment;
      use MyApp\PaymentBundle\Event\PayablePaymentStatusChangeEvent;
      use MyApp\PaymentBundle\PaymentEvents;
      
      class PaymentListener
      {
          protected $logger;
      
          public function __construct(LoggerInterface $logger)
          {
              $this->logger = $logger;
          }
      
          public function onPayumGatewayPostexecute(ExecuteEvent $event, $eventName, EventDispatcherInterface $eventDispatcher)
          {
              $request = $event->getContext()->getRequest();
      
              // Exclude Payum GetStatus request
              // => protect from infinite loop as following code execute one GetStatus request
              if ($request instanceof BaseGetStatus) {
                  return;
              }
              // Request types requiring dispatching an event
              if (!($request instanceof Authorize || $request instanceof Capture)) {
                  return;
              }
      
              $payment = $request->getFirstModel();
              if (!$payment instanceof PaymentInterface) {
                  return;
              }
      
              $event->getContext()->getGateway()->execute($status = new GetHumanStatus($payment));
      
              if (!$payment->isCustomPaymentEventDispatched()) {
                  if ($request instanceof Capture && $status->isCaptured())
                  {
                      $payable = $payment->getPayable();
      
                      $this->logger->info('Dispatching PAYMENT_SUCCESS for '.$payable->__toString());
      
                      $tmEvent = new PayablePaymentStatusChangeEvent($payment->getPayable());
                      $eventDispatcher->dispatch(PaymentEvents::PAYMENT_PENDING, $tmEvent);
      
                      $payment->markAsCustomPaymentEventDispatched();
                  }
                  elseif ($request instanceof Authorize && $status->isAuthorized())
                  {
                      $payable = $payment->getPayable();
      
                      $this->logger->info('Dispatching PAYMENT_PENDING for '.$payable->__toString());
      
                      $tmEvent = new PayablePaymentStatusChangeEvent($payment->getPayable());
                      $eventDispatcher->dispatch(PaymentEvents::PAYMENT_PENDING, $tmEvent);
      
                      $payment->markAsCustomPaymentEventDispatched();
                  }
              }
          }
      }
      

      我对这个实现并不完全满意,但我没有找到更好的方法来实现它。如有任何反馈,我将不胜感激!

      【讨论】:

        【解决方案3】:

        这就是您可以检查付款是否被捕获的方法:

        use Payum\Core\Action\CapturePaymentAction;
        use Payum\Core\Bridge\Symfony\Event\ExecuteEvent;
        use Payum\Core\Request\Capture;
        use Payum\Core\Request\GetHumanStatus;
        
        class SuccessPaymentListener
        {
            public function onPostExecute(ExecuteEvent $event) {
                $context = $event->getContext();
                $action = $context->getAction();
                $request = $context->getRequest();
                if ($action instanceof CapturePaymentAction && $request instanceof Capture) {
                    $status = new GetHumanStatus($request->getToken());
                    $gateway = $context->getGateway();
                    $gateway->execute($status);
                    if ($status->isCaptured()) {
                        $payment = $status->getFirstModel();
                        //here is your stuff
                    }
                }
            }
        }
        

        services.yml:

        app.payum.extension.event_dispatcher:
            class: Payum\Core\Bridge\Symfony\Extension\EventDispatcherExtension
            arguments: ["@event_dispatcher"]
            tags:
                - { name: payum.extension, all: true, prepend: false }
        
        app.success_payment_listener:
            class: AppBundle\Listener\SuccessPaymentListener
            tags:
                - { name: kernel.event_listener, event: payum.gateway.post_execute, method: onPostExecute }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2011-05-25
          • 1970-01-01
          • 2018-05-29
          • 1970-01-01
          • 2016-10-31
          • 2013-11-02
          • 2010-12-06
          • 1970-01-01
          相关资源
          最近更新 更多